Commit e4686c2d authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-ll_temac-Bugfixes'



Esben Haabendal says:

====================
net: ll_temac: Bugfixes

Fix a number of bugs which have been present since the first commit.

The bugs fixed in patch 1,2 and 4 have all been observed in real systems, and
was relatively easy to reproduce given an appropriate stress setup.

Changes since v1:

- Changed error handling of of dma_map_single() in temac_start_xmit() to drop
  packet instead of returning NETDEV_TX_BUSY.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6132c1d9 1d63b8d6
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -375,10 +375,14 @@ struct temac_local {
	int tx_bd_next;
	int tx_bd_tail;
	int rx_bd_ci;
	int rx_bd_tail;

	/* DMA channel control setup */
	u32 tx_chnl_ctrl;
	u32 rx_chnl_ctrl;
	u8 coalesce_count_rx;

	struct delayed_work restart_work;
};

/* Wrappers for temac_ior()/temac_iow() function pointers above */
+171 −38
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@
#include <linux/ip.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/dma-mapping.h>
#include <linux/processor.h>
#include <linux/platform_data/xilinx-ll-temac.h>
@@ -367,6 +368,8 @@ static int temac_dma_bd_init(struct net_device *ndev)
		skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data,
					      XTE_MAX_JUMBO_FRAME_SIZE,
					      DMA_FROM_DEVICE);
		if (dma_mapping_error(ndev->dev.parent, skb_dma_addr))
			goto out;
		lp->rx_bd_v[i].phys = cpu_to_be32(skb_dma_addr);
		lp->rx_bd_v[i].len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE);
		lp->rx_bd_v[i].app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
@@ -387,12 +390,13 @@ static int temac_dma_bd_init(struct net_device *ndev)
	lp->tx_bd_next = 0;
	lp->tx_bd_tail = 0;
	lp->rx_bd_ci = 0;
	lp->rx_bd_tail = RX_BD_NUM - 1;

	/* Enable RX DMA transfers */
	wmb();
	lp->dma_out(lp, RX_CURDESC_PTR,  lp->rx_bd_p);
	lp->dma_out(lp, RX_TAILDESC_PTR,
		       lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
		       lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * lp->rx_bd_tail));

	/* Prepare for TX DMA transfer */
	lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p);
@@ -788,6 +792,9 @@ static void temac_start_xmit_done(struct net_device *ndev)
		stat = be32_to_cpu(cur_p->app0);
	}

	/* Matches barrier in temac_start_xmit */
	smp_mb();

	netif_wake_queue(ndev);
}

@@ -830,9 +837,19 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
	cur_p = &lp->tx_bd_v[lp->tx_bd_tail];

	if (temac_check_tx_bd_space(lp, num_frag + 1)) {
		if (!netif_queue_stopped(ndev))
		if (netif_queue_stopped(ndev))
			return NETDEV_TX_BUSY;

		netif_stop_queue(ndev);

		/* Matches barrier in temac_start_xmit_done */
		smp_mb();

		/* Space might have just been freed - check again */
		if (temac_check_tx_bd_space(lp, num_frag))
			return NETDEV_TX_BUSY;

		netif_wake_queue(ndev);
	}

	cur_p->app0 = 0;
@@ -850,12 +867,16 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
	skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data,
				      skb_headlen(skb), DMA_TO_DEVICE);
	cur_p->len = cpu_to_be32(skb_headlen(skb));
	if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent, skb_dma_addr))) {
		dev_kfree_skb_any(skb);
		ndev->stats.tx_dropped++;
		return NETDEV_TX_OK;
	}
	cur_p->phys = cpu_to_be32(skb_dma_addr);
	ptr_to_txbd((void *)skb, cur_p);

	for (ii = 0; ii < num_frag; ii++) {
		lp->tx_bd_tail++;
		if (lp->tx_bd_tail >= TX_BD_NUM)
		if (++lp->tx_bd_tail >= TX_BD_NUM)
			lp->tx_bd_tail = 0;

		cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
@@ -863,6 +884,27 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
					      skb_frag_address(frag),
					      skb_frag_size(frag),
					      DMA_TO_DEVICE);
		if (dma_mapping_error(ndev->dev.parent, skb_dma_addr)) {
			if (--lp->tx_bd_tail < 0)
				lp->tx_bd_tail = TX_BD_NUM - 1;
			cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
			while (--ii >= 0) {
				--frag;
				dma_unmap_single(ndev->dev.parent,
						 be32_to_cpu(cur_p->phys),
						 skb_frag_size(frag),
						 DMA_TO_DEVICE);
				if (--lp->tx_bd_tail < 0)
					lp->tx_bd_tail = TX_BD_NUM - 1;
				cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
			}
			dma_unmap_single(ndev->dev.parent,
					 be32_to_cpu(cur_p->phys),
					 skb_headlen(skb), DMA_TO_DEVICE);
			dev_kfree_skb_any(skb);
			ndev->stats.tx_dropped++;
			return NETDEV_TX_OK;
		}
		cur_p->phys = cpu_to_be32(skb_dma_addr);
		cur_p->len = cpu_to_be32(skb_frag_size(frag));
		cur_p->app0 = 0;
