aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarini Katakam <harini.katakam@xilinx.com>2018-01-27 01:39:01 -0500
committerDavid S. Miller <davem@davemloft.net>2018-01-29 14:25:47 -0500
commit032dc41ba6e2744a8105e1743607fc4ee155278d (patch)
treeef820ab373218126c2ee71901e50101bbdd1e9b2
parent468330e886ee347778f106b343580cf018ad650f (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.h3
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c59
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
1261static 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
1261static irqreturn_t macb_interrupt(int irq, void *dev_id) 1312static 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",