summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/emulex/benet/be_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c211
1 files changed, 95 insertions, 116 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 181edb5..3df1503 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -247,54 +247,54 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped)
static int be_mac_addr_set(struct net_device *netdev, void *p)
{
struct be_adapter *adapter = netdev_priv(netdev);
+ struct device *dev = &adapter->pdev->dev;
struct sockaddr *addr = p;
- int status = 0;
- u8 current_mac[ETH_ALEN];
- u32 pmac_id = adapter->pmac_id[0];
- bool active_mac = true;
+ int status;
+ u8 mac[ETH_ALEN];
+ u32 old_pmac_id = adapter->pmac_id[0], curr_pmac_id = 0;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- /* For BE VF, MAC address is already activated by PF.
- * Hence only operation left is updating netdev->devaddr.
- * Update it if user is passing the same MAC which was used
- * during configuring VF MAC from PF(Hypervisor).
+ /* The PMAC_ADD cmd may fail if the VF doesn't have FILTMGMT
+ * privilege or if PF did not provision the new MAC address.
+ * On BE3, this cmd will always fail if the VF doesn't have the
+ * FILTMGMT privilege. This failure is OK, only if the PF programmed
+ * the MAC for the VF.
*/
- if (!lancer_chip(adapter) && !be_physfn(adapter)) {
- status = be_cmd_mac_addr_query(adapter, current_mac,
- false, adapter->if_handle, 0);
- if (!status && !memcmp(current_mac, addr->sa_data, ETH_ALEN))
- goto done;
- else
- goto err;
- }
+ status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
+ adapter->if_handle, &adapter->pmac_id[0], 0);
+ if (!status) {
+ curr_pmac_id = adapter->pmac_id[0];
- if (!memcmp(addr->sa_data, netdev->dev_addr, ETH_ALEN))
- goto done;
+ /* Delete the old programmed MAC. This call may fail if the
+ * old MAC was already deleted by the PF driver.
+ */
+ if (adapter->pmac_id[0] != old_pmac_id)
+ be_cmd_pmac_del(adapter, adapter->if_handle,
+ old_pmac_id, 0);
+ }
- /* For Lancer check if any MAC is active.
- * If active, get its mac id.
+ /* Decide if the new MAC is successfully activated only after
+ * querying the FW
*/
- if (lancer_chip(adapter) && !be_physfn(adapter))
- be_cmd_get_mac_from_list(adapter, current_mac, &active_mac,
- &pmac_id, 0);
-
- status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
- adapter->if_handle,
- &adapter->pmac_id[0], 0);
-
+ status = be_cmd_get_active_mac(adapter, curr_pmac_id, mac);
if (status)
goto err;
- if (active_mac)
- be_cmd_pmac_del(adapter, adapter->if_handle,
- pmac_id, 0);
-done:
+ /* The MAC change did not happen, either due to lack of privilege
+ * or PF didn't pre-provision.
+ */
+ if (memcmp(addr->sa_data, mac, ETH_ALEN)) {
+ status = -EPERM;
+ goto err;
+ }
+
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ dev_info(dev, "MAC address changed to %pM\n", mac);
return 0;
err:
- dev_err(&adapter->pdev->dev, "MAC %pM set Failed\n", addr->sa_data);
+ dev_warn(dev, "MAC address change to %pM failed\n", addr->sa_data);
return status;
}
@@ -1146,9 +1146,6 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
struct be_adapter *adapter = netdev_priv(netdev);
struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
int status;
- bool active_mac = false;
- u32 pmac_id;
- u8 old_mac[ETH_ALEN];
if (!sriov_enabled(adapter))
return -EPERM;
@@ -1156,20 +1153,15 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
if (!is_valid_ether_addr(mac) || vf >= adapter->num_vfs)
return -EINVAL;
- if (lancer_chip(adapter)) {
- status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
- &pmac_id, vf + 1);
- if (!status && active_mac)
- be_cmd_pmac_del(adapter, vf_cfg->if_handle,
- pmac_id, vf + 1);
-
- status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1);
- } else {
- status = be_cmd_pmac_del(adapter, vf_cfg->if_handle,
- vf_cfg->pmac_id, vf + 1);
+ if (BEx_chip(adapter)) {
+ be_cmd_pmac_del(adapter, vf_cfg->if_handle, vf_cfg->pmac_id,
+ vf + 1);
status = be_cmd_pmac_add(adapter, mac, vf_cfg->if_handle,
&vf_cfg->pmac_id, vf + 1);
+ } else {
+ status = be_cmd_set_mac(adapter, mac, vf_cfg->if_handle,
+ vf + 1);
}
if (status)
@@ -2735,13 +2727,13 @@ static int be_vf_eth_addr_config(struct be_adapter *adapter)
be_vf_eth_addr_generate(adapter, mac);
for_all_vfs(adapter, vf_cfg, vf) {
- if (lancer_chip(adapter)) {
- status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1);
- } else {
+ if (BEx_chip(adapter))
status = be_cmd_pmac_add(adapter, mac,
vf_cfg->if_handle,
&vf_cfg->pmac_id, vf + 1);
- }
+ else
+ status = be_cmd_set_mac(adapter, mac, vf_cfg->if_handle,
+ vf + 1);
if (status)
dev_err(&adapter->pdev->dev,
@@ -2759,7 +2751,7 @@ 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;
+ bool active = false;
for_all_vfs(adapter, vf_cfg, vf) {
be_cmd_get_mac_from_list(adapter, mac, &active,
@@ -2788,11 +2780,12 @@ static void be_vf_clear(struct be_adapter *adapter)
pci_disable_sriov(adapter->pdev);
for_all_vfs(adapter, vf_cfg, vf) {
- if (lancer_chip(adapter))
- be_cmd_set_mac_list(adapter, NULL, 0, vf + 1);
- else
+ if (BEx_chip(adapter))
be_cmd_pmac_del(adapter, vf_cfg->if_handle,
vf_cfg->pmac_id, vf + 1);
+ else
+ be_cmd_set_mac(adapter, NULL, vf_cfg->if_handle,
+ vf + 1);
be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1);
}
@@ -2803,7 +2796,7 @@ done:
static int be_clear(struct be_adapter *adapter)
{
- int i = 1;
+ int i;
if (adapter->flags & BE_FLAGS_WORKER_SCHEDULED) {
cancel_delayed_work_sync(&adapter->work);
@@ -2813,9 +2806,11 @@ static int be_clear(struct be_adapter *adapter)
if (sriov_enabled(adapter))
be_vf_clear(adapter);
- for (; adapter->uc_macs > 0; adapter->uc_macs--, i++)
+ /* delete the primary mac along with the uc-mac list */
+ for (i = 0; i < (adapter->uc_macs + 1); i++)
be_cmd_pmac_del(adapter, adapter->if_handle,
- adapter->pmac_id[i], 0);
+ adapter->pmac_id[i], 0);
+ adapter->uc_macs = 0;
be_cmd_if_destroy(adapter, adapter->if_handle, 0);
@@ -2880,6 +2875,7 @@ static int be_vf_setup(struct be_adapter *adapter)
u16 def_vlan, lnk_speed;
int status, old_vfs, vf;
struct device *dev = &adapter->pdev->dev;
+ u32 privileges;
old_vfs = pci_num_vf(adapter->pdev);
if (old_vfs) {
@@ -2923,6 +2919,18 @@ static int be_vf_setup(struct be_adapter *adapter)
}
for_all_vfs(adapter, vf_cfg, vf) {
+ /* Allow VFs to programs MAC/VLAN filters */
+ status = be_cmd_get_fn_privileges(adapter, &privileges, vf + 1);
+ if (!status && !(privileges & BE_PRIV_FILTMGMT)) {
+ status = be_cmd_set_fn_privileges(adapter,
+ privileges |
+ BE_PRIV_FILTMGMT,
+ vf + 1);
+ if (!status)
+ dev_info(dev, "VF%d has FILTMGMT privilege\n",
+ vf);
+ }
+
/* BE3 FW, by default, caps VF TX-rate to 100mbps.
* Allow full available bandwidth
*/
@@ -2971,41 +2979,6 @@ static void be_setup_init(struct be_adapter *adapter)
adapter->cmd_privileges = MIN_PRIVILEGES;
}
-static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
- bool *active_mac, u32 *pmac_id)
-{
- int status = 0;
-
- if (!is_zero_ether_addr(adapter->netdev->perm_addr)) {
- memcpy(mac, adapter->netdev->dev_addr, ETH_ALEN);
- if (!lancer_chip(adapter) && !be_physfn(adapter))
- *active_mac = true;
- else
- *active_mac = false;
-
- return status;
- }
-
- if (lancer_chip(adapter)) {
- status = be_cmd_get_mac_from_list(adapter, mac,
- active_mac, pmac_id, 0);
- if (*active_mac) {
- status = be_cmd_mac_addr_query(adapter, mac, false,
- if_handle, *pmac_id);
- }
- } else if (be_physfn(adapter)) {
- /* For BE3, for PF get permanent MAC */
- status = be_cmd_mac_addr_query(adapter, mac, true, 0, 0);
- *active_mac = false;
- } else {
- /* For BE3, for VF get soft MAC assigned by PF*/
- status = be_cmd_mac_addr_query(adapter, mac, false,
- if_handle, 0);
- *active_mac = true;
- }
- return status;
-}
-
static void be_get_resources(struct be_adapter *adapter)
{
u16 dev_num_vfs;
@@ -3111,14 +3084,38 @@ err:
return status;
}
+static int be_mac_setup(struct be_adapter *adapter)
+{
+ u8 mac[ETH_ALEN];
+ int status;
+
+ if (is_zero_ether_addr(adapter->netdev->dev_addr)) {
+ status = be_cmd_get_perm_mac(adapter, mac);
+ if (status)
+ return status;
+
+ memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
+ memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
+ } else {
+ /* Maybe the HW was reset; dev_addr must be re-programmed */
+ memcpy(mac, adapter->netdev->dev_addr, ETH_ALEN);
+ }
+
+ /* On BE3 VFs this cmd may fail due to lack of privilege.
+ * Ignore the failure as in this case pmac_id is fetched
+ * in the IFACE_CREATE cmd.
+ */
+ be_cmd_pmac_add(adapter, mac, adapter->if_handle,
+ &adapter->pmac_id[0], 0);
+ return 0;
+}
+
static int be_setup(struct be_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
u32 en_flags;
u32 tx_fc, rx_fc;
int status;
- u8 mac[ETH_ALEN];
- bool active_mac;
be_setup_init(adapter);
@@ -3158,36 +3155,18 @@ static int be_setup(struct be_adapter *adapter)
en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
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,
&adapter->if_handle, 0);
if (status != 0)
goto err;
- memset(mac, 0, ETH_ALEN);
- active_mac = false;
- status = be_get_mac_addr(adapter, mac, adapter->if_handle,
- &active_mac, &adapter->pmac_id[0]);
- if (status != 0)
+ status = be_mac_setup(adapter);
+ if (status)
goto err;
- if (!active_mac) {
- status = be_cmd_pmac_add(adapter, mac, adapter->if_handle,
- &adapter->pmac_id[0], 0);
- if (status != 0)
- goto err;
- }
-
- if (is_zero_ether_addr(adapter->netdev->dev_addr)) {
- memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
- memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
- }
-
status = be_tx_qs_create(adapter);
if (status)
goto err;
@@ -4253,7 +4232,7 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
status = pci_enable_pcie_error_reporting(pdev);
if (status)
- dev_err(&pdev->dev, "Could not use PCIe error reporting\n");
+ dev_info(&pdev->dev, "Could not use PCIe error reporting\n");
status = be_ctrl_init(adapter);
if (status)