@@ -884,31 +926,56 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
	return NETDEV_TX_OK;
}

static int ll_temac_recv_buffers_available(struct temac_local *lp)
{
	int available;

	if (!lp->rx_skb[lp->rx_bd_ci])
		return 0;
	available = 1 + lp->rx_bd_tail - lp->rx_bd_ci;
	if (available <= 0)
		available += RX_BD_NUM;
	return available;
}

static void ll_temac_recv(struct net_device *ndev)
{
	struct temac_local *lp = netdev_priv(ndev);
	struct sk_buff *skb, *new_skb;
	unsigned int bdstat;
	struct cdmac_bd *cur_p;
	dma_addr_t tail_p, skb_dma_addr;
	int length;
	unsigned long flags;
	int rx_bd;
	bool update_tail = false;

	spin_lock_irqsave(&lp->rx_lock, flags);

	tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
	cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
	/* Process all received buffers, passing them on network
	 * stack.  After this, the buffer descriptors will be in an
	 * un-allocated stage, where no skb is allocated for it, and
	 * they are therefore not available for TEMAC/DMA.
	 */
	do {
		struct cdmac_bd *bd = &lp->rx_bd_v[lp->rx_bd_ci];
		struct sk_buff *skb = lp->rx_skb[lp->rx_bd_ci];
		unsigned int bdstat = be32_to_cpu(bd->app0);
		int length;

	bdstat = be32_to_cpu(cur_p->app0);
	while ((bdstat & STS_CTRL_APP0_CMPLT)) {
		/* While this should not normally happen, we can end
		 * here when GFP_ATOMIC allocations fail, and we
		 * therefore have un-allocated buffers.
		 */
		if (!skb)
			break;

		skb = lp->rx_skb[lp->rx_bd_ci];
		length = be32_to_cpu(cur_p->app4) & 0x3FFF;
		/* Loop over all completed buffer descriptors */
		if (!(bdstat & STS_CTRL_APP0_CMPLT))
			break;

		dma_unmap_single(ndev->dev.parent, be32_to_cpu(cur_p->phys),
		dma_unmap_single(ndev->dev.parent, be32_to_cpu(bd->phys),
				 XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE);
		/* The buffer is not valid for DMA anymore */
		bd->phys = 0;
		bd->len = 0;

		length = be32_to_cpu(bd->app4) & 0x3FFF;
		skb_put(skb, length);
		skb->protocol = eth_type_trans(skb, ndev);
		skb_checksum_none_assert(skb);
@@ -923,43 +990,102 @@ static void ll_temac_recv(struct net_device *ndev)
			 * (back) for proper IP checksum byte order
			 * (be16).
			 */
			skb->csum = htons(be32_to_cpu(cur_p->app3) & 0xFFFF);
			skb->csum = htons(be32_to_cpu(bd->app3) & 0xFFFF);
			skb->ip_summed = CHECKSUM_COMPLETE;
		}

		if (!skb_defer_rx_timestamp(skb))
			netif_rx(skb);
		/* The skb buffer is now owned by network stack above */
		lp->rx_skb[lp->rx_bd_ci] = NULL;

		ndev->stats.rx_packets++;
		ndev->stats.rx_bytes += length;

		new_skb = netdev_alloc_skb_ip_align(ndev,
						XTE_MAX_JUMBO_FRAME_SIZE);
		if (!new_skb) {
			spin_unlock_irqrestore(&lp->rx_lock, flags);
			return;
		rx_bd = lp->rx_bd_ci;
		if (++lp->rx_bd_ci >= RX_BD_NUM)
			lp->rx_bd_ci = 0;
	} while (rx_bd != lp->rx_bd_tail);

	/* DMA operations will halt when the last buffer descriptor is
	 * processed (ie. the one pointed to by RX_TAILDESC_PTR).
	 * When that happens, no more interrupt events will be
	 * generated.  No IRQ_COAL or IRQ_DLY, and not even an
	 * IRQ_ERR.  To avoid stalling, we schedule a delayed work
	 * when there is a potential risk of that happening.  The work
	 * will call this function, and thus re-schedule itself until
	 * enough buffers are available again.
	 */
	if (ll_temac_recv_buffers_available(lp) < lp->coalesce_count_rx)
		schedule_delayed_work(&lp->restart_work, HZ / 1000);

	/* Allocate new buffers for those buffer descriptors that were
	 * passed to network stack.  Note that GFP_ATOMIC allocations
	 * can fail (e.g. when a larger burst of GFP_ATOMIC
	 * allocations occurs), so while we try to allocate all
	 * buffers in the same interrupt where they were processed, we
	 * continue with what we could get in case of allocation
	 * failure.  Allocation of remaining buffers will be retried
	 * in following calls.
	 */
	while (1) {
		struct sk_buff *skb;
		struct cdmac_bd *bd;
		dma_addr_t skb_dma_addr;

		rx_bd = lp->rx_bd_tail + 1;
		if (rx_bd >= RX_BD_NUM)
			rx_bd = 0;
		bd = &lp->rx_bd_v[rx_bd];

		if (bd->phys)
			break;	/* All skb's allocated */

		skb = netdev_alloc_skb_ip_align(ndev, XTE_MAX_JUMBO_FRAME_SIZE);
		if (!skb) {
			dev_warn(&ndev->dev, "skb alloc failed\n");
			break;
		}

		cur_p->app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
		skb_dma_addr = dma_map_single(ndev->dev.parent, new_skb->data,
		skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data,
					      XTE_MAX_JUMBO_FRAME_SIZE,
					      DMA_FROM_DEVICE);
		cur_p->phys = cpu_to_be32(skb_dma_addr);
		cur_p->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE);
		lp->rx_skb[lp->rx_bd_ci] = new_skb;
		if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent,
						   skb_dma_addr))) {
			dev_kfree_skb_any(skb);
			break;
		}

		lp->rx_bd_ci++;
		if (lp->rx_bd_ci >= RX_BD_NUM)
			lp->rx_bd_ci = 0;
		bd->phys = cpu_to_be32(skb_dma_addr);
		bd->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE);
		bd->app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
		lp->rx_skb[rx_bd] = skb;

		lp->rx_bd_tail = rx_bd;
		update_tail = true;
	}

		cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
		bdstat = be32_to_cpu(cur_p->app0);
	/* Move tail pointer when buffers have been allocated */
	if (update_tail) {
		lp->dma_out(lp, RX_TAILDESC_PTR,
			lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_tail);
	}
	lp->dma_out(lp, RX_TAILDESC_PTR, tail_p);

	spin_unlock_irqrestore(&lp->rx_lock, flags);
}

/* Function scheduled to ensure a restart in case of DMA halt
 * condition caused by running out of buffer descriptors.
 */
static void ll_temac_restart_work_func(struct work_struct *work)
{
	struct temac_local *lp = container_of(work, struct temac_local,
					      restart_work.work);
	struct net_device *ndev = lp->ndev;

	ll_temac_recv(ndev);
}

static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev)
{
	struct net_device *ndev = _ndev;
@@ -1052,6 +1178,8 @@ static int temac_stop(struct net_device *ndev)

	dev_dbg(&ndev->dev, "temac_close()\n");

	cancel_delayed_work_sync(&lp->restart_work);

	free_irq(lp->tx_irq, ndev);
	free_irq(lp->rx_irq, ndev);

@@ -1173,6 +1301,7 @@ static int temac_probe(struct platform_device *pdev)
	lp->dev = &pdev->dev;
	lp->options = XTE_OPTION_DEFAULTS;
	spin_lock_init(&lp->rx_lock);
	INIT_DELAYED_WORK(&lp->restart_work, ll_temac_restart_work_func);

	/* Setup mutex for synchronization of indirect register access */
	if (pdata) {
@@ -1279,6 +1408,7 @@ static int temac_probe(struct platform_device *pdev)
		 */
		lp->tx_chnl_ctrl = 0x10220000;
		lp->rx_chnl_ctrl = 0xff070000;
		lp->coalesce_count_rx = 0x07;

		/* Finished with the DMA node; drop the reference */
		of_node_put(dma_np);
@@ -1310,11 +1440,14 @@ static int temac_probe(struct platform_device *pdev)
				(pdata->tx_irq_count << 16);
		else
			lp->tx_chnl_ctrl = 0x10220000;
		if (pdata->rx_irq_timeout || pdata->rx_irq_count)
		if (pdata->rx_irq_timeout || pdata->rx_irq_count) {
			lp->rx_chnl_ctrl = (pdata->rx_irq_timeout << 24) |
				(pdata->rx_irq_count << 16);
		else
			lp->coalesce_count_rx = pdata->rx_irq_count;
		} else {
			lp->rx_chnl_ctrl = 0xff070000;
			lp->coalesce_count_rx = 0x07;
		}
	}

	/* Error handle returned DMA RX and TX interrupts */