Commit b38c83dd authored by Felix Fietkau's avatar Felix Fietkau Committed by David S. Miller
Browse files

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: default avatarFelix Fietkau <nbd@openwrt.org>
Acked-by: default avatarRafał Miłecki <zajec5@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e0767834
Loading
Loading
Loading
Loading
+20 −26
Original line number Original line Diff line number Diff line
@@ -142,11 +142,10 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac,
{
{
	struct device *dma_dev = bgmac->core->dma_dev;
	struct device *dma_dev = bgmac->core->dma_dev;
	struct net_device *net_dev = bgmac->net_dev;
	struct net_device *net_dev = bgmac->net_dev;
	struct bgmac_slot_info *slot = &ring->slots[ring->end];
	int index = ring->end % BGMAC_TX_RING_SLOTS;
	int free_slots;
	struct bgmac_slot_info *slot = &ring->slots[index];
	int nr_frags;
	int nr_frags;
	u32 flags;
	u32 flags;
	int index = ring->end;
	int i;
	int i;


	if (skb->len > BGMAC_DESC_CTL1_LEN) {
	if (skb->len > BGMAC_DESC_CTL1_LEN) {
@@ -159,12 +158,10 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac,


	nr_frags = skb_shinfo(skb)->nr_frags;
	nr_frags = skb_shinfo(skb)->nr_frags;


	if (ring->start <= ring->end)
	/* ring->end - ring->start will return the number of valid slots,
		free_slots = ring->start - ring->end + BGMAC_TX_RING_SLOTS;
	 * even when ring->end overflows
	else
	 */
		free_slots = ring->start - ring->end;
	if (ring->end - ring->start + nr_frags + 1 >= BGMAC_TX_RING_SLOTS) {

	if (free_slots <= nr_frags + 1) {
		bgmac_err(bgmac, "TX ring is full, queue should be stopped!\n");
		bgmac_err(bgmac, "TX ring is full, queue should be stopped!\n");
		netif_stop_queue(net_dev);
		netif_stop_queue(net_dev);
		return NETDEV_TX_BUSY;
		return NETDEV_TX_BUSY;
@@ -200,7 +197,7 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac,
	}
	}


	slot->skb = skb;
	slot->skb = skb;

	ring->end += nr_frags + 1;
	netdev_sent_queue(net_dev, skb->len);
	netdev_sent_queue(net_dev, skb->len);


	wmb();
	wmb();
@@ -208,13 +205,12 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac,
	/* Increase ring->end to point empty slot. We tell hardware the first
	/* Increase ring->end to point empty slot. We tell hardware the first
	 * slot it should *not* read.
	 * slot it should *not* read.
	 */
	 */
	ring->end = (index + 1) % BGMAC_TX_RING_SLOTS;
	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX,
	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX,
		    ring->index_base +
		    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 (ring->end - ring->start >= BGMAC_TX_RING_SLOTS - 8)
	if (free_slots < 8)
		netif_stop_queue(net_dev);
		netif_stop_queue(net_dev);


	return NETDEV_TX_OK;
	return NETDEV_TX_OK;
@@ -256,17 +252,17 @@ static void bgmac_dma_tx_free(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
	empty_slot &= BGMAC_DMA_TX_STATDPTR;
	empty_slot &= BGMAC_DMA_TX_STATDPTR;
	empty_slot /= sizeof(struct bgmac_dma_desc);
	empty_slot /= sizeof(struct bgmac_dma_desc);


	while (ring->start != empty_slot) {
	while (ring->start != ring->end) {
		struct bgmac_slot_info *slot = &ring->slots[ring->start];
		int slot_idx = ring->start % BGMAC_TX_RING_SLOTS;
		u32 ctl1 = le32_to_cpu(ring->cpu_base[ring->start].ctl1);
		struct bgmac_slot_info *slot = &ring->slots[slot_idx];
		int len = ctl1 & BGMAC_DESC_CTL1_LEN;
		u32 ctl1;
		int len;


		if (!slot->dma_addr) {
		if (slot_idx == empty_slot)
			bgmac_err(bgmac, "Hardware reported transmission for empty TX ring slot %d! End of ring: %d\n",
			break;
				  ring->start, ring->end);
			goto next;
		}


		ctl1 = le32_to_cpu(ring->cpu_base[slot_idx].ctl1);
		len = ctl1 & BGMAC_DESC_CTL1_LEN;
		if (ctl1 & BGMAC_DESC_CTL0_SOF)
		if (ctl1 & BGMAC_DESC_CTL0_SOF)
			/* Unmap no longer used buffer */
			/* Unmap no longer used buffer */
			dma_unmap_single(dma_dev, slot->dma_addr, len,
			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)
			slot->skb = NULL;
			slot->skb = NULL;
		}
		}


next:
		slot->dma_addr = 0;
		slot->dma_addr = 0;
		if (++ring->start >= BGMAC_TX_RING_SLOTS)
		ring->start++;
			ring->start = 0;
		freed = true;
		freed = true;
	}
	}


+3 −3
Original line number Original line Diff line number Diff line
@@ -414,10 +414,10 @@ enum bgmac_dma_ring_type {
 * empty.
 * empty.
 */
 */
struct bgmac_dma_ring {
struct bgmac_dma_ring {
	u16 num_slots;
	u32 start;
	u16 start;
	u32 end;
	u16 end;


	u16 num_slots;
	u16 mmio_base;
	u16 mmio_base;
	struct bgmac_dma_desc *cpu_base;
	struct bgmac_dma_desc *cpu_base;
	dma_addr_t dma_base;
	dma_addr_t dma_base;