Commit b590ace0 authored by Ben Hutchings's avatar Ben Hutchings

sfc: Fix efx_rx_buf_offset() in the presence of swiotlb

We assume that the mapping between DMA and virtual addresses is done
on whole pages, so we can find the page offset of an RX buffer using
the lower bits of the DMA address.  However, swiotlb maps in units of
2K, breaking this assumption.

Add an explicit page_offset field to struct efx_rx_buffer.
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
parent 3a68f19d
...@@ -210,6 +210,7 @@ struct efx_tx_queue { ...@@ -210,6 +210,7 @@ struct efx_tx_queue {
* Will be %NULL if the buffer slot is currently free. * Will be %NULL if the buffer slot is currently free.
* @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE. * @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE.
* Will be %NULL if the buffer slot is currently free. * Will be %NULL if the buffer slot is currently free.
* @page_offset: Offset within page. Valid iff @flags & %EFX_RX_BUF_PAGE.
* @len: Buffer length, in bytes. * @len: Buffer length, in bytes.
* @flags: Flags for buffer and packet state. * @flags: Flags for buffer and packet state.
*/ */
...@@ -219,7 +220,8 @@ struct efx_rx_buffer { ...@@ -219,7 +220,8 @@ struct efx_rx_buffer {
struct sk_buff *skb; struct sk_buff *skb;
struct page *page; struct page *page;
} u; } u;
unsigned int len; u16 page_offset;
u16 len;
u16 flags; u16 flags;
}; };
#define EFX_RX_BUF_PAGE 0x0001 #define EFX_RX_BUF_PAGE 0x0001
......
...@@ -90,11 +90,7 @@ static unsigned int rx_refill_threshold; ...@@ -90,11 +90,7 @@ static unsigned int rx_refill_threshold;
static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx, static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx,
struct efx_rx_buffer *buf) struct efx_rx_buffer *buf)
{ {
/* Offset is always within one page, so we don't need to consider return buf->page_offset + efx->type->rx_buffer_hash_size;
* the page order.
*/
return ((unsigned int) buf->dma_addr & (PAGE_SIZE - 1)) +
efx->type->rx_buffer_hash_size;
} }
static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) static inline unsigned int efx_rx_buf_size(struct efx_nic *efx)
{ {
...@@ -187,6 +183,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) ...@@ -187,6 +183,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
struct efx_nic *efx = rx_queue->efx; struct efx_nic *efx = rx_queue->efx;
struct efx_rx_buffer *rx_buf; struct efx_rx_buffer *rx_buf;
struct page *page; struct page *page;
unsigned int page_offset;
struct efx_rx_page_state *state; struct efx_rx_page_state *state;
dma_addr_t dma_addr; dma_addr_t dma_addr;
unsigned index, count; unsigned index, count;
...@@ -211,12 +208,14 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) ...@@ -211,12 +208,14 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
state->dma_addr = dma_addr; state->dma_addr = dma_addr;
dma_addr += sizeof(struct efx_rx_page_state); dma_addr += sizeof(struct efx_rx_page_state);
page_offset = sizeof(struct efx_rx_page_state);
split: split:
index = rx_queue->added_count & rx_queue->ptr_mask; index = rx_queue->added_count & rx_queue->ptr_mask;
rx_buf = efx_rx_buffer(rx_queue, index); rx_buf = efx_rx_buffer(rx_queue, index);
rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN; rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
rx_buf->u.page = page; rx_buf->u.page = page;
rx_buf->page_offset = page_offset;
rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
rx_buf->flags = EFX_RX_BUF_PAGE; rx_buf->flags = EFX_RX_BUF_PAGE;
++rx_queue->added_count; ++rx_queue->added_count;
...@@ -227,6 +226,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) ...@@ -227,6 +226,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
/* Use the second half of the page */ /* Use the second half of the page */
get_page(page); get_page(page);
dma_addr += (PAGE_SIZE >> 1); dma_addr += (PAGE_SIZE >> 1);
page_offset += (PAGE_SIZE >> 1);
++count; ++count;
goto split; goto split;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment