diff options
author | Jonas Jensen <jonas.jensen@gmail.com> | 2014-08-25 10:22:40 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-08-25 20:25:39 -0400 |
commit | 2b7890e757bc42f963c835521c2657bd16d7b7d6 (patch) | |
tree | 329a381b4a657a7964f5b58b0d909ad50537c304 | |
parent | 777fbc31447f111a1492c90fae2bc616f836d407 (diff) |
net: moxa: continue loop on skb allocation failure
If netdev_alloc_skb_ip_align() fails, subsequent code will
try to dereference an invalid pointer.
Continue to next descriptor on error.
While we're at it,
1. eliminate the chance of an endless loop, replace the main
loop with while(rx < budget)
2. use napi_complete() and remove the explicit napi_gro_flush()
Signed-off-by: Jonas Jensen <jonas.jensen@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/moxa/moxart_ether.c | 12 |
1 files changed, 5 insertions, 7 deletions
diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c index 983d01949795..2f12c88c66ab 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c | |||
@@ -206,7 +206,7 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget) | |||
206 | int rx_head = priv->rx_head; | 206 | int rx_head = priv->rx_head; |
207 | int rx = 0; | 207 | int rx = 0; |
208 | 208 | ||
209 | while (1) { | 209 | while (rx < budget) { |
210 | desc = priv->rx_desc_base + (RX_REG_DESC_SIZE * rx_head); | 210 | desc = priv->rx_desc_base + (RX_REG_DESC_SIZE * rx_head); |
211 | desc0 = readl(desc + RX_REG_OFFSET_DESC0); | 211 | desc0 = readl(desc + RX_REG_OFFSET_DESC0); |
212 | 212 | ||
@@ -218,7 +218,7 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget) | |||
218 | net_dbg_ratelimited("packet error\n"); | 218 | net_dbg_ratelimited("packet error\n"); |
219 | priv->stats.rx_dropped++; | 219 | priv->stats.rx_dropped++; |
220 | priv->stats.rx_errors++; | 220 | priv->stats.rx_errors++; |
221 | continue; | 221 | goto rx_next; |
222 | } | 222 | } |
223 | 223 | ||
224 | len = desc0 & RX_DESC0_FRAME_LEN_MASK; | 224 | len = desc0 & RX_DESC0_FRAME_LEN_MASK; |
@@ -235,6 +235,7 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget) | |||
235 | net_dbg_ratelimited("netdev_alloc_skb_ip_align failed\n"); | 235 | net_dbg_ratelimited("netdev_alloc_skb_ip_align failed\n"); |
236 | priv->stats.rx_dropped++; | 236 | priv->stats.rx_dropped++; |
237 | priv->stats.rx_errors++; | 237 | priv->stats.rx_errors++; |
238 | goto rx_next; | ||
238 | } | 239 | } |
239 | 240 | ||
240 | memcpy(skb->data, priv->rx_buf[rx_head], len); | 241 | memcpy(skb->data, priv->rx_buf[rx_head], len); |
@@ -249,18 +250,15 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget) | |||
249 | if (desc0 & RX_DESC0_MULTICAST) | 250 | if (desc0 & RX_DESC0_MULTICAST) |
250 | priv->stats.multicast++; | 251 | priv->stats.multicast++; |
251 | 252 | ||
253 | rx_next: | ||
252 | writel(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0); | 254 | writel(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0); |
253 | 255 | ||
254 | rx_head = RX_NEXT(rx_head); | 256 | rx_head = RX_NEXT(rx_head); |
255 | priv->rx_head = rx_head; | 257 | priv->rx_head = rx_head; |
256 | |||
257 | if (rx >= budget) | ||
258 | break; | ||
259 | } | 258 | } |
260 | 259 | ||
261 | if (rx < budget) { | 260 | if (rx < budget) { |
262 | napi_gro_flush(napi, false); | 261 | napi_complete(napi); |
263 | __napi_complete(napi); | ||
264 | } | 262 | } |
265 | 263 | ||
266 | priv->reg_imr |= RPKT_FINISH_M; | 264 | priv->reg_imr |= RPKT_FINISH_M; |