aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorVince Bridgers <vbridger@altera.com>2014-04-24 17:58:10 -0400
committerDavid S. Miller <davem@davemloft.net>2014-04-26 12:26:26 -0400
commita76420092d3d9f2e52ad7469c210c0e2fa962fe4 (patch)
tree65c8efdbdc2618ae5f892ca99d5daaa7141a224f /drivers/net
parent5aec4ee3724ad93ee63cafc6f6b5f9cd40adda52 (diff)
Altera TSE: Fix Panic in probe routine when phy probe fails
This patch addresses a fault in the error recovery path of the probe routine where the netdev structure was not being unregistered properly leading to a panic only when the phy probe failed. Abbreviated panic stack seen is as follows: (free_netdev+0xXX) from (altera_tse_probe+0xXX) (altera_tse_probe+0xXX) from (platform_drv_probe+0xXX) (platform_drv_probe+0xXX) from (driver_probe_device+0xXX) (driver_probe_device+0xXX) from (__driver_attach+0xXX) (__driver_attach+0xXX) from (bus_for_each_dev+0xXX) (bus_for_each_dev+0xXX) from (driver_attach+0xXX) (driver_attach+0xXX) from (bus_add_driver+0xXX) (bus_add_driver+0xXX) from (driver_register+0xXX) (driver_register+0xXX) from (__platform_driver_register+0xXX) (__platform_driver_register+0xXX) from (altera_tse_driver_init+0xXX) (altera_tse_driver_init+0xXX) from (do_one_initcall+0xXX) (do_one_initcall+0xXX) from (kernel_init_freeable+0xXX) (kernel_init_freeable+0xXX) from (kernel_init+0xXX) (kernel_init+0xXX) from (ret_from_fork+0xXX) Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/altera/altera_tse_main.c45
1 files changed, 24 insertions, 21 deletions
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 63712830b333..e44a4aeb9701 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -1245,7 +1245,7 @@ static int altera_tse_probe(struct platform_device *pdev)
1245 /* Get the mapped address to the SGDMA descriptor memory */ 1245 /* Get the mapped address to the SGDMA descriptor memory */
1246 ret = request_and_map(pdev, "s1", &dma_res, &descmap); 1246 ret = request_and_map(pdev, "s1", &dma_res, &descmap);
1247 if (ret) 1247 if (ret)
1248 goto out_free; 1248 goto err_free_netdev;
1249 1249
1250 /* Start of that memory is for transmit descriptors */ 1250 /* Start of that memory is for transmit descriptors */
1251 priv->tx_dma_desc = descmap; 1251 priv->tx_dma_desc = descmap;
@@ -1264,24 +1264,24 @@ static int altera_tse_probe(struct platform_device *pdev)
1264 if (upper_32_bits(priv->rxdescmem_busaddr)) { 1264 if (upper_32_bits(priv->rxdescmem_busaddr)) {
1265 dev_dbg(priv->device, 1265 dev_dbg(priv->device,
1266 "SGDMA bus addresses greater than 32-bits\n"); 1266 "SGDMA bus addresses greater than 32-bits\n");
1267 goto out_free; 1267 goto err_free_netdev;
1268 } 1268 }
1269 if (upper_32_bits(priv->txdescmem_busaddr)) { 1269 if (upper_32_bits(priv->txdescmem_busaddr)) {
1270 dev_dbg(priv->device, 1270 dev_dbg(priv->device,
1271 "SGDMA bus addresses greater than 32-bits\n"); 1271 "SGDMA bus addresses greater than 32-bits\n");
1272 goto out_free; 1272 goto err_free_netdev;
1273 } 1273 }
1274 } else if (priv->dmaops && 1274 } else if (priv->dmaops &&
1275 priv->dmaops->altera_dtype == ALTERA_DTYPE_MSGDMA) { 1275 priv->dmaops->altera_dtype == ALTERA_DTYPE_MSGDMA) {
1276 ret = request_and_map(pdev, "rx_resp", &dma_res, 1276 ret = request_and_map(pdev, "rx_resp", &dma_res,
1277 &priv->rx_dma_resp); 1277 &priv->rx_dma_resp);
1278 if (ret) 1278 if (ret)
1279 goto out_free; 1279 goto err_free_netdev;
1280 1280
1281 ret = request_and_map(pdev, "tx_desc", &dma_res, 1281 ret = request_and_map(pdev, "tx_desc", &dma_res,
1282 &priv->tx_dma_desc); 1282 &priv->tx_dma_desc);
1283 if (ret) 1283 if (ret)
1284 goto out_free; 1284 goto err_free_netdev;
1285 1285
1286 priv->txdescmem = resource_size(dma_res); 1286 priv->txdescmem = resource_size(dma_res);
1287 priv->txdescmem_busaddr = dma_res->start; 1287 priv->txdescmem_busaddr = dma_res->start;
@@ -1289,13 +1289,13 @@ static int altera_tse_probe(struct platform_device *pdev)
1289 ret = request_and_map(pdev, "rx_desc", &dma_res, 1289 ret = request_and_map(pdev, "rx_desc", &dma_res,
1290 &priv->rx_dma_desc); 1290 &priv->rx_dma_desc);
1291 if (ret) 1291 if (ret)
1292 goto out_free; 1292 goto err_free_netdev;
1293 1293
1294 priv->rxdescmem = resource_size(dma_res); 1294 priv->rxdescmem = resource_size(dma_res);
1295 priv->rxdescmem_busaddr = dma_res->start; 1295 priv->rxdescmem_busaddr = dma_res->start;
1296 1296
1297 } else { 1297 } else {
1298 goto out_free; 1298 goto err_free_netdev;
1299 } 1299 }
1300 1300
1301 if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) 1301 if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask)))
@@ -1304,26 +1304,26 @@ static int altera_tse_probe(struct platform_device *pdev)
1304 else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) 1304 else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32)))
1305 dma_set_coherent_mask(priv->device, DMA_BIT_MASK(32)); 1305 dma_set_coherent_mask(priv->device, DMA_BIT_MASK(32));
1306 else 1306 else
1307 goto out_free; 1307 goto err_free_netdev;
1308 1308
1309 /* MAC address space */ 1309 /* MAC address space */
1310 ret = request_and_map(pdev, "control_port", &control_port, 1310 ret = request_and_map(pdev, "control_port", &control_port,
1311 (void __iomem **)&priv->mac_dev); 1311 (void __iomem **)&priv->mac_dev);
1312 if (ret) 1312 if (ret)
1313 goto out_free; 1313 goto err_free_netdev;
1314 1314
1315 /* xSGDMA Rx Dispatcher address space */ 1315 /* xSGDMA Rx Dispatcher address space */
1316 ret = request_and_map(pdev, "rx_csr", &dma_res, 1316 ret = request_and_map(pdev, "rx_csr", &dma_res,
1317 &priv->rx_dma_csr); 1317 &priv->rx_dma_csr);
1318 if (ret) 1318 if (ret)
1319 goto out_free; 1319 goto err_free_netdev;
1320 1320
1321 1321
1322 /* xSGDMA Tx Dispatcher address space */ 1322 /* xSGDMA Tx Dispatcher address space */
1323 ret = request_and_map(pdev, "tx_csr", &dma_res, 1323 ret = request_and_map(pdev, "tx_csr", &dma_res,
1324 &priv->tx_dma_csr); 1324 &priv->tx_dma_csr);
1325 if (ret) 1325 if (ret)
1326 goto out_free; 1326 goto err_free_netdev;
1327 1327
1328 1328
1329 /* Rx IRQ */ 1329 /* Rx IRQ */
@@ -1331,7 +1331,7 @@ static int altera_tse_probe(struct platform_device *pdev)
1331 if (priv->rx_irq == -ENXIO) { 1331 if (priv->rx_irq == -ENXIO) {
1332 dev_err(&pdev->dev, "cannot obtain Rx IRQ\n"); 1332 dev_err(&pdev->dev, "cannot obtain Rx IRQ\n");
1333 ret = -ENXIO; 1333 ret = -ENXIO;
1334 goto out_free; 1334 goto err_free_netdev;
1335 } 1335 }
1336 1336
1337 /* Tx IRQ */ 1337 /* Tx IRQ */
@@ -1339,7 +1339,7 @@ static int altera_tse_probe(struct platform_device *pdev)
1339 if (priv->tx_irq == -ENXIO) { 1339 if (priv->tx_irq == -ENXIO) {
1340 dev_err(&pdev->dev, "cannot obtain Tx IRQ\n"); 1340 dev_err(&pdev->dev, "cannot obtain Tx IRQ\n");
1341 ret = -ENXIO; 1341 ret = -ENXIO;
1342 goto out_free; 1342 goto err_free_netdev;
1343 } 1343 }
1344 1344
1345 /* get FIFO depths from device tree */ 1345 /* get FIFO depths from device tree */
@@ -1347,14 +1347,14 @@ static int altera_tse_probe(struct platform_device *pdev)
1347 &priv->rx_fifo_depth)) { 1347 &priv->rx_fifo_depth)) {
1348 dev_err(&pdev->dev, "cannot obtain rx-fifo-depth\n"); 1348 dev_err(&pdev->dev, "cannot obtain rx-fifo-depth\n");
1349 ret = -ENXIO; 1349 ret = -ENXIO;
1350 goto out_free; 1350 goto err_free_netdev;
1351 } 1351 }
1352 1352
1353 if (of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", 1353 if (of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth",
1354 &priv->rx_fifo_depth)) { 1354 &priv->rx_fifo_depth)) {
1355 dev_err(&pdev->dev, "cannot obtain tx-fifo-depth\n"); 1355 dev_err(&pdev->dev, "cannot obtain tx-fifo-depth\n");
1356 ret = -ENXIO; 1356 ret = -ENXIO;
1357 goto out_free; 1357 goto err_free_netdev;
1358 } 1358 }
1359 1359
1360 /* get hash filter settings for this instance */ 1360 /* get hash filter settings for this instance */
@@ -1403,7 +1403,7 @@ static int altera_tse_probe(struct platform_device *pdev)
1403 ((priv->phy_addr >= 0) && (priv->phy_addr < PHY_MAX_ADDR)))) { 1403 ((priv->phy_addr >= 0) && (priv->phy_addr < PHY_MAX_ADDR)))) {
1404 dev_err(&pdev->dev, "invalid phy-addr specified %d\n", 1404 dev_err(&pdev->dev, "invalid phy-addr specified %d\n",
1405 priv->phy_addr); 1405 priv->phy_addr);
1406 goto out_free; 1406 goto err_free_netdev;
1407 } 1407 }
1408 1408
1409 /* Create/attach to MDIO bus */ 1409 /* Create/attach to MDIO bus */
@@ -1411,7 +1411,7 @@ static int altera_tse_probe(struct platform_device *pdev)
1411 atomic_add_return(1, &instance_count)); 1411 atomic_add_return(1, &instance_count));
1412 1412
1413 if (ret) 1413 if (ret)
1414 goto out_free; 1414 goto err_free_netdev;
1415 1415
1416 /* initialize netdev */ 1416 /* initialize netdev */
1417 ether_setup(ndev); 1417 ether_setup(ndev);
@@ -1448,7 +1448,7 @@ static int altera_tse_probe(struct platform_device *pdev)
1448 ret = register_netdev(ndev); 1448 ret = register_netdev(ndev);
1449 if (ret) { 1449 if (ret) {
1450 dev_err(&pdev->dev, "failed to register TSE net device\n"); 1450 dev_err(&pdev->dev, "failed to register TSE net device\n");
1451 goto out_free_mdio; 1451 goto err_register_netdev;
1452 } 1452 }
1453 1453
1454 platform_set_drvdata(pdev, ndev); 1454 platform_set_drvdata(pdev, ndev);
@@ -1465,13 +1465,16 @@ static int altera_tse_probe(struct platform_device *pdev)
1465 ret = init_phy(ndev); 1465 ret = init_phy(ndev);
1466 if (ret != 0) { 1466 if (ret != 0) {
1467 netdev_err(ndev, "Cannot attach to PHY (error: %d)\n", ret); 1467 netdev_err(ndev, "Cannot attach to PHY (error: %d)\n", ret);
1468 goto out_free_mdio; 1468 goto err_init_phy;
1469 } 1469 }
1470 return 0; 1470 return 0;
1471 1471
1472out_free_mdio: 1472err_init_phy:
1473 unregister_netdev(ndev);
1474err_register_netdev:
1475 netif_napi_del(&priv->napi);
1473 altera_tse_mdio_destroy(ndev); 1476 altera_tse_mdio_destroy(ndev);
1474out_free: 1477err_free_netdev:
1475 free_netdev(ndev); 1478 free_netdev(ndev);
1476 return ret; 1479 return ret;
1477} 1480}