diff options
-rw-r--r-- | drivers/net/ethernet/ti/cpsw.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 25c364209a21..5f581bc511ba 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c | |||
@@ -867,6 +867,15 @@ static void cpsw_init_host_port(struct cpsw_priv *priv) | |||
867 | } | 867 | } |
868 | } | 868 | } |
869 | 869 | ||
870 | static void cpsw_slave_stop(struct cpsw_slave *slave, struct cpsw_priv *priv) | ||
871 | { | ||
872 | if (!slave->phy) | ||
873 | return; | ||
874 | phy_stop(slave->phy); | ||
875 | phy_disconnect(slave->phy); | ||
876 | slave->phy = NULL; | ||
877 | } | ||
878 | |||
870 | static int cpsw_ndo_open(struct net_device *ndev) | 879 | static int cpsw_ndo_open(struct net_device *ndev) |
871 | { | 880 | { |
872 | struct cpsw_priv *priv = netdev_priv(ndev); | 881 | struct cpsw_priv *priv = netdev_priv(ndev); |
@@ -912,14 +921,16 @@ static int cpsw_ndo_open(struct net_device *ndev) | |||
912 | struct sk_buff *skb; | 921 | struct sk_buff *skb; |
913 | 922 | ||
914 | ret = -ENOMEM; | 923 | ret = -ENOMEM; |
915 | skb = netdev_alloc_skb_ip_align(priv->ndev, | 924 | skb = __netdev_alloc_skb_ip_align(priv->ndev, |
916 | priv->rx_packet_max); | 925 | priv->rx_packet_max, GFP_KERNEL); |
917 | if (!skb) | 926 | if (!skb) |
918 | break; | 927 | goto err_cleanup; |
919 | ret = cpdma_chan_submit(priv->rxch, skb, skb->data, | 928 | ret = cpdma_chan_submit(priv->rxch, skb, skb->data, |
920 | skb_tailroom(skb), 0, GFP_KERNEL); | 929 | skb_tailroom(skb), 0, GFP_KERNEL); |
921 | if (WARN_ON(ret < 0)) | 930 | if (ret < 0) { |
922 | break; | 931 | kfree_skb(skb); |
932 | goto err_cleanup; | ||
933 | } | ||
923 | } | 934 | } |
924 | /* continue even if we didn't manage to submit all | 935 | /* continue even if we didn't manage to submit all |
925 | * receive descs | 936 | * receive descs |
@@ -944,15 +955,13 @@ static int cpsw_ndo_open(struct net_device *ndev) | |||
944 | if (priv->data.dual_emac) | 955 | if (priv->data.dual_emac) |
945 | priv->slaves[priv->emac_port].open_stat = true; | 956 | priv->slaves[priv->emac_port].open_stat = true; |
946 | return 0; | 957 | return 0; |
947 | } | ||
948 | 958 | ||
949 | static void cpsw_slave_stop(struct cpsw_slave *slave, struct cpsw_priv *priv) | 959 | err_cleanup: |
950 | { | 960 | cpdma_ctlr_stop(priv->dma); |
951 | if (!slave->phy) | 961 | for_each_slave(priv, cpsw_slave_stop, priv); |
952 | return; | 962 | pm_runtime_put_sync(&priv->pdev->dev); |
953 | phy_stop(slave->phy); | 963 | netif_carrier_off(priv->ndev); |
954 | phy_disconnect(slave->phy); | 964 | return ret; |
955 | slave->phy = NULL; | ||
956 | } | 965 | } |
957 | 966 | ||
958 | static int cpsw_ndo_stop(struct net_device *ndev) | 967 | static int cpsw_ndo_stop(struct net_device *ndev) |