Skip to content

Commit 032dc41

Browse files
harini-katakamdavem330
authored andcommitted
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 <[email protected]> Signed-off-by: Michal Simek <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 468330e commit 032dc41

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

drivers/net/ethernet/cadence/macb.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/phy.h>
1414
#include <linux/ptp_clock_kernel.h>
1515
#include <linux/net_tstamp.h>
16+
#include <linux/interrupt.h>
1617

1718
#if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) || defined(CONFIG_MACB_USE_HWSTAMP)
1819
#define MACB_EXT_DESC
@@ -1200,6 +1201,8 @@ struct macb {
12001201
struct ethtool_rx_fs_list rx_fs_list;
12011202
spinlock_t rx_fs_lock;
12021203
unsigned int max_tuples;
1204+
1205+
struct tasklet_struct hresp_err_tasklet;
12031206
};
12041207

12051208
#ifdef CONFIG_MACB_USE_HWSTAMP

drivers/net/ethernet/cadence/macb_main.c

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,57 @@ static int macb_poll(struct napi_struct *napi, int budget)
12581258
return work_done;
12591259
}
12601260

1261+
static void macb_hresp_error_task(unsigned long data)
1262+
{
1263+
struct macb *bp = (struct macb *)data;
1264+
struct net_device *dev = bp->dev;
1265+
struct macb_queue *queue = bp->queues;
1266+
unsigned int q;
1267+
u32 ctrl;
1268+
1269+
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
1270+
queue_writel(queue, IDR, MACB_RX_INT_FLAGS |
1271+
MACB_TX_INT_FLAGS |
1272+
MACB_BIT(HRESP));
1273+
}
1274+
ctrl = macb_readl(bp, NCR);
1275+
ctrl &= ~(MACB_BIT(RE) | MACB_BIT(TE));
1276+
macb_writel(bp, NCR, ctrl);
1277+
1278+
netif_tx_stop_all_queues(dev);
1279+
netif_carrier_off(dev);
1280+
1281+
bp->macbgem_ops.mog_init_rings(bp);
1282+
1283+
/* Initialize TX and RX buffers */
1284+
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
1285+
queue_writel(queue, RBQP, lower_32_bits(queue->rx_ring_dma));
1286+
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
1287+
if (bp->hw_dma_cap & HW_DMA_CAP_64B)
1288+
queue_writel(queue, RBQPH,
1289+
upper_32_bits(queue->rx_ring_dma));
1290+
#endif
1291+
queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
1292+
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
1293+
if (bp->hw_dma_cap & HW_DMA_CAP_64B)
1294+
queue_writel(queue, TBQPH,
1295+
upper_32_bits(queue->tx_ring_dma));
1296+
#endif
1297+
1298+
/* Enable interrupts */
1299+
queue_writel(queue, IER,
1300+
MACB_RX_INT_FLAGS |
1301+
MACB_TX_INT_FLAGS |
1302+
MACB_BIT(HRESP));
1303+
}
1304+
1305+
ctrl |= MACB_BIT(RE) | MACB_BIT(TE);
1306+
macb_writel(bp, NCR, ctrl);
1307+
1308+
netif_carrier_on(dev);
1309+
netif_tx_start_all_queues(dev);
1310+
}
1311+
12611312
static irqreturn_t macb_interrupt(int irq, void *dev_id)
12621313
{
12631314
struct macb_queue *queue = dev_id;
@@ -1347,10 +1398,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
13471398
}
13481399

13491400
if (status & MACB_BIT(HRESP)) {
1350-
/* TODO: Reset the hardware, and maybe move the
1351-
* netdev_err to a lower-priority context as well
1352-
* (work queue?)
1353-
*/
1401+
tasklet_schedule(&bp->hresp_err_tasklet);
13541402
netdev_err(dev, "DMA bus error: HRESP not OK\n");
13551403

13561404
if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
@@ -3937,6 +3985,9 @@ static int macb_probe(struct platform_device *pdev)
39373985
goto err_out_unregister_mdio;
39383986
}
39393987

3988+
tasklet_init(&bp->hresp_err_tasklet, macb_hresp_error_task,
3989+
(unsigned long)bp);
3990+
39403991
phy_attached_info(phydev);
39413992

39423993
netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n",

0 commit comments

Comments
 (0)