|
@@ -2597,7 +2597,7 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable)
|
|
|
* These addresses are programmed in the ASIC by the PF and the VF driver
|
|
|
* queries for the MAC address during its probe.
|
|
|
*/
|
|
|
-static inline int be_vf_eth_addr_config(struct be_adapter *adapter)
|
|
|
+static int be_vf_eth_addr_config(struct be_adapter *adapter)
|
|
|
{
|
|
|
u32 vf;
|
|
|
int status = 0;
|
|
@@ -2626,13 +2626,34 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter)
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+static int be_vfs_mac_query(struct be_adapter *adapter)
|
|
|
+{
|
|
|
+ int status, vf;
|
|
|
+ u8 mac[ETH_ALEN];
|
|
|
+ struct be_vf_cfg *vf_cfg;
|
|
|
+ bool active;
|
|
|
+
|
|
|
+ for_all_vfs(adapter, vf_cfg, vf) {
|
|
|
+ be_cmd_get_mac_from_list(adapter, mac, &active,
|
|
|
+ &vf_cfg->pmac_id, 0);
|
|
|
+
|
|
|
+ status = be_cmd_mac_addr_query(adapter, mac, false,
|
|
|
+ vf_cfg->if_handle, 0);
|
|
|
+ if (status)
|
|
|
+ return status;
|
|
|
+ memcpy(vf_cfg->mac_addr, mac, ETH_ALEN);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static void be_vf_clear(struct be_adapter *adapter)
|
|
|
{
|
|
|
struct be_vf_cfg *vf_cfg;
|
|
|
u32 vf;
|
|
|
|
|
|
if (be_find_vfs(adapter, ASSIGNED)) {
|
|
|
- dev_warn(&adapter->pdev->dev, "VFs are assigned to VMs\n");
|
|
|
+ dev_warn(&adapter->pdev->dev,
|
|
|
+ "VFs are assigned to VMs: not disabling VFs\n");
|
|
|
goto done;
|
|
|
}
|
|
|
|
|
@@ -2681,21 +2702,29 @@ static int be_clear(struct be_adapter *adapter)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void be_get_vf_if_cap_flags(struct be_adapter *adapter,
|
|
|
- u32 *cap_flags, u8 domain)
|
|
|
+static int be_vfs_if_create(struct be_adapter *adapter)
|
|
|
{
|
|
|
- bool profile_present = false;
|
|
|
+ struct be_vf_cfg *vf_cfg;
|
|
|
+ u32 cap_flags, en_flags, vf;
|
|
|
int status;
|
|
|
|
|
|
- if (lancer_chip(adapter)) {
|
|
|
- status = be_cmd_get_profile_config(adapter, cap_flags, domain);
|
|
|
- if (!status)
|
|
|
- profile_present = true;
|
|
|
- }
|
|
|
+ cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
|
|
|
+ BE_IF_FLAGS_MULTICAST;
|
|
|
|
|
|
- if (!profile_present)
|
|
|
- *cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
|
|
|
- BE_IF_FLAGS_MULTICAST;
|
|
|
+ for_all_vfs(adapter, vf_cfg, vf) {
|
|
|
+ if (!BE3_chip(adapter))
|
|
|
+ be_cmd_get_profile_config(adapter, &cap_flags, vf + 1);
|
|
|
+
|
|
|
+ /* If a FW profile exists, then cap_flags are updated */
|
|
|
+ en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED |
|
|
|
+ BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_MULTICAST);
|
|
|
+ status = be_cmd_if_create(adapter, cap_flags, en_flags,
|
|
|
+ &vf_cfg->if_handle, vf + 1);
|
|
|
+ if (status)
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+err:
|
|
|
+ return status;
|
|
|
}
|
|
|
|
|
|
static int be_vf_setup_init(struct be_adapter *adapter)
|
|
@@ -2718,65 +2747,70 @@ static int be_vf_setup_init(struct be_adapter *adapter)
|
|
|
static int be_vf_setup(struct be_adapter *adapter)
|
|
|
{
|
|
|
struct be_vf_cfg *vf_cfg;
|
|
|
- struct device *dev = &adapter->pdev->dev;
|
|
|
- u32 cap_flags, en_flags, vf;
|
|
|
u16 def_vlan, lnk_speed;
|
|
|
- int status, enabled_vfs;
|
|
|
-
|
|
|
- enabled_vfs = be_find_vfs(adapter, ENABLED);
|
|
|
- if (enabled_vfs) {
|
|
|
- dev_warn(dev, "%d VFs are already enabled\n", enabled_vfs);
|
|
|
- dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (num_vfs > adapter->dev_num_vfs) {
|
|
|
- dev_warn(dev, "Device supports %d VFs and not %d\n",
|
|
|
- adapter->dev_num_vfs, num_vfs);
|
|
|
- num_vfs = adapter->dev_num_vfs;
|
|
|
- }
|
|
|
+ int status, old_vfs, vf;
|
|
|
+ struct device *dev = &adapter->pdev->dev;
|
|
|
|
|
|
- status = pci_enable_sriov(adapter->pdev, num_vfs);
|
|
|
- if (!status) {
|
|
|
- adapter->num_vfs = num_vfs;
|
|
|
+ old_vfs = be_find_vfs(adapter, ENABLED);
|
|
|
+ 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);
|
|
|
+ adapter->num_vfs = old_vfs;
|
|
|
} else {
|
|
|
- /* Platform doesn't support SRIOV though device supports it */
|
|
|
- dev_warn(dev, "SRIOV enable failed\n");
|
|
|
- return 0;
|
|
|
+ if (num_vfs > adapter->dev_num_vfs)
|
|
|
+ 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);
|
|
|
+
|
|
|
+ status = pci_enable_sriov(adapter->pdev, num_vfs);
|
|
|
+ if (status) {
|
|
|
+ dev_err(dev, "SRIOV enable failed\n");
|
|
|
+ adapter->num_vfs = 0;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
status = be_vf_setup_init(adapter);
|
|
|
if (status)
|
|
|
goto err;
|
|
|
|
|
|
- for_all_vfs(adapter, vf_cfg, vf) {
|
|
|
- be_get_vf_if_cap_flags(adapter, &cap_flags, vf + 1);
|
|
|
-
|
|
|
- en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED |
|
|
|
- BE_IF_FLAGS_BROADCAST |
|
|
|
- BE_IF_FLAGS_MULTICAST);
|
|
|
-
|
|
|
- status = be_cmd_if_create(adapter, cap_flags, en_flags,
|
|
|
- &vf_cfg->if_handle, vf + 1);
|
|
|
+ if (old_vfs) {
|
|
|
+ for_all_vfs(adapter, vf_cfg, vf) {
|
|
|
+ status = be_cmd_get_if_id(adapter, vf_cfg, vf);
|
|
|
+ if (status)
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ status = be_vfs_if_create(adapter);
|
|
|
if (status)
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
- if (!enabled_vfs) {
|
|
|
+ if (old_vfs) {
|
|
|
+ status = be_vfs_mac_query(adapter);
|
|
|
+ if (status)
|
|
|
+ goto err;
|
|
|
+ } else {
|
|
|
status = be_vf_eth_addr_config(adapter);
|
|
|
if (status)
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
for_all_vfs(adapter, vf_cfg, vf) {
|
|
|
- lnk_speed = 1000;
|
|
|
- status = be_cmd_set_qos(adapter, lnk_speed, vf + 1);
|
|
|
- if (status)
|
|
|
- goto err;
|
|
|
- vf_cfg->tx_rate = lnk_speed * 10;
|
|
|
+ /* BE3 FW, by default, caps VF TX-rate to 100mbps.
|
|
|
+ * Allow full available bandwidth
|
|
|
+ */
|
|
|
+ if (BE3_chip(adapter) && !old_vfs)
|
|
|
+ be_cmd_set_qos(adapter, 1000, vf+1);
|
|
|
+
|
|
|
+ status = be_cmd_link_status_query(adapter, &lnk_speed,
|
|
|
+ NULL, vf + 1);
|
|
|
+ if (!status)
|
|
|
+ vf_cfg->tx_rate = lnk_speed;
|
|
|
|
|
|
status = be_cmd_get_hsw_config(adapter, &def_vlan,
|
|
|
- vf + 1, vf_cfg->if_handle);
|
|
|
+ vf + 1, vf_cfg->if_handle);
|
|
|
if (status)
|
|
|
goto err;
|
|
|
vf_cfg->def_vid = def_vlan;
|
|
@@ -2785,6 +2819,8 @@ static int be_vf_setup(struct be_adapter *adapter)
|
|
|
}
|
|
|
return 0;
|
|
|
err:
|
|
|
+ dev_err(dev, "VF setup failed\n");
|
|
|
+ be_vf_clear(adapter);
|
|
|
return status;
|
|
|
}
|
|
|
|
|
@@ -2838,12 +2874,12 @@ static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
|
|
|
|
|
|
static void be_get_resources(struct be_adapter *adapter)
|
|
|
{
|
|
|
- int status;
|
|
|
+ u16 dev_num_vfs;
|
|
|
+ int pos, status;
|
|
|
bool profile_present = false;
|
|
|
|
|
|
- if (lancer_chip(adapter)) {
|
|
|
+ if (!BEx_chip(adapter)) {
|
|
|
status = be_cmd_get_func_config(adapter);
|
|
|
-
|
|
|
if (!status)
|
|
|
profile_present = true;
|
|
|
}
|
|
@@ -2899,13 +2935,21 @@ static void be_get_resources(struct be_adapter *adapter)
|
|
|
if (adapter->function_caps & BE_FUNCTION_CAPS_RSS)
|
|
|
adapter->if_cap_flags |= BE_IF_FLAGS_RSS;
|
|
|
}
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* Routine to query per function resource limits */
|
|
|
static int be_get_config(struct be_adapter *adapter)
|
|
|
{
|
|
|
- int pos, status;
|
|
|
- u16 dev_num_vfs;
|
|
|
+ int status;
|
|
|
|
|
|
status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
|
|
|
&adapter->function_mode,
|
|
@@ -2923,14 +2967,6 @@ static int be_get_config(struct be_adapter *adapter)
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
- 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 (!lancer_chip(adapter))
|
|
|
- dev_num_vfs = min_t(u16, dev_num_vfs, MAX_VFS);
|
|
|
- adapter->dev_num_vfs = dev_num_vfs;
|
|
|
- }
|
|
|
err:
|
|
|
return status;
|
|
|
}
|