diff options
author | Himanshu Madhani <himanshu.madhani@qlogic.com> | 2014-01-23 17:18:33 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-23 16:13:09 -0800 |
commit | cb9327d567be71ae9248d1a9bbc9c274831f5b6a (patch) | |
tree | d4cea4d1a62524136ee8059271321ed46e6e7091 /drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |
parent | qlcnic: Refactor interrupt coalescing code for all adapters. (diff) | |
download | linux-dev-cb9327d567be71ae9248d1a9bbc9c274831f5b6a.tar.xz linux-dev-cb9327d567be71ae9248d1a9bbc9c274831f5b6a.zip |
qlcnic: Enhance logic to calculate msix vectors.
o Refactored MSI-x vector calculation for All adapters.
Decoupled logic in the code which was using same call to
request MSI-x vectors in default driver load, as well as
during set_channel() operation for TSS/RSS. This refactoring
simplifies code for TSS/RSS code path as well as probe path
of the driver load for all adapters.
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 190 |
1 files changed, 126 insertions, 64 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 68f792a62296..1f79d47c45fa 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -603,9 +603,6 @@ void qlcnic_set_tx_ring_count(struct qlcnic_adapter *adapter, u8 tx_cnt) QLCNIC_TX_QUEUE); else adapter->drv_tx_rings = tx_cnt; - - dev_info(&adapter->pdev->dev, "Set %d Tx rings\n", - adapter->drv_tx_rings); } void qlcnic_set_sds_ring_count(struct qlcnic_adapter *adapter, u8 rx_cnt) @@ -616,25 +613,79 @@ void qlcnic_set_sds_ring_count(struct qlcnic_adapter *adapter, u8 rx_cnt) QLCNIC_RX_QUEUE); else adapter->drv_sds_rings = rx_cnt; - - dev_info(&adapter->pdev->dev, "Set %d SDS rings\n", - adapter->drv_sds_rings); } -int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) +int qlcnic_setup_tss_rss_intr(struct qlcnic_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; - int drv_tx_rings, drv_sds_rings, tx_vector; - int err = -1, i; + int num_msix = 0, err = 0, vector; + + adapter->flags &= ~QLCNIC_TSS_RSS; + + if (adapter->drv_tss_rings > 0) + num_msix += adapter->drv_tss_rings; + else + num_msix += adapter->drv_tx_rings; + + if (adapter->drv_rss_rings > 0) + num_msix += adapter->drv_rss_rings; + else + num_msix += adapter->drv_sds_rings; + + if (qlcnic_83xx_check(adapter)) + num_msix += 1; + + if (!adapter->msix_entries) { + adapter->msix_entries = kcalloc(num_msix, + sizeof(struct msix_entry), + GFP_KERNEL); + if (!adapter->msix_entries) + return -ENOMEM; + } + +restore: + for (vector = 0; vector < num_msix; vector++) + adapter->msix_entries[vector].entry = vector; + + err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); + if (err == 0) { + adapter->ahw->num_msix = num_msix; + if (adapter->drv_tss_rings > 0) + adapter->drv_tx_rings = adapter->drv_tss_rings; - if (adapter->flags & QLCNIC_TX_INTR_SHARED) { - drv_tx_rings = 0; - tx_vector = 0; + if (adapter->drv_rss_rings > 0) + adapter->drv_sds_rings = adapter->drv_rss_rings; } else { - drv_tx_rings = adapter->drv_tx_rings; - tx_vector = 1; + netdev_info(adapter->netdev, + "Unable to allocate %d MSI-X vectors, Available vectors %d\n", + num_msix, err); + + num_msix = adapter->drv_tx_rings + adapter->drv_sds_rings; + + /* Set rings to 0 so we can restore original TSS/RSS count */ + adapter->drv_tss_rings = 0; + adapter->drv_rss_rings = 0; + + if (qlcnic_83xx_check(adapter)) + num_msix += 1; + + netdev_info(adapter->netdev, + "Restoring %d Tx, %d SDS rings for total %d vectors.\n", + adapter->drv_tx_rings, adapter->drv_sds_rings, + num_msix); + goto restore; + + err = -EIO; } + return err; +} + +int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) +{ + struct pci_dev *pdev = adapter->pdev; + int err = -1, vector; + if (!adapter->msix_entries) { adapter->msix_entries = kcalloc(num_msix, sizeof(struct msix_entry), @@ -643,47 +694,43 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) return -ENOMEM; } - adapter->drv_sds_rings = QLCNIC_SINGLE_RING; adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED); if (adapter->ahw->msix_supported) { - enable_msix: - for (i = 0; i < num_msix; i++) - adapter->msix_entries[i].entry = i; +enable_msix: + for (vector = 0; vector < num_msix; vector++) + adapter->msix_entries[vector].entry = vector; + err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); if (err == 0) { adapter->flags |= QLCNIC_MSIX_ENABLED; - if (qlcnic_83xx_check(adapter)) { - adapter->ahw->num_msix = num_msix; - /* subtract mail box and tx ring vectors */ - adapter->drv_sds_rings = num_msix - - drv_tx_rings - 1; - } else { - adapter->ahw->num_msix = num_msix; - if (qlcnic_check_multi_tx(adapter) && - !adapter->ahw->diag_test) - drv_sds_rings = num_msix - drv_tx_rings; - else - drv_sds_rings = num_msix; - - adapter->drv_sds_rings = drv_sds_rings; - } + adapter->ahw->num_msix = num_msix; dev_info(&pdev->dev, "using msi-x interrupts\n"); return err; } else if (err > 0) { dev_info(&pdev->dev, - "Unable to allocate %d MSI-X interrupt vectors\n", - num_msix); - if (qlcnic_83xx_check(adapter)) { - if (err < (QLC_83XX_MINIMUM_VECTOR - tx_vector)) - return err; - err -= drv_tx_rings + 1; + "Unable to allocate %d MSI-X vectors, Available vectors %d\n", + num_msix, err); + + if (qlcnic_82xx_check(adapter)) { num_msix = rounddown_pow_of_two(err); - num_msix += drv_tx_rings + 1; + if (err < QLCNIC_82XX_MINIMUM_VECTOR) + return -EIO; } else { - num_msix = rounddown_pow_of_two(err); - if (qlcnic_check_multi_tx(adapter)) - num_msix += drv_tx_rings; + num_msix = rounddown_pow_of_two(err - 1); + num_msix += 1; + if (err < QLCNIC_83XX_MINIMUM_VECTOR) + return -EIO; + } + + if (qlcnic_82xx_check(adapter) && + !qlcnic_check_multi_tx(adapter)) { + adapter->drv_sds_rings = num_msix; + adapter->drv_tx_rings = QLCNIC_SINGLE_RING; + } else { + /* Distribute vectors equally */ + adapter->drv_tx_rings = num_msix / 2; + adapter->drv_sds_rings = adapter->drv_tx_rings; } if (num_msix) { @@ -694,14 +741,29 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) } } else { dev_info(&pdev->dev, - "Unable to allocate %d MSI-X interrupt vectors\n", - num_msix); + "Unable to allocate %d MSI-X vectors, err=%d\n", + num_msix, err); + return err; } } return err; } +static int qlcnic_82xx_calculate_msix_vector(struct qlcnic_adapter *adapter) +{ + int num_msix; + + num_msix = adapter->drv_sds_rings; + + if (qlcnic_check_multi_tx(adapter)) + num_msix += adapter->drv_tx_rings; + else + num_msix += QLCNIC_SINGLE_RING; + + return num_msix; +} + static int qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter) { int err = 0; @@ -740,21 +802,25 @@ static int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter) { int num_msix, err = 0; - num_msix = adapter->drv_sds_rings; - - if (qlcnic_check_multi_tx(adapter)) - num_msix += adapter->drv_tx_rings; + if (adapter->flags & QLCNIC_TSS_RSS) { + err = qlcnic_setup_tss_rss_intr(adapter); + if (err < 0) + return err; + num_msix = adapter->ahw->num_msix; + } else { + num_msix = qlcnic_82xx_calculate_msix_vector(adapter); - err = qlcnic_enable_msix(adapter, num_msix); - if (err == -ENOMEM) - return err; + err = qlcnic_enable_msix(adapter, num_msix); + if (err == -ENOMEM) + return err; - if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) { - qlcnic_disable_multi_tx(adapter); + if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) { + qlcnic_disable_multi_tx(adapter); - err = qlcnic_enable_msi_legacy(adapter); - if (!err) - return err; + err = qlcnic_enable_msi_legacy(adapter); + if (!err) + return err; + } } return 0; @@ -3834,7 +3900,7 @@ int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt, return 0; } -int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt) +int qlcnic_setup_rings(struct qlcnic_adapter *adapter) { struct net_device *netdev = adapter->netdev; int err; @@ -3855,12 +3921,6 @@ int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt) qlcnic_teardown_intr(adapter); - /* compute and set default and max tx/sds rings */ - qlcnic_set_tx_ring_count(adapter, tx_cnt); - qlcnic_set_sds_ring_count(adapter, rx_cnt); - - netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings); - err = qlcnic_setup_intr(adapter); if (err) { kfree(adapter->msix_entries); @@ -3868,6 +3928,8 @@ int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt) return err; } + netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings); + if (qlcnic_83xx_check(adapter)) { qlcnic_83xx_initialize_nic(adapter, 1); err = qlcnic_83xx_setup_mbx_intr(adapter); |