Skip to content

Commit

Permalink
sfc: Fix memory leak when discarding scattered packets
Browse files Browse the repository at this point in the history
Commit 2768935 ('sfc: reuse pages to avoid DMA mapping/unmapping
costs') did not fully take account of DMA scattering which was
introduced immediately before.  If a received packet is invalid and
must be discarded, we only drop a reference to the first buffer's
page, but we need to drop a reference for each buffer the packet
used.

I think this bug was missed partly because efx_recycle_rx_buffers()
was not renamed and so no longer does what its name says.  It does not
change the state of buffers, but only prepares the underlying pages
for recycling.  Rename it accordingly.

Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Ben Hutchings authored and davem330 committed Jul 5, 2013
1 parent 86bd68b commit 734d4e1
Showing 1 changed file with 20 additions and 7 deletions.
27 changes: 20 additions & 7 deletions drivers/net/ethernet/sfc/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,9 @@ static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
}

/* Recycle the pages that are used by buffers that have just been received. */
static void efx_recycle_rx_buffers(struct efx_channel *channel,
struct efx_rx_buffer *rx_buf,
unsigned int n_frags)
static void efx_recycle_rx_pages(struct efx_channel *channel,
struct efx_rx_buffer *rx_buf,
unsigned int n_frags)
{
struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);

Expand All @@ -294,6 +294,20 @@ static void efx_recycle_rx_buffers(struct efx_channel *channel,
} while (--n_frags);
}

static void efx_discard_rx_packet(struct efx_channel *channel,
struct efx_rx_buffer *rx_buf,
unsigned int n_frags)
{
struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);

efx_recycle_rx_pages(channel, rx_buf, n_frags);

do {
efx_free_rx_buffer(rx_buf);
rx_buf = efx_rx_buf_next(rx_queue, rx_buf);
} while (--n_frags);
}

/**
* efx_fast_push_rx_descriptors - push new RX descriptors quickly
* @rx_queue: RX descriptor queue
Expand Down Expand Up @@ -533,8 +547,7 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
*/
if (unlikely(rx_buf->flags & EFX_RX_PKT_DISCARD)) {
efx_rx_flush_packet(channel);
put_page(rx_buf->page);
efx_recycle_rx_buffers(channel, rx_buf, n_frags);
efx_discard_rx_packet(channel, rx_buf, n_frags);
return;
}

Expand Down Expand Up @@ -570,9 +583,9 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
efx_sync_rx_buffer(efx, rx_buf, rx_buf->len);
}

/* All fragments have been DMA-synced, so recycle buffers and pages. */
/* All fragments have been DMA-synced, so recycle pages. */
rx_buf = efx_rx_buffer(rx_queue, index);
efx_recycle_rx_buffers(channel, rx_buf, n_frags);
efx_recycle_rx_pages(channel, rx_buf, n_frags);

/* Pipeline receives so that we give time for packet headers to be
* prefetched into cache.
Expand Down

0 comments on commit 734d4e1

Please sign in to comment.