@@ -1002,13 +1002,22 @@ static void emac_rx_handler(void *token, int len, int status)
struct sk_buff *skb = token;
struct net_device *ndev = skb->dev;
struct emac_priv *priv = netdev_priv(ndev);
+ struct device *emac_dev = &ndev->dev;
int ret;
+ /* free and bail if we are shutting down */
+ if (unlikely(!netif_running(ndev))) {
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
+ /* recycle on recieve error */
if (status < 0) {
- /* error */
+ ndev->stats.rx_errors++;
goto recycle;
}
+ /* feed received packet up the stack */
skb_put(skb, len);
skb->protocol = eth_type_trans(skb, ndev);
netif_receive_skb(skb);
@@ -1017,13 +1026,17 @@ static void emac_rx_handler(void *token, int len, int status)
/* alloc a new packet for receive */
skb = emac_rx_alloc(priv);
+ if (!skb) {
+ if (netif_msg_rx_err(priv) && net_ratelimit())
+ dev_err(emac_dev, "failed rx buffer alloc\n");
+ return;
+ }
recycle:
- if (skb) {
- ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
- skb_tailroom(skb), GFP_KERNEL);
- WARN_ON(ret < 0);
- }
+ ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
+ skb_tailroom(skb), GFP_KERNEL);
+ if (WARN_ON(ret < 0))
+ dev_kfree_skb_any(skb);
}
static void emac_tx_handler(void *token, int len, int status)