Commit bcc84140 authored by Kalesh AP's avatar Kalesh AP Committed by David S. Miller

be2net: enable IFACE filters only after creating RXQs

HW issues were observed on Lancer adapters if IFACE filters
(flags, mac addrs etc) are enabled *before* creating RXQs.  This patch
changes the driver design by enabling filters in be_open() --
instead of be_setup() -- after RXQs are created and buffers posted.
Two new wrapper functions, be_enable_if_filters() and
be_disable_if_filters() are introduced to enable/disable IFACE filters in
be_open()/be_close() respectively. In be_setup() the IFACE is now created
only with the RSS flag.
Signed-off-by: default avatarKalesh AP <kalesh.purayil@avagotech.com>
Signed-off-by: default avatarSathya Perla <sathya.perla@avagotech.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 48900cb6
...@@ -620,6 +620,11 @@ enum be_if_flags { ...@@ -620,6 +620,11 @@ enum be_if_flags {
BE_IF_FLAGS_VLAN_PROMISCUOUS |\ BE_IF_FLAGS_VLAN_PROMISCUOUS |\
BE_IF_FLAGS_MCAST_PROMISCUOUS) BE_IF_FLAGS_MCAST_PROMISCUOUS)
#define BE_IF_EN_FLAGS (BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |\
BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_UNTAGGED)
#define BE_IF_ALL_FILT_FLAGS (BE_IF_EN_FLAGS | BE_IF_FLAGS_ALL_PROMISCUOUS)
/* An RX interface is an object with one or more MAC addresses and /* An RX interface is an object with one or more MAC addresses and
* filtering capabilities. */ * filtering capabilities. */
struct be_cmd_req_if_create { struct be_cmd_req_if_create {
......
...@@ -273,6 +273,10 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) ...@@ -273,6 +273,10 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
if (ether_addr_equal(addr->sa_data, netdev->dev_addr)) if (ether_addr_equal(addr->sa_data, netdev->dev_addr))
return 0; return 0;
/* if device is not running, copy MAC to netdev->dev_addr */
if (!netif_running(netdev))
goto done;
/* The PMAC_ADD cmd may fail if the VF doesn't have FILTMGMT /* The PMAC_ADD cmd may fail if the VF doesn't have FILTMGMT
* privilege or if PF did not provision the new MAC address. * 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 * On BE3, this cmd will always fail if the VF doesn't have the
...@@ -307,9 +311,9 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) ...@@ -307,9 +311,9 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
status = -EPERM; status = -EPERM;
goto err; goto err;
} }
done:
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); ether_addr_copy(netdev->dev_addr, addr->sa_data);
dev_info(dev, "MAC address changed to %pM\n", mac); dev_info(dev, "MAC address changed to %pM\n", addr->sa_data);
return 0; return 0;
err: err:
dev_warn(dev, "MAC address change to %pM failed\n", addr->sa_data); dev_warn(dev, "MAC address change to %pM failed\n", addr->sa_data);
...@@ -3361,6 +3365,33 @@ static void be_rx_qs_destroy(struct be_adapter *adapter) ...@@ -3361,6 +3365,33 @@ static void be_rx_qs_destroy(struct be_adapter *adapter)
} }
} }
static void be_disable_if_filters(struct be_adapter *adapter)
{
be_cmd_pmac_del(adapter, adapter->if_handle,
adapter->pmac_id[0], 0);
be_clear_uc_list(adapter);
/* The IFACE flags are enabled in the open path and cleared
* in the close path. When a VF gets detached from the host and
* assigned to a VM the following happens:
* - VF's IFACE flags get cleared in the detach path
* - IFACE create is issued by the VF in the attach path
* Due to a bug in the BE3/Skyhawk-R FW
* (Lancer FW doesn't have the bug), the IFACE capability flags
* specified along with the IFACE create cmd issued by a VF are not
* honoured by FW. As a consequence, if a *new* driver
* (that enables/disables IFACE flags in open/close)
* is loaded in the host and an *old* driver is * used by a VM/VF,
* the IFACE gets created *without* the needed flags.
* To avoid this, disable RX-filter flags only for Lancer.
*/
if (lancer_chip(adapter)) {
be_cmd_rx_filter(adapter, BE_IF_ALL_FILT_FLAGS, OFF);
adapter->if_flags &= ~BE_IF_ALL_FILT_FLAGS;
}
}
static int be_close(struct net_device *netdev) static int be_close(struct net_device *netdev)
{ {
struct be_adapter *adapter = netdev_priv(netdev); struct be_adapter *adapter = netdev_priv(netdev);
...@@ -3373,6 +3404,8 @@ static int be_close(struct net_device *netdev) ...@@ -3373,6 +3404,8 @@ static int be_close(struct net_device *netdev)
if (!(adapter->flags & BE_FLAGS_SETUP_DONE)) if (!(adapter->flags & BE_FLAGS_SETUP_DONE))
return 0; return 0;
be_disable_if_filters(adapter);
be_roce_dev_close(adapter); be_roce_dev_close(adapter);
if (adapter->flags & BE_FLAGS_NAPI_ENABLED) { if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
...@@ -3392,7 +3425,6 @@ static int be_close(struct net_device *netdev) ...@@ -3392,7 +3425,6 @@ static int be_close(struct net_device *netdev)
be_tx_compl_clean(adapter); be_tx_compl_clean(adapter);
be_rx_qs_destroy(adapter); be_rx_qs_destroy(adapter);
be_clear_uc_list(adapter);
for_all_evt_queues(adapter, eqo, i) { for_all_evt_queues(adapter, eqo, i) {
if (msix_enabled(adapter)) if (msix_enabled(adapter))
...@@ -3477,6 +3509,31 @@ static int be_rx_qs_create(struct be_adapter *adapter) ...@@ -3477,6 +3509,31 @@ static int be_rx_qs_create(struct be_adapter *adapter)
return 0; return 0;
} }
static int be_enable_if_filters(struct be_adapter *adapter)
{
int status;
status = be_cmd_rx_filter(adapter, BE_IF_EN_FLAGS, ON);
if (status)
return status;
/* For BE3 VFs, the PF programs the initial MAC address */
if (!(BEx_chip(adapter) && be_virtfn(adapter))) {
status = be_cmd_pmac_add(adapter, adapter->netdev->dev_addr,
adapter->if_handle,
&adapter->pmac_id[0], 0);
if (status)
return status;
}
if (adapter->vlans_added)
be_vid_config(adapter);
be_set_rx_mode(adapter->netdev);
return 0;
}
static int be_open(struct net_device *netdev) static int be_open(struct net_device *netdev)
{ {
struct be_adapter *adapter = netdev_priv(netdev); struct be_adapter *adapter = netdev_priv(netdev);
...@@ -3490,6 +3547,10 @@ static int be_open(struct net_device *netdev) ...@@ -3490,6 +3547,10 @@ static int be_open(struct net_device *netdev)
if (status) if (status)
goto err; goto err;
status = be_enable_if_filters(adapter);
if (status)
goto err;
status = be_irq_register(adapter); status = be_irq_register(adapter);
if (status) if (status)
goto err; goto err;
...@@ -3686,16 +3747,6 @@ static void be_cancel_err_detection(struct be_adapter *adapter) ...@@ -3686,16 +3747,6 @@ static void be_cancel_err_detection(struct be_adapter *adapter)
} }
} }
static void be_mac_clear(struct be_adapter *adapter)
{
if (adapter->pmac_id) {
be_cmd_pmac_del(adapter, adapter->if_handle,
adapter->pmac_id[0], 0);
kfree(adapter->pmac_id);
adapter->pmac_id = NULL;
}
}
#ifdef CONFIG_BE2NET_VXLAN #ifdef CONFIG_BE2NET_VXLAN
static void be_disable_vxlan_offloads(struct be_adapter *adapter) static void be_disable_vxlan_offloads(struct be_adapter *adapter)
{ {
...@@ -3770,8 +3821,8 @@ static int be_clear(struct be_adapter *adapter) ...@@ -3770,8 +3821,8 @@ static int be_clear(struct be_adapter *adapter)
#ifdef CONFIG_BE2NET_VXLAN #ifdef CONFIG_BE2NET_VXLAN
be_disable_vxlan_offloads(adapter); be_disable_vxlan_offloads(adapter);
#endif #endif
/* delete the primary mac along with the uc-mac list */ kfree(adapter->pmac_id);
be_mac_clear(adapter); adapter->pmac_id = NULL;
be_cmd_if_destroy(adapter, adapter->if_handle, 0); be_cmd_if_destroy(adapter, adapter->if_handle, 0);
...@@ -3782,25 +3833,11 @@ static int be_clear(struct be_adapter *adapter) ...@@ -3782,25 +3833,11 @@ static int be_clear(struct be_adapter *adapter)
return 0; return 0;
} }
static int be_if_create(struct be_adapter *adapter, u32 *if_handle,
u32 cap_flags, u32 vf)
{
u32 en_flags;
en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |
BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
en_flags &= cap_flags;
return be_cmd_if_create(adapter, cap_flags, en_flags, if_handle, vf);
}
static int be_vfs_if_create(struct be_adapter *adapter) static int be_vfs_if_create(struct be_adapter *adapter)
{ {
struct be_resources res = {0}; struct be_resources res = {0};
u32 cap_flags, en_flags, vf;
struct be_vf_cfg *vf_cfg; struct be_vf_cfg *vf_cfg;
u32 cap_flags, vf;
int status; int status;
/* If a FW profile exists, then cap_flags are updated */ /* If a FW profile exists, then cap_flags are updated */
...@@ -3821,8 +3858,12 @@ static int be_vfs_if_create(struct be_adapter *adapter) ...@@ -3821,8 +3858,12 @@ static int be_vfs_if_create(struct be_adapter *adapter)
} }
} }
status = be_if_create(adapter, &vf_cfg->if_handle, en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED |
cap_flags, vf + 1); BE_IF_FLAGS_BROADCAST |
BE_IF_FLAGS_MULTICAST |
BE_IF_FLAGS_PASS_L3L4_ERRORS);
status = be_cmd_if_create(adapter, cap_flags, en_flags,
&vf_cfg->if_handle, vf + 1);
if (status) if (status)
return status; return status;
} }
...@@ -4194,15 +4235,8 @@ static int be_mac_setup(struct be_adapter *adapter) ...@@ -4194,15 +4235,8 @@ static int be_mac_setup(struct be_adapter *adapter)
memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
memcpy(adapter->netdev->perm_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);
} }
/* For BE3-R VFs, the PF programs the initial MAC address */
if (!(BEx_chip(adapter) && be_virtfn(adapter)))
be_cmd_pmac_add(adapter, mac, adapter->if_handle,
&adapter->pmac_id[0], 0);
return 0; return 0;
} }
...@@ -4342,6 +4376,7 @@ static int be_func_init(struct be_adapter *adapter) ...@@ -4342,6 +4376,7 @@ static int be_func_init(struct be_adapter *adapter)
static int be_setup(struct be_adapter *adapter) static int be_setup(struct be_adapter *adapter)
{ {
struct device *dev = &adapter->pdev->dev; struct device *dev = &adapter->pdev->dev;
u32 en_flags;
int status; int status;
status = be_func_init(adapter); status = be_func_init(adapter);
...@@ -4364,8 +4399,11 @@ static int be_setup(struct be_adapter *adapter) ...@@ -4364,8 +4399,11 @@ static int be_setup(struct be_adapter *adapter)
if (status) if (status)
goto err; goto err;
status = be_if_create(adapter, &adapter->if_handle, /* will enable all the needed filter flags in be_open() */
be_if_cap_flags(adapter), 0); en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
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) if (status)
goto err; goto err;
...@@ -4391,11 +4429,6 @@ static int be_setup(struct be_adapter *adapter) ...@@ -4391,11 +4429,6 @@ static int be_setup(struct be_adapter *adapter)
dev_err(dev, "Please upgrade firmware to version >= 4.0\n"); dev_err(dev, "Please upgrade firmware to version >= 4.0\n");
} }
if (adapter->vlans_added)
be_vid_config(adapter);
be_set_rx_mode(adapter->netdev);
status = be_cmd_set_flow_control(adapter, adapter->tx_fc, status = be_cmd_set_flow_control(adapter, adapter->tx_fc,
adapter->rx_fc); adapter->rx_fc);
if (status) if (status)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment