aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2015-04-14 06:07:54 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-14 14:57:10 -0400
commitb38c83dd08665a93e439c4ffd9eef31bc098a6ea (patch)
treee35af7b479d02c713b303d24bbf60442e0f52bc8 /drivers/net/ethernet/broadcom
parente07678341b612bbf98c2bf205c3f26f3ef5f8e93 (diff)
bgmac: simplify tx ring index handling
Keep incrementing ring->start and ring->end instead of pointing it to the actual ring slot entry. This simplifies the calculation of the number of free slots. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Acked-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/broadcom')
-rw-r--r--drivers/net/ethernet/broadcom/bgmac.c46
-rw-r--r--drivers/net/ethernet/broadcom/bgmac.h6
2 files changed, 23 insertions, 29 deletions
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index fa8f9e147c34..b9e02e484d72 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -142,11 +142,10 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac,
142{ 142{
143 struct device *dma_dev = bgmac->core->dma_dev; 143 struct device *dma_dev = bgmac->core->dma_dev;
144 struct net_device *net_dev = bgmac->net_dev; 144 struct net_device *net_dev = bgmac->net_dev;
145 struct bgmac_slot_info *slot = &ring->slots[ring->end]; 145 int index = ring->end % BGMAC_TX_RING_SLOTS;
146 int free_slots; 146 struct bgmac_slot_info *slot = &ring->slots[index];
147 int nr_frags; 147 int nr_frags;
148 u32 flags; 148 u32 flags;
149 int index = ring->end;
150 int i; 149 int i;
151 150
152 if (skb->len > BGMAC_DESC_CTL1_LEN) { 151 if (skb->len > BGMAC_DESC_CTL1_LEN) {
@@ -159,12 +158,10 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac,
159 158
160 nr_frags = skb_shinfo(skb)->nr_frags; 159 nr_frags = skb_shinfo(skb)->nr_frags;
161 160
162 if (ring->start <= ring->end) 161 /* ring->end - ring->start will return the number of valid slots,
163 free_slots = ring->start - ring->end + BGMAC_TX_RING_SLOTS; 162 * even when ring->end overflows
164 else 163 */
165 free_slots = ring->start - ring->end; 164 if (ring->end - ring->start + nr_frags + 1 >= BGMAC_TX_RING_SLOTS) {
166
167 if (free_slots <= nr_frags + 1) {
168 bgmac_err(bgmac, "TX ring is full, queue should be stopped!\n"); 165 bgmac_err(bgmac, "TX ring is full, queue should be stopped!\n");
169 netif_stop_queue(net_dev); 166 netif_stop_queue(net_dev);
170 return NETDEV_TX_BUSY; 167 return NETDEV_TX_BUSY;
@@ -200,7 +197,7 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac,
200 } 197 }
201 198
202 slot->skb = skb; 199 slot->skb = skb;
203 200 ring->end += nr_frags + 1;
204 netdev_sent_queue(net_dev, skb->len); 201 netdev_sent_queue(net_dev, skb->len);
205 202
206 wmb(); 203 wmb();
@@ -208,13 +205,12 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac,
208 /* Increase ring->end to point empty slot. We tell hardware the first 205 /* Increase ring->end to point empty slot. We tell hardware the first
209 * slot it should *not* read. 206 * slot it should *not* read.
210 */ 207 */
211 ring->end = (index + 1) % BGMAC_TX_RING_SLOTS;
212 bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX, 208 bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX,
213 ring->index_base + 209 ring->index_base +
214 ring->end * sizeof(struct bgmac_dma_desc)); 210 (ring->end % BGMAC_TX_RING_SLOTS) *
211 sizeof(struct bgmac_dma_desc));
215 212
216 free_slots -= nr_frags + 1; 213 if (ring->end - ring->start >= BGMAC_TX_RING_SLOTS - 8)
217 if (free_slots < 8)
218 netif_stop_queue(net_dev); 214 netif_stop_queue(net_dev);
219 215
220 return NETDEV_TX_OK; 216 return NETDEV_TX_OK;
@@ -256,17 +252,17 @@ static void bgmac_dma_tx_free(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
256 empty_slot &= BGMAC_DMA_TX_STATDPTR; 252 empty_slot &= BGMAC_DMA_TX_STATDPTR;
257 empty_slot /= sizeof(struct bgmac_dma_desc); 253 empty_slot /= sizeof(struct bgmac_dma_desc);
258 254
259 while (ring->start != empty_slot) { 255 while (ring->start != ring->end) {
260 struct bgmac_slot_info *slot = &ring->slots[ring->start]; 256 int slot_idx = ring->start % BGMAC_TX_RING_SLOTS;
261 u32 ctl1 = le32_to_cpu(ring->cpu_base[ring->start].ctl1); 257 struct bgmac_slot_info *slot = &ring->slots[slot_idx];
262 int len = ctl1 & BGMAC_DESC_CTL1_LEN; 258 u32 ctl1;
259 int len;
263 260
264 if (!slot->dma_addr) { 261 if (slot_idx == empty_slot)
265 bgmac_err(bgmac, "Hardware reported transmission for empty TX ring slot %d! End of ring: %d\n", 262 break;
266 ring->start, ring->end);
267 goto next;
268 }
269 263
264 ctl1 = le32_to_cpu(ring->cpu_base[slot_idx].ctl1);
265 len = ctl1 & BGMAC_DESC_CTL1_LEN;
270 if (ctl1 & BGMAC_DESC_CTL0_SOF) 266 if (ctl1 & BGMAC_DESC_CTL0_SOF)
271 /* Unmap no longer used buffer */ 267 /* Unmap no longer used buffer */
272 dma_unmap_single(dma_dev, slot->dma_addr, len, 268 dma_unmap_single(dma_dev, slot->dma_addr, len,
@@ -284,10 +280,8 @@ static void bgmac_dma_tx_free(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
284 slot->skb = NULL; 280 slot->skb = NULL;
285 } 281 }
286 282
287next:
288 slot->dma_addr = 0; 283 slot->dma_addr = 0;
289 if (++ring->start >= BGMAC_TX_RING_SLOTS) 284 ring->start++;
290 ring->start = 0;
291 freed = true; 285 freed = true;
292 } 286 }
293 287
diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h
index 3ad965fe7fcc..5a198d56f3e7 100644
--- a/drivers/net/ethernet/broadcom/bgmac.h
+++ b/drivers/net/ethernet/broadcom/bgmac.h
@@ -414,10 +414,10 @@ enum bgmac_dma_ring_type {
414 * empty. 414 * empty.
415 */ 415 */
416struct bgmac_dma_ring { 416struct bgmac_dma_ring {
417 u16 num_slots; 417 u32 start;
418 u16 start; 418 u32 end;
419 u16 end;
420 419
420 u16 num_slots;
421 u16 mmio_base; 421 u16 mmio_base;
422 struct bgmac_dma_desc *cpu_base; 422 struct bgmac_dma_desc *cpu_base;
423 dma_addr_t dma_base; 423 dma_addr_t dma_base;