241a3083a95316af075b56f0e36506692acd0c2d
[openwrt.git] / target / linux / generic / patches-3.18 / 077-04-bgmac-simplify-tx-ring-index-handling.patch
1 From: Felix Fietkau <nbd@openwrt.org>
2 Date: Sun, 12 Apr 2015 09:58:56 +0200
3 Subject: [PATCH] bgmac: simplify tx ring index handling
4
5 Keep incrementing ring->start and ring->end instead of pointing it to
6 the actual ring slot entry. This simplifies the calculation of the
7 number of free slots.
8
9 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
10 ---
11
12 --- a/drivers/net/ethernet/broadcom/bgmac.c
13 +++ b/drivers/net/ethernet/broadcom/bgmac.c
14 @@ -142,11 +142,10 @@ static netdev_tx_t bgmac_dma_tx_add(stru
15  {
16         struct device *dma_dev = bgmac->core->dma_dev;
17         struct net_device *net_dev = bgmac->net_dev;
18 -       struct bgmac_slot_info *slot = &ring->slots[ring->end];
19 -       int free_slots;
20 +       int index = ring->end % BGMAC_TX_RING_SLOTS;
21 +       struct bgmac_slot_info *slot = &ring->slots[index];
22         int nr_frags;
23         u32 flags;
24 -       int index = ring->end;
25         int i;
26  
27         if (skb->len > BGMAC_DESC_CTL1_LEN) {
28 @@ -159,12 +158,10 @@ static netdev_tx_t bgmac_dma_tx_add(stru
29  
30         nr_frags = skb_shinfo(skb)->nr_frags;
31  
32 -       if (ring->start <= ring->end)
33 -               free_slots = ring->start - ring->end + BGMAC_TX_RING_SLOTS;
34 -       else
35 -               free_slots = ring->start - ring->end;
36 -
37 -       if (free_slots <= nr_frags + 1) {
38 +       /* ring->end - ring->start will return the number of valid slots,
39 +        * even when ring->end overflows
40 +        */
41 +       if (ring->end - ring->start + nr_frags + 1 >= BGMAC_TX_RING_SLOTS) {
42                 bgmac_err(bgmac, "TX ring is full, queue should be stopped!\n");
43                 netif_stop_queue(net_dev);
44                 return NETDEV_TX_BUSY;
45 @@ -200,7 +197,7 @@ static netdev_tx_t bgmac_dma_tx_add(stru
46         }
47  
48         slot->skb = skb;
49 -
50 +       ring->end += nr_frags + 1;
51         netdev_sent_queue(net_dev, skb->len);
52  
53         wmb();
54 @@ -208,13 +205,12 @@ static netdev_tx_t bgmac_dma_tx_add(stru
55         /* Increase ring->end to point empty slot. We tell hardware the first
56          * slot it should *not* read.
57          */
58 -       ring->end = (index + 1) % BGMAC_TX_RING_SLOTS;
59         bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX,
60                     ring->index_base +
61 -                   ring->end * sizeof(struct bgmac_dma_desc));
62 +                   (ring->end % BGMAC_TX_RING_SLOTS) *
63 +                   sizeof(struct bgmac_dma_desc));
64  
65 -       free_slots -= nr_frags + 1;
66 -       if (free_slots < 8)
67 +       if (ring->end - ring->start >= BGMAC_TX_RING_SLOTS - 8)
68                 netif_stop_queue(net_dev);
69  
70         return NETDEV_TX_OK;
71 @@ -256,17 +252,17 @@ static void bgmac_dma_tx_free(struct bgm
72         empty_slot &= BGMAC_DMA_TX_STATDPTR;
73         empty_slot /= sizeof(struct bgmac_dma_desc);
74  
75 -       while (ring->start != empty_slot) {
76 -               struct bgmac_slot_info *slot = &ring->slots[ring->start];
77 -               u32 ctl1 = le32_to_cpu(ring->cpu_base[ring->start].ctl1);
78 -               int len = ctl1 & BGMAC_DESC_CTL1_LEN;
79 +       while (ring->start != ring->end) {
80 +               int slot_idx = ring->start % BGMAC_TX_RING_SLOTS;
81 +               struct bgmac_slot_info *slot = &ring->slots[slot_idx];
82 +               u32 ctl1;
83 +               int len;
84  
85 -               if (!slot->dma_addr) {
86 -                       bgmac_err(bgmac, "Hardware reported transmission for empty TX ring slot %d! End of ring: %d\n",
87 -                                 ring->start, ring->end);
88 -                       goto next;
89 -               }
90 +               if (slot_idx == empty_slot)
91 +                       break;
92  
93 +               ctl1 = le32_to_cpu(ring->cpu_base[slot_idx].ctl1);
94 +               len = ctl1 & BGMAC_DESC_CTL1_LEN;
95                 if (ctl1 & BGMAC_DESC_CTL0_SOF)
96                         /* Unmap no longer used buffer */
97                         dma_unmap_single(dma_dev, slot->dma_addr, len,
98 @@ -284,10 +280,8 @@ static void bgmac_dma_tx_free(struct bgm
99                         slot->skb = NULL;
100                 }
101  
102 -next:
103                 slot->dma_addr = 0;
104 -               if (++ring->start >= BGMAC_TX_RING_SLOTS)
105 -                       ring->start = 0;
106 +               ring->start++;
107                 freed = true;
108         }
109  
110 --- a/drivers/net/ethernet/broadcom/bgmac.h
111 +++ b/drivers/net/ethernet/broadcom/bgmac.h
112 @@ -414,10 +414,10 @@ enum bgmac_dma_ring_type {
113   * empty.
114   */
115  struct bgmac_dma_ring {
116 -       u16 num_slots;
117 -       u16 start;
118 -       u16 end;
119 +       u32 start;
120 +       u32 end;
121  
122 +       u16 num_slots;
123         u16 mmio_base;
124         struct bgmac_dma_desc *cpu_base;
125         dma_addr_t dma_base;