Commit 91b7282b authored by Rajesh Borundia's avatar Rajesh Borundia Committed by David S. Miller
Browse files

qlcnic: Support VLAN id config.



o Add support for VLAN id configuration per VF using
  iproute2 tool.
o VLAN id's 1-4094 are treated as PVID by the PF and
  Guest VLAN tagging is not allowed by default.
o PVID is disabled when the VLAN id is set to 0
o Guest VLAN tagging is allowed when the VLAN id is set to 4095.
o Only one Guest VLAN id  is supported.
o VLAN id can be changed only when the VF driver is not loaded.

Signed-off-by: default avatarManish Chopra <manish.chopra@qlogic.com>
Signed-off-by: default avatarSucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: default avatarRajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4000e7a7
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -979,7 +979,8 @@ struct qlcnic_adapter {
	u8 reset_ctx_cnt;

	u16 is_up;
	u16 pvid;
	u16 rx_pvid;
	u16 tx_pvid;

	u32 irq;
	u32 heartbeat;
@@ -1445,10 +1446,10 @@ void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
		struct qlcnic_host_rds_ring *rds_ring, u8 ring_id);
int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max);
void qlcnic_set_multi(struct net_device *netdev);
void __qlcnic_set_multi(struct net_device *netdev);
int qlcnic_nic_add_mac(struct qlcnic_adapter *, const u8 *);
void __qlcnic_set_multi(struct net_device *, u16);
int qlcnic_nic_add_mac(struct qlcnic_adapter *, const u8 *, u16);
int qlcnic_nic_del_mac(struct qlcnic_adapter *, const u8 *);
void qlcnic_free_mac_list(struct qlcnic_adapter *adapter);
void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter);

int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu);
int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *);
@@ -1530,7 +1531,7 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter);
int qlcnic_read_mac_addr(struct qlcnic_adapter *);
int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
void qlcnic_sriov_vf_schedule_multi(struct net_device *);
void qlcnic_vf_add_mc_list(struct net_device *);
void qlcnic_vf_add_mc_list(struct net_device *, u16);

/*
 * QLOGIC Board information
@@ -1606,6 +1607,7 @@ struct qlcnic_hardware_ops {
	int (*config_promisc_mode) (struct qlcnic_adapter *, u32);
	void (*change_l2_filter) (struct qlcnic_adapter *, u64 *, u16);
	int (*get_board_info) (struct qlcnic_adapter *);
	void (*free_mac_list) (struct qlcnic_adapter *);
};

extern struct qlcnic_nic_template qlcnic_vf_ops;
@@ -1815,6 +1817,11 @@ static inline int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
	return adapter->ahw->hw_ops->get_board_info(adapter);
}

static inline void qlcnic_free_mac_list(struct qlcnic_adapter *adapter)
{
	return adapter->ahw->hw_ops->free_mac_list(adapter);
}

static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter,
					    u32 key)
{
+5 −0
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
	.config_promisc_mode		= qlcnic_83xx_nic_set_promisc,
	.change_l2_filter		= qlcnic_83xx_change_l2_filter,
	.get_board_info			= qlcnic_83xx_get_port_info,
	.free_mac_list			= qlcnic_82xx_free_mac_list,
};

static struct qlcnic_nic_template qlcnic_83xx_ops = {
@@ -1797,6 +1798,10 @@ int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
	if (err)
		return err;

	if (vlan_id)
		op = (op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
		     QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL;

	cmd.req.arg[1] = op | (1 << 8);
	qlcnic_83xx_set_interface_id_macaddr(adapter, &temp);
	cmd.req.arg[1] |= temp;
+9 −9
Original line number Diff line number Diff line
@@ -468,7 +468,7 @@ int qlcnic_nic_del_mac(struct qlcnic_adapter *adapter, const u8 *addr)
	return err;
}

int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr)
int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan)
{
	struct list_head *head;
	struct qlcnic_mac_list_s *cur;
@@ -487,7 +487,7 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr)
	memcpy(cur->mac_addr, addr, ETH_ALEN);

	if (qlcnic_sre_macaddr_change(adapter,
				cur->mac_addr, 0, QLCNIC_MAC_ADD)) {
				cur->mac_addr, vlan, QLCNIC_MAC_ADD)) {
		kfree(cur);
		return -EIO;
	}
@@ -496,7 +496,7 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr)
	return 0;
}

void __qlcnic_set_multi(struct net_device *netdev)
void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct netdev_hw_addr *ha;
@@ -509,8 +509,8 @@ void __qlcnic_set_multi(struct net_device *netdev)
		return;

	if (!qlcnic_sriov_vf_check(adapter))
		qlcnic_nic_add_mac(adapter, adapter->mac_addr);
	qlcnic_nic_add_mac(adapter, bcast_addr);
		qlcnic_nic_add_mac(adapter, adapter->mac_addr, vlan);
	qlcnic_nic_add_mac(adapter, bcast_addr, vlan);

	if (netdev->flags & IFF_PROMISC) {
		if (!(adapter->flags & QLCNIC_PROMISC_DISABLED))
@@ -526,12 +526,12 @@ void __qlcnic_set_multi(struct net_device *netdev)

	if (!netdev_mc_empty(netdev) && !qlcnic_sriov_vf_check(adapter)) {
		netdev_for_each_mc_addr(ha, netdev) {
			qlcnic_nic_add_mac(adapter, ha->addr);
			qlcnic_nic_add_mac(adapter, ha->addr, vlan);
		}
	}

	if (qlcnic_sriov_vf_check(adapter))
		qlcnic_vf_add_mc_list(netdev);
		qlcnic_vf_add_mc_list(netdev, vlan);

send_fw_cmd:
	if (!qlcnic_sriov_vf_check(adapter)) {
@@ -570,7 +570,7 @@ void qlcnic_set_multi(struct net_device *netdev)
		qlcnic_sriov_vf_schedule_multi(adapter->netdev);
		return;
	}
	__qlcnic_set_multi(netdev);
	__qlcnic_set_multi(netdev, 0);
}

int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
@@ -592,7 +592,7 @@ int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
				(struct cmd_desc_type0 *)&req, 1);
}

void qlcnic_free_mac_list(struct qlcnic_adapter *adapter)
void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter)
{
	struct qlcnic_mac_list_s *cur;
	struct list_head *head = &adapter->mac_list;
+4 −4
Original line number Diff line number Diff line
@@ -344,14 +344,14 @@ static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
		flags = FLAGS_VLAN_OOB;
		vlan_tci = vlan_tx_tag_get(skb);
	}
	if (unlikely(adapter->pvid)) {
	if (unlikely(adapter->tx_pvid)) {
		if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
			return -EIO;
		if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
			goto set_flags;

		flags = FLAGS_VLAN_OOB;
		vlan_tci = adapter->pvid;
		vlan_tci = adapter->tx_pvid;
	}
set_flags:
	qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
@@ -980,10 +980,10 @@ static inline int qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter,
		memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
		skb_pull(skb, VLAN_HLEN);
	}
	if (!adapter->pvid)
	if (!adapter->rx_pvid)
		return 0;

	if (*vlan_tag == adapter->pvid) {
	if (*vlan_tag == adapter->rx_pvid) {
		/* Outer vlan tag. Packet should follow non-vlan path */
		*vlan_tag = 0xffff;
		return 0;
+36 −5
Original line number Diff line number Diff line
@@ -290,7 +290,7 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
		return err;

	if (is_unicast_ether_addr(addr))
		err = qlcnic_nic_add_mac(adapter, addr);
		err = qlcnic_nic_add_mac(adapter, addr, 0);
	else if (is_multicast_ether_addr(addr))
		err = dev_mc_add_excl(netdev, addr);
	else
@@ -345,6 +345,7 @@ static const struct net_device_ops qlcnic_netdev_ops = {
	.ndo_set_vf_mac		= qlcnic_sriov_set_vf_mac,
	.ndo_set_vf_tx_rate	= qlcnic_sriov_set_vf_tx_rate,
	.ndo_get_vf_config	= qlcnic_sriov_get_vf_config,
	.ndo_set_vf_vlan	= qlcnic_sriov_set_vf_vlan,
#endif
};

@@ -404,6 +405,7 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
	.config_promisc_mode		= qlcnic_82xx_nic_set_promisc,
	.change_l2_filter		= qlcnic_82xx_change_filter,
	.get_board_info			= qlcnic_82xx_get_board_info,
	.free_mac_list			= qlcnic_82xx_free_mac_list,
};

int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
@@ -900,16 +902,31 @@ void qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
	else
		adapter->flags |= QLCNIC_TAGGING_ENABLED;

	if (esw_cfg->vlan_id)
		adapter->pvid = esw_cfg->vlan_id;
	else
		adapter->pvid = 0;
	if (esw_cfg->vlan_id) {
		adapter->rx_pvid = esw_cfg->vlan_id;
		adapter->tx_pvid = esw_cfg->vlan_id;
	} else {
		adapter->rx_pvid = 0;
		adapter->tx_pvid = 0;
	}
}

static int
qlcnic_vlan_rx_add(struct net_device *netdev, __be16 proto, u16 vid)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	int err;

	if (qlcnic_sriov_vf_check(adapter)) {
		err = qlcnic_sriov_cfg_vf_guest_vlan(adapter, vid, 1);
		if (err) {
			netdev_err(netdev,
				   "Cannot add VLAN filter for VLAN id %d, err=%d",
				   vid, err);
			return err;
		}
	}

	set_bit(vid, adapter->vlans);
	return 0;
}
@@ -918,6 +935,17 @@ static int
qlcnic_vlan_rx_del(struct net_device *netdev, __be16 proto, u16 vid)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	int err;

	if (qlcnic_sriov_vf_check(adapter)) {
		err = qlcnic_sriov_cfg_vf_guest_vlan(adapter, vid, 0);
		if (err) {
			netdev_err(netdev,
				   "Cannot delete VLAN filter for VLAN id %d, err=%d",
				   vid, err);
			return err;
		}
	}

	qlcnic_restore_indev_addr(netdev, NETDEV_DOWN);
	clear_bit(vid, adapter->vlans);
@@ -1736,6 +1764,9 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
	if (qlcnic_vlan_tx_check(adapter))
		netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX);

	if (qlcnic_sriov_vf_check(adapter))
		netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;

	if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
		netdev->features |= NETIF_F_LRO;

Loading