123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- From: Felix Fietkau <nbd@openwrt.org>
- Date: Sun, 12 Apr 2015 09:58:56 +0200
- Subject: [PATCH] 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>
- ---
- --- 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(stru
- {
- struct device *dma_dev = bgmac->core->dma_dev;
- struct net_device *net_dev = bgmac->net_dev;
- - struct bgmac_slot_info *slot = &ring->slots[ring->end];
- - int free_slots;
- + int index = ring->end % BGMAC_TX_RING_SLOTS;
- + struct bgmac_slot_info *slot = &ring->slots[index];
- int nr_frags;
- u32 flags;
- - int index = ring->end;
- int i;
-
- if (skb->len > BGMAC_DESC_CTL1_LEN) {
- @@ -159,12 +158,10 @@ static netdev_tx_t bgmac_dma_tx_add(stru
-
- nr_frags = skb_shinfo(skb)->nr_frags;
-
- - if (ring->start <= ring->end)
- - free_slots = ring->start - ring->end + BGMAC_TX_RING_SLOTS;
- - else
- - free_slots = ring->start - ring->end;
- -
- - if (free_slots <= nr_frags + 1) {
- + /* ring->end - ring->start will return the number of valid slots,
- + * even when ring->end overflows
- + */
- + if (ring->end - ring->start + nr_frags + 1 >= BGMAC_TX_RING_SLOTS) {
- bgmac_err(bgmac, "TX ring is full, queue should be stopped!\n");
- netif_stop_queue(net_dev);
- return NETDEV_TX_BUSY;
- @@ -200,7 +197,7 @@ static netdev_tx_t bgmac_dma_tx_add(stru
- }
-
- slot->skb = skb;
- -
- + ring->end += nr_frags + 1;
- netdev_sent_queue(net_dev, skb->len);
-
- wmb();
- @@ -208,13 +205,12 @@ static netdev_tx_t bgmac_dma_tx_add(stru
- /* Increase ring->end to point empty slot. We tell hardware the first
- * slot it should *not* read.
- */
- - ring->end = (index + 1) % BGMAC_TX_RING_SLOTS;
- bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX,
- ring->index_base +
- - ring->end * sizeof(struct bgmac_dma_desc));
- + (ring->end % BGMAC_TX_RING_SLOTS) *
- + sizeof(struct bgmac_dma_desc));
-
- - free_slots -= nr_frags + 1;
- - if (free_slots < 8)
- + if (ring->end - ring->start >= BGMAC_TX_RING_SLOTS - 8)
- netif_stop_queue(net_dev);
-
- return NETDEV_TX_OK;
- @@ -256,17 +252,17 @@ static void bgmac_dma_tx_free(struct bgm
- empty_slot &= BGMAC_DMA_TX_STATDPTR;
- empty_slot /= sizeof(struct bgmac_dma_desc);
-
- - while (ring->start != empty_slot) {
- - struct bgmac_slot_info *slot = &ring->slots[ring->start];
- - u32 ctl1 = le32_to_cpu(ring->cpu_base[ring->start].ctl1);
- - int len = ctl1 & BGMAC_DESC_CTL1_LEN;
- + while (ring->start != ring->end) {
- + int slot_idx = ring->start % BGMAC_TX_RING_SLOTS;
- + struct bgmac_slot_info *slot = &ring->slots[slot_idx];
- + u32 ctl1;
- + int len;
-
- - if (!slot->dma_addr) {
- - bgmac_err(bgmac, "Hardware reported transmission for empty TX ring slot %d! End of ring: %d\n",
- - ring->start, ring->end);
- - goto next;
- - }
- + if (slot_idx == empty_slot)
- + break;
-
- + ctl1 = le32_to_cpu(ring->cpu_base[slot_idx].ctl1);
- + len = ctl1 & BGMAC_DESC_CTL1_LEN;
- if (ctl1 & BGMAC_DESC_CTL0_SOF)
- /* Unmap no longer used buffer */
- dma_unmap_single(dma_dev, slot->dma_addr, len,
- @@ -284,10 +280,8 @@ static void bgmac_dma_tx_free(struct bgm
- slot->skb = NULL;
- }
-
- -next:
- slot->dma_addr = 0;
- - if (++ring->start >= BGMAC_TX_RING_SLOTS)
- - ring->start = 0;
- + ring->start++;
- freed = true;
- }
-
- --- a/drivers/net/ethernet/broadcom/bgmac.h
- +++ b/drivers/net/ethernet/broadcom/bgmac.h
- @@ -414,10 +414,10 @@ enum bgmac_dma_ring_type {
- * empty.
- */
- struct bgmac_dma_ring {
- - u16 num_slots;
- - u16 start;
- - u16 end;
- + u32 start;
- + u32 end;
-
- + u16 num_slots;
- u16 mmio_base;
- struct bgmac_dma_desc *cpu_base;
- dma_addr_t dma_base;
|