diff options
author | Ron Mercer <ron.mercer@qlogic.com> | 2009-08-27 07:02:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-29 02:22:31 -0400 |
commit | a4ab613717184138763c5fb4a4b4bbc354d5b0ee (patch) | |
tree | 80a69e608482f4a169cfe6ab4d2138c40b98bce6 /drivers/net/qlge | |
parent | b2014ff8ac314f58d6542ec4ea7b576a2de21c8b (diff) |
qlge: Allow running MSIx with fewer vectors.
Currently we downshift to MSI/Legacy if we don't get enough vectors for
cpu_count RSS rings plus cpu_count TX completion rings. This patch
allows running MSIX with the vector count that the platform provides.
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlge')
-rw-r--r-- | drivers/net/qlge/qlge_main.c | 85 |
1 files changed, 38 insertions, 47 deletions
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 89ea9c7a58c8..0cbda4d47dc7 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c | |||
@@ -2815,17 +2815,20 @@ static void ql_disable_msix(struct ql_adapter *qdev) | |||
2815 | } | 2815 | } |
2816 | } | 2816 | } |
2817 | 2817 | ||
2818 | /* We start by trying to get the number of vectors | ||
2819 | * stored in qdev->intr_count. If we don't get that | ||
2820 | * many then we reduce the count and try again. | ||
2821 | */ | ||
2818 | static void ql_enable_msix(struct ql_adapter *qdev) | 2822 | static void ql_enable_msix(struct ql_adapter *qdev) |
2819 | { | 2823 | { |
2820 | int i; | 2824 | int i, err; |
2821 | 2825 | ||
2822 | qdev->intr_count = 1; | ||
2823 | /* Get the MSIX vectors. */ | 2826 | /* Get the MSIX vectors. */ |
2824 | if (irq_type == MSIX_IRQ) { | 2827 | if (irq_type == MSIX_IRQ) { |
2825 | /* Try to alloc space for the msix struct, | 2828 | /* Try to alloc space for the msix struct, |
2826 | * if it fails then go to MSI/legacy. | 2829 | * if it fails then go to MSI/legacy. |
2827 | */ | 2830 | */ |
2828 | qdev->msi_x_entry = kcalloc(qdev->rx_ring_count, | 2831 | qdev->msi_x_entry = kcalloc(qdev->intr_count, |
2829 | sizeof(struct msix_entry), | 2832 | sizeof(struct msix_entry), |
2830 | GFP_KERNEL); | 2833 | GFP_KERNEL); |
2831 | if (!qdev->msi_x_entry) { | 2834 | if (!qdev->msi_x_entry) { |
@@ -2833,26 +2836,36 @@ static void ql_enable_msix(struct ql_adapter *qdev) | |||
2833 | goto msi; | 2836 | goto msi; |
2834 | } | 2837 | } |
2835 | 2838 | ||
2836 | for (i = 0; i < qdev->rx_ring_count; i++) | 2839 | for (i = 0; i < qdev->intr_count; i++) |
2837 | qdev->msi_x_entry[i].entry = i; | 2840 | qdev->msi_x_entry[i].entry = i; |
2838 | 2841 | ||
2839 | if (!pci_enable_msix | 2842 | /* Loop to get our vectors. We start with |
2840 | (qdev->pdev, qdev->msi_x_entry, qdev->rx_ring_count)) { | 2843 | * what we want and settle for what we get. |
2841 | set_bit(QL_MSIX_ENABLED, &qdev->flags); | 2844 | */ |
2842 | qdev->intr_count = qdev->rx_ring_count; | 2845 | do { |
2843 | QPRINTK(qdev, IFUP, DEBUG, | 2846 | err = pci_enable_msix(qdev->pdev, |
2844 | "MSI-X Enabled, got %d vectors.\n", | 2847 | qdev->msi_x_entry, qdev->intr_count); |
2845 | qdev->intr_count); | 2848 | if (err > 0) |
2846 | return; | 2849 | qdev->intr_count = err; |
2847 | } else { | 2850 | } while (err > 0); |
2851 | |||
2852 | if (err < 0) { | ||
2848 | kfree(qdev->msi_x_entry); | 2853 | kfree(qdev->msi_x_entry); |
2849 | qdev->msi_x_entry = NULL; | 2854 | qdev->msi_x_entry = NULL; |
2850 | QPRINTK(qdev, IFUP, WARNING, | 2855 | QPRINTK(qdev, IFUP, WARNING, |
2851 | "MSI-X Enable failed, trying MSI.\n"); | 2856 | "MSI-X Enable failed, trying MSI.\n"); |
2857 | qdev->intr_count = 1; | ||
2852 | irq_type = MSI_IRQ; | 2858 | irq_type = MSI_IRQ; |
2859 | } else if (err == 0) { | ||
2860 | set_bit(QL_MSIX_ENABLED, &qdev->flags); | ||
2861 | QPRINTK(qdev, IFUP, INFO, | ||
2862 | "MSI-X Enabled, got %d vectors.\n", | ||
2863 | qdev->intr_count); | ||
2864 | return; | ||
2853 | } | 2865 | } |
2854 | } | 2866 | } |
2855 | msi: | 2867 | msi: |
2868 | qdev->intr_count = 1; | ||
2856 | if (irq_type == MSI_IRQ) { | 2869 | if (irq_type == MSI_IRQ) { |
2857 | if (!pci_enable_msi(qdev->pdev)) { | 2870 | if (!pci_enable_msi(qdev->pdev)) { |
2858 | set_bit(QL_MSI_ENABLED, &qdev->flags); | 2871 | set_bit(QL_MSI_ENABLED, &qdev->flags); |
@@ -2876,8 +2889,6 @@ static void ql_resolve_queues_to_irqs(struct ql_adapter *qdev) | |||
2876 | int i = 0; | 2889 | int i = 0; |
2877 | struct intr_context *intr_context = &qdev->intr_context[0]; | 2890 | struct intr_context *intr_context = &qdev->intr_context[0]; |
2878 | 2891 | ||
2879 | ql_enable_msix(qdev); | ||
2880 | |||
2881 | if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags))) { | 2892 | if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags))) { |
2882 | /* Each rx_ring has it's | 2893 | /* Each rx_ring has it's |
2883 | * own intr_context since we have separate | 2894 | * own intr_context since we have separate |
@@ -3438,40 +3449,20 @@ static int ql_configure_rings(struct ql_adapter *qdev) | |||
3438 | int i; | 3449 | int i; |
3439 | struct rx_ring *rx_ring; | 3450 | struct rx_ring *rx_ring; |
3440 | struct tx_ring *tx_ring; | 3451 | struct tx_ring *tx_ring; |
3441 | int cpu_cnt = num_online_cpus(); | 3452 | int cpu_cnt = min(MAX_CPUS, (int)num_online_cpus()); |
3442 | 3453 | ||
3443 | /* | 3454 | /* In a perfect world we have one RSS ring for each CPU |
3444 | * For each processor present we allocate one | 3455 | * and each has it's own vector. To do that we ask for |
3445 | * rx_ring for outbound completions, and one | 3456 | * cpu_cnt vectors. ql_enable_msix() will adjust the |
3446 | * rx_ring for inbound completions. Plus there is | 3457 | * vector count to what we actually get. We then |
3447 | * always the one default queue. For the CPU | 3458 | * allocate an RSS ring for each. |
3448 | * counts we end up with the following rx_rings: | 3459 | * Essentially, we are doing min(cpu_count, msix_vector_count). |
3449 | * rx_ring count = | ||
3450 | * one default queue + | ||
3451 | * (CPU count * outbound completion rx_ring) + | ||
3452 | * (CPU count * inbound (RSS) completion rx_ring) | ||
3453 | * To keep it simple we limit the total number of | ||
3454 | * queues to < 32, so we truncate CPU to 8. | ||
3455 | * This limitation can be removed when requested. | ||
3456 | */ | 3460 | */ |
3457 | 3461 | qdev->intr_count = cpu_cnt; | |
3458 | if (cpu_cnt > MAX_CPUS) | 3462 | ql_enable_msix(qdev); |
3459 | cpu_cnt = MAX_CPUS; | 3463 | /* Adjust the RSS ring count to the actual vector count. */ |
3460 | 3464 | qdev->rss_ring_count = qdev->intr_count; | |
3461 | /* | ||
3462 | * rx_ring[0] is always the default queue. | ||
3463 | */ | ||
3464 | /* Allocate outbound completion ring for each CPU. */ | ||
3465 | qdev->tx_ring_count = cpu_cnt; | 3465 | qdev->tx_ring_count = cpu_cnt; |
3466 | /* Allocate inbound completion (RSS) ring for each CPU. */ | ||
3467 | qdev->rss_ring_count = cpu_cnt; | ||
3468 | /* | ||
3469 | * qdev->rx_ring_count: | ||
3470 | * Total number of rx_rings. This includes the one | ||
3471 | * default queue, a number of outbound completion | ||
3472 | * handler rx_rings, and the number of inbound | ||
3473 | * completion handler rx_rings. | ||
3474 | */ | ||
3475 | qdev->rx_ring_count = qdev->tx_ring_count + qdev->rss_ring_count; | 3466 | qdev->rx_ring_count = qdev->tx_ring_count + qdev->rss_ring_count; |
3476 | 3467 | ||
3477 | for (i = 0; i < qdev->tx_ring_count; i++) { | 3468 | for (i = 0; i < qdev->tx_ring_count; i++) { |