aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/sfc/rx.c42
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
227static void efx_free_rx_buffer(struct efx_rx_buffer *rx_buf) 227static 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