diff options
author | Harini Katakam <harini.katakam@xilinx.com> | 2018-01-27 01:39:01 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-01-29 14:25:47 -0500 |
commit | 032dc41ba6e2744a8105e1743607fc4ee155278d (patch) | |
tree | ef820ab373218126c2ee71901e50101bbdd1e9b2 | |
parent | 468330e886ee347778f106b343580cf018ad650f (diff) |
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>
-rw-r--r-- | drivers/net/ethernet/cadence/macb.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/cadence/macb_main.c | 59 |
2 files changed, 58 insertions, 4 deletions
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index c50c5ec49b1d..86659823b259 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/phy.h> | 13 | #include <linux/phy.h> |
14 | #include <linux/ptp_clock_kernel.h> | 14 | #include <linux/ptp_clock_kernel.h> |
15 | #include <linux/net_tstamp.h> | 15 | #include <linux/net_tstamp.h> |
16 | #include <linux/interrupt.h> | ||
16 | 17 | ||
17 | #if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) || defined(CONFIG_MACB_USE_HWSTAMP) | 18 | #if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) || defined(CONFIG_MACB_USE_HWSTAMP) |
18 | #define MACB_EXT_DESC | 19 | #define MACB_EXT_DESC |
@@ -1200,6 +1201,8 @@ struct macb { | |||
1200 | struct ethtool_rx_fs_list rx_fs_list; | 1201 | struct ethtool_rx_fs_list rx_fs_list; |
1201 | spinlock_t rx_fs_lock; | 1202 | spinlock_t rx_fs_lock; |
1202 | unsigned int max_tuples; | 1203 | unsigned int max_tuples; |
1204 | |||
1205 | struct tasklet_struct hresp_err_tasklet; | ||
1203 | }; | 1206 | }; |
1204 | 1207 | ||
1205 | #ifdef CONFIG_MACB_USE_HWSTAMP | 1208 | #ifdef CONFIG_MACB_USE_HWSTAMP |
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 234667eaaa92..e84afcf1ecb5 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c | |||
@@ -1258,6 +1258,57 @@ static int macb_poll(struct napi_struct *napi, int budget) | |||
1258 | return work_done; | 1258 | return work_done; |
1259 | } | 1259 | } |
1260 | 1260 | ||
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 | |||
1261 | static irqreturn_t macb_interrupt(int irq, void *dev_id) | 1312 | static irqreturn_t macb_interrupt(int irq, void *dev_id) |
1262 | { | 1313 | { |
1263 | struct macb_queue *queue = dev_id; | 1314 | struct macb_queue *queue = dev_id; |
@@ -1347,10 +1398,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) | |||
1347 | } | 1398 | } |
1348 | 1399 | ||
1349 | if (status & MACB_BIT(HRESP)) { | 1400 | if (status & MACB_BIT(HRESP)) { |
1350 | /* TODO: Reset the hardware, and maybe move the | 1401 | tasklet_schedule(&bp->hresp_err_tasklet); |
1351 | * netdev_err to a lower-priority context as well | ||
1352 | * (work queue?) | ||
1353 | */ | ||
1354 | netdev_err(dev, "DMA bus error: HRESP not OK\n"); | 1402 | netdev_err(dev, "DMA bus error: HRESP not OK\n"); |
1355 | 1403 | ||
1356 | if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) | 1404 | if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) |
@@ -3937,6 +3985,9 @@ static int macb_probe(struct platform_device *pdev) | |||
3937 | goto err_out_unregister_mdio; | 3985 | goto err_out_unregister_mdio; |
3938 | } | 3986 | } |
3939 | 3987 | ||
3988 | tasklet_init(&bp->hresp_err_tasklet, macb_hresp_error_task, | ||
3989 | (unsigned long)bp); | ||
3990 | |||
3940 | phy_attached_info(phydev); | 3991 | phy_attached_info(phydev); |
3941 | 3992 | ||
3942 | netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n", | 3993 | netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n", |