diff options
Diffstat (limited to 'drivers/net/ethernet/amd/xgbe/xgbe-drv.c')
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 175 |
1 files changed, 93 insertions, 82 deletions
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index b93d4404d975..885b02b5be07 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c | |||
@@ -609,6 +609,68 @@ static void xgbe_napi_disable(struct xgbe_prv_data *pdata, unsigned int del) | |||
609 | } | 609 | } |
610 | } | 610 | } |
611 | 611 | ||
612 | static int xgbe_request_irqs(struct xgbe_prv_data *pdata) | ||
613 | { | ||
614 | struct xgbe_channel *channel; | ||
615 | struct net_device *netdev = pdata->netdev; | ||
616 | unsigned int i; | ||
617 | int ret; | ||
618 | |||
619 | ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0, | ||
620 | netdev->name, pdata); | ||
621 | if (ret) { | ||
622 | netdev_alert(netdev, "error requesting irq %d\n", | ||
623 | pdata->dev_irq); | ||
624 | return ret; | ||
625 | } | ||
626 | |||
627 | if (!pdata->per_channel_irq) | ||
628 | return 0; | ||
629 | |||
630 | channel = pdata->channel; | ||
631 | for (i = 0; i < pdata->channel_count; i++, channel++) { | ||
632 | snprintf(channel->dma_irq_name, | ||
633 | sizeof(channel->dma_irq_name) - 1, | ||
634 | "%s-TxRx-%u", netdev_name(netdev), | ||
635 | channel->queue_index); | ||
636 | |||
637 | ret = devm_request_irq(pdata->dev, channel->dma_irq, | ||
638 | xgbe_dma_isr, 0, | ||
639 | channel->dma_irq_name, channel); | ||
640 | if (ret) { | ||
641 | netdev_alert(netdev, "error requesting irq %d\n", | ||
642 | channel->dma_irq); | ||
643 | goto err_irq; | ||
644 | } | ||
645 | } | ||
646 | |||
647 | return 0; | ||
648 | |||
649 | err_irq: | ||
650 | /* Using an unsigned int, 'i' will go to UINT_MAX and exit */ | ||
651 | for (i--, channel--; i < pdata->channel_count; i--, channel--) | ||
652 | devm_free_irq(pdata->dev, channel->dma_irq, channel); | ||
653 | |||
654 | devm_free_irq(pdata->dev, pdata->dev_irq, pdata); | ||
655 | |||
656 | return ret; | ||
657 | } | ||
658 | |||
659 | static void xgbe_free_irqs(struct xgbe_prv_data *pdata) | ||
660 | { | ||
661 | struct xgbe_channel *channel; | ||
662 | unsigned int i; | ||
663 | |||
664 | devm_free_irq(pdata->dev, pdata->dev_irq, pdata); | ||
665 | |||
666 | if (!pdata->per_channel_irq) | ||
667 | return; | ||
668 | |||
669 | channel = pdata->channel; | ||
670 | for (i = 0; i < pdata->channel_count; i++, channel++) | ||
671 | devm_free_irq(pdata->dev, channel->dma_irq, channel); | ||
672 | } | ||
673 | |||
612 | void xgbe_init_tx_coalesce(struct xgbe_prv_data *pdata) | 674 | void xgbe_init_tx_coalesce(struct xgbe_prv_data *pdata) |
613 | { | 675 | { |
614 | struct xgbe_hw_if *hw_if = &pdata->hw_if; | 676 | struct xgbe_hw_if *hw_if = &pdata->hw_if; |
@@ -810,20 +872,20 @@ int xgbe_powerdown(struct net_device *netdev, unsigned int caller) | |||
810 | return -EINVAL; | 872 | return -EINVAL; |
811 | } | 873 | } |
812 | 874 | ||
813 | phy_stop(pdata->phydev); | ||
814 | |||
815 | spin_lock_irqsave(&pdata->lock, flags); | 875 | spin_lock_irqsave(&pdata->lock, flags); |
816 | 876 | ||
817 | if (caller == XGMAC_DRIVER_CONTEXT) | 877 | if (caller == XGMAC_DRIVER_CONTEXT) |
818 | netif_device_detach(netdev); | 878 | netif_device_detach(netdev); |
819 | 879 | ||
820 | netif_tx_stop_all_queues(netdev); | 880 | netif_tx_stop_all_queues(netdev); |
821 | xgbe_napi_disable(pdata, 0); | ||
822 | 881 | ||
823 | /* Powerdown Tx/Rx */ | ||
824 | hw_if->powerdown_tx(pdata); | 882 | hw_if->powerdown_tx(pdata); |
825 | hw_if->powerdown_rx(pdata); | 883 | hw_if->powerdown_rx(pdata); |
826 | 884 | ||
885 | xgbe_napi_disable(pdata, 0); | ||
886 | |||
887 | phy_stop(pdata->phydev); | ||
888 | |||
827 | pdata->power_down = 1; | 889 | pdata->power_down = 1; |
828 | 890 | ||
829 | spin_unlock_irqrestore(&pdata->lock, flags); | 891 | spin_unlock_irqrestore(&pdata->lock, flags); |
@@ -854,14 +916,14 @@ int xgbe_powerup(struct net_device *netdev, unsigned int caller) | |||
854 | 916 | ||
855 | phy_start(pdata->phydev); | 917 | phy_start(pdata->phydev); |
856 | 918 | ||
857 | /* Enable Tx/Rx */ | 919 | xgbe_napi_enable(pdata, 0); |
920 | |||
858 | hw_if->powerup_tx(pdata); | 921 | hw_if->powerup_tx(pdata); |
859 | hw_if->powerup_rx(pdata); | 922 | hw_if->powerup_rx(pdata); |
860 | 923 | ||
861 | if (caller == XGMAC_DRIVER_CONTEXT) | 924 | if (caller == XGMAC_DRIVER_CONTEXT) |
862 | netif_device_attach(netdev); | 925 | netif_device_attach(netdev); |
863 | 926 | ||
864 | xgbe_napi_enable(pdata, 0); | ||
865 | netif_tx_start_all_queues(netdev); | 927 | netif_tx_start_all_queues(netdev); |
866 | 928 | ||
867 | spin_unlock_irqrestore(&pdata->lock, flags); | 929 | spin_unlock_irqrestore(&pdata->lock, flags); |
@@ -875,6 +937,7 @@ static int xgbe_start(struct xgbe_prv_data *pdata) | |||
875 | { | 937 | { |
876 | struct xgbe_hw_if *hw_if = &pdata->hw_if; | 938 | struct xgbe_hw_if *hw_if = &pdata->hw_if; |
877 | struct net_device *netdev = pdata->netdev; | 939 | struct net_device *netdev = pdata->netdev; |
940 | int ret; | ||
878 | 941 | ||
879 | DBGPR("-->xgbe_start\n"); | 942 | DBGPR("-->xgbe_start\n"); |
880 | 943 | ||
@@ -884,17 +947,31 @@ static int xgbe_start(struct xgbe_prv_data *pdata) | |||
884 | 947 | ||
885 | phy_start(pdata->phydev); | 948 | phy_start(pdata->phydev); |
886 | 949 | ||
950 | xgbe_napi_enable(pdata, 1); | ||
951 | |||
952 | ret = xgbe_request_irqs(pdata); | ||
953 | if (ret) | ||
954 | goto err_napi; | ||
955 | |||
887 | hw_if->enable_tx(pdata); | 956 | hw_if->enable_tx(pdata); |
888 | hw_if->enable_rx(pdata); | 957 | hw_if->enable_rx(pdata); |
889 | 958 | ||
890 | xgbe_init_tx_timers(pdata); | 959 | xgbe_init_tx_timers(pdata); |
891 | 960 | ||
892 | xgbe_napi_enable(pdata, 1); | ||
893 | netif_tx_start_all_queues(netdev); | 961 | netif_tx_start_all_queues(netdev); |
894 | 962 | ||
895 | DBGPR("<--xgbe_start\n"); | 963 | DBGPR("<--xgbe_start\n"); |
896 | 964 | ||
897 | return 0; | 965 | return 0; |
966 | |||
967 | err_napi: | ||
968 | xgbe_napi_disable(pdata, 1); | ||
969 | |||
970 | phy_stop(pdata->phydev); | ||
971 | |||
972 | hw_if->exit(pdata); | ||
973 | |||
974 | return ret; | ||
898 | } | 975 | } |
899 | 976 | ||
900 | static void xgbe_stop(struct xgbe_prv_data *pdata) | 977 | static void xgbe_stop(struct xgbe_prv_data *pdata) |
@@ -907,16 +984,21 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) | |||
907 | 984 | ||
908 | DBGPR("-->xgbe_stop\n"); | 985 | DBGPR("-->xgbe_stop\n"); |
909 | 986 | ||
910 | phy_stop(pdata->phydev); | ||
911 | |||
912 | netif_tx_stop_all_queues(netdev); | 987 | netif_tx_stop_all_queues(netdev); |
913 | xgbe_napi_disable(pdata, 1); | ||
914 | 988 | ||
915 | xgbe_stop_tx_timers(pdata); | 989 | xgbe_stop_tx_timers(pdata); |
916 | 990 | ||
917 | hw_if->disable_tx(pdata); | 991 | hw_if->disable_tx(pdata); |
918 | hw_if->disable_rx(pdata); | 992 | hw_if->disable_rx(pdata); |
919 | 993 | ||
994 | xgbe_free_irqs(pdata); | ||
995 | |||
996 | xgbe_napi_disable(pdata, 1); | ||
997 | |||
998 | phy_stop(pdata->phydev); | ||
999 | |||
1000 | hw_if->exit(pdata); | ||
1001 | |||
920 | channel = pdata->channel; | 1002 | channel = pdata->channel; |
921 | for (i = 0; i < pdata->channel_count; i++, channel++) { | 1003 | for (i = 0; i < pdata->channel_count; i++, channel++) { |
922 | if (!channel->tx_ring) | 1004 | if (!channel->tx_ring) |
@@ -931,10 +1013,6 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) | |||
931 | 1013 | ||
932 | static void xgbe_restart_dev(struct xgbe_prv_data *pdata) | 1014 | static void xgbe_restart_dev(struct xgbe_prv_data *pdata) |
933 | { | 1015 | { |
934 | struct xgbe_channel *channel; | ||
935 | struct xgbe_hw_if *hw_if = &pdata->hw_if; | ||
936 | unsigned int i; | ||
937 | |||
938 | DBGPR("-->xgbe_restart_dev\n"); | 1016 | DBGPR("-->xgbe_restart_dev\n"); |
939 | 1017 | ||
940 | /* If not running, "restart" will happen on open */ | 1018 | /* If not running, "restart" will happen on open */ |
@@ -942,19 +1020,10 @@ static void xgbe_restart_dev(struct xgbe_prv_data *pdata) | |||
942 | return; | 1020 | return; |
943 | 1021 | ||
944 | xgbe_stop(pdata); | 1022 | xgbe_stop(pdata); |
945 | synchronize_irq(pdata->dev_irq); | ||
946 | if (pdata->per_channel_irq) { | ||
947 | channel = pdata->channel; | ||
948 | for (i = 0; i < pdata->channel_count; i++, channel++) | ||
949 | synchronize_irq(channel->dma_irq); | ||
950 | } | ||
951 | 1023 | ||
952 | xgbe_free_tx_data(pdata); | 1024 | xgbe_free_tx_data(pdata); |
953 | xgbe_free_rx_data(pdata); | 1025 | xgbe_free_rx_data(pdata); |
954 | 1026 | ||
955 | /* Issue software reset to device */ | ||
956 | hw_if->exit(pdata); | ||
957 | |||
958 | xgbe_start(pdata); | 1027 | xgbe_start(pdata); |
959 | 1028 | ||
960 | DBGPR("<--xgbe_restart_dev\n"); | 1029 | DBGPR("<--xgbe_restart_dev\n"); |
@@ -1283,10 +1352,7 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata, | |||
1283 | static int xgbe_open(struct net_device *netdev) | 1352 | static int xgbe_open(struct net_device *netdev) |
1284 | { | 1353 | { |
1285 | struct xgbe_prv_data *pdata = netdev_priv(netdev); | 1354 | struct xgbe_prv_data *pdata = netdev_priv(netdev); |
1286 | struct xgbe_hw_if *hw_if = &pdata->hw_if; | ||
1287 | struct xgbe_desc_if *desc_if = &pdata->desc_if; | 1355 | struct xgbe_desc_if *desc_if = &pdata->desc_if; |
1288 | struct xgbe_channel *channel = NULL; | ||
1289 | unsigned int i = 0; | ||
1290 | int ret; | 1356 | int ret; |
1291 | 1357 | ||
1292 | DBGPR("-->xgbe_open\n"); | 1358 | DBGPR("-->xgbe_open\n"); |
@@ -1329,55 +1395,14 @@ static int xgbe_open(struct net_device *netdev) | |||
1329 | INIT_WORK(&pdata->restart_work, xgbe_restart); | 1395 | INIT_WORK(&pdata->restart_work, xgbe_restart); |
1330 | INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp); | 1396 | INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp); |
1331 | 1397 | ||
1332 | /* Request interrupts */ | ||
1333 | ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0, | ||
1334 | netdev->name, pdata); | ||
1335 | if (ret) { | ||
1336 | netdev_alert(netdev, "error requesting irq %d\n", | ||
1337 | pdata->dev_irq); | ||
1338 | goto err_rings; | ||
1339 | } | ||
1340 | |||
1341 | if (pdata->per_channel_irq) { | ||
1342 | channel = pdata->channel; | ||
1343 | for (i = 0; i < pdata->channel_count; i++, channel++) { | ||
1344 | snprintf(channel->dma_irq_name, | ||
1345 | sizeof(channel->dma_irq_name) - 1, | ||
1346 | "%s-TxRx-%u", netdev_name(netdev), | ||
1347 | channel->queue_index); | ||
1348 | |||
1349 | ret = devm_request_irq(pdata->dev, channel->dma_irq, | ||
1350 | xgbe_dma_isr, 0, | ||
1351 | channel->dma_irq_name, channel); | ||
1352 | if (ret) { | ||
1353 | netdev_alert(netdev, | ||
1354 | "error requesting irq %d\n", | ||
1355 | channel->dma_irq); | ||
1356 | goto err_irq; | ||
1357 | } | ||
1358 | } | ||
1359 | } | ||
1360 | |||
1361 | ret = xgbe_start(pdata); | 1398 | ret = xgbe_start(pdata); |
1362 | if (ret) | 1399 | if (ret) |
1363 | goto err_start; | 1400 | goto err_rings; |
1364 | 1401 | ||
1365 | DBGPR("<--xgbe_open\n"); | 1402 | DBGPR("<--xgbe_open\n"); |
1366 | 1403 | ||
1367 | return 0; | 1404 | return 0; |
1368 | 1405 | ||
1369 | err_start: | ||
1370 | hw_if->exit(pdata); | ||
1371 | |||
1372 | err_irq: | ||
1373 | if (pdata->per_channel_irq) { | ||
1374 | /* Using an unsigned int, 'i' will go to UINT_MAX and exit */ | ||
1375 | for (i--, channel--; i < pdata->channel_count; i--, channel--) | ||
1376 | devm_free_irq(pdata->dev, channel->dma_irq, channel); | ||
1377 | } | ||
1378 | |||
1379 | devm_free_irq(pdata->dev, pdata->dev_irq, pdata); | ||
1380 | |||
1381 | err_rings: | 1406 | err_rings: |
1382 | desc_if->free_ring_resources(pdata); | 1407 | desc_if->free_ring_resources(pdata); |
1383 | 1408 | ||
@@ -1399,30 +1424,16 @@ err_phy_init: | |||
1399 | static int xgbe_close(struct net_device *netdev) | 1424 | static int xgbe_close(struct net_device *netdev) |
1400 | { | 1425 | { |
1401 | struct xgbe_prv_data *pdata = netdev_priv(netdev); | 1426 | struct xgbe_prv_data *pdata = netdev_priv(netdev); |
1402 | struct xgbe_hw_if *hw_if = &pdata->hw_if; | ||
1403 | struct xgbe_desc_if *desc_if = &pdata->desc_if; | 1427 | struct xgbe_desc_if *desc_if = &pdata->desc_if; |
1404 | struct xgbe_channel *channel; | ||
1405 | unsigned int i; | ||
1406 | 1428 | ||
1407 | DBGPR("-->xgbe_close\n"); | 1429 | DBGPR("-->xgbe_close\n"); |
1408 | 1430 | ||
1409 | /* Stop the device */ | 1431 | /* Stop the device */ |
1410 | xgbe_stop(pdata); | 1432 | xgbe_stop(pdata); |
1411 | 1433 | ||
1412 | /* Issue software reset to device */ | ||
1413 | hw_if->exit(pdata); | ||
1414 | |||
1415 | /* Free the ring descriptors and buffers */ | 1434 | /* Free the ring descriptors and buffers */ |
1416 | desc_if->free_ring_resources(pdata); | 1435 | desc_if->free_ring_resources(pdata); |
1417 | 1436 | ||
1418 | /* Release the interrupts */ | ||
1419 | devm_free_irq(pdata->dev, pdata->dev_irq, pdata); | ||
1420 | if (pdata->per_channel_irq) { | ||
1421 | channel = pdata->channel; | ||
1422 | for (i = 0; i < pdata->channel_count; i++, channel++) | ||
1423 | devm_free_irq(pdata->dev, channel->dma_irq, channel); | ||
1424 | } | ||
1425 | |||
1426 | /* Free the channel and ring structures */ | 1437 | /* Free the channel and ring structures */ |
1427 | xgbe_free_channels(pdata); | 1438 | xgbe_free_channels(pdata); |
1428 | 1439 | ||