aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSteve Hodgson <shodgson@solarflare.com>2010-06-01 07:20:53 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-02 05:21:10 -0400
commit62b330baede3849897ce7fc5534eadc34cd03a51 (patch)
tree8b1108981cac25a732fed7e488d5a6004e49015e /drivers
parent244558006cf02f0096fb247f3a54dc7e7d81a256 (diff)
sfc: Allow shared pages to be recycled
Insert a structure at the start of the shared page that tracks the dma mapping refcnt. DMA into the next cache line of the (shared) page (plus EFX_PAGE_IP_ALIGN). When recycling a page, check the page refcnt. If the page is otherwise unused, then resurrect the other receive buffer that previously referenced the page. Be careful not to overflow the receive ring, since we can now resurrect n receive buffers in a row. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sfc/efx.c3
-rw-r--r--drivers/net/sfc/net_driver.h18
-rw-r--r--drivers/net/sfc/rx.c84
3 files changed, 62 insertions, 43 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 5d9ef05e6abb..aae33471029a 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 59c8ecc39aee..40c0d931b182 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 */
245struct 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 dfebd73cf863..9fb698e3519d 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
90static inline unsigned int efx_rx_buf_offset(struct efx_rx_buffer *buf) 92static 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,
256static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue, 264static 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);