diff options
-rw-r--r-- | drivers/net/sfc/efx.c | 3 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 18 | ||||
-rw-r--r-- | drivers/net/sfc/rx.c | 84 |
3 files changed, 62 insertions, 43 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 5d9ef05e6ab..aae33471029 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -469,7 +469,8 @@ static void efx_init_channels(struct efx_nic *efx) | |||
469 | efx->rx_buffer_len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) + | 469 | efx->rx_buffer_len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) + |
470 | EFX_MAX_FRAME_LEN(efx->net_dev->mtu) + | 470 | EFX_MAX_FRAME_LEN(efx->net_dev->mtu) + |
471 | efx->type->rx_buffer_padding); | 471 | efx->type->rx_buffer_padding); |
472 | efx->rx_buffer_order = get_order(efx->rx_buffer_len); | 472 | efx->rx_buffer_order = get_order(efx->rx_buffer_len + |
473 | sizeof(struct efx_rx_page_state)); | ||
473 | 474 | ||
474 | /* Initialise the channels */ | 475 | /* Initialise the channels */ |
475 | efx_for_each_channel(channel, efx) { | 476 | efx_for_each_channel(channel, efx) { |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 59c8ecc39ae..40c0d931b18 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -232,6 +232,24 @@ struct efx_rx_buffer { | |||
232 | }; | 232 | }; |
233 | 233 | ||
234 | /** | 234 | /** |
235 | * struct efx_rx_page_state - Page-based rx buffer state | ||
236 | * | ||
237 | * Inserted at the start of every page allocated for receive buffers. | ||
238 | * Used to facilitate sharing dma mappings between recycled rx buffers | ||
239 | * and those passed up to the kernel. | ||
240 | * | ||
241 | * @refcnt: Number of struct efx_rx_buffer's referencing this page. | ||
242 | * When refcnt falls to zero, the page is unmapped for dma | ||
243 | * @dma_addr: The dma address of this page. | ||
244 | */ | ||
245 | struct efx_rx_page_state { | ||
246 | unsigned refcnt; | ||
247 | dma_addr_t dma_addr; | ||
248 | |||
249 | unsigned int __pad[0] ____cacheline_aligned; | ||
250 | }; | ||
251 | |||
252 | /** | ||
235 | * struct efx_rx_queue - An Efx RX queue | 253 | * struct efx_rx_queue - An Efx RX queue |
236 | * @efx: The associated Efx NIC | 254 | * @efx: The associated Efx NIC |
237 | * @queue: DMA queue number | 255 | * @queue: DMA queue number |
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index dfebd73cf86..9fb698e3519 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c | |||
@@ -25,6 +25,9 @@ | |||
25 | /* Number of RX descriptors pushed at once. */ | 25 | /* Number of RX descriptors pushed at once. */ |
26 | #define EFX_RX_BATCH 8 | 26 | #define EFX_RX_BATCH 8 |
27 | 27 | ||
28 | /* Maximum size of a buffer sharing a page */ | ||
29 | #define EFX_RX_HALF_PAGE ((PAGE_SIZE >> 1) - sizeof(struct efx_rx_page_state)) | ||
30 | |||
28 | /* Size of buffer allocated for skb header area. */ | 31 | /* Size of buffer allocated for skb header area. */ |
29 | #define EFX_SKB_HEADERS 64u | 32 | #define EFX_SKB_HEADERS 64u |
30 | 33 | ||
@@ -82,10 +85,9 @@ static unsigned int rx_refill_limit = 95; | |||
82 | * RX maximum head room required. | 85 | * RX maximum head room required. |
83 | * | 86 | * |
84 | * This must be at least 1 to prevent overflow and at least 2 to allow | 87 | * This must be at least 1 to prevent overflow and at least 2 to allow |
85 | * pipelined receives. Then a further 1 because efx_recycle_rx_buffer() | 88 | * pipelined receives. |
86 | * might insert two buffers. | ||
87 | */ | 89 | */ |
88 | #define EFX_RXD_HEAD_ROOM 3 | 90 | #define EFX_RXD_HEAD_ROOM 2 |
89 | 91 | ||
90 | static inline unsigned int efx_rx_buf_offset(struct efx_rx_buffer *buf) | 92 | static inline unsigned int efx_rx_buf_offset(struct efx_rx_buffer *buf) |
91 | { | 93 | { |
@@ -164,7 +166,8 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) | |||
164 | struct efx_nic *efx = rx_queue->efx; | 166 | struct efx_nic *efx = rx_queue->efx; |
165 | struct efx_rx_buffer *rx_buf; | 167 | struct efx_rx_buffer *rx_buf; |
166 | struct page *page; | 168 | struct page *page; |
167 | char *page_addr; | 169 | void *page_addr; |
170 | struct efx_rx_page_state *state; | ||
168 | dma_addr_t dma_addr; | 171 | dma_addr_t dma_addr; |
169 | unsigned index, count; | 172 | unsigned index, count; |
170 | 173 | ||
@@ -183,22 +186,27 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) | |||
183 | __free_pages(page, efx->rx_buffer_order); | 186 | __free_pages(page, efx->rx_buffer_order); |
184 | return -EIO; | 187 | return -EIO; |
185 | } | 188 | } |
186 | EFX_BUG_ON_PARANOID(dma_addr & (PAGE_SIZE - 1)); | 189 | page_addr = page_address(page); |
187 | page_addr = page_address(page) + EFX_PAGE_IP_ALIGN; | 190 | state = page_addr; |
188 | dma_addr += EFX_PAGE_IP_ALIGN; | 191 | state->refcnt = 0; |
192 | state->dma_addr = dma_addr; | ||
193 | |||
194 | page_addr += sizeof(struct efx_rx_page_state); | ||
195 | dma_addr += sizeof(struct efx_rx_page_state); | ||
189 | 196 | ||
190 | split: | 197 | split: |
191 | index = rx_queue->added_count & EFX_RXQ_MASK; | 198 | index = rx_queue->added_count & EFX_RXQ_MASK; |
192 | rx_buf = efx_rx_buffer(rx_queue, index); | 199 | rx_buf = efx_rx_buffer(rx_queue, index); |
193 | rx_buf->dma_addr = dma_addr; | 200 | rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN; |
194 | rx_buf->skb = NULL; | 201 | rx_buf->skb = NULL; |
195 | rx_buf->page = page; | 202 | rx_buf->page = page; |
196 | rx_buf->data = page_addr; | 203 | rx_buf->data = page_addr + EFX_PAGE_IP_ALIGN; |
197 | rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; | 204 | rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; |
198 | ++rx_queue->added_count; | 205 | ++rx_queue->added_count; |
199 | ++rx_queue->alloc_page_count; | 206 | ++rx_queue->alloc_page_count; |
207 | ++state->refcnt; | ||
200 | 208 | ||
201 | if ((~count & 1) && (efx->rx_buffer_len < (PAGE_SIZE >> 1))) { | 209 | if ((~count & 1) && (efx->rx_buffer_len <= EFX_RX_HALF_PAGE)) { |
202 | /* Use the second half of the page */ | 210 | /* Use the second half of the page */ |
203 | get_page(page); | 211 | get_page(page); |
204 | dma_addr += (PAGE_SIZE >> 1); | 212 | dma_addr += (PAGE_SIZE >> 1); |
@@ -215,14 +223,14 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx, | |||
215 | struct efx_rx_buffer *rx_buf) | 223 | struct efx_rx_buffer *rx_buf) |
216 | { | 224 | { |
217 | if (rx_buf->page) { | 225 | if (rx_buf->page) { |
226 | struct efx_rx_page_state *state; | ||
227 | |||
218 | EFX_BUG_ON_PARANOID(rx_buf->skb); | 228 | EFX_BUG_ON_PARANOID(rx_buf->skb); |
219 | 229 | ||
220 | /* Unmap the buffer if there's only one buffer per page(s), | 230 | state = page_address(rx_buf->page); |
221 | * or this is the second half of a two buffer page. */ | 231 | if (--state->refcnt == 0) { |
222 | if (efx->rx_buffer_order != 0 || | ||
223 | (efx_rx_buf_offset(rx_buf) & (PAGE_SIZE >> 1)) != 0) { | ||
224 | pci_unmap_page(efx->pci_dev, | 232 | pci_unmap_page(efx->pci_dev, |
225 | rx_buf->dma_addr & ~(PAGE_SIZE - 1), | 233 | state->dma_addr, |
226 | efx_rx_buf_size(efx), | 234 | efx_rx_buf_size(efx), |
227 | PCI_DMA_FROMDEVICE); | 235 | PCI_DMA_FROMDEVICE); |
228 | } | 236 | } |
@@ -256,21 +264,30 @@ static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, | |||
256 | static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue, | 264 | static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue, |
257 | struct efx_rx_buffer *rx_buf) | 265 | struct efx_rx_buffer *rx_buf) |
258 | { | 266 | { |
267 | struct efx_rx_page_state *state = page_address(rx_buf->page); | ||
259 | struct efx_rx_buffer *new_buf; | 268 | struct efx_rx_buffer *new_buf; |
260 | unsigned index; | 269 | unsigned fill_level, index; |
270 | |||
271 | /* +1 because efx_rx_packet() incremented removed_count. +1 because | ||
272 | * we'd like to insert an additional descriptor whilst leaving | ||
273 | * EFX_RXD_HEAD_ROOM for the non-recycle path */ | ||
274 | fill_level = (rx_queue->added_count - rx_queue->removed_count + 2); | ||
275 | if (unlikely(fill_level >= EFX_RXQ_SIZE - EFX_RXD_HEAD_ROOM)) { | ||
276 | /* We could place "state" on a list, and drain the list in | ||
277 | * efx_fast_push_rx_descriptors(). For now, this will do. */ | ||
278 | return; | ||
279 | } | ||
261 | 280 | ||
262 | /* We could have recycled the 1st half, then refilled | 281 | ++state->refcnt; |
263 | * the queue, and now recycle the 2nd half. | ||
264 | * EFX_RXD_HEAD_ROOM ensures that there is always room | ||
265 | * to reinsert two buffers (once). */ | ||
266 | get_page(rx_buf->page); | 282 | get_page(rx_buf->page); |
267 | 283 | ||
268 | index = rx_queue->added_count & EFX_RXQ_MASK; | 284 | index = rx_queue->added_count & EFX_RXQ_MASK; |
269 | new_buf = efx_rx_buffer(rx_queue, index); | 285 | new_buf = efx_rx_buffer(rx_queue, index); |
270 | new_buf->dma_addr = rx_buf->dma_addr - (PAGE_SIZE >> 1); | 286 | new_buf->dma_addr = rx_buf->dma_addr ^ (PAGE_SIZE >> 1); |
271 | new_buf->skb = NULL; | 287 | new_buf->skb = NULL; |
272 | new_buf->page = rx_buf->page; | 288 | new_buf->page = rx_buf->page; |
273 | new_buf->data = rx_buf->data - (PAGE_SIZE >> 1); | 289 | new_buf->data = (void *) |
290 | ((__force unsigned long)rx_buf->data ^ (PAGE_SIZE >> 1)); | ||
274 | new_buf->len = rx_buf->len; | 291 | new_buf->len = rx_buf->len; |
275 | ++rx_queue->added_count; | 292 | ++rx_queue->added_count; |
276 | } | 293 | } |
@@ -285,26 +302,9 @@ static void efx_recycle_rx_buffer(struct efx_channel *channel, | |||
285 | struct efx_rx_buffer *new_buf; | 302 | struct efx_rx_buffer *new_buf; |
286 | unsigned index; | 303 | unsigned index; |
287 | 304 | ||
288 | if (rx_buf->page != NULL && efx->rx_buffer_len < (PAGE_SIZE >> 1)) { | 305 | if (rx_buf->page != NULL && efx->rx_buffer_len <= EFX_RX_HALF_PAGE && |
289 | if (efx_rx_buf_offset(rx_buf) & (PAGE_SIZE >> 1)) { | 306 | page_count(rx_buf->page) == 1) |
290 | /* This is the 2nd half of a page split between two | 307 | efx_resurrect_rx_buffer(rx_queue, rx_buf); |
291 | * buffers, If page_count() is > 1 then the kernel | ||
292 | * is holding onto the previous buffer */ | ||
293 | if (page_count(rx_buf->page) != 1) { | ||
294 | efx_fini_rx_buffer(rx_queue, rx_buf); | ||
295 | return; | ||
296 | } | ||
297 | |||
298 | efx_resurrect_rx_buffer(rx_queue, rx_buf); | ||
299 | } else { | ||
300 | /* Free the 1st buffer's reference on the page. If the | ||
301 | * 2nd buffer is also discarded, this buffer will be | ||
302 | * resurrected above */ | ||
303 | put_page(rx_buf->page); | ||
304 | rx_buf->page = NULL; | ||
305 | return; | ||
306 | } | ||
307 | } | ||
308 | 308 | ||
309 | index = rx_queue->added_count & EFX_RXQ_MASK; | 309 | index = rx_queue->added_count & EFX_RXQ_MASK; |
310 | new_buf = efx_rx_buffer(rx_queue, index); | 310 | new_buf = efx_rx_buffer(rx_queue, index); |