From 5721f9432de025065b42375f0cbeaf936958b8b6 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Tue, 6 Aug 2013 09:27:21 +0530 Subject: be2net: update driver version Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ethernet/emulex/benet/be.h') diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index c827b1b6b1ce..11c815db5442 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -34,7 +34,7 @@ #include "be_hw.h" #include "be_roce.h" -#define DRV_VER "4.6.62.0u" +#define DRV_VER "4.9.134.0u" #define DRV_NAME "be2net" #define BE_NAME "Emulex BladeEngine2" #define BE3_NAME "Emulex BladeEngine3" -- cgit v1.2.3 From f2f781a759e0471e440668c7c90c03696b73b65e Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Tue, 27 Aug 2013 16:57:30 +0530 Subject: be2net: use EQ_CREATEv2 for SH-R EQ_CREATEv2 explicitly returns the msix-index associated with a EQ. For SH-R this is needed if EQs need to be deleted and re-created without resetting a function. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 1 + drivers/net/ethernet/emulex/benet/be_cmds.c | 47 ++++++++--------------------- drivers/net/ethernet/emulex/benet/be_cmds.h | 5 ++- drivers/net/ethernet/emulex/benet/be_main.c | 4 +-- 4 files changed, 18 insertions(+), 39 deletions(-) (limited to 'drivers/net/ethernet/emulex/benet/be.h') diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 11c815db5442..7c5f9f2c5e03 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -189,6 +189,7 @@ struct be_eq_obj { u32 cur_eqd; /* in usecs */ u8 idx; /* array index */ + u8 msix_idx; u16 tx_budget; u16 spurious_intr; struct napi_struct napi; diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 85923e2d63b9..e69835c6532c 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -678,31 +678,6 @@ static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, } } -/* Converts interrupt delay in microseconds to multiplier value */ -static u32 eq_delay_to_mult(u32 usec_delay) -{ -#define MAX_INTR_RATE 651042 - const u32 round = 10; - u32 multiplier; - - if (usec_delay == 0) - multiplier = 0; - else { - u32 interrupt_rate = 1000000 / usec_delay; - /* Max delay, corresponding to the lowest interrupt rate */ - if (interrupt_rate == 0) - multiplier = 1023; - else { - multiplier = (MAX_INTR_RATE - interrupt_rate) * round; - multiplier /= interrupt_rate; - /* Round the multiplier to the closest value.*/ - multiplier = (multiplier + round/2) / round; - multiplier = min(multiplier, (u32)1023); - } - } - return multiplier; -} - static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter) { struct be_dma_mem *mbox_mem = &adapter->mbox_mem; @@ -790,13 +765,12 @@ int be_cmd_fw_clean(struct be_adapter *adapter) return status; } -int be_cmd_eq_create(struct be_adapter *adapter, - struct be_queue_info *eq, int eq_delay) +int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo) { struct be_mcc_wrb *wrb; struct be_cmd_req_eq_create *req; - struct be_dma_mem *q_mem = &eq->dma_mem; - int status; + struct be_dma_mem *q_mem = &eqo->q.dma_mem; + int status, ver = 0; if (mutex_lock_interruptible(&adapter->mbox_lock)) return -1; @@ -807,15 +781,18 @@ int be_cmd_eq_create(struct be_adapter *adapter, be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_EQ_CREATE, sizeof(*req), wrb, NULL); + /* Support for EQ_CREATEv2 available only SH-R onwards */ + if (!(BEx_chip(adapter) || lancer_chip(adapter))) + ver = 2; + + req->hdr.version = ver; req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); /* 4byte eqe*/ AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); AMAP_SET_BITS(struct amap_eq_context, count, req->context, - __ilog2_u32(eq->len/256)); - AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context, - eq_delay_to_mult(eq_delay)); + __ilog2_u32(eqo->q.len / 256)); be_dws_cpu_to_le(req->context, sizeof(req->context)); be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); @@ -823,8 +800,10 @@ int be_cmd_eq_create(struct be_adapter *adapter, status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); - eq->id = le16_to_cpu(resp->eq_id); - eq->created = true; + eqo->q.id = le16_to_cpu(resp->eq_id); + eqo->msix_idx = + (ver == 2) ? le16_to_cpu(resp->msix_idx) : eqo->idx; + eqo->q.created = true; } mutex_unlock(&adapter->mbox_lock); diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 6237192a55d1..880c85aea6bb 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -307,7 +307,7 @@ struct be_cmd_req_eq_create { struct be_cmd_resp_eq_create { struct be_cmd_resp_hdr resp_hdr; u16 eq_id; /* sword */ - u16 rsvd0; /* sword */ + u16 msix_idx; /* available only in v2 */ } __packed; /******************** Mac query ***************************/ @@ -1851,8 +1851,7 @@ extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, u32 *if_handle, u32 domain); extern int be_cmd_if_destroy(struct be_adapter *adapter, int if_handle, u32 domain); -extern int be_cmd_eq_create(struct be_adapter *adapter, - struct be_queue_info *eq, int eq_delay); +extern int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo); extern int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq, struct be_queue_info *eq, bool no_delay, int num_cqe_dma_coalesce); diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 08f64178c7a1..6f040d851eb2 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1939,7 +1939,7 @@ static int be_evt_queues_create(struct be_adapter *adapter) if (rc) return rc; - rc = be_cmd_eq_create(adapter, eq, eqo->cur_eqd); + rc = be_cmd_eq_create(adapter, eqo); if (rc) return rc; } @@ -2443,7 +2443,7 @@ done: static inline int be_msix_vec_get(struct be_adapter *adapter, struct be_eq_obj *eqo) { - return adapter->msix_entries[eqo->idx].vector; + return adapter->msix_entries[eqo->msix_idx].vector; } static int be_msix_register(struct be_adapter *adapter) -- cgit v1.2.3 From 92bf14abf7a064936b5e6baab30661da86a86e52 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Tue, 27 Aug 2013 16:57:32 +0530 Subject: be2net: refactor be_get_resources() code 1) use be_resources{} struct to query/store HW resource limits 2) The HW queue/resource limits for BE2/BE3 chips are mostly called out in driver as constants. Code to handle this is scattered across various places in be_setup(). Consolidate this code into BEx_get_resources(). For Lancer-R, Skyhawk-R, these limits are queried from FW. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 60 ++++-- drivers/net/ethernet/emulex/benet/be_cmds.c | 51 ++--- drivers/net/ethernet/emulex/benet/be_cmds.h | 8 +- drivers/net/ethernet/emulex/benet/be_main.c | 293 ++++++++++++++-------------- drivers/net/ethernet/emulex/benet/be_roce.c | 2 +- drivers/net/ethernet/emulex/benet/be_roce.h | 4 +- 6 files changed, 229 insertions(+), 189 deletions(-) (limited to 'drivers/net/ethernet/emulex/benet/be.h') diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 7c5f9f2c5e03..8b416355879f 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -101,12 +101,15 @@ static inline char *nic_name(struct pci_dev *pdev) #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 MAX_TX_QS 8 #define MAX_ROCE_EQS 5 #define MAX_MSIX_VECTORS (MAX_RSS_QS + MAX_ROCE_EQS) /* RSS qs + RoCE */ +#define MIN_MSIX_VECTORS 1 #define BE_TX_BUDGET 256 #define BE_NAPI_WEIGHT 64 #define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ @@ -353,6 +356,18 @@ struct phy_info { u32 supported; }; +struct be_resources { + u16 max_vfs; /* Total VFs "really" supported by FW/HW */ + u16 max_mcast_mac; + u16 max_tx_qs; + u16 max_rss_qs; + u16 max_rx_qs; + u16 max_uc_mac; /* Max UC MACs programmable */ + u16 max_vlans; /* Number of vlans supported */ + u16 max_evt_qs; + u32 if_cap_flags; +}; + struct be_adapter { struct pci_dev *pdev; struct net_device *netdev; @@ -370,18 +385,19 @@ struct be_adapter { spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ spinlock_t mcc_cq_lock; - u32 num_msix_vec; - u32 num_evt_qs; - struct be_eq_obj eq_obj[MAX_MSIX_VECTORS]; + u16 cfg_num_qs; /* configured via set-channels */ + u16 num_evt_qs; + u16 num_msix_vec; + struct be_eq_obj eq_obj[MAX_EVT_QS]; struct msix_entry msix_entries[MAX_MSIX_VECTORS]; bool isr_registered; /* TX Rings */ - u32 num_tx_qs; + u16 num_tx_qs; struct be_tx_obj tx_obj[MAX_TX_QS]; /* Rx rings */ - u32 num_rx_qs; + u16 num_rx_qs; struct be_rx_obj rx_obj[MAX_RX_QS]; u32 big_page_size; /* Compounded page size shared by rx wrbs */ @@ -431,8 +447,8 @@ struct be_adapter { u32 flash_status; struct completion flash_compl; - u32 num_vfs; /* Number of VFs provisioned by PF driver */ - u32 dev_num_vfs; /* Number of VFs supported by HW */ + struct be_resources res; /* resources available for the func */ + u16 num_vfs; /* Number of VFs provisioned by PF */ u8 virtfn; struct be_vf_cfg *vf_cfg; bool be3_native; @@ -447,21 +463,13 @@ struct be_adapter { u16 qnq_vid; u32 msg_enable; int be_get_temp_freq; - u16 max_mcast_mac; - u16 max_tx_queues; - u16 max_rss_queues; - u16 max_rx_queues; - u16 max_pmac_cnt; - u16 max_vlans; - u16 max_event_queues; - u32 if_cap_flags; u8 pf_number; u64 rss_flags; }; #define be_physfn(adapter) (!adapter->virtfn) #define sriov_enabled(adapter) (adapter->num_vfs > 0) -#define sriov_want(adapter) (adapter->dev_num_vfs && num_vfs && \ +#define sriov_want(adapter) (be_max_vfs(adapter) && num_vfs && \ be_physfn(adapter)) #define for_all_vfs(adapter, vf_cfg, i) \ for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \ @@ -470,6 +478,26 @@ struct be_adapter { #define ON 1 #define OFF 0 +#define be_max_vlans(adapter) (adapter->res.max_vlans) +#define be_max_uc(adapter) (adapter->res.max_uc_mac) +#define be_max_mc(adapter) (adapter->res.max_mcast_mac) +#define be_max_vfs(adapter) (adapter->res.max_vfs) +#define be_max_rss(adapter) (adapter->res.max_rss_qs) +#define be_max_txqs(adapter) (adapter->res.max_tx_qs) +#define be_max_prio_txqs(adapter) (adapter->res.max_prio_tx_qs) +#define be_max_rxqs(adapter) (adapter->res.max_rx_qs) +#define be_max_eqs(adapter) (adapter->res.max_evt_qs) +#define be_if_cap_flags(adapter) (adapter->res.if_cap_flags) + +static inline u16 be_max_qs(struct be_adapter *adapter) +{ + /* If no RSS, need atleast the one def RXQ */ + u16 num = max_t(u16, be_max_rss(adapter), 1); + + num = min(num, be_max_eqs(adapter)); + return min_t(u16, num, num_online_cpus()); +} + #define lancer_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID3 || \ adapter->pdev->device == OC_DEVICE_ID4) diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index bc6f95814998..5458a4357ae0 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1776,8 +1776,7 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) */ req->if_flags_mask |= cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS & - adapter->if_cap_flags); - + be_if_cap_flags(adapter)); req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev)); netdev_for_each_mc_addr(ha, adapter->netdev) memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN); @@ -3103,8 +3102,26 @@ static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf, return NULL; } +static void be_copy_nic_desc(struct be_resources *res, + struct be_nic_res_desc *desc) +{ + res->max_uc_mac = le16_to_cpu(desc->unicast_mac_count); + res->max_vlans = le16_to_cpu(desc->vlan_count); + res->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count); + res->max_tx_qs = le16_to_cpu(desc->txq_count); + res->max_rss_qs = le16_to_cpu(desc->rssq_count); + res->max_rx_qs = le16_to_cpu(desc->rq_count); + res->max_evt_qs = le16_to_cpu(desc->eq_count); + /* Clear flags that driver is not interested in */ + res->if_cap_flags = le32_to_cpu(desc->cap_flags) & + BE_IF_CAP_FLAGS_WANT; + /* Need 1 RXQ as the default RXQ */ + if (res->max_rss_qs && res->max_rss_qs == res->max_rx_qs) + res->max_rss_qs -= 1; +} + /* Uses Mbox */ -int be_cmd_get_func_config(struct be_adapter *adapter) +int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res) { struct be_mcc_wrb *wrb; struct be_cmd_req_get_func_config *req; @@ -3152,18 +3169,7 @@ int be_cmd_get_func_config(struct be_adapter *adapter) } adapter->pf_number = desc->pf_num; - adapter->max_pmac_cnt = le16_to_cpu(desc->unicast_mac_count); - adapter->max_vlans = le16_to_cpu(desc->vlan_count); - adapter->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count); - adapter->max_tx_queues = le16_to_cpu(desc->txq_count); - adapter->max_rss_queues = le16_to_cpu(desc->rssq_count); - adapter->max_rx_queues = le16_to_cpu(desc->rq_count); - - adapter->max_event_queues = le16_to_cpu(desc->eq_count); - adapter->if_cap_flags = le32_to_cpu(desc->cap_flags); - - /* Clear flags that driver is not interested in */ - adapter->if_cap_flags &= BE_IF_CAP_FLAGS_WANT; + be_copy_nic_desc(res, desc); } err: mutex_unlock(&adapter->mbox_lock); @@ -3234,8 +3240,8 @@ err: } /* Uses sync mcc, if MCCQ is already created otherwise mbox */ -int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags, - u16 *txq_count, u8 domain) +int be_cmd_get_profile_config(struct be_adapter *adapter, + struct be_resources *res, u8 domain) { struct be_cmd_resp_get_profile_config *resp; struct be_pcie_res_desc *pcie; @@ -3264,15 +3270,12 @@ int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags, pcie = be_get_pcie_desc(adapter->pdev->devfn, resp->func_param, desc_count); if (pcie) - adapter->dev_num_vfs = le16_to_cpu(pcie->num_vfs); + res->max_vfs = le16_to_cpu(pcie->num_vfs); nic = be_get_nic_desc(resp->func_param, desc_count); - if (nic) { - if (cap_flags) - *cap_flags = le32_to_cpu(nic->cap_flags); - if (txq_count) - *txq_count = le16_to_cpu(nic->txq_count); - } + if (nic) + be_copy_nic_desc(res, nic); + err: if (cmd.va) pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 8ebed17b57f1..52f3d4ca0056 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -1980,10 +1980,10 @@ extern int lancer_initiate_dump(struct be_adapter *adapter); extern bool dump_present(struct be_adapter *adapter); extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter); extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name); -extern int be_cmd_get_func_config(struct be_adapter *adapter); -extern int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags, - u16 *txq_count, u8 domain); - +int be_cmd_get_func_config(struct be_adapter *adapter, + struct be_resources *res); +int be_cmd_get_profile_config(struct be_adapter *adapter, + struct be_resources *res, u8 domain); extern int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps, u8 domain); extern int be_cmd_get_if_id(struct be_adapter *adapter, diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 6f040d851eb2..d34ea98ea2c4 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1001,7 +1001,7 @@ static int be_vid_config(struct be_adapter *adapter) if (adapter->promiscuous) return 0; - if (adapter->vlans_added > adapter->max_vlans) + if (adapter->vlans_added > be_max_vlans(adapter)) goto set_vlan_promisc; /* Construct VLAN Table to give to HW */ @@ -1042,7 +1042,7 @@ static int be_vlan_add_vid(struct net_device *netdev, __be16 proto, u16 vid) goto ret; adapter->vlan_tag[vid] = 1; - if (adapter->vlans_added <= (adapter->max_vlans + 1)) + if (adapter->vlans_added <= (be_max_vlans(adapter) + 1)) status = be_vid_config(adapter); if (!status) @@ -1068,7 +1068,7 @@ static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid) goto ret; adapter->vlan_tag[vid] = 0; - if (adapter->vlans_added <= adapter->max_vlans) + if (adapter->vlans_added <= be_max_vlans(adapter)) status = be_vid_config(adapter); if (!status) @@ -1101,7 +1101,7 @@ static void be_set_rx_mode(struct net_device *netdev) /* Enable multicast promisc if num configured exceeds what we support */ if (netdev->flags & IFF_ALLMULTI || - netdev_mc_count(netdev) > adapter->max_mcast_mac) { + netdev_mc_count(netdev) > be_max_mc(adapter)) { be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); goto done; } @@ -1115,7 +1115,7 @@ static void be_set_rx_mode(struct net_device *netdev) adapter->pmac_id[i], 0); } - if (netdev_uc_count(netdev) > adapter->max_pmac_cnt) { + if (netdev_uc_count(netdev) > be_max_uc(adapter)) { be_cmd_rx_filter(adapter, IFF_PROMISC, ON); adapter->promiscuous = true; goto done; @@ -1924,7 +1924,8 @@ static int be_evt_queues_create(struct be_adapter *adapter) struct be_eq_obj *eqo; int i, rc; - adapter->num_evt_qs = num_irqs(adapter); + adapter->num_evt_qs = min_t(u16, num_irqs(adapter), + adapter->cfg_num_qs); for_all_evt_queues(adapter, eqo, i) { eqo->adapter = adapter; @@ -2013,25 +2014,13 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) } } -static int be_num_txqs_want(struct be_adapter *adapter) -{ - if ((!lancer_chip(adapter) && sriov_want(adapter)) || - be_is_mc(adapter) || - (!lancer_chip(adapter) && !be_physfn(adapter)) || - BE2_chip(adapter)) - return 1; - else - return adapter->max_tx_queues; -} - static int be_tx_cqs_create(struct be_adapter *adapter) { struct be_queue_info *cq, *eq; - int status; struct be_tx_obj *txo; - u8 i; + int status, i; - adapter->num_tx_qs = be_num_txqs_want(adapter); + 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, @@ -2098,11 +2087,15 @@ static int be_rx_cqs_create(struct be_adapter *adapter) struct be_rx_obj *rxo; int rc, i; - /* We'll create as many RSS rings as there are irqs. - * But when there's only one irq there's no use creating RSS rings + /* We can create as many RSS rings as there are EQs. */ + adapter->num_rx_qs = adapter->num_evt_qs; + + /* We'll use RSS only if atleast 2 RSS rings are supported. + * When RSS is used, we'll need a default RXQ for non-IP traffic. */ - adapter->num_rx_qs = (num_irqs(adapter) > 1) ? - num_irqs(adapter) + 1 : 1; + 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, @@ -2375,35 +2368,20 @@ static void be_msix_disable(struct be_adapter *adapter) } } -static uint be_num_rss_want(struct be_adapter *adapter) -{ - u32 num = 0; - - if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && - (lancer_chip(adapter) || - (!sriov_want(adapter) && be_physfn(adapter)))) { - num = adapter->max_rss_queues; - num = min_t(u32, num, (u32)netif_get_num_default_rss_queues()); - } - return num; -} - static int be_msix_enable(struct be_adapter *adapter) { -#define BE_MIN_MSIX_VECTORS 1 - int i, status, num_vec, num_roce_vec = 0; + int i, status, num_vec; struct device *dev = &adapter->pdev->dev; - /* If RSS queues are not used, need a vec for default RX Q */ - num_vec = min(be_num_rss_want(adapter), num_online_cpus()); - if (be_roce_supported(adapter)) { - num_roce_vec = min_t(u32, MAX_ROCE_MSIX_VECTORS, - (num_online_cpus() + 1)); - num_roce_vec = min(num_roce_vec, MAX_ROCE_EQS); - num_vec += num_roce_vec; - num_vec = min(num_vec, MAX_MSIX_VECTORS); - } - num_vec = max(num_vec, BE_MIN_MSIX_VECTORS); + /* If RoCE is supported, program the max number of NIC vectors that + * may be configured via set-channels, along with vectors needed for + * RoCe. Else, just program the number we'll use initially. + */ + if (be_roce_supported(adapter)) + num_vec = min_t(int, 2 * be_max_eqs(adapter), + 2 * num_online_cpus()); + else + num_vec = adapter->cfg_num_qs; for (i = 0; i < num_vec; i++) adapter->msix_entries[i].entry = i; @@ -2411,7 +2389,7 @@ static int be_msix_enable(struct be_adapter *adapter) status = pci_enable_msix(adapter->pdev, adapter->msix_entries, num_vec); if (status == 0) { goto done; - } else if (status >= BE_MIN_MSIX_VECTORS) { + } else if (status >= MIN_MSIX_VECTORS) { num_vec = status; status = pci_enable_msix(adapter->pdev, adapter->msix_entries, num_vec); @@ -2420,23 +2398,22 @@ static int be_msix_enable(struct be_adapter *adapter) } dev_warn(dev, "MSIx enable failed\n"); + /* INTx is not supported in VFs, so fail probe if enable_msix fails */ if (!be_physfn(adapter)) return status; return 0; done: - if (be_roce_supported(adapter)) { - if (num_vec > num_roce_vec) { - adapter->num_msix_vec = num_vec - num_roce_vec; - adapter->num_msix_roce_vec = - num_vec - adapter->num_msix_vec; - } else { - adapter->num_msix_vec = num_vec; - adapter->num_msix_roce_vec = 0; - } - } else - adapter->num_msix_vec = num_vec; - dev_info(dev, "enabled %d MSI-x vector(s)\n", adapter->num_msix_vec); + if (be_roce_supported(adapter) && num_vec > MIN_MSIX_VECTORS) { + adapter->num_msix_roce_vec = num_vec / 2; + dev_info(dev, "enabled %d MSI-x vector(s) for RoCE\n", + adapter->num_msix_roce_vec); + } + + adapter->num_msix_vec = num_vec - adapter->num_msix_roce_vec; + + dev_info(dev, "enabled %d MSI-x vector(s) for NIC\n", + adapter->num_msix_vec); return 0; } @@ -2829,6 +2806,7 @@ static int be_clear(struct be_adapter *adapter) static int be_vfs_if_create(struct be_adapter *adapter) { + struct be_resources res = {0}; struct be_vf_cfg *vf_cfg; u32 cap_flags, en_flags, vf; int status; @@ -2837,9 +2815,12 @@ static int be_vfs_if_create(struct be_adapter *adapter) BE_IF_FLAGS_MULTICAST; for_all_vfs(adapter, vf_cfg, vf) { - if (!BE3_chip(adapter)) - be_cmd_get_profile_config(adapter, &cap_flags, - NULL, vf + 1); + if (!BE3_chip(adapter)) { + status = be_cmd_get_profile_config(adapter, &res, + vf + 1); + if (!status) + cap_flags = res.if_cap_flags; + } /* If a FW profile exists, then cap_flags are updated */ en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED | @@ -2885,10 +2866,10 @@ static int be_vf_setup(struct be_adapter *adapter) dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs); adapter->num_vfs = old_vfs; } else { - if (num_vfs > adapter->dev_num_vfs) + if (num_vfs > be_max_vfs(adapter)) dev_info(dev, "Device supports %d VFs and not %d\n", - adapter->dev_num_vfs, num_vfs); - adapter->num_vfs = min_t(u16, num_vfs, adapter->dev_num_vfs); + be_max_vfs(adapter), num_vfs); + adapter->num_vfs = min_t(u16, num_vfs, be_max_vfs(adapter)); if (!adapter->num_vfs) return 0; } @@ -2967,6 +2948,51 @@ err: return status; } +/* On BE2/BE3 FW does not suggest the supported limits */ +static void BEx_get_resources(struct be_adapter *adapter, + struct be_resources *res) +{ + struct pci_dev *pdev = adapter->pdev; + bool use_sriov = false; + + if (BE3_chip(adapter) && be_physfn(adapter)) { + int max_vfs; + + max_vfs = pci_sriov_get_totalvfs(pdev); + res->max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0; + use_sriov = res->max_vfs && num_vfs; + } + + if (be_physfn(adapter)) + res->max_uc_mac = BE_UC_PMAC_COUNT; + else + res->max_uc_mac = BE_VF_UC_PMAC_COUNT; + + if (adapter->function_mode & FLEX10_MODE) + res->max_vlans = BE_NUM_VLANS_SUPPORTED/8; + else + res->max_vlans = BE_NUM_VLANS_SUPPORTED; + res->max_mcast_mac = BE_MAX_MC; + + if (BE2_chip(adapter) || use_sriov || be_is_mc(adapter) || + !be_physfn(adapter)) + res->max_tx_qs = 1; + else + res->max_tx_qs = BE3_MAX_TX_QS; + + if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && + !use_sriov && be_physfn(adapter)) + res->max_rss_qs = (adapter->be3_native) ? + 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->if_cap_flags = BE_IF_CAP_FLAGS_WANT; + if (!(adapter->function_caps & BE_FUNCTION_CAPS_RSS)) + res->if_cap_flags &= ~BE_IF_FLAGS_RSS; +} + static void be_setup_init(struct be_adapter *adapter) { adapter->vlan_prio_bmap = 0xff; @@ -2980,76 +3006,56 @@ static void be_setup_init(struct be_adapter *adapter) adapter->cmd_privileges = MIN_PRIVILEGES; } -static void be_get_resources(struct be_adapter *adapter) +static int be_get_resources(struct be_adapter *adapter) { - u16 dev_num_vfs; - int pos, status; - bool profile_present = false; - u16 txq_count = 0; + struct device *dev = &adapter->pdev->dev; + struct be_resources res = {0}; + int status; - if (!BEx_chip(adapter)) { - status = be_cmd_get_func_config(adapter); - if (!status) - profile_present = true; - } else if (BE3_chip(adapter) && be_physfn(adapter)) { - be_cmd_get_profile_config(adapter, NULL, &txq_count, 0); + if (BEx_chip(adapter)) { + BEx_get_resources(adapter, &res); + adapter->res = res; } - if (profile_present) { - adapter->max_tx_queues = min_t(u16, adapter->max_tx_queues, - MAX_TX_QS); - adapter->max_rss_queues = min_t(u16, adapter->max_rss_queues, - BE3_MAX_RSS_QS); - adapter->max_event_queues = min_t(u16, - adapter->max_event_queues, - BE3_MAX_RSS_QS); - - if (adapter->max_rss_queues && - adapter->max_rss_queues == adapter->max_rx_queues) - adapter->max_rss_queues -= 1; - - if (adapter->max_event_queues < adapter->max_rss_queues) - adapter->max_rss_queues = adapter->max_event_queues; - - } else { - if (be_physfn(adapter)) - adapter->max_pmac_cnt = BE_UC_PMAC_COUNT; - else - adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT; + /* For BE3 only check if FW suggests a different max-txqs value */ + if (BE3_chip(adapter)) { + status = be_cmd_get_profile_config(adapter, &res, 0); + if (!status && res.max_tx_qs) + adapter->res.max_tx_qs = + min(adapter->res.max_tx_qs, res.max_tx_qs); + } - if (adapter->function_mode & FLEX10_MODE) - adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8; - else - adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; + /* For Lancer, SH etc read per-function resource limits from FW. + * GET_FUNC_CONFIG returns per function guaranteed limits. + * GET_PROFILE_CONFIG returns PCI-E related limits PF-pool limits + */ + if (!BEx_chip(adapter)) { + status = be_cmd_get_func_config(adapter, &res); + if (status) + return status; - adapter->max_mcast_mac = BE_MAX_MC; - adapter->max_tx_queues = txq_count ? txq_count : MAX_TX_QS; - adapter->max_tx_queues = min_t(u16, adapter->max_tx_queues, - MAX_TX_QS); - adapter->max_rss_queues = (adapter->be3_native) ? - BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; - adapter->max_event_queues = BE3_MAX_RSS_QS; + /* If RoCE may be enabled stash away half the EQs for RoCE */ + if (be_roce_supported(adapter)) + res.max_evt_qs /= 2; + adapter->res = res; - adapter->if_cap_flags = BE_IF_FLAGS_UNTAGGED | - BE_IF_FLAGS_BROADCAST | - BE_IF_FLAGS_MULTICAST | - BE_IF_FLAGS_PASS_L3L4_ERRORS | - BE_IF_FLAGS_MCAST_PROMISCUOUS | - BE_IF_FLAGS_VLAN_PROMISCUOUS | - BE_IF_FLAGS_PROMISCUOUS; + if (be_physfn(adapter)) { + status = be_cmd_get_profile_config(adapter, &res, 0); + if (status) + return status; + adapter->res.max_vfs = res.max_vfs; + } - if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) - adapter->if_cap_flags |= BE_IF_FLAGS_RSS; + dev_info(dev, "Max: txqs %d, rxqs %d, rss %d, eqs %d, vfs %d\n", + be_max_txqs(adapter), be_max_rxqs(adapter), + be_max_rss(adapter), be_max_eqs(adapter), + be_max_vfs(adapter)); + dev_info(dev, "Max: uc-macs %d, mc-macs %d, vlans %d\n", + be_max_uc(adapter), be_max_mc(adapter), + be_max_vlans(adapter)); } - pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV); - if (pos) { - pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF, - &dev_num_vfs); - if (BE3_chip(adapter)) - dev_num_vfs = min_t(u16, dev_num_vfs, MAX_VFS); - adapter->dev_num_vfs = dev_num_vfs; - } + return 0; } /* Routine to query per function resource limits */ @@ -3062,20 +3068,22 @@ static int be_get_config(struct be_adapter *adapter) &adapter->function_caps, &adapter->asic_rev); if (status) - goto err; + return status; - be_get_resources(adapter); + status = be_get_resources(adapter); + if (status) + return status; /* primary mac needs 1 pmac entry */ - adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1, - sizeof(u32), GFP_KERNEL); - if (!adapter->pmac_id) { - status = -ENOMEM; - goto err; - } + adapter->pmac_id = kcalloc(be_max_uc(adapter) + 1, sizeof(u32), + GFP_KERNEL); + if (!adapter->pmac_id) + return -ENOMEM; -err: - return status; + /* Sanitize cfg_num_qs based on HW and platform limits */ + adapter->cfg_num_qs = min(adapter->cfg_num_qs, be_max_qs(adapter)); + + return 0; } static int be_mac_setup(struct be_adapter *adapter) @@ -3151,8 +3159,8 @@ static int be_setup(struct be_adapter *adapter) BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS; if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) en_flags |= BE_IF_FLAGS_RSS; - en_flags = en_flags & adapter->if_cap_flags; - status = be_cmd_if_create(adapter, adapter->if_cap_flags, en_flags, + en_flags = en_flags & be_if_cap_flags(adapter); + status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags, &adapter->if_handle, 0); if (status != 0) goto err; @@ -3178,8 +3186,8 @@ static int be_setup(struct be_adapter *adapter) be_cmd_set_flow_control(adapter, adapter->tx_fc, adapter->rx_fc); - if (be_physfn(adapter)) { - if (adapter->dev_num_vfs) + if (be_physfn(adapter) && num_vfs) { + if (be_max_vfs(adapter)) be_vf_setup(adapter); else dev_warn(dev, "device doesn't support SRIOV\n"); @@ -4045,6 +4053,7 @@ static int be_get_initial_config(struct be_adapter *adapter) level = be_get_fw_log_level(adapter); adapter->msg_enable = level <= FW_LOG_LEVEL_DEFAULT ? NETIF_MSG_HW : 0; + adapter->cfg_num_qs = netif_get_num_default_rss_queues(); return 0; } diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c index 645e846daa5c..9cd5415fe017 100644 --- a/drivers/net/ethernet/emulex/benet/be_roce.c +++ b/drivers/net/ethernet/emulex/benet/be_roce.c @@ -60,7 +60,7 @@ static void _be_roce_dev_add(struct be_adapter *adapter) */ num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec; dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX; - dev_info.msix.num_vectors = min(num_vec, MAX_ROCE_MSIX_VECTORS); + dev_info.msix.num_vectors = min(num_vec, MAX_MSIX_VECTORS); /* provide start index of the vector, * so in case of linear usage, * it can use the base as starting point. diff --git a/drivers/net/ethernet/emulex/benet/be_roce.h b/drivers/net/ethernet/emulex/benet/be_roce.h index 276572998463..2cd1129e19af 100644 --- a/drivers/net/ethernet/emulex/benet/be_roce.h +++ b/drivers/net/ethernet/emulex/benet/be_roce.h @@ -29,7 +29,7 @@ enum be_interrupt_mode { BE_INTERRUPT_MODE_MSI = 2, }; -#define MAX_ROCE_MSIX_VECTORS 16 +#define MAX_MSIX_VECTORS 32 struct be_dev_info { u8 __iomem *db; u64 unmapped_db; @@ -45,7 +45,7 @@ struct be_dev_info { struct { int num_vectors; int start_vector; - u32 vector_list[MAX_ROCE_MSIX_VECTORS]; + u32 vector_list[MAX_MSIX_VECTORS]; } msix; }; -- cgit v1.2.3 From 68d7bdcb4c00ec799ad949f4b4c50985539710e2 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Tue, 27 Aug 2013 16:57:35 +0530 Subject: be2net: implement ethtool set/get_channel hooks Support is provided only for combined channels. When SR-IOV is not enabled, BE3 supports upto 16 channels and Lancer-R/SH-R support upto 32 channels. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 17 +++-- drivers/net/ethernet/emulex/benet/be_ethtool.c | 25 +++++++ drivers/net/ethernet/emulex/benet/be_main.c | 94 +++++++++++++++++++------- 3 files changed, 104 insertions(+), 32 deletions(-) (limited to 'drivers/net/ethernet/emulex/benet/be.h') 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) -- cgit v1.2.3