diff options
author | Rajesh Borundia <rajesh.borundia@qlogic.com> | 2013-03-29 01:46:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-03-29 15:51:05 -0400 |
commit | da6c806311b9fd2b1aa79f9d5d151bc40060a1fc (patch) | |
tree | d19ec0e00add59f92c3d7808a0e8421dabcbae51 /drivers/net/ethernet/qlogic | |
parent | f8468331645ea6d9bed057673378ccd580465b8c (diff) |
qlcnic: Use shared interrupt vector for Tx and Rx
o VF will use shared MSI-X interrupt vector for Tx and Rx.
o When QLCNIC_INTR_SHARED flag is set Tx and Rx will
share MSI-X interrupt vector. Tx will use a separate
MSI-X interrupt vector from Rx otherwise.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/qlogic')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 21 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 56 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 23 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 1 |
5 files changed, 80 insertions, 22 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 2332d2e4a5e9..002f0bdc5b5e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
@@ -897,6 +897,7 @@ struct qlcnic_ipaddr { | |||
897 | #define QLCNIC_FW_RESET_OWNER 0x2000 | 897 | #define QLCNIC_FW_RESET_OWNER 0x2000 |
898 | #define QLCNIC_FW_HANG 0x4000 | 898 | #define QLCNIC_FW_HANG 0x4000 |
899 | #define QLCNIC_FW_LRO_MSS_CAP 0x8000 | 899 | #define QLCNIC_FW_LRO_MSS_CAP 0x8000 |
900 | #define QLCNIC_TX_INTR_SHARED 0x10000 | ||
900 | #define QLCNIC_IS_MSI_FAMILY(adapter) \ | 901 | #define QLCNIC_IS_MSI_FAMILY(adapter) \ |
901 | ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) | 902 | ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) |
902 | 903 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 433456b14306..c08974fd07e3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | |||
@@ -410,7 +410,10 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr) | |||
410 | num_intr)); | 410 | num_intr)); |
411 | /* account for AEN interrupt MSI-X based interrupts */ | 411 | /* account for AEN interrupt MSI-X based interrupts */ |
412 | num_msix += 1; | 412 | num_msix += 1; |
413 | num_msix += adapter->max_drv_tx_rings; | 413 | |
414 | if (!(adapter->flags & QLCNIC_TX_INTR_SHARED)) | ||
415 | num_msix += adapter->max_drv_tx_rings; | ||
416 | |||
414 | err = qlcnic_enable_msix(adapter, num_msix); | 417 | err = qlcnic_enable_msix(adapter, num_msix); |
415 | if (err == -ENOMEM) | 418 | if (err == -ENOMEM) |
416 | return err; | 419 | return err; |
@@ -1243,6 +1246,7 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter, | |||
1243 | struct qlcnic_tx_mbx mbx; | 1246 | struct qlcnic_tx_mbx mbx; |
1244 | struct qlcnic_tx_mbx_out *mbx_out; | 1247 | struct qlcnic_tx_mbx_out *mbx_out; |
1245 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 1248 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1249 | u32 msix_vector; | ||
1246 | 1250 | ||
1247 | /* Reset host resources */ | 1251 | /* Reset host resources */ |
1248 | tx->producer = 0; | 1252 | tx->producer = 0; |
@@ -1257,10 +1261,16 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter, | |||
1257 | mbx.cnsmr_index_low = LSD(tx->hw_cons_phys_addr); | 1261 | mbx.cnsmr_index_low = LSD(tx->hw_cons_phys_addr); |
1258 | mbx.cnsmr_index_high = MSD(tx->hw_cons_phys_addr); | 1262 | mbx.cnsmr_index_high = MSD(tx->hw_cons_phys_addr); |
1259 | mbx.size = tx->num_desc; | 1263 | mbx.size = tx->num_desc; |
1260 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | 1264 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { |
1261 | msix_id = ahw->intr_tbl[adapter->max_sds_rings + ring].id; | 1265 | if (!(adapter->flags & QLCNIC_TX_INTR_SHARED)) |
1262 | else | 1266 | msix_vector = adapter->max_sds_rings + ring; |
1267 | else | ||
1268 | msix_vector = adapter->max_sds_rings - 1; | ||
1269 | msix_id = ahw->intr_tbl[msix_vector].id; | ||
1270 | } else { | ||
1263 | msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID); | 1271 | msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID); |
1272 | } | ||
1273 | |||
1264 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) | 1274 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) |
1265 | mbx.intr_id = msix_id; | 1275 | mbx.intr_id = msix_id; |
1266 | else | 1276 | else |
@@ -1282,7 +1292,8 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter, | |||
1282 | mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2]; | 1292 | mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2]; |
1283 | tx->crb_cmd_producer = ahw->pci_base0 + mbx_out->host_prod; | 1293 | tx->crb_cmd_producer = ahw->pci_base0 + mbx_out->host_prod; |
1284 | tx->ctx_id = mbx_out->ctx_id; | 1294 | tx->ctx_id = mbx_out->ctx_id; |
1285 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | 1295 | if ((adapter->flags & QLCNIC_MSIX_ENABLED) && |
1296 | !(adapter->flags & QLCNIC_TX_INTR_SHARED)) { | ||
1286 | intr_mask = ahw->intr_tbl[adapter->max_sds_rings + ring].src; | 1297 | intr_mask = ahw->intr_tbl[adapter->max_sds_rings + ring].src; |
1287 | tx->crb_intr_mask = ahw->pci_base0 + intr_mask; | 1298 | tx->crb_intr_mask = ahw->pci_base0 + intr_mask; |
1288 | } | 1299 | } |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c index 891f12d47c9c..25b61884585a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | |||
@@ -1691,6 +1691,29 @@ skip: | |||
1691 | return count; | 1691 | return count; |
1692 | } | 1692 | } |
1693 | 1693 | ||
1694 | static int qlcnic_83xx_msix_sriov_vf_poll(struct napi_struct *napi, int budget) | ||
1695 | { | ||
1696 | int tx_complete; | ||
1697 | int work_done; | ||
1698 | struct qlcnic_host_sds_ring *sds_ring; | ||
1699 | struct qlcnic_adapter *adapter; | ||
1700 | struct qlcnic_host_tx_ring *tx_ring; | ||
1701 | |||
1702 | sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); | ||
1703 | adapter = sds_ring->adapter; | ||
1704 | /* tx ring count = 1 */ | ||
1705 | tx_ring = adapter->tx_ring; | ||
1706 | |||
1707 | tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, budget); | ||
1708 | work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget); | ||
1709 | if ((work_done < budget) && tx_complete) { | ||
1710 | napi_complete(&sds_ring->napi); | ||
1711 | qlcnic_83xx_enable_intr(adapter, sds_ring); | ||
1712 | } | ||
1713 | |||
1714 | return work_done; | ||
1715 | } | ||
1716 | |||
1694 | static int qlcnic_83xx_poll(struct napi_struct *napi, int budget) | 1717 | static int qlcnic_83xx_poll(struct napi_struct *napi, int budget) |
1695 | { | 1718 | { |
1696 | int tx_complete; | 1719 | int tx_complete; |
@@ -1768,7 +1791,8 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter) | |||
1768 | qlcnic_83xx_enable_intr(adapter, sds_ring); | 1791 | qlcnic_83xx_enable_intr(adapter, sds_ring); |
1769 | } | 1792 | } |
1770 | 1793 | ||
1771 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | 1794 | if ((adapter->flags & QLCNIC_MSIX_ENABLED) && |
1795 | !(adapter->flags & QLCNIC_TX_INTR_SHARED)) { | ||
1772 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | 1796 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { |
1773 | tx_ring = &adapter->tx_ring[ring]; | 1797 | tx_ring = &adapter->tx_ring[ring]; |
1774 | napi_enable(&tx_ring->napi); | 1798 | napi_enable(&tx_ring->napi); |
@@ -1795,7 +1819,8 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter) | |||
1795 | napi_disable(&sds_ring->napi); | 1819 | napi_disable(&sds_ring->napi); |
1796 | } | 1820 | } |
1797 | 1821 | ||
1798 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | 1822 | if ((adapter->flags & QLCNIC_MSIX_ENABLED) && |
1823 | !(adapter->flags & QLCNIC_TX_INTR_SHARED)) { | ||
1799 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | 1824 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { |
1800 | tx_ring = &adapter->tx_ring[ring]; | 1825 | tx_ring = &adapter->tx_ring[ring]; |
1801 | qlcnic_83xx_disable_tx_intr(adapter, tx_ring); | 1826 | qlcnic_83xx_disable_tx_intr(adapter, tx_ring); |
@@ -1808,7 +1833,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter) | |||
1808 | int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, | 1833 | int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, |
1809 | struct net_device *netdev) | 1834 | struct net_device *netdev) |
1810 | { | 1835 | { |
1811 | int ring, max_sds_rings; | 1836 | int ring, max_sds_rings, temp; |
1812 | struct qlcnic_host_sds_ring *sds_ring; | 1837 | struct qlcnic_host_sds_ring *sds_ring; |
1813 | struct qlcnic_host_tx_ring *tx_ring; | 1838 | struct qlcnic_host_tx_ring *tx_ring; |
1814 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 1839 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
@@ -1819,14 +1844,23 @@ int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, | |||
1819 | max_sds_rings = adapter->max_sds_rings; | 1844 | max_sds_rings = adapter->max_sds_rings; |
1820 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 1845 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
1821 | sds_ring = &recv_ctx->sds_rings[ring]; | 1846 | sds_ring = &recv_ctx->sds_rings[ring]; |
1822 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | 1847 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { |
1823 | netif_napi_add(netdev, &sds_ring->napi, | 1848 | if (!(adapter->flags & QLCNIC_TX_INTR_SHARED)) { |
1824 | qlcnic_83xx_rx_poll, | 1849 | netif_napi_add(netdev, &sds_ring->napi, |
1825 | QLCNIC_NETDEV_WEIGHT * 2); | 1850 | qlcnic_83xx_rx_poll, |
1826 | else | 1851 | QLCNIC_NETDEV_WEIGHT * 2); |
1852 | } else { | ||
1853 | temp = QLCNIC_NETDEV_WEIGHT / max_sds_rings; | ||
1854 | netif_napi_add(netdev, &sds_ring->napi, | ||
1855 | qlcnic_83xx_msix_sriov_vf_poll, | ||
1856 | temp); | ||
1857 | } | ||
1858 | |||
1859 | } else { | ||
1827 | netif_napi_add(netdev, &sds_ring->napi, | 1860 | netif_napi_add(netdev, &sds_ring->napi, |
1828 | qlcnic_83xx_poll, | 1861 | qlcnic_83xx_poll, |
1829 | QLCNIC_NETDEV_WEIGHT / max_sds_rings); | 1862 | QLCNIC_NETDEV_WEIGHT / max_sds_rings); |
1863 | } | ||
1830 | } | 1864 | } |
1831 | 1865 | ||
1832 | if (qlcnic_alloc_tx_rings(adapter, netdev)) { | 1866 | if (qlcnic_alloc_tx_rings(adapter, netdev)) { |
@@ -1834,7 +1868,8 @@ int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, | |||
1834 | return -ENOMEM; | 1868 | return -ENOMEM; |
1835 | } | 1869 | } |
1836 | 1870 | ||
1837 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | 1871 | if ((adapter->flags & QLCNIC_MSIX_ENABLED) && |
1872 | !(adapter->flags & QLCNIC_TX_INTR_SHARED)) { | ||
1838 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | 1873 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { |
1839 | tx_ring = &adapter->tx_ring[ring]; | 1874 | tx_ring = &adapter->tx_ring[ring]; |
1840 | netif_napi_add(netdev, &tx_ring->napi, | 1875 | netif_napi_add(netdev, &tx_ring->napi, |
@@ -1860,7 +1895,8 @@ void qlcnic_83xx_napi_del(struct qlcnic_adapter *adapter) | |||
1860 | 1895 | ||
1861 | qlcnic_free_sds_rings(adapter->recv_ctx); | 1896 | qlcnic_free_sds_rings(adapter->recv_ctx); |
1862 | 1897 | ||
1863 | if ((adapter->flags & QLCNIC_MSIX_ENABLED)) { | 1898 | if ((adapter->flags & QLCNIC_MSIX_ENABLED) && |
1899 | !(adapter->flags & QLCNIC_TX_INTR_SHARED)) { | ||
1864 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | 1900 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { |
1865 | tx_ring = &adapter->tx_ring[ring]; | 1901 | tx_ring = &adapter->tx_ring[ring]; |
1866 | netif_napi_del(&tx_ring->napi); | 1902 | netif_napi_del(&tx_ring->napi); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 2f3001c6c6c6..f67e8c65350e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -400,7 +400,15 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) | |||
400 | { | 400 | { |
401 | struct pci_dev *pdev = adapter->pdev; | 401 | struct pci_dev *pdev = adapter->pdev; |
402 | int err = -1, i; | 402 | int err = -1, i; |
403 | int max_tx_rings; | 403 | int max_tx_rings, tx_vector; |
404 | |||
405 | if (adapter->flags & QLCNIC_TX_INTR_SHARED) { | ||
406 | max_tx_rings = 0; | ||
407 | tx_vector = 0; | ||
408 | } else { | ||
409 | max_tx_rings = adapter->max_drv_tx_rings; | ||
410 | tx_vector = 1; | ||
411 | } | ||
404 | 412 | ||
405 | if (!adapter->msix_entries) { | 413 | if (!adapter->msix_entries) { |
406 | adapter->msix_entries = kcalloc(num_msix, | 414 | adapter->msix_entries = kcalloc(num_msix, |
@@ -423,7 +431,6 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) | |||
423 | if (qlcnic_83xx_check(adapter)) { | 431 | if (qlcnic_83xx_check(adapter)) { |
424 | adapter->ahw->num_msix = num_msix; | 432 | adapter->ahw->num_msix = num_msix; |
425 | /* subtract mail box and tx ring vectors */ | 433 | /* subtract mail box and tx ring vectors */ |
426 | max_tx_rings = adapter->max_drv_tx_rings; | ||
427 | adapter->max_sds_rings = num_msix - | 434 | adapter->max_sds_rings = num_msix - |
428 | max_tx_rings - 1; | 435 | max_tx_rings - 1; |
429 | } else { | 436 | } else { |
@@ -436,11 +443,11 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) | |||
436 | "Unable to allocate %d MSI-X interrupt vectors\n", | 443 | "Unable to allocate %d MSI-X interrupt vectors\n", |
437 | num_msix); | 444 | num_msix); |
438 | if (qlcnic_83xx_check(adapter)) { | 445 | if (qlcnic_83xx_check(adapter)) { |
439 | if (err < QLC_83XX_MINIMUM_VECTOR) | 446 | if (err < (QLC_83XX_MINIMUM_VECTOR - tx_vector)) |
440 | return err; | 447 | return err; |
441 | err -= (adapter->max_drv_tx_rings + 1); | 448 | err -= (max_tx_rings + 1); |
442 | num_msix = rounddown_pow_of_two(err); | 449 | num_msix = rounddown_pow_of_two(err); |
443 | num_msix += (adapter->max_drv_tx_rings + 1); | 450 | num_msix += (max_tx_rings + 1); |
444 | } else { | 451 | } else { |
445 | num_msix = rounddown_pow_of_two(err); | 452 | num_msix = rounddown_pow_of_two(err); |
446 | } | 453 | } |
@@ -1285,7 +1292,8 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) | |||
1285 | } | 1292 | } |
1286 | } | 1293 | } |
1287 | if (qlcnic_83xx_check(adapter) && | 1294 | if (qlcnic_83xx_check(adapter) && |
1288 | (adapter->flags & QLCNIC_MSIX_ENABLED)) { | 1295 | (adapter->flags & QLCNIC_MSIX_ENABLED) && |
1296 | !(adapter->flags & QLCNIC_TX_INTR_SHARED)) { | ||
1289 | handler = qlcnic_msix_tx_intr; | 1297 | handler = qlcnic_msix_tx_intr; |
1290 | for (ring = 0; ring < adapter->max_drv_tx_rings; | 1298 | for (ring = 0; ring < adapter->max_drv_tx_rings; |
1291 | ring++) { | 1299 | ring++) { |
@@ -1321,7 +1329,8 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter) | |||
1321 | free_irq(sds_ring->irq, sds_ring); | 1329 | free_irq(sds_ring->irq, sds_ring); |
1322 | } | 1330 | } |
1323 | } | 1331 | } |
1324 | if (qlcnic_83xx_check(adapter)) { | 1332 | if (qlcnic_83xx_check(adapter) && |
1333 | !(adapter->flags & QLCNIC_TX_INTR_SHARED)) { | ||
1325 | for (ring = 0; ring < adapter->max_drv_tx_rings; | 1334 | for (ring = 0; ring < adapter->max_drv_tx_rings; |
1326 | ring++) { | 1335 | ring++) { |
1327 | tx_ring = &adapter->tx_ring[ring]; | 1336 | tx_ring = &adapter->tx_ring[ring]; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 0c04e886cdc8..0e097f79a14a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | |||
@@ -137,6 +137,7 @@ int qlcnic_sriov_vf_init(struct qlcnic_adapter *adapter, int pci_using_dac) | |||
137 | spin_lock_init(&ahw->mbx_lock); | 137 | spin_lock_init(&ahw->mbx_lock); |
138 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | 138 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); |
139 | ahw->msix_supported = 1; | 139 | ahw->msix_supported = 1; |
140 | adapter->flags |= QLCNIC_TX_INTR_SHARED; | ||
140 | 141 | ||
141 | if (qlcnic_sriov_setup_vf(adapter, pci_using_dac)) | 142 | if (qlcnic_sriov_setup_vf(adapter, pci_using_dac)) |
142 | return -EIO; | 143 | return -EIO; |