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>
This commit is contained in:
parent
bc6fc9fa0e
commit
a77dcb8c8f
|
@ -2876,7 +2876,7 @@ int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom)
|
|||
}
|
||||
|
||||
int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
|
||||
u32 domain, u16 intf_id)
|
||||
u32 domain, u16 intf_id, u16 hsw_mode)
|
||||
{
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_cmd_req_set_hsw_config *req;
|
||||
|
@ -2903,6 +2903,13 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
|
|||
AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1);
|
||||
AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid);
|
||||
}
|
||||
if (!BEx_chip(adapter) && hsw_mode) {
|
||||
AMAP_SET_BITS(struct amap_set_hsw_context, interface_id,
|
||||
ctxt, adapter->hba_port_num);
|
||||
AMAP_SET_BITS(struct amap_set_hsw_context, pport, ctxt, 1);
|
||||
AMAP_SET_BITS(struct amap_set_hsw_context, port_fwd_type,
|
||||
ctxt, hsw_mode);
|
||||
}
|
||||
|
||||
be_dws_cpu_to_le(req->context, sizeof(req->context));
|
||||
status = be_mcc_notify_wait(adapter);
|
||||
|
@ -2914,7 +2921,7 @@ err:
|
|||
|
||||
/* Get Hyper switch config */
|
||||
int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
|
||||
u32 domain, u16 intf_id)
|
||||
u32 domain, u16 intf_id, u8 *mode)
|
||||
{
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_cmd_req_get_hsw_config *req;
|
||||
|
@ -2937,9 +2944,15 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
|
|||
OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb, NULL);
|
||||
|
||||
req->hdr.domain = domain;
|
||||
AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id, ctxt,
|
||||
intf_id);
|
||||
AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
|
||||
ctxt, intf_id);
|
||||
AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1);
|
||||
|
||||
if (!BEx_chip(adapter)) {
|
||||
AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id,
|
||||
ctxt, adapter->hba_port_num);
|
||||
AMAP_SET_BITS(struct amap_get_hsw_req_context, pport, ctxt, 1);
|
||||
}
|
||||
be_dws_cpu_to_le(req->context, sizeof(req->context));
|
||||
|
||||
status = be_mcc_notify_wait(adapter);
|
||||
|
@ -2950,7 +2963,11 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
|
|||
sizeof(resp->context));
|
||||
vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
|
||||
pvid, &resp->context);
|
||||
*pvid = le16_to_cpu(vid);
|
||||
if (pvid)
|
||||
*pvid = le16_to_cpu(vid);
|
||||
if (mode)
|
||||
*mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
|
||||
port_fwd_type, &resp->context);
|
||||
}
|
||||
|
||||
err:
|
||||
|
|
|
@ -1533,12 +1533,17 @@ struct be_cmd_req_set_mac_list {
|
|||
} __packed;
|
||||
|
||||
/*********************** HSW Config ***********************/
|
||||
#define PORT_FWD_TYPE_VEPA 0x3
|
||||
#define PORT_FWD_TYPE_VEB 0x2
|
||||
|
||||
struct amap_set_hsw_context {
|
||||
u8 interface_id[16];
|
||||
u8 rsvd0[14];
|
||||
u8 pvid_valid;
|
||||
u8 rsvd1;
|
||||
u8 rsvd2[16];
|
||||
u8 pport;
|
||||
u8 rsvd1[6];
|
||||
u8 port_fwd_type[3];
|
||||
u8 rsvd2[7];
|
||||
u8 pvid[16];
|
||||
u8 rsvd3[32];
|
||||
u8 rsvd4[32];
|
||||
|
@ -1563,7 +1568,9 @@ struct amap_get_hsw_req_context {
|
|||
} __packed;
|
||||
|
||||
struct amap_get_hsw_resp_context {
|
||||
u8 rsvd1[16];
|
||||
u8 rsvd0[6];
|
||||
u8 port_fwd_type[3];
|
||||
u8 rsvd1[7];
|
||||
u8 pvid[16];
|
||||
u8 rsvd2[32];
|
||||
u8 rsvd3[32];
|
||||
|
@ -1965,9 +1972,9 @@ extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
|
|||
extern int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id,
|
||||
u32 dom);
|
||||
extern int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
|
||||
u32 domain, u16 intf_id);
|
||||
u32 domain, u16 intf_id, u16 hsw_mode);
|
||||
extern int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
|
||||
u32 domain, u16 intf_id);
|
||||
u32 domain, u16 intf_id, u8 *mode);
|
||||
extern int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter);
|
||||
extern int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
|
||||
struct be_dma_mem *cmd);
|
||||
|
|
|
@ -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 @@ static int be_set_vf_vlan(struct net_device *netdev,
|
|||
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 @@ static int be_vf_setup(struct be_adapter *adapter)
|
|||
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 @@ fw_exit:
|
|||
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 @@ static const struct net_device_ops be_netdev_ops = {
|
|||
#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)
|
||||
|
|
Loading…
Reference in New Issue