diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 8b416355879f..ace5050dba38 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -99,16 +99,17 @@ static inline char *nic_name(struct pci_dev *pdev) #define MCC_Q_LEN 128 /* total size not to exceed 8 pages */ #define MCC_CQ_LEN 256 -#define BE3_MAX_RSS_QS 8 #define BE2_MAX_RSS_QS 4 -#define BE3_MAX_TX_QS 8 -#define MAX_RSS_QS BE3_MAX_RSS_QS -#define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */ -#define MAX_EVT_QS MAX_RSS_QS +#define BE3_MAX_RSS_QS 16 +#define BE3_MAX_TX_QS 16 +#define BE3_MAX_EVT_QS 16 + +#define MAX_RX_QS 32 +#define MAX_EVT_QS 32 +#define MAX_TX_QS 32 -#define MAX_TX_QS 8 #define MAX_ROCE_EQS 5 -#define MAX_MSIX_VECTORS (MAX_RSS_QS + MAX_ROCE_EQS) /* RSS qs + RoCE */ +#define MAX_MSIX_VECTORS 32 #define MIN_MSIX_VECTORS 1 #define BE_TX_BUDGET 256 #define BE_NAPI_WEIGHT 64 @@ -701,6 +702,8 @@ extern int be_load_fw(struct be_adapter *adapter, u8 *func); extern bool be_is_wol_supported(struct be_adapter *adapter); extern bool be_pause_supported(struct be_adapter *adapter); extern u32 be_get_fw_log_level(struct be_adapter *adapter); +int be_update_queues(struct be_adapter *adapter); +int be_poll(struct napi_struct *napi, int budget); /* * internal function to initialize-cleanup roce device. diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 4f8c941217cc..b440a1fac77b 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -1119,6 +1119,29 @@ static int be_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) return status; } +static void be_get_channels(struct net_device *netdev, + struct ethtool_channels *ch) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + ch->combined_count = adapter->num_evt_qs; + ch->max_combined = be_max_qs(adapter); +} + +static int be_set_channels(struct net_device *netdev, + struct ethtool_channels *ch) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + if (ch->rx_count || ch->tx_count || ch->other_count || + !ch->combined_count || ch->combined_count > be_max_qs(adapter)) + return -EINVAL; + + adapter->cfg_num_qs = ch->combined_count; + + return be_update_queues(adapter); +} + const struct ethtool_ops be_ethtool_ops = { .get_settings = be_get_settings, .get_drvinfo = be_get_drvinfo, @@ -1145,4 +1168,6 @@ const struct ethtool_ops be_ethtool_ops = { .self_test = be_self_test, .get_rxnfc = be_get_rxnfc, .set_rxnfc = be_set_rxnfc, + .get_channels = be_get_channels, + .set_channels = be_set_channels }; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index b08459d268b4..50116f8ed576 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1913,6 +1913,7 @@ static void be_evt_queues_destroy(struct be_adapter *adapter) if (eqo->q.created) { be_eq_clean(eqo); be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ); + netif_napi_del(&eqo->napi); } be_queue_free(adapter, &eqo->q); } @@ -1928,6 +1929,8 @@ static int be_evt_queues_create(struct be_adapter *adapter) adapter->cfg_num_qs); for_all_evt_queues(adapter, eqo, i) { + netif_napi_add(adapter->netdev, &eqo->napi, be_poll, + BE_NAPI_WEIGHT); eqo->adapter = adapter; eqo->tx_budget = BE_TX_BUDGET; eqo->idx = i; @@ -2021,12 +2024,6 @@ static int be_tx_qs_create(struct be_adapter *adapter) int status, i; adapter->num_tx_qs = min(adapter->num_evt_qs, be_max_txqs(adapter)); - if (adapter->num_tx_qs != MAX_TX_QS) { - rtnl_lock(); - netif_set_real_num_tx_queues(adapter->netdev, - adapter->num_tx_qs); - rtnl_unlock(); - } for_all_tx_queues(adapter, txo, i) { cq = &txo->cq; @@ -2087,13 +2084,6 @@ static int be_rx_cqs_create(struct be_adapter *adapter) if (adapter->num_rx_qs > 1) adapter->num_rx_qs++; - if (adapter->num_rx_qs != MAX_RX_QS) { - rtnl_lock(); - netif_set_real_num_rx_queues(adapter->netdev, - adapter->num_rx_qs); - rtnl_unlock(); - } - adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; for_all_rx_queues(adapter, rxo, i) { rxo->adapter = adapter; @@ -2244,7 +2234,7 @@ static bool be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo, return (work_done < budget); /* Done */ } -static int be_poll(struct napi_struct *napi, int budget) +int be_poll(struct napi_struct *napi, int budget) { struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi); struct be_adapter *adapter = eqo->adapter; @@ -2356,6 +2346,7 @@ static void be_msix_disable(struct be_adapter *adapter) if (msix_enabled(adapter)) { pci_disable_msix(adapter->pdev); adapter->num_msix_vec = 0; + adapter->num_msix_roce_vec = 0; } } @@ -2771,14 +2762,19 @@ static void be_clear_queues(struct be_adapter *adapter) be_evt_queues_destroy(adapter); } -static int be_clear(struct be_adapter *adapter) +static void be_cancel_worker(struct be_adapter *adapter) { - int i; - if (adapter->flags & BE_FLAGS_WORKER_SCHEDULED) { cancel_delayed_work_sync(&adapter->work); adapter->flags &= ~BE_FLAGS_WORKER_SCHEDULED; } +} + +static int be_clear(struct be_adapter *adapter) +{ + int i; + + be_cancel_worker(adapter); if (sriov_enabled(adapter)) be_vf_clear(adapter); @@ -2982,7 +2978,7 @@ static void BEx_get_resources(struct be_adapter *adapter, BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; res->max_rx_qs = res->max_rss_qs + 1; - res->max_evt_qs = be_physfn(adapter) ? MAX_EVT_QS : 1; + res->max_evt_qs = be_physfn(adapter) ? BE3_MAX_EVT_QS : 1; res->if_cap_flags = BE_IF_CAP_FLAGS_WANT; if (!(adapter->function_caps & BE_FUNCTION_CAPS_RSS)) @@ -3108,8 +3104,15 @@ static int be_mac_setup(struct be_adapter *adapter) return 0; } +static void be_schedule_worker(struct be_adapter *adapter) +{ + schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); + adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; +} + static int be_setup_queues(struct be_adapter *adapter) { + struct net_device *netdev = adapter->netdev; int status; status = be_evt_queues_create(adapter); @@ -3128,12 +3131,56 @@ static int be_setup_queues(struct be_adapter *adapter) if (status) goto err; + status = netif_set_real_num_rx_queues(netdev, adapter->num_rx_qs); + if (status) + goto err; + + status = netif_set_real_num_tx_queues(netdev, adapter->num_tx_qs); + if (status) + goto err; + return 0; err: dev_err(&adapter->pdev->dev, "queue_setup failed\n"); return status; } +int be_update_queues(struct be_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int status; + + if (netif_running(netdev)) + be_close(netdev); + + be_cancel_worker(adapter); + + /* If any vectors have been shared with RoCE we cannot re-program + * the MSIx table. + */ + if (!adapter->num_msix_roce_vec) + be_msix_disable(adapter); + + be_clear_queues(adapter); + + if (!msix_enabled(adapter)) { + status = be_msix_enable(adapter); + if (status) + return status; + } + + status = be_setup_queues(adapter); + if (status) + return status; + + be_schedule_worker(adapter); + + if (netif_running(netdev)) + status = be_open(netdev); + + return status; +} + static int be_setup(struct be_adapter *adapter) { struct device *dev = &adapter->pdev->dev; @@ -3163,7 +3210,10 @@ static int be_setup(struct be_adapter *adapter) if (status) goto err; + /* Updating real_num_tx/rx_queues() requires rtnl_lock() */ + rtnl_lock(); status = be_setup_queues(adapter); + rtnl_unlock(); if (status) goto err; @@ -3202,8 +3252,7 @@ static int be_setup(struct be_adapter *adapter) if (!status && be_pause_supported(adapter)) adapter->phy.fc_autoneg = 1; - schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); - adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; + be_schedule_worker(adapter); return 0; err: be_clear(adapter); @@ -3769,8 +3818,6 @@ static const struct net_device_ops be_netdev_ops = { static void be_netdev_init(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); - struct be_eq_obj *eqo; - int i; netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | @@ -3793,9 +3840,6 @@ static void be_netdev_init(struct net_device *netdev) netdev->netdev_ops = &be_netdev_ops; SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); - - for_all_evt_queues(adapter, eqo, i) - netif_napi_add(netdev, &eqo->napi, be_poll, BE_NAPI_WEIGHT); } static void be_unmap_pci_bars(struct be_adapter *adapter)