mirror of
https://github.com/torvalds/linux.git
synced 2024-12-13 22:53:20 +00:00
net: macb: Handle HRESP error
Handle HRESP error by doing a SW reset of RX and TX and re-initializing the descriptors, RX and TX queue pointers. Signed-off-by: Harini Katakam <harinik@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
468330e886
commit
032dc41ba6
@ -13,6 +13,7 @@
|
||||
#include <linux/phy.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) || defined(CONFIG_MACB_USE_HWSTAMP)
|
||||
#define MACB_EXT_DESC
|
||||
@ -1200,6 +1201,8 @@ struct macb {
|
||||
struct ethtool_rx_fs_list rx_fs_list;
|
||||
spinlock_t rx_fs_lock;
|
||||
unsigned int max_tuples;
|
||||
|
||||
struct tasklet_struct hresp_err_tasklet;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MACB_USE_HWSTAMP
|
||||
|
@ -1258,6 +1258,57 @@ static int macb_poll(struct napi_struct *napi, int budget)
|
||||
return work_done;
|
||||
}
|
||||
|
||||
static void macb_hresp_error_task(unsigned long data)
|
||||
{
|
||||
struct macb *bp = (struct macb *)data;
|
||||
struct net_device *dev = bp->dev;
|
||||
struct macb_queue *queue = bp->queues;
|
||||
unsigned int q;
|
||||
u32 ctrl;
|
||||
|
||||
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
|
||||
queue_writel(queue, IDR, MACB_RX_INT_FLAGS |
|
||||
MACB_TX_INT_FLAGS |
|
||||
MACB_BIT(HRESP));
|
||||
}
|
||||
ctrl = macb_readl(bp, NCR);
|
||||
ctrl &= ~(MACB_BIT(RE) | MACB_BIT(TE));
|
||||
macb_writel(bp, NCR, ctrl);
|
||||
|
||||
netif_tx_stop_all_queues(dev);
|
||||
netif_carrier_off(dev);
|
||||
|
||||
bp->macbgem_ops.mog_init_rings(bp);
|
||||
|
||||
/* Initialize TX and RX buffers */
|
||||
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
|
||||
queue_writel(queue, RBQP, lower_32_bits(queue->rx_ring_dma));
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
if (bp->hw_dma_cap & HW_DMA_CAP_64B)
|
||||
queue_writel(queue, RBQPH,
|
||||
upper_32_bits(queue->rx_ring_dma));
|
||||
#endif
|
||||
queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
if (bp->hw_dma_cap & HW_DMA_CAP_64B)
|
||||
queue_writel(queue, TBQPH,
|
||||
upper_32_bits(queue->tx_ring_dma));
|
||||
#endif
|
||||
|
||||
/* Enable interrupts */
|
||||
queue_writel(queue, IER,
|
||||
MACB_RX_INT_FLAGS |
|
||||
MACB_TX_INT_FLAGS |
|
||||
MACB_BIT(HRESP));
|
||||
}
|
||||
|
||||
ctrl |= MACB_BIT(RE) | MACB_BIT(TE);
|
||||
macb_writel(bp, NCR, ctrl);
|
||||
|
||||
netif_carrier_on(dev);
|
||||
netif_tx_start_all_queues(dev);
|
||||
}
|
||||
|
||||
static irqreturn_t macb_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct macb_queue *queue = dev_id;
|
||||
@ -1347,10 +1398,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
if (status & MACB_BIT(HRESP)) {
|
||||
/* TODO: Reset the hardware, and maybe move the
|
||||
* netdev_err to a lower-priority context as well
|
||||
* (work queue?)
|
||||
*/
|
||||
tasklet_schedule(&bp->hresp_err_tasklet);
|
||||
netdev_err(dev, "DMA bus error: HRESP not OK\n");
|
||||
|
||||
if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
|
||||
@ -3937,6 +3985,9 @@ static int macb_probe(struct platform_device *pdev)
|
||||
goto err_out_unregister_mdio;
|
||||
}
|
||||
|
||||
tasklet_init(&bp->hresp_err_tasklet, macb_hresp_error_task,
|
||||
(unsigned long)bp);
|
||||
|
||||
phy_attached_info(phydev);
|
||||
|
||||
netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n",
|
||||
|
Loading…
Reference in New Issue
Block a user