diff options
Diffstat (limited to 'drivers/net/ethernet/sfc/rx.c')
-rw-r--r-- | drivers/net/ethernet/sfc/rx.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index c0ad95d2f63d..809ea4610a77 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c | |||
@@ -224,12 +224,17 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx, | |||
224 | } | 224 | } |
225 | } | 225 | } |
226 | 226 | ||
227 | static void efx_free_rx_buffer(struct efx_rx_buffer *rx_buf) | 227 | static void efx_free_rx_buffers(struct efx_rx_queue *rx_queue, |
228 | struct efx_rx_buffer *rx_buf, | ||
229 | unsigned int num_bufs) | ||
228 | { | 230 | { |
229 | if (rx_buf->page) { | 231 | do { |
230 | put_page(rx_buf->page); | 232 | if (rx_buf->page) { |
231 | rx_buf->page = NULL; | 233 | put_page(rx_buf->page); |
232 | } | 234 | rx_buf->page = NULL; |
235 | } | ||
236 | rx_buf = efx_rx_buf_next(rx_queue, rx_buf); | ||
237 | } while (--num_bufs); | ||
233 | } | 238 | } |
234 | 239 | ||
235 | /* Attempt to recycle the page if there is an RX recycle ring; the page can | 240 | /* Attempt to recycle the page if there is an RX recycle ring; the page can |
@@ -278,7 +283,7 @@ static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, | |||
278 | /* If this is the last buffer in a page, unmap and free it. */ | 283 | /* If this is the last buffer in a page, unmap and free it. */ |
279 | if (rx_buf->flags & EFX_RX_BUF_LAST_IN_PAGE) { | 284 | if (rx_buf->flags & EFX_RX_BUF_LAST_IN_PAGE) { |
280 | efx_unmap_rx_buffer(rx_queue->efx, rx_buf); | 285 | efx_unmap_rx_buffer(rx_queue->efx, rx_buf); |
281 | efx_free_rx_buffer(rx_buf); | 286 | efx_free_rx_buffers(rx_queue, rx_buf, 1); |
282 | } | 287 | } |
283 | rx_buf->page = NULL; | 288 | rx_buf->page = NULL; |
284 | } | 289 | } |
@@ -304,10 +309,7 @@ static void efx_discard_rx_packet(struct efx_channel *channel, | |||
304 | 309 | ||
305 | efx_recycle_rx_pages(channel, rx_buf, n_frags); | 310 | efx_recycle_rx_pages(channel, rx_buf, n_frags); |
306 | 311 | ||
307 | do { | 312 | efx_free_rx_buffers(rx_queue, rx_buf, n_frags); |
308 | efx_free_rx_buffer(rx_buf); | ||
309 | rx_buf = efx_rx_buf_next(rx_queue, rx_buf); | ||
310 | } while (--n_frags); | ||
311 | } | 313 | } |
312 | 314 | ||
313 | /** | 315 | /** |
@@ -431,11 +433,10 @@ efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf, | |||
431 | 433 | ||
432 | skb = napi_get_frags(napi); | 434 | skb = napi_get_frags(napi); |
433 | if (unlikely(!skb)) { | 435 | if (unlikely(!skb)) { |
434 | while (n_frags--) { | 436 | struct efx_rx_queue *rx_queue; |
435 | put_page(rx_buf->page); | 437 | |
436 | rx_buf->page = NULL; | 438 | rx_queue = efx_channel_get_rx_queue(channel); |
437 | rx_buf = efx_rx_buf_next(&channel->rx_queue, rx_buf); | 439 | efx_free_rx_buffers(rx_queue, rx_buf, n_frags); |
438 | } | ||
439 | return; | 440 | return; |
440 | } | 441 | } |
441 | 442 | ||
@@ -622,7 +623,10 @@ static void efx_rx_deliver(struct efx_channel *channel, u8 *eh, | |||
622 | 623 | ||
623 | skb = efx_rx_mk_skb(channel, rx_buf, n_frags, eh, hdr_len); | 624 | skb = efx_rx_mk_skb(channel, rx_buf, n_frags, eh, hdr_len); |
624 | if (unlikely(skb == NULL)) { | 625 | if (unlikely(skb == NULL)) { |
625 | efx_free_rx_buffer(rx_buf); | 626 | struct efx_rx_queue *rx_queue; |
627 | |||
628 | rx_queue = efx_channel_get_rx_queue(channel); | ||
629 | efx_free_rx_buffers(rx_queue, rx_buf, n_frags); | ||
626 | return; | 630 | return; |
627 | } | 631 | } |
628 | skb_record_rx_queue(skb, channel->rx_queue.core_index); | 632 | skb_record_rx_queue(skb, channel->rx_queue.core_index); |
@@ -661,8 +665,12 @@ void __efx_rx_packet(struct efx_channel *channel) | |||
661 | * loopback layer, and free the rx_buf here | 665 | * loopback layer, and free the rx_buf here |
662 | */ | 666 | */ |
663 | if (unlikely(efx->loopback_selftest)) { | 667 | if (unlikely(efx->loopback_selftest)) { |
668 | struct efx_rx_queue *rx_queue; | ||
669 | |||
664 | efx_loopback_rx_packet(efx, eh, rx_buf->len); | 670 | efx_loopback_rx_packet(efx, eh, rx_buf->len); |
665 | efx_free_rx_buffer(rx_buf); | 671 | rx_queue = efx_channel_get_rx_queue(channel); |
672 | efx_free_rx_buffers(rx_queue, rx_buf, | ||
673 | channel->rx_pkt_n_frags); | ||
666 | goto out; | 674 | goto out; |
667 | } | 675 | } |
668 | 676 | ||