|
@@ -30,6 +30,9 @@ MODULE_DESCRIPTION(DRV_DESC " " DRV_VER);
|
|
MODULE_AUTHOR("Emulex Corporation");
|
|
MODULE_AUTHOR("Emulex Corporation");
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_LICENSE("GPL");
|
|
|
|
|
|
|
|
+/* num_vfs module param is obsolete.
|
|
|
|
+ * Use sysfs method to enable/disable VFs.
|
|
|
|
+ */
|
|
static unsigned int num_vfs;
|
|
static unsigned int num_vfs;
|
|
module_param(num_vfs, uint, S_IRUGO);
|
|
module_param(num_vfs, uint, S_IRUGO);
|
|
MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize");
|
|
MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize");
|
|
@@ -2454,13 +2457,19 @@ static int be_rx_cqs_create(struct be_adapter *adapter)
|
|
int rc, i;
|
|
int rc, i;
|
|
|
|
|
|
/* We can create as many RSS rings as there are EQs. */
|
|
/* We can create as many RSS rings as there are EQs. */
|
|
- adapter->num_rx_qs = adapter->num_evt_qs;
|
|
|
|
|
|
+ adapter->num_rss_qs = adapter->num_evt_qs;
|
|
|
|
+
|
|
|
|
+ /* We'll use RSS only if atleast 2 RSS rings are supported. */
|
|
|
|
+ if (adapter->num_rss_qs <= 1)
|
|
|
|
+ adapter->num_rss_qs = 0;
|
|
|
|
|
|
- /* 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 = adapter->num_rss_qs + adapter->need_def_rxq;
|
|
|
|
+
|
|
|
|
+ /* When the interface is not capable of RSS rings (and there is no
|
|
|
|
+ * need to create a default RXQ) we'll still need one RXQ
|
|
*/
|
|
*/
|
|
- if (adapter->num_rx_qs > 1)
|
|
|
|
- adapter->num_rx_qs++;
|
|
|
|
|
|
+ if (adapter->num_rx_qs == 0)
|
|
|
|
+ adapter->num_rx_qs = 1;
|
|
|
|
|
|
adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
|
|
adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
|
|
for_all_rx_queues(adapter, rxo, i) {
|
|
for_all_rx_queues(adapter, rxo, i) {
|
|
@@ -2479,8 +2488,7 @@ static int be_rx_cqs_create(struct be_adapter *adapter)
|
|
}
|
|
}
|
|
|
|
|
|
dev_info(&adapter->pdev->dev,
|
|
dev_info(&adapter->pdev->dev,
|
|
- "created %d RSS queue(s) and 1 default RX queue\n",
|
|
|
|
- adapter->num_rx_qs - 1);
|
|
|
|
|
|
+ "created %d RX queue(s)\n", adapter->num_rx_qs);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3110,12 +3118,14 @@ static int be_rx_qs_create(struct be_adapter *adapter)
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|
|
- /* The FW would like the default RXQ to be created first */
|
|
|
|
- rxo = default_rxo(adapter);
|
|
|
|
- rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id, rx_frag_size,
|
|
|
|
- adapter->if_handle, false, &rxo->rss_id);
|
|
|
|
- if (rc)
|
|
|
|
- return rc;
|
|
|
|
|
|
+ if (adapter->need_def_rxq || !adapter->num_rss_qs) {
|
|
|
|
+ rxo = default_rxo(adapter);
|
|
|
|
+ rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id,
|
|
|
|
+ rx_frag_size, adapter->if_handle,
|
|
|
|
+ false, &rxo->rss_id);
|
|
|
|
+ if (rc)
|
|
|
|
+ return rc;
|
|
|
|
+ }
|
|
|
|
|
|
for_all_rss_queues(adapter, rxo, i) {
|
|
for_all_rss_queues(adapter, rxo, i) {
|
|
rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id,
|
|
rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id,
|
|
@@ -3126,8 +3136,7 @@ static int be_rx_qs_create(struct be_adapter *adapter)
|
|
}
|
|
}
|
|
|
|
|
|
if (be_multi_rxq(adapter)) {
|
|
if (be_multi_rxq(adapter)) {
|
|
- for (j = 0; j < RSS_INDIR_TABLE_LEN;
|
|
|
|
- j += adapter->num_rx_qs - 1) {
|
|
|
|
|
|
+ for (j = 0; j < RSS_INDIR_TABLE_LEN; j += adapter->num_rss_qs) {
|
|
for_all_rss_queues(adapter, rxo, i) {
|
|
for_all_rss_queues(adapter, rxo, i) {
|
|
if ((j + i) >= RSS_INDIR_TABLE_LEN)
|
|
if ((j + i) >= RSS_INDIR_TABLE_LEN)
|
|
break;
|
|
break;
|
|
@@ -3402,8 +3411,39 @@ static void be_disable_vxlan_offloads(struct be_adapter *adapter)
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+static u16 be_calculate_vf_qs(struct be_adapter *adapter, u16 num_vfs)
|
|
|
|
+{
|
|
|
|
+ struct be_resources res = adapter->pool_res;
|
|
|
|
+ u16 num_vf_qs = 1;
|
|
|
|
+
|
|
|
|
+ /* Distribute the queue resources equally among the PF and it's VFs
|
|
|
|
+ * Do not distribute queue resources in multi-channel configuration.
|
|
|
|
+ */
|
|
|
|
+ if (num_vfs && !be_is_mc(adapter)) {
|
|
|
|
+ /* If number of VFs requested is 8 less than max supported,
|
|
|
|
+ * assign 8 queue pairs to the PF and divide the remaining
|
|
|
|
+ * resources evenly among the VFs
|
|
|
|
+ */
|
|
|
|
+ if (num_vfs < (be_max_vfs(adapter) - 8))
|
|
|
|
+ num_vf_qs = (res.max_rss_qs - 8) / num_vfs;
|
|
|
|
+ else
|
|
|
|
+ num_vf_qs = res.max_rss_qs / num_vfs;
|
|
|
|
+
|
|
|
|
+ /* Skyhawk-R chip supports only MAX_RSS_IFACES RSS capable
|
|
|
|
+ * interfaces per port. Provide RSS on VFs, only if number
|
|
|
|
+ * of VFs requested is less than MAX_RSS_IFACES limit.
|
|
|
|
+ */
|
|
|
|
+ if (num_vfs >= MAX_RSS_IFACES)
|
|
|
|
+ num_vf_qs = 1;
|
|
|
|
+ }
|
|
|
|
+ return num_vf_qs;
|
|
|
|
+}
|
|
|
|
+
|
|
static int be_clear(struct be_adapter *adapter)
|
|
static int be_clear(struct be_adapter *adapter)
|
|
{
|
|
{
|
|
|
|
+ struct pci_dev *pdev = adapter->pdev;
|
|
|
|
+ u16 num_vf_qs;
|
|
|
|
+
|
|
be_cancel_worker(adapter);
|
|
be_cancel_worker(adapter);
|
|
|
|
|
|
if (sriov_enabled(adapter))
|
|
if (sriov_enabled(adapter))
|
|
@@ -3412,9 +3452,14 @@ static int be_clear(struct be_adapter *adapter)
|
|
/* Re-configure FW to distribute resources evenly across max-supported
|
|
/* Re-configure FW to distribute resources evenly across max-supported
|
|
* number of VFs, only when VFs are not already enabled.
|
|
* number of VFs, only when VFs are not already enabled.
|
|
*/
|
|
*/
|
|
- if (be_physfn(adapter) && !pci_vfs_assigned(adapter->pdev))
|
|
|
|
|
|
+ if (skyhawk_chip(adapter) && be_physfn(adapter) &&
|
|
|
|
+ !pci_vfs_assigned(pdev)) {
|
|
|
|
+ num_vf_qs = be_calculate_vf_qs(adapter,
|
|
|
|
+ pci_sriov_get_totalvfs(pdev));
|
|
be_cmd_set_sriov_config(adapter, adapter->pool_res,
|
|
be_cmd_set_sriov_config(adapter, adapter->pool_res,
|
|
- pci_sriov_get_totalvfs(adapter->pdev));
|
|
|
|
|
|
+ pci_sriov_get_totalvfs(pdev),
|
|
|
|
+ num_vf_qs);
|
|
|
|
+ }
|
|
|
|
|
|
#ifdef CONFIG_BE2NET_VXLAN
|
|
#ifdef CONFIG_BE2NET_VXLAN
|
|
be_disable_vxlan_offloads(adapter);
|
|
be_disable_vxlan_offloads(adapter);
|
|
@@ -3439,7 +3484,7 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle,
|
|
|
|
|
|
en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
|
|
en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
|
|
BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |
|
|
BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |
|
|
- BE_IF_FLAGS_RSS;
|
|
|
|
|
|
+ BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
|
|
|
|
|
|
en_flags &= cap_flags;
|
|
en_flags &= cap_flags;
|
|
|
|
|
|
@@ -3463,6 +3508,7 @@ static int be_vfs_if_create(struct be_adapter *adapter)
|
|
for_all_vfs(adapter, vf_cfg, vf) {
|
|
for_all_vfs(adapter, vf_cfg, vf) {
|
|
if (!BE3_chip(adapter)) {
|
|
if (!BE3_chip(adapter)) {
|
|
status = be_cmd_get_profile_config(adapter, &res,
|
|
status = be_cmd_get_profile_config(adapter, &res,
|
|
|
|
+ RESOURCE_LIMITS,
|
|
vf + 1);
|
|
vf + 1);
|
|
if (!status)
|
|
if (!status)
|
|
cap_flags = res.if_cap_flags;
|
|
cap_flags = res.if_cap_flags;
|
|
@@ -3629,7 +3675,8 @@ static void BEx_get_resources(struct be_adapter *adapter,
|
|
/* On a SuperNIC profile, the driver needs to use the
|
|
/* On a SuperNIC profile, the driver needs to use the
|
|
* GET_PROFILE_CONFIG cmd to query the per-function TXQ limits
|
|
* GET_PROFILE_CONFIG cmd to query the per-function TXQ limits
|
|
*/
|
|
*/
|
|
- be_cmd_get_profile_config(adapter, &super_nic_res, 0);
|
|
|
|
|
|
+ be_cmd_get_profile_config(adapter, &super_nic_res,
|
|
|
|
+ RESOURCE_LIMITS, 0);
|
|
/* Some old versions of BE3 FW don't report max_tx_qs value */
|
|
/* Some old versions of BE3 FW don't report max_tx_qs value */
|
|
res->max_tx_qs = super_nic_res.max_tx_qs ? : BE3_MAX_TX_QS;
|
|
res->max_tx_qs = super_nic_res.max_tx_qs ? : BE3_MAX_TX_QS;
|
|
} else {
|
|
} else {
|
|
@@ -3649,6 +3696,7 @@ static void BEx_get_resources(struct be_adapter *adapter,
|
|
res->max_evt_qs = 1;
|
|
res->max_evt_qs = 1;
|
|
|
|
|
|
res->if_cap_flags = BE_IF_CAP_FLAGS_WANT;
|
|
res->if_cap_flags = BE_IF_CAP_FLAGS_WANT;
|
|
|
|
+ res->if_cap_flags &= ~BE_IF_FLAGS_DEFQ_RSS;
|
|
if (!(adapter->function_caps & BE_FUNCTION_CAPS_RSS))
|
|
if (!(adapter->function_caps & BE_FUNCTION_CAPS_RSS))
|
|
res->if_cap_flags &= ~BE_IF_FLAGS_RSS;
|
|
res->if_cap_flags &= ~BE_IF_FLAGS_RSS;
|
|
}
|
|
}
|
|
@@ -3668,13 +3716,12 @@ static void be_setup_init(struct be_adapter *adapter)
|
|
|
|
|
|
static int be_get_sriov_config(struct be_adapter *adapter)
|
|
static int be_get_sriov_config(struct be_adapter *adapter)
|
|
{
|
|
{
|
|
- struct device *dev = &adapter->pdev->dev;
|
|
|
|
struct be_resources res = {0};
|
|
struct be_resources res = {0};
|
|
int max_vfs, old_vfs;
|
|
int max_vfs, old_vfs;
|
|
|
|
|
|
- /* Some old versions of BE3 FW don't report max_vfs value */
|
|
|
|
- be_cmd_get_profile_config(adapter, &res, 0);
|
|
|
|
|
|
+ be_cmd_get_profile_config(adapter, &res, RESOURCE_LIMITS, 0);
|
|
|
|
|
|
|
|
+ /* Some old versions of BE3 FW don't report max_vfs value */
|
|
if (BE3_chip(adapter) && !res.max_vfs) {
|
|
if (BE3_chip(adapter) && !res.max_vfs) {
|
|
max_vfs = pci_sriov_get_totalvfs(adapter->pdev);
|
|
max_vfs = pci_sriov_get_totalvfs(adapter->pdev);
|
|
res.max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0;
|
|
res.max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0;
|
|
@@ -3682,35 +3729,49 @@ static int be_get_sriov_config(struct be_adapter *adapter)
|
|
|
|
|
|
adapter->pool_res = res;
|
|
adapter->pool_res = res;
|
|
|
|
|
|
- if (!be_max_vfs(adapter)) {
|
|
|
|
- if (num_vfs)
|
|
|
|
- dev_warn(dev, "SRIOV is disabled. Ignoring num_vfs\n");
|
|
|
|
- adapter->num_vfs = 0;
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pci_sriov_set_totalvfs(adapter->pdev, be_max_vfs(adapter));
|
|
|
|
-
|
|
|
|
- /* validate num_vfs module param */
|
|
|
|
|
|
+ /* If during previous unload of the driver, the VFs were not disabled,
|
|
|
|
+ * then we cannot rely on the PF POOL limits for the TotalVFs value.
|
|
|
|
+ * Instead use the TotalVFs value stored in the pci-dev struct.
|
|
|
|
+ */
|
|
old_vfs = pci_num_vf(adapter->pdev);
|
|
old_vfs = pci_num_vf(adapter->pdev);
|
|
if (old_vfs) {
|
|
if (old_vfs) {
|
|
- dev_info(dev, "%d VFs are already enabled\n", old_vfs);
|
|
|
|
- if (old_vfs != num_vfs)
|
|
|
|
- dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs);
|
|
|
|
|
|
+ dev_info(&adapter->pdev->dev, "%d VFs are already enabled\n",
|
|
|
|
+ old_vfs);
|
|
|
|
+
|
|
|
|
+ adapter->pool_res.max_vfs =
|
|
|
|
+ pci_sriov_get_totalvfs(adapter->pdev);
|
|
adapter->num_vfs = old_vfs;
|
|
adapter->num_vfs = old_vfs;
|
|
- } else {
|
|
|
|
- if (num_vfs > be_max_vfs(adapter)) {
|
|
|
|
- dev_info(dev, "Resources unavailable to init %d VFs\n",
|
|
|
|
- num_vfs);
|
|
|
|
- dev_info(dev, "Limiting to %d VFs\n",
|
|
|
|
- be_max_vfs(adapter));
|
|
|
|
- }
|
|
|
|
- adapter->num_vfs = min_t(u16, num_vfs, be_max_vfs(adapter));
|
|
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void be_alloc_sriov_res(struct be_adapter *adapter)
|
|
|
|
+{
|
|
|
|
+ int old_vfs = pci_num_vf(adapter->pdev);
|
|
|
|
+ u16 num_vf_qs;
|
|
|
|
+ int status;
|
|
|
|
+
|
|
|
|
+ be_get_sriov_config(adapter);
|
|
|
|
+
|
|
|
|
+ if (!old_vfs)
|
|
|
|
+ pci_sriov_set_totalvfs(adapter->pdev, be_max_vfs(adapter));
|
|
|
|
+
|
|
|
|
+ /* When the HW is in SRIOV capable configuration, the PF-pool
|
|
|
|
+ * resources are given to PF during driver load, if there are no
|
|
|
|
+ * old VFs. This facility is not available in BE3 FW.
|
|
|
|
+ * Also, this is done by FW in Lancer chip.
|
|
|
|
+ */
|
|
|
|
+ if (skyhawk_chip(adapter) && be_max_vfs(adapter) && !old_vfs) {
|
|
|
|
+ num_vf_qs = be_calculate_vf_qs(adapter, 0);
|
|
|
|
+ status = be_cmd_set_sriov_config(adapter, adapter->pool_res, 0,
|
|
|
|
+ num_vf_qs);
|
|
|
|
+ if (status)
|
|
|
|
+ dev_err(&adapter->pdev->dev,
|
|
|
|
+ "Failed to optimize SRIOV resources\n");
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static int be_get_resources(struct be_adapter *adapter)
|
|
static int be_get_resources(struct be_adapter *adapter)
|
|
{
|
|
{
|
|
struct device *dev = &adapter->pdev->dev;
|
|
struct device *dev = &adapter->pdev->dev;
|
|
@@ -3731,12 +3792,23 @@ static int be_get_resources(struct be_adapter *adapter)
|
|
if (status)
|
|
if (status)
|
|
return status;
|
|
return status;
|
|
|
|
|
|
|
|
+ /* If a deafault RXQ must be created, we'll use up one RSSQ*/
|
|
|
|
+ if (res.max_rss_qs && res.max_rss_qs == res.max_rx_qs &&
|
|
|
|
+ !(res.if_cap_flags & BE_IF_FLAGS_DEFQ_RSS))
|
|
|
|
+ res.max_rss_qs -= 1;
|
|
|
|
+
|
|
/* If RoCE may be enabled stash away half the EQs for RoCE */
|
|
/* If RoCE may be enabled stash away half the EQs for RoCE */
|
|
if (be_roce_supported(adapter))
|
|
if (be_roce_supported(adapter))
|
|
res.max_evt_qs /= 2;
|
|
res.max_evt_qs /= 2;
|
|
adapter->res = res;
|
|
adapter->res = res;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* If FW supports RSS default queue, then skip creating non-RSS
|
|
|
|
+ * queue for non-IP traffic.
|
|
|
|
+ */
|
|
|
|
+ adapter->need_def_rxq = (be_if_cap_flags(adapter) &
|
|
|
|
+ BE_IF_FLAGS_DEFQ_RSS) ? 0 : 1;
|
|
|
|
+
|
|
dev_info(dev, "Max: txqs %d, rxqs %d, rss %d, eqs %d, vfs %d\n",
|
|
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_txqs(adapter), be_max_rxqs(adapter),
|
|
be_max_rss(adapter), be_max_eqs(adapter),
|
|
be_max_rss(adapter), be_max_eqs(adapter),
|
|
@@ -3745,38 +3817,12 @@ static int be_get_resources(struct be_adapter *adapter)
|
|
be_max_uc(adapter), be_max_mc(adapter),
|
|
be_max_uc(adapter), be_max_mc(adapter),
|
|
be_max_vlans(adapter));
|
|
be_max_vlans(adapter));
|
|
|
|
|
|
|
|
+ /* Sanitize cfg_num_qs based on HW and platform limits */
|
|
|
|
+ adapter->cfg_num_qs = min_t(u16, netif_get_num_default_rss_queues(),
|
|
|
|
+ be_max_qs(adapter));
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static void be_sriov_config(struct be_adapter *adapter)
|
|
|
|
-{
|
|
|
|
- struct device *dev = &adapter->pdev->dev;
|
|
|
|
- int status;
|
|
|
|
-
|
|
|
|
- status = be_get_sriov_config(adapter);
|
|
|
|
- if (status) {
|
|
|
|
- dev_err(dev, "Failed to query SR-IOV configuration\n");
|
|
|
|
- dev_err(dev, "SR-IOV cannot be enabled\n");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* When the HW is in SRIOV capable configuration, the PF-pool
|
|
|
|
- * resources are equally distributed across the max-number of
|
|
|
|
- * VFs. The user may request only a subset of the max-vfs to be
|
|
|
|
- * enabled. Based on num_vfs, redistribute the resources across
|
|
|
|
- * num_vfs so that each VF will have access to more number of
|
|
|
|
- * resources. This facility is not available in BE3 FW.
|
|
|
|
- * Also, this is done by FW in Lancer chip.
|
|
|
|
- */
|
|
|
|
- if (be_max_vfs(adapter) && !pci_num_vf(adapter->pdev)) {
|
|
|
|
- status = be_cmd_set_sriov_config(adapter,
|
|
|
|
- adapter->pool_res,
|
|
|
|
- adapter->num_vfs);
|
|
|
|
- if (status)
|
|
|
|
- dev_err(dev, "Failed to optimize SR-IOV resources\n");
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int be_get_config(struct be_adapter *adapter)
|
|
static int be_get_config(struct be_adapter *adapter)
|
|
{
|
|
{
|
|
int status, level;
|
|
int status, level;
|
|
@@ -3807,9 +3853,6 @@ static int be_get_config(struct be_adapter *adapter)
|
|
"Using profile 0x%x\n", profile_id);
|
|
"Using profile 0x%x\n", profile_id);
|
|
}
|
|
}
|
|
|
|
|
|
- if (!BE2_chip(adapter) && be_physfn(adapter))
|
|
|
|
- be_sriov_config(adapter);
|
|
|
|
-
|
|
|
|
status = be_get_resources(adapter);
|
|
status = be_get_resources(adapter);
|
|
if (status)
|
|
if (status)
|
|
return status;
|
|
return status;
|
|
@@ -3819,9 +3862,6 @@ static int be_get_config(struct be_adapter *adapter)
|
|
if (!adapter->pmac_id)
|
|
if (!adapter->pmac_id)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
- /* 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;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3996,6 +4036,9 @@ static int be_setup(struct be_adapter *adapter)
|
|
if (!lancer_chip(adapter))
|
|
if (!lancer_chip(adapter))
|
|
be_cmd_req_native_mode(adapter);
|
|
be_cmd_req_native_mode(adapter);
|
|
|
|
|
|
|
|
+ if (!BE2_chip(adapter) && be_physfn(adapter))
|
|
|
|
+ be_alloc_sriov_res(adapter);
|
|
|
|
+
|
|
status = be_get_config(adapter);
|
|
status = be_get_config(adapter);
|
|
if (status)
|
|
if (status)
|
|
goto err;
|
|
goto err;
|
|
@@ -5217,7 +5260,6 @@ static int be_drv_init(struct be_adapter *adapter)
|
|
|
|
|
|
/* Must be a power of 2 or else MODULO will BUG_ON */
|
|
/* Must be a power of 2 or else MODULO will BUG_ON */
|
|
adapter->be_get_temp_freq = 64;
|
|
adapter->be_get_temp_freq = 64;
|
|
- adapter->cfg_num_qs = netif_get_num_default_rss_queues();
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -5541,6 +5583,60 @@ err:
|
|
dev_err(&adapter->pdev->dev, "EEH resume failed\n");
|
|
dev_err(&adapter->pdev->dev, "EEH resume failed\n");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int be_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
|
|
|
|
+{
|
|
|
|
+ struct be_adapter *adapter = pci_get_drvdata(pdev);
|
|
|
|
+ u16 num_vf_qs;
|
|
|
|
+ int status;
|
|
|
|
+
|
|
|
|
+ if (!num_vfs)
|
|
|
|
+ be_vf_clear(adapter);
|
|
|
|
+
|
|
|
|
+ adapter->num_vfs = num_vfs;
|
|
|
|
+
|
|
|
|
+ if (adapter->num_vfs == 0 && pci_vfs_assigned(pdev)) {
|
|
|
|
+ dev_warn(&pdev->dev,
|
|
|
|
+ "Cannot disable VFs while they are assigned\n");
|
|
|
|
+ return -EBUSY;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* When the HW is in SRIOV capable configuration, the PF-pool resources
|
|
|
|
+ * are equally distributed across the max-number of VFs. The user may
|
|
|
|
+ * request only a subset of the max-vfs to be enabled.
|
|
|
|
+ * Based on num_vfs, redistribute the resources across num_vfs so that
|
|
|
|
+ * each VF will have access to more number of resources.
|
|
|
|
+ * This facility is not available in BE3 FW.
|
|
|
|
+ * Also, this is done by FW in Lancer chip.
|
|
|
|
+ */
|
|
|
|
+ if (skyhawk_chip(adapter) && !pci_num_vf(pdev)) {
|
|
|
|
+ num_vf_qs = be_calculate_vf_qs(adapter, adapter->num_vfs);
|
|
|
|
+ status = be_cmd_set_sriov_config(adapter, adapter->pool_res,
|
|
|
|
+ adapter->num_vfs, num_vf_qs);
|
|
|
|
+ if (status)
|
|
|
|
+ dev_err(&pdev->dev,
|
|
|
|
+ "Failed to optimize SR-IOV resources\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ status = be_get_resources(adapter);
|
|
|
|
+ if (status)
|
|
|
|
+ return be_cmd_status(status);
|
|
|
|
+
|
|
|
|
+ /* Updating real_num_tx/rx_queues() requires rtnl_lock() */
|
|
|
|
+ rtnl_lock();
|
|
|
|
+ status = be_update_queues(adapter);
|
|
|
|
+ rtnl_unlock();
|
|
|
|
+ if (status)
|
|
|
|
+ return be_cmd_status(status);
|
|
|
|
+
|
|
|
|
+ if (adapter->num_vfs)
|
|
|
|
+ status = be_vf_setup(adapter);
|
|
|
|
+
|
|
|
|
+ if (!status)
|
|
|
|
+ return adapter->num_vfs;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct pci_error_handlers be_eeh_handlers = {
|
|
static const struct pci_error_handlers be_eeh_handlers = {
|
|
.error_detected = be_eeh_err_detected,
|
|
.error_detected = be_eeh_err_detected,
|
|
.slot_reset = be_eeh_reset,
|
|
.slot_reset = be_eeh_reset,
|
|
@@ -5555,6 +5651,7 @@ static struct pci_driver be_driver = {
|
|
.suspend = be_suspend,
|
|
.suspend = be_suspend,
|
|
.resume = be_pci_resume,
|
|
.resume = be_pci_resume,
|
|
.shutdown = be_shutdown,
|
|
.shutdown = be_shutdown,
|
|
|
|
+ .sriov_configure = be_pci_sriov_configure,
|
|
.err_handler = &be_eeh_handlers
|
|
.err_handler = &be_eeh_handlers
|
|
};
|
|
};
|
|
|
|
|
|
@@ -5568,6 +5665,11 @@ static int __init be_init_module(void)
|
|
rx_frag_size = 2048;
|
|
rx_frag_size = 2048;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (num_vfs > 0) {
|
|
|
|
+ pr_info(DRV_NAME " : Module param num_vfs is obsolete.");
|
|
|
|
+ pr_info(DRV_NAME " : Use sysfs method to enable VFs\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
return pci_register_driver(&be_driver);
|
|
return pci_register_driver(&be_driver);
|
|
}
|
|
}
|
|
module_init(be_init_module);
|
|
module_init(be_init_module);
|