Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a77dcb8c authored by Ajit Khaparde's avatar Ajit Khaparde Committed by David S. Miller
Browse files

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: default avatarAjit Khaparde <ajit.khaparde@emulex.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bc6fc9fa
Loading
Loading
Loading
Loading
+22 −5
Original line number Diff line number Diff line
@@ -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 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,

/* 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);
		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:
+12 −5
Original line number Diff line number Diff line
@@ -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);
+74 −3
Original line number Diff line number Diff line
@@ -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 @@ int be_load_fw(struct be_adapter *adapter, u8 *fw_file)
	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)