be2net: set and query VEB/VEPA mode of the PF interface
SkyHawk-R can support VEB or VEPA mode.
This patch will allow the user to set/query this switch setting.
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 39e0a76..e104db7 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -21,6 +21,7 @@
#include "be_cmds.h"
#include <asm/div64.h>
#include <linux/aer.h>
+#include <linux/if_bridge.h>
MODULE_VERSION(DRV_VER);
MODULE_DEVICE_TABLE(pci, be_dev_ids);
@@ -1212,14 +1213,14 @@
adapter->vf_cfg[vf].vlan_tag = vlan;
status = be_cmd_set_hsw_config(adapter, vlan,
- vf + 1, adapter->vf_cfg[vf].if_handle);
+ vf + 1, adapter->vf_cfg[vf].if_handle, 0);
}
} else {
/* Reset Transparent Vlan Tagging. */
adapter->vf_cfg[vf].vlan_tag = 0;
vlan = adapter->vf_cfg[vf].def_vid;
status = be_cmd_set_hsw_config(adapter, vlan, vf + 1,
- adapter->vf_cfg[vf].if_handle);
+ adapter->vf_cfg[vf].if_handle, 0);
}
@@ -2917,7 +2918,7 @@
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, NULL);
if (status)
goto err;
vf_cfg->def_vid = def_vlan;
@@ -3795,6 +3796,74 @@
return status;
}
+static int be_ndo_bridge_setlink(struct net_device *dev,
+ struct nlmsghdr *nlh)
+{
+ struct be_adapter *adapter = netdev_priv(dev);
+ struct nlattr *attr, *br_spec;
+ int rem;
+ int status = 0;
+ u16 mode = 0;
+
+ if (!sriov_enabled(adapter))
+ return -EOPNOTSUPP;
+
+ br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+
+ nla_for_each_nested(attr, br_spec, rem) {
+ if (nla_type(attr) != IFLA_BRIDGE_MODE)
+ continue;
+
+ mode = nla_get_u16(attr);
+ if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB)
+ return -EINVAL;
+
+ status = be_cmd_set_hsw_config(adapter, 0, 0,
+ adapter->if_handle,
+ mode == BRIDGE_MODE_VEPA ?
+ PORT_FWD_TYPE_VEPA :
+ PORT_FWD_TYPE_VEB);
+ if (status)
+ goto err;
+
+ dev_info(&adapter->pdev->dev, "enabled switch mode: %s\n",
+ mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB");
+
+ return status;
+ }
+err:
+ dev_err(&adapter->pdev->dev, "Failed to set switch mode %s\n",
+ mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB");
+
+ return status;
+}
+
+static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+ struct net_device *dev,
+ u32 filter_mask)
+{
+ struct be_adapter *adapter = netdev_priv(dev);
+ int status = 0;
+ u8 hsw_mode;
+
+ if (!sriov_enabled(adapter))
+ return 0;
+
+ /* BE and Lancer chips support VEB mode only */
+ if (BEx_chip(adapter) || lancer_chip(adapter)) {
+ hsw_mode = PORT_FWD_TYPE_VEB;
+ } else {
+ status = be_cmd_get_hsw_config(adapter, NULL, 0,
+ adapter->if_handle, &hsw_mode);
+ if (status)
+ return 0;
+ }
+
+ return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
+ hsw_mode == PORT_FWD_TYPE_VEPA ?
+ BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB);
+}
+
static const struct net_device_ops be_netdev_ops = {
.ndo_open = be_open,
.ndo_stop = be_close,
@@ -3813,6 +3882,8 @@
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = be_netpoll,
#endif
+ .ndo_bridge_setlink = be_ndo_bridge_setlink,
+ .ndo_bridge_getlink = be_ndo_bridge_getlink,
};
static void be_netdev_init(struct net_device *netdev)