diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 327 |
1 files changed, 163 insertions, 164 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index fab5f3b6be4b..007b7df73510 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -548,36 +548,75 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = { .io_resume = qlcnic_82xx_io_resume, }; -static void qlcnic_get_multiq_capability(struct qlcnic_adapter *adapter) +static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter) { struct qlcnic_hardware_context *ahw = adapter->ahw; - int num_tx_q; - if (ahw->msix_supported && + if (qlcnic_82xx_check(adapter) && (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_MULTI_TX)) { - num_tx_q = min_t(int, QLCNIC_DEF_NUM_TX_RINGS, - num_online_cpus()); - if (num_tx_q > 1) { - test_and_set_bit(__QLCNIC_MULTI_TX_UNIQUE, - &adapter->state); - adapter->max_drv_tx_rings = num_tx_q; - } + test_and_set_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state); + return 0; } else { - adapter->max_drv_tx_rings = 1; + return 1; } } +static int qlcnic_max_rings(struct qlcnic_adapter *adapter, u8 ring_cnt, + int queue_type) +{ + int num_rings, max_rings = QLCNIC_MAX_SDS_RINGS; + + if (queue_type == QLCNIC_RX_QUEUE) + max_rings = adapter->max_sds_rings; + else if (queue_type == QLCNIC_TX_QUEUE) + max_rings = adapter->max_tx_rings; + + num_rings = rounddown_pow_of_two(min_t(int, num_online_cpus(), + max_rings)); + + if (ring_cnt > num_rings) + return num_rings; + else + return ring_cnt; +} + +void qlcnic_set_tx_ring_count(struct qlcnic_adapter *adapter, u8 tx_cnt) +{ + /* 83xx adapter does not have max_tx_rings intialized in probe */ + if (adapter->max_tx_rings) + adapter->drv_tx_rings = qlcnic_max_rings(adapter, 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) +{ + /* 83xx adapter does not have max_sds_rings intialized in probe */ + if (adapter->max_sds_rings) + adapter->drv_sds_rings = qlcnic_max_rings(adapter, 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) { struct pci_dev *pdev = adapter->pdev; - int max_tx_rings, max_sds_rings, tx_vector; + int drv_tx_rings, drv_sds_rings, tx_vector; int err = -1, i; if (adapter->flags & QLCNIC_TX_INTR_SHARED) { - max_tx_rings = 0; + drv_tx_rings = 0; tx_vector = 0; } else { - max_tx_rings = adapter->max_drv_tx_rings; + drv_tx_rings = adapter->drv_tx_rings; tx_vector = 1; } @@ -589,7 +628,7 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) return -ENOMEM; } - adapter->max_sds_rings = 1; + adapter->drv_sds_rings = QLCNIC_SINGLE_RING; adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED); if (adapter->ahw->msix_supported) { @@ -602,18 +641,18 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) if (qlcnic_83xx_check(adapter)) { adapter->ahw->num_msix = num_msix; /* subtract mail box and tx ring vectors */ - adapter->max_sds_rings = num_msix - - max_tx_rings - 1; + 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 && - (adapter->max_drv_tx_rings > 1)) - max_sds_rings = num_msix - max_tx_rings; + (adapter->drv_tx_rings > 1)) + drv_sds_rings = num_msix - drv_tx_rings; else - max_sds_rings = num_msix; + drv_sds_rings = num_msix; - adapter->max_sds_rings = max_sds_rings; + adapter->drv_sds_rings = drv_sds_rings; } dev_info(&pdev->dev, "using msi-x interrupts\n"); return err; @@ -624,13 +663,13 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) if (qlcnic_83xx_check(adapter)) { if (err < (QLC_83XX_MINIMUM_VECTOR - tx_vector)) return err; - err -= (max_tx_rings + 1); + err -= drv_tx_rings + 1; num_msix = rounddown_pow_of_two(err); - num_msix += (max_tx_rings + 1); + num_msix += drv_tx_rings + 1; } else { num_msix = rounddown_pow_of_two(err); if (qlcnic_check_multi_tx(adapter)) - num_msix += max_tx_rings; + num_msix += drv_tx_rings; } if (num_msix) { @@ -683,25 +722,14 @@ static int qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter) return err; } -int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr, int txq) +int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter) { - struct qlcnic_hardware_context *ahw = adapter->ahw; int num_msix, err = 0; - if (!num_intr) - num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS; + num_msix = adapter->drv_sds_rings; - if (ahw->msix_supported) { - num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(), - num_intr)); - if (qlcnic_check_multi_tx(adapter)) { - if (txq) - adapter->max_drv_tx_rings = txq; - num_msix += adapter->max_drv_tx_rings; - } - } else { - num_msix = 1; - } + if (qlcnic_check_multi_tx(adapter)) + num_msix += adapter->drv_tx_rings; err = qlcnic_enable_msix(adapter, num_msix); if (err == -ENOMEM) @@ -1140,14 +1168,18 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter) adapter->ahw->max_mac_filters = nic_info.max_mac_filters; adapter->ahw->max_mtu = nic_info.max_mtu; - /* Disable NPAR for 83XX */ - if (qlcnic_83xx_check(adapter)) - return err; - - if (adapter->ahw->capabilities & BIT_6) + if (adapter->ahw->capabilities & BIT_6) { adapter->flags |= QLCNIC_ESWITCH_ENABLED; - else + adapter->ahw->nic_mode = QLCNIC_VNIC_MODE; + adapter->max_tx_rings = QLCNIC_MAX_HW_VNIC_TX_RINGS; + adapter->max_sds_rings = QLCNIC_MAX_VNIC_SDS_RINGS; + + dev_info(&adapter->pdev->dev, "vNIC mode enabled.\n"); + } else { + adapter->ahw->nic_mode = QLCNIC_DEFAULT_MODE; + adapter->max_tx_rings = QLCNIC_MAX_HW_TX_RINGS; adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; + } return err; } @@ -1295,6 +1327,8 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter) "HAL Version: %d, Privileged function\n", adapter->ahw->fw_hal_version); } + } else { + adapter->ahw->nic_mode = QLCNIC_DEFAULT_MODE; } adapter->flags |= QLCNIC_ADAPTER_INITIALIZED; @@ -1554,7 +1588,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) if (qlcnic_82xx_check(adapter) || (qlcnic_83xx_check(adapter) && (adapter->flags & QLCNIC_MSIX_ENABLED))) { - num_sds_rings = adapter->max_sds_rings; + num_sds_rings = adapter->drv_sds_rings; for (ring = 0; ring < num_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; if (qlcnic_82xx_check(adapter) && @@ -1588,7 +1622,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) (adapter->flags & QLCNIC_MSIX_ENABLED) && !(adapter->flags & QLCNIC_TX_INTR_SHARED))) { handler = qlcnic_msix_tx_intr; - for (ring = 0; ring < adapter->max_drv_tx_rings; + for (ring = 0; ring < adapter->drv_tx_rings; ring++) { tx_ring = &adapter->tx_ring[ring]; snprintf(tx_ring->name, sizeof(tx_ring->name), @@ -1616,7 +1650,7 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter) if (qlcnic_82xx_check(adapter) || (qlcnic_83xx_check(adapter) && (adapter->flags & QLCNIC_MSIX_ENABLED))) { - for (ring = 0; ring < adapter->max_sds_rings; ring++) { + for (ring = 0; ring < adapter->drv_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; free_irq(sds_ring->irq, sds_ring); } @@ -1625,7 +1659,7 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter) !(adapter->flags & QLCNIC_TX_INTR_SHARED)) || (qlcnic_82xx_check(adapter) && qlcnic_check_multi_tx(adapter))) { - for (ring = 0; ring < adapter->max_drv_tx_rings; + for (ring = 0; ring < adapter->drv_tx_rings; ring++) { tx_ring = &adapter->tx_ring[ring]; if (tx_ring->irq) @@ -1679,7 +1713,7 @@ int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) adapter->ahw->linkup = 0; - if (adapter->max_sds_rings > 1) + if (adapter->drv_sds_rings > 1) qlcnic_config_rss(adapter, 1); qlcnic_config_intr_coalesce(adapter); @@ -1721,6 +1755,7 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) if (qlcnic_sriov_vf_check(adapter)) qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc); smp_mb(); + spin_lock(&adapter->tx_clean_lock); netif_carrier_off(netdev); adapter->ahw->linkup = 0; netif_tx_disable(netdev); @@ -1739,8 +1774,9 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) qlcnic_reset_rx_buffers_list(adapter); - for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) + for (ring = 0; ring < adapter->drv_tx_rings; ring++) qlcnic_release_tx_buffers(adapter, &adapter->tx_ring[ring]); + spin_unlock(&adapter->tx_clean_lock); } /* Usage: During suspend and firmware recovery module */ @@ -1816,16 +1852,16 @@ void qlcnic_detach(struct qlcnic_adapter *adapter) adapter->is_up = 0; } -void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings) +void qlcnic_diag_free_res(struct net_device *netdev, int drv_sds_rings) { struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_host_sds_ring *sds_ring; - int max_tx_rings = adapter->max_drv_tx_rings; + int drv_tx_rings = adapter->drv_tx_rings; int ring; clear_bit(__QLCNIC_DEV_UP, &adapter->state); if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { - for (ring = 0; ring < adapter->max_sds_rings; ring++) { + for (ring = 0; ring < adapter->drv_sds_rings; ring++) { sds_ring = &adapter->recv_ctx->sds_rings[ring]; qlcnic_disable_int(sds_ring); } @@ -1836,8 +1872,8 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings) qlcnic_detach(adapter); adapter->ahw->diag_test = 0; - adapter->max_sds_rings = max_sds_rings; - adapter->max_drv_tx_rings = max_tx_rings; + adapter->drv_sds_rings = drv_sds_rings; + adapter->drv_tx_rings = drv_tx_rings; if (qlcnic_attach(adapter)) goto out; @@ -1903,10 +1939,10 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) qlcnic_detach(adapter); - adapter->max_sds_rings = 1; + adapter->drv_sds_rings = QLCNIC_SINGLE_RING; + adapter->drv_tx_rings = QLCNIC_SINGLE_RING; adapter->ahw->diag_test = test; adapter->ahw->linkup = 0; - adapter->max_drv_tx_rings = 1; ret = qlcnic_attach(adapter); if (ret) { @@ -1927,7 +1963,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) } if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { - for (ring = 0; ring < adapter->max_sds_rings; ring++) { + for (ring = 0; ring < adapter->drv_sds_rings; ring++) { sds_ring = &adapter->recv_ctx->sds_rings[ring]; qlcnic_enable_int(sds_ring); } @@ -2100,7 +2136,7 @@ void qlcnic_free_tx_rings(struct qlcnic_adapter *adapter) int ring; struct qlcnic_host_tx_ring *tx_ring; - for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { + for (ring = 0; ring < adapter->drv_tx_rings; ring++) { tx_ring = &adapter->tx_ring[ring]; if (tx_ring && tx_ring->cmd_buf_arr != NULL) { vfree(tx_ring->cmd_buf_arr); @@ -2118,14 +2154,14 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter, struct qlcnic_host_tx_ring *tx_ring; struct qlcnic_cmd_buffer *cmd_buf_arr; - tx_ring = kcalloc(adapter->max_drv_tx_rings, + tx_ring = kcalloc(adapter->drv_tx_rings, sizeof(struct qlcnic_host_tx_ring), GFP_KERNEL); if (tx_ring == NULL) return -ENOMEM; adapter->tx_ring = tx_ring; - for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { + for (ring = 0; ring < adapter->drv_tx_rings; ring++) { tx_ring = &adapter->tx_ring[ring]; tx_ring->num_desc = adapter->num_txd; tx_ring->txq = netdev_get_tx_queue(netdev, ring); @@ -2140,11 +2176,11 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter, if (qlcnic_83xx_check(adapter) || (qlcnic_82xx_check(adapter) && qlcnic_check_multi_tx(adapter))) { - for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { + for (ring = 0; ring < adapter->drv_tx_rings; ring++) { tx_ring = &adapter->tx_ring[ring]; tx_ring->adapter = adapter; if (adapter->flags & QLCNIC_MSIX_ENABLED) { - index = adapter->max_sds_rings + ring; + index = adapter->drv_sds_rings + ring; vector = adapter->msix_entries[index].vector; tx_ring->irq = vector; } @@ -2263,6 +2299,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rwlock_init(&adapter->ahw->crb_lock); mutex_init(&adapter->ahw->mem_lock); + spin_lock_init(&adapter->tx_clean_lock); INIT_LIST_HEAD(&adapter->mac_list); qlcnic_register_dcb(adapter); @@ -2277,20 +2314,21 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_maintenance_mode; } - qlcnic_get_multiq_capability(adapter); - - if ((adapter->ahw->act_pci_func > 2) && - qlcnic_check_multi_tx(adapter)) { - adapter->max_drv_tx_rings = QLCNIC_DEF_NUM_TX_RINGS; - dev_info(&adapter->pdev->dev, - "vNIC mode enabled, Set max TX rings = %d\n", - adapter->max_drv_tx_rings); + /* compute and set default and max tx/sds rings */ + if (adapter->ahw->msix_supported) { + if (qlcnic_check_multi_tx_capability(adapter) == 1) + qlcnic_set_tx_ring_count(adapter, + QLCNIC_SINGLE_RING); + else + qlcnic_set_tx_ring_count(adapter, + QLCNIC_DEF_TX_RINGS); + qlcnic_set_sds_ring_count(adapter, + QLCNIC_DEF_SDS_RINGS); + } else { + qlcnic_set_tx_ring_count(adapter, QLCNIC_SINGLE_RING); + qlcnic_set_sds_ring_count(adapter, QLCNIC_SINGLE_RING); } - if (!qlcnic_check_multi_tx(adapter)) { - clear_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state); - adapter->max_drv_tx_rings = 1; - } err = qlcnic_setup_idc_param(adapter); if (err) goto err_out_free_hw; @@ -2301,13 +2339,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (dcb && qlcnic_dcb_attach(dcb)) qlcnic_clear_dcb_ops(dcb); - } else if (qlcnic_83xx_check(adapter)) { - adapter->max_drv_tx_rings = 1; qlcnic_83xx_check_vf(adapter, ent); adapter->portnum = adapter->ahw->pci_func; err = qlcnic_83xx_init(adapter, pci_using_dac); - if (err) { switch (err) { case -ENOTRECOVERABLE: @@ -2351,7 +2386,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) "Device does not support MSI interrupts\n"); if (qlcnic_82xx_check(adapter)) { - err = qlcnic_setup_intr(adapter, 0, 0); + err = qlcnic_setup_intr(adapter); if (err) { dev_err(&pdev->dev, "Failed to setup interrupt\n"); goto err_out_disable_msi; @@ -2722,7 +2757,7 @@ static void qlcnic_tx_timeout(struct net_device *netdev) QLCNIC_FORCE_FW_DUMP_KEY); } else { netdev_info(netdev, "Tx timeout, reset adapter context.\n"); - for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { + for (ring = 0; ring < adapter->drv_tx_rings; ring++) { tx_ring = &adapter->tx_ring[ring]; netdev_info(netdev, "Tx ring=%d\n", ring); netdev_info(netdev, @@ -2850,7 +2885,7 @@ static void qlcnic_poll_controller(struct net_device *netdev) struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; disable_irq(adapter->irq); - for (ring = 0; ring < adapter->max_sds_rings; ring++) { + for (ring = 0; ring < adapter->drv_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; qlcnic_intr(adapter->irq, sds_ring); } @@ -3517,7 +3552,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev) qlcnic_clr_drv_state(adapter); kfree(adapter->msix_entries); adapter->msix_entries = NULL; - err = qlcnic_setup_intr(adapter, 0, 0); + err = qlcnic_setup_intr(adapter); if (err) { kfree(adapter->msix_entries); @@ -3662,130 +3697,94 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) return err; } -int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *adapter, u32 txq) +int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt, + int queue_type) { struct net_device *netdev = adapter->netdev; - u8 max_hw = QLCNIC_MAX_TX_RINGS; - u32 max_allowed; + u8 max_hw_rings = 0; + char buf[8]; + int cur_rings; + + if (queue_type == QLCNIC_RX_QUEUE) { + max_hw_rings = adapter->max_sds_rings; + cur_rings = adapter->drv_sds_rings; + strcpy(buf, "SDS"); + } else if (queue_type == QLCNIC_TX_QUEUE) { + if (qlcnic_83xx_check(adapter)) + max_hw_rings = QLCNIC_SINGLE_RING; + else + max_hw_rings = adapter->max_tx_rings; - if (!qlcnic_use_msi_x && !qlcnic_use_msi) { - netdev_err(netdev, "No Multi TX-Q support in INT-x mode\n"); - return -EINVAL; + cur_rings = adapter->drv_tx_rings; + strcpy(buf, "Tx"); } - if (!qlcnic_check_multi_tx(adapter)) { - netdev_err(netdev, "No Multi TX-Q support\n"); + if (!qlcnic_use_msi_x && !qlcnic_use_msi) { + netdev_err(netdev, "No RSS/TSS support in INT-x mode\n"); return -EINVAL; } - if (txq > QLCNIC_MAX_TX_RINGS) { - netdev_err(netdev, "Invalid ring count\n"); + if (adapter->flags & QLCNIC_MSI_ENABLED) { + netdev_err(netdev, "No RSS/TSS support in MSI mode\n"); return -EINVAL; } - max_allowed = rounddown_pow_of_two(min_t(int, max_hw, - num_online_cpus())); - if ((txq > max_allowed) || !is_power_of_2(txq)) { - if (!is_power_of_2(txq)) - netdev_err(netdev, - "TX queue should be a power of 2\n"); - if (txq > num_online_cpus()) - netdev_err(netdev, - "Tx queue should not be higher than [%u], number of online CPUs in the system\n", - num_online_cpus()); - netdev_err(netdev, "Unable to configure %u Tx rings\n", txq); + if (ring_cnt < 2) { + netdev_err(netdev, + "%s rings value should not be lower than 2\n", buf); return -EINVAL; } - return 0; -} - -int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter, - __u32 val) -{ - struct net_device *netdev = adapter->netdev; - u8 max_hw = adapter->ahw->max_rx_ques; - u32 max_allowed; - - if (!qlcnic_use_msi_x && !qlcnic_use_msi) { - netdev_err(netdev, "No RSS support in INT-x mode\n"); + if (!is_power_of_2(ring_cnt)) { + netdev_err(netdev, "%s rings value should be a power of 2\n", + buf); return -EINVAL; } - if (val > QLCNIC_MAX_SDS_RINGS) { - netdev_err(netdev, "RSS value should not be higher than %u\n", - QLCNIC_MAX_SDS_RINGS); - return -EINVAL; + if (qlcnic_82xx_check(adapter) && (queue_type == QLCNIC_TX_QUEUE) && + !qlcnic_check_multi_tx(adapter)) { + netdev_err(netdev, "No Multi Tx queue support\n"); + return -EINVAL; } - max_allowed = rounddown_pow_of_two(min_t(int, max_hw, - num_online_cpus())); - if ((val > max_allowed) || (val < 2) || !is_power_of_2(val)) { - if (!is_power_of_2(val)) - netdev_err(netdev, "RSS value should be a power of 2\n"); - - if (val < 2) - netdev_err(netdev, "RSS value should not be lower than 2\n"); - - if (val > max_hw) - netdev_err(netdev, - "RSS value should not be higher than[%u], the max RSS rings supported by the adapter\n", - max_hw); - - if (val > num_online_cpus()) - netdev_err(netdev, - "RSS value should not be higher than[%u], number of online CPUs in the system\n", - num_online_cpus()); - - netdev_err(netdev, "Unable to configure %u RSS rings\n", val); - + if (ring_cnt > num_online_cpus()) { + netdev_err(netdev, + "%s value[%u] should not be higher than, number of online CPUs\n", + buf, num_online_cpus()); return -EINVAL; } + return 0; } -int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, int txq) +int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt) { - int err; struct net_device *netdev = adapter->netdev; - int num_msix; + int err; if (test_bit(__QLCNIC_RESETTING, &adapter->state)) return -EBUSY; - if (qlcnic_82xx_check(adapter) && !qlcnic_use_msi_x && - !qlcnic_use_msi) { - netdev_err(netdev, "No RSS support in INT-x mode\n"); - return -EINVAL; - } - netif_device_detach(netdev); if (netif_running(netdev)) __qlcnic_down(adapter, netdev); qlcnic_detach(adapter); - if (qlcnic_82xx_check(adapter)) { - if (txq != 0) - adapter->max_drv_tx_rings = txq; - - if (qlcnic_check_multi_tx(adapter) && - (txq > adapter->max_drv_tx_rings)) - num_msix = adapter->max_drv_tx_rings; - else - num_msix = data; - } - if (qlcnic_83xx_check(adapter)) { qlcnic_83xx_free_mbx_intr(adapter); qlcnic_83xx_enable_mbx_poll(adapter); } - netif_set_real_num_tx_queues(netdev, adapter->max_drv_tx_rings); - qlcnic_teardown_intr(adapter); - err = qlcnic_setup_intr(adapter, data, txq); + /* 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); netdev_err(netdev, "failed to setup interrupt\n"); |