diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/sfc/rx.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/sfc/rx.c')
-rw-r--r-- | drivers/net/sfc/rx.c | 83 |
1 files changed, 43 insertions, 40 deletions
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index 98bff5ada09a..e308818b9f55 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /**************************************************************************** | 1 | /**************************************************************************** |
2 | * Driver for Solarflare Solarstorm network controllers and boards | 2 | * Driver for Solarflare Solarstorm network controllers and boards |
3 | * Copyright 2005-2006 Fen Systems Ltd. | 3 | * Copyright 2005-2006 Fen Systems Ltd. |
4 | * Copyright 2005-2008 Solarflare Communications Inc. | 4 | * Copyright 2005-2009 Solarflare Communications Inc. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License version 2 as published | 7 | * under the terms of the GNU General Public License version 2 as published |
@@ -10,15 +10,15 @@ | |||
10 | 10 | ||
11 | #include <linux/socket.h> | 11 | #include <linux/socket.h> |
12 | #include <linux/in.h> | 12 | #include <linux/in.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/ip.h> | 14 | #include <linux/ip.h> |
14 | #include <linux/tcp.h> | 15 | #include <linux/tcp.h> |
15 | #include <linux/udp.h> | 16 | #include <linux/udp.h> |
16 | #include <net/ip.h> | 17 | #include <net/ip.h> |
17 | #include <net/checksum.h> | 18 | #include <net/checksum.h> |
18 | #include "net_driver.h" | 19 | #include "net_driver.h" |
19 | #include "rx.h" | ||
20 | #include "efx.h" | 20 | #include "efx.h" |
21 | #include "falcon.h" | 21 | #include "nic.h" |
22 | #include "selftest.h" | 22 | #include "selftest.h" |
23 | #include "workarounds.h" | 23 | #include "workarounds.h" |
24 | 24 | ||
@@ -61,7 +61,7 @@ | |||
61 | * rx_alloc_method = (rx_alloc_level > RX_ALLOC_LEVEL_LRO ? | 61 | * rx_alloc_method = (rx_alloc_level > RX_ALLOC_LEVEL_LRO ? |
62 | * RX_ALLOC_METHOD_PAGE : RX_ALLOC_METHOD_SKB) | 62 | * RX_ALLOC_METHOD_PAGE : RX_ALLOC_METHOD_SKB) |
63 | */ | 63 | */ |
64 | static int rx_alloc_method = RX_ALLOC_METHOD_PAGE; | 64 | static int rx_alloc_method = RX_ALLOC_METHOD_AUTO; |
65 | 65 | ||
66 | #define RX_ALLOC_LEVEL_LRO 0x2000 | 66 | #define RX_ALLOC_LEVEL_LRO 0x2000 |
67 | #define RX_ALLOC_LEVEL_MAX 0x3000 | 67 | #define RX_ALLOC_LEVEL_MAX 0x3000 |
@@ -293,8 +293,7 @@ static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, | |||
293 | * fill anyway. | 293 | * fill anyway. |
294 | */ | 294 | */ |
295 | fill_level = (rx_queue->added_count - rx_queue->removed_count); | 295 | fill_level = (rx_queue->added_count - rx_queue->removed_count); |
296 | EFX_BUG_ON_PARANOID(fill_level > | 296 | EFX_BUG_ON_PARANOID(fill_level > EFX_RXQ_SIZE); |
297 | rx_queue->efx->type->rxd_ring_mask + 1); | ||
298 | 297 | ||
299 | /* Don't fill if we don't need to */ | 298 | /* Don't fill if we don't need to */ |
300 | if (fill_level >= rx_queue->fast_fill_trigger) | 299 | if (fill_level >= rx_queue->fast_fill_trigger) |
@@ -316,8 +315,7 @@ static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, | |||
316 | retry: | 315 | retry: |
317 | /* Recalculate current fill level now that we have the lock */ | 316 | /* Recalculate current fill level now that we have the lock */ |
318 | fill_level = (rx_queue->added_count - rx_queue->removed_count); | 317 | fill_level = (rx_queue->added_count - rx_queue->removed_count); |
319 | EFX_BUG_ON_PARANOID(fill_level > | 318 | EFX_BUG_ON_PARANOID(fill_level > EFX_RXQ_SIZE); |
320 | rx_queue->efx->type->rxd_ring_mask + 1); | ||
321 | space = rx_queue->fast_fill_limit - fill_level; | 319 | space = rx_queue->fast_fill_limit - fill_level; |
322 | if (space < EFX_RX_BATCH) | 320 | if (space < EFX_RX_BATCH) |
323 | goto out_unlock; | 321 | goto out_unlock; |
@@ -329,8 +327,7 @@ static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, | |||
329 | 327 | ||
330 | do { | 328 | do { |
331 | for (i = 0; i < EFX_RX_BATCH; ++i) { | 329 | for (i = 0; i < EFX_RX_BATCH; ++i) { |
332 | index = (rx_queue->added_count & | 330 | index = rx_queue->added_count & EFX_RXQ_MASK; |
333 | rx_queue->efx->type->rxd_ring_mask); | ||
334 | rx_buf = efx_rx_buffer(rx_queue, index); | 331 | rx_buf = efx_rx_buffer(rx_queue, index); |
335 | rc = efx_init_rx_buffer(rx_queue, rx_buf); | 332 | rc = efx_init_rx_buffer(rx_queue, rx_buf); |
336 | if (unlikely(rc)) | 333 | if (unlikely(rc)) |
@@ -345,7 +342,7 @@ static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, | |||
345 | 342 | ||
346 | out: | 343 | out: |
347 | /* Send write pointer to card. */ | 344 | /* Send write pointer to card. */ |
348 | falcon_notify_rx_desc(rx_queue); | 345 | efx_nic_notify_rx_desc(rx_queue); |
349 | 346 | ||
350 | /* If the fast fill is running inside from the refill tasklet, then | 347 | /* If the fast fill is running inside from the refill tasklet, then |
351 | * for SMP systems it may be running on a different CPU to | 348 | * for SMP systems it may be running on a different CPU to |
@@ -448,17 +445,23 @@ static void efx_rx_packet_lro(struct efx_channel *channel, | |||
448 | bool checksummed) | 445 | bool checksummed) |
449 | { | 446 | { |
450 | struct napi_struct *napi = &channel->napi_str; | 447 | struct napi_struct *napi = &channel->napi_str; |
448 | gro_result_t gro_result; | ||
451 | 449 | ||
452 | /* Pass the skb/page into the LRO engine */ | 450 | /* Pass the skb/page into the LRO engine */ |
453 | if (rx_buf->page) { | 451 | if (rx_buf->page) { |
454 | struct sk_buff *skb = napi_get_frags(napi); | 452 | struct page *page = rx_buf->page; |
453 | struct sk_buff *skb; | ||
455 | 454 | ||
455 | EFX_BUG_ON_PARANOID(rx_buf->skb); | ||
456 | rx_buf->page = NULL; | ||
457 | |||
458 | skb = napi_get_frags(napi); | ||
456 | if (!skb) { | 459 | if (!skb) { |
457 | put_page(rx_buf->page); | 460 | put_page(page); |
458 | goto out; | 461 | return; |
459 | } | 462 | } |
460 | 463 | ||
461 | skb_shinfo(skb)->frags[0].page = rx_buf->page; | 464 | skb_shinfo(skb)->frags[0].page = page; |
462 | skb_shinfo(skb)->frags[0].page_offset = | 465 | skb_shinfo(skb)->frags[0].page_offset = |
463 | efx_rx_buf_offset(rx_buf); | 466 | efx_rx_buf_offset(rx_buf); |
464 | skb_shinfo(skb)->frags[0].size = rx_buf->len; | 467 | skb_shinfo(skb)->frags[0].size = rx_buf->len; |
@@ -470,17 +473,24 @@ static void efx_rx_packet_lro(struct efx_channel *channel, | |||
470 | skb->ip_summed = | 473 | skb->ip_summed = |
471 | checksummed ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE; | 474 | checksummed ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE; |
472 | 475 | ||
473 | napi_gro_frags(napi); | 476 | skb_record_rx_queue(skb, channel->channel); |
474 | 477 | ||
475 | out: | 478 | gro_result = napi_gro_frags(napi); |
476 | EFX_BUG_ON_PARANOID(rx_buf->skb); | ||
477 | rx_buf->page = NULL; | ||
478 | } else { | 479 | } else { |
479 | EFX_BUG_ON_PARANOID(!rx_buf->skb); | 480 | struct sk_buff *skb = rx_buf->skb; |
480 | EFX_BUG_ON_PARANOID(!checksummed); | ||
481 | 481 | ||
482 | napi_gro_receive(napi, rx_buf->skb); | 482 | EFX_BUG_ON_PARANOID(!skb); |
483 | EFX_BUG_ON_PARANOID(!checksummed); | ||
483 | rx_buf->skb = NULL; | 484 | rx_buf->skb = NULL; |
485 | |||
486 | gro_result = napi_gro_receive(napi, skb); | ||
487 | } | ||
488 | |||
489 | if (gro_result == GRO_NORMAL) { | ||
490 | channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; | ||
491 | } else if (gro_result != GRO_DROP) { | ||
492 | channel->rx_alloc_level += RX_ALLOC_FACTOR_LRO; | ||
493 | channel->irq_mod_score += 2; | ||
484 | } | 494 | } |
485 | } | 495 | } |
486 | 496 | ||
@@ -558,7 +568,7 @@ void __efx_rx_packet(struct efx_channel *channel, | |||
558 | if (unlikely(efx->loopback_selftest)) { | 568 | if (unlikely(efx->loopback_selftest)) { |
559 | efx_loopback_rx_packet(efx, rx_buf->data, rx_buf->len); | 569 | efx_loopback_rx_packet(efx, rx_buf->data, rx_buf->len); |
560 | efx_free_rx_buffer(efx, rx_buf); | 570 | efx_free_rx_buffer(efx, rx_buf); |
561 | goto done; | 571 | return; |
562 | } | 572 | } |
563 | 573 | ||
564 | if (rx_buf->skb) { | 574 | if (rx_buf->skb) { |
@@ -570,34 +580,28 @@ void __efx_rx_packet(struct efx_channel *channel, | |||
570 | * at the ethernet header */ | 580 | * at the ethernet header */ |
571 | rx_buf->skb->protocol = eth_type_trans(rx_buf->skb, | 581 | rx_buf->skb->protocol = eth_type_trans(rx_buf->skb, |
572 | efx->net_dev); | 582 | efx->net_dev); |
583 | |||
584 | skb_record_rx_queue(rx_buf->skb, channel->channel); | ||
573 | } | 585 | } |
574 | 586 | ||
575 | if (likely(checksummed || rx_buf->page)) { | 587 | if (likely(checksummed || rx_buf->page)) { |
576 | efx_rx_packet_lro(channel, rx_buf, checksummed); | 588 | efx_rx_packet_lro(channel, rx_buf, checksummed); |
577 | goto done; | 589 | return; |
578 | } | 590 | } |
579 | 591 | ||
580 | /* We now own the SKB */ | 592 | /* We now own the SKB */ |
581 | skb = rx_buf->skb; | 593 | skb = rx_buf->skb; |
582 | rx_buf->skb = NULL; | 594 | rx_buf->skb = NULL; |
583 | |||
584 | EFX_BUG_ON_PARANOID(rx_buf->page); | ||
585 | EFX_BUG_ON_PARANOID(rx_buf->skb); | ||
586 | EFX_BUG_ON_PARANOID(!skb); | 595 | EFX_BUG_ON_PARANOID(!skb); |
587 | 596 | ||
588 | /* Set the SKB flags */ | 597 | /* Set the SKB flags */ |
589 | skb->ip_summed = CHECKSUM_NONE; | 598 | skb->ip_summed = CHECKSUM_NONE; |
590 | 599 | ||
591 | skb_record_rx_queue(skb, channel->channel); | ||
592 | |||
593 | /* Pass the packet up */ | 600 | /* Pass the packet up */ |
594 | netif_receive_skb(skb); | 601 | netif_receive_skb(skb); |
595 | 602 | ||
596 | /* Update allocation strategy method */ | 603 | /* Update allocation strategy method */ |
597 | channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; | 604 | channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; |
598 | |||
599 | done: | ||
600 | ; | ||
601 | } | 605 | } |
602 | 606 | ||
603 | void efx_rx_strategy(struct efx_channel *channel) | 607 | void efx_rx_strategy(struct efx_channel *channel) |
@@ -632,12 +636,12 @@ int efx_probe_rx_queue(struct efx_rx_queue *rx_queue) | |||
632 | EFX_LOG(efx, "creating RX queue %d\n", rx_queue->queue); | 636 | EFX_LOG(efx, "creating RX queue %d\n", rx_queue->queue); |
633 | 637 | ||
634 | /* Allocate RX buffers */ | 638 | /* Allocate RX buffers */ |
635 | rxq_size = (efx->type->rxd_ring_mask + 1) * sizeof(*rx_queue->buffer); | 639 | rxq_size = EFX_RXQ_SIZE * sizeof(*rx_queue->buffer); |
636 | rx_queue->buffer = kzalloc(rxq_size, GFP_KERNEL); | 640 | rx_queue->buffer = kzalloc(rxq_size, GFP_KERNEL); |
637 | if (!rx_queue->buffer) | 641 | if (!rx_queue->buffer) |
638 | return -ENOMEM; | 642 | return -ENOMEM; |
639 | 643 | ||
640 | rc = falcon_probe_rx(rx_queue); | 644 | rc = efx_nic_probe_rx(rx_queue); |
641 | if (rc) { | 645 | if (rc) { |
642 | kfree(rx_queue->buffer); | 646 | kfree(rx_queue->buffer); |
643 | rx_queue->buffer = NULL; | 647 | rx_queue->buffer = NULL; |
@@ -647,7 +651,6 @@ int efx_probe_rx_queue(struct efx_rx_queue *rx_queue) | |||
647 | 651 | ||
648 | void efx_init_rx_queue(struct efx_rx_queue *rx_queue) | 652 | void efx_init_rx_queue(struct efx_rx_queue *rx_queue) |
649 | { | 653 | { |
650 | struct efx_nic *efx = rx_queue->efx; | ||
651 | unsigned int max_fill, trigger, limit; | 654 | unsigned int max_fill, trigger, limit; |
652 | 655 | ||
653 | EFX_LOG(rx_queue->efx, "initialising RX queue %d\n", rx_queue->queue); | 656 | EFX_LOG(rx_queue->efx, "initialising RX queue %d\n", rx_queue->queue); |
@@ -660,7 +663,7 @@ void efx_init_rx_queue(struct efx_rx_queue *rx_queue) | |||
660 | rx_queue->min_overfill = -1U; | 663 | rx_queue->min_overfill = -1U; |
661 | 664 | ||
662 | /* Initialise limit fields */ | 665 | /* Initialise limit fields */ |
663 | max_fill = efx->type->rxd_ring_mask + 1 - EFX_RXD_HEAD_ROOM; | 666 | max_fill = EFX_RXQ_SIZE - EFX_RXD_HEAD_ROOM; |
664 | trigger = max_fill * min(rx_refill_threshold, 100U) / 100U; | 667 | trigger = max_fill * min(rx_refill_threshold, 100U) / 100U; |
665 | limit = max_fill * min(rx_refill_limit, 100U) / 100U; | 668 | limit = max_fill * min(rx_refill_limit, 100U) / 100U; |
666 | 669 | ||
@@ -669,7 +672,7 @@ void efx_init_rx_queue(struct efx_rx_queue *rx_queue) | |||
669 | rx_queue->fast_fill_limit = limit; | 672 | rx_queue->fast_fill_limit = limit; |
670 | 673 | ||
671 | /* Set up RX descriptor ring */ | 674 | /* Set up RX descriptor ring */ |
672 | falcon_init_rx(rx_queue); | 675 | efx_nic_init_rx(rx_queue); |
673 | } | 676 | } |
674 | 677 | ||
675 | void efx_fini_rx_queue(struct efx_rx_queue *rx_queue) | 678 | void efx_fini_rx_queue(struct efx_rx_queue *rx_queue) |
@@ -679,11 +682,11 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue) | |||
679 | 682 | ||
680 | EFX_LOG(rx_queue->efx, "shutting down RX queue %d\n", rx_queue->queue); | 683 | EFX_LOG(rx_queue->efx, "shutting down RX queue %d\n", rx_queue->queue); |
681 | 684 | ||
682 | falcon_fini_rx(rx_queue); | 685 | efx_nic_fini_rx(rx_queue); |
683 | 686 | ||
684 | /* Release RX buffers NB start at index 0 not current HW ptr */ | 687 | /* Release RX buffers NB start at index 0 not current HW ptr */ |
685 | if (rx_queue->buffer) { | 688 | if (rx_queue->buffer) { |
686 | for (i = 0; i <= rx_queue->efx->type->rxd_ring_mask; i++) { | 689 | for (i = 0; i <= EFX_RXQ_MASK; i++) { |
687 | rx_buf = efx_rx_buffer(rx_queue, i); | 690 | rx_buf = efx_rx_buffer(rx_queue, i); |
688 | efx_fini_rx_buffer(rx_queue, rx_buf); | 691 | efx_fini_rx_buffer(rx_queue, rx_buf); |
689 | } | 692 | } |
@@ -704,7 +707,7 @@ void efx_remove_rx_queue(struct efx_rx_queue *rx_queue) | |||
704 | { | 707 | { |
705 | EFX_LOG(rx_queue->efx, "destroying RX queue %d\n", rx_queue->queue); | 708 | EFX_LOG(rx_queue->efx, "destroying RX queue %d\n", rx_queue->queue); |
706 | 709 | ||
707 | falcon_remove_rx(rx_queue); | 710 | efx_nic_remove_rx(rx_queue); |
708 | 711 | ||
709 | kfree(rx_queue->buffer); | 712 | kfree(rx_queue->buffer); |
710 | rx_queue->buffer = NULL; | 713 | rx_queue->buffer = NULL; |