aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Siewior <bigeasy@linutronix.de>2013-04-23 03:31:36 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-25 04:11:49 -0400
commitaacebbf8026ecdae1b55db3912e65c6b1308f5ed (patch)
treef9b54c50ec8822b253feefd1b41ded0e20e681d7
parent817f6d1a13754b043e1a6c1cb713763022860689 (diff)
net/cpsw: don't continue if we miss to allocate rx skbs
if during "ifconfig up" we run out of mem we continue regardless how many skbs we got. In worst case we have zero RX skbs and can't ever receive further packets since the RX skbs are never reallocated. If cpdma_chan_submit() fails we even leak the skb. This patch changes the behavior here: If we fail to allocate an skb during bring up we don't continue and report that error. Same goes for errors from cpdma_chan_submit(). While here I changed to __netdev_alloc_skb_ip_align() so GFP_KERNEL can be used. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Acked-by: Mugunthan V N <mugunthanvnm@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/ti/cpsw.c35
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
870static 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
870static int cpsw_ndo_open(struct net_device *ndev) 879static 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
949static void cpsw_slave_stop(struct cpsw_slave *slave, struct cpsw_priv *priv) 959err_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
958static int cpsw_ndo_stop(struct net_device *ndev) 967static int cpsw_ndo_stop(struct net_device *ndev)