1004b26b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
202feda17SRajesh Borundia /*
302feda17SRajesh Borundia  * QLogic qlcnic NIC Driver
402feda17SRajesh Borundia  * Copyright (c) 2009-2013 QLogic Corporation
502feda17SRajesh Borundia  */
602feda17SRajesh Borundia 
7a930a463SHarish Patil #include <linux/types.h>
8a930a463SHarish Patil 
902feda17SRajesh Borundia #include "qlcnic_sriov.h"
1002feda17SRajesh Borundia #include "qlcnic.h"
1102feda17SRajesh Borundia 
121414abeaSSucheta Chakraborty #define QLCNIC_SRIOV_VF_MAX_MAC 7
134000e7a7SRajesh Borundia #define QLC_VF_MIN_TX_RATE	100
144000e7a7SRajesh Borundia #define QLC_VF_MAX_TX_RATE	9999
151414abeaSSucheta Chakraborty #define QLC_MAC_OPCODE_MASK	0x7
16820b52fdSSucheta Chakraborty #define QLC_VF_FLOOD_BIT	BIT_16
17820b52fdSSucheta Chakraborty #define QLC_FLOOD_MODE		0x5
18cecd59d8SRajesh Borundia #define QLC_SRIOV_ALLOW_VLAN0	BIT_19
19868e9144SSucheta Chakraborty #define QLC_INTR_COAL_TYPE_MASK	0x7
2002feda17SRajesh Borundia 
2102feda17SRajesh Borundia static int qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter *, u8);
2202feda17SRajesh Borundia 
23f197a7aaSRajesh Borundia struct qlcnic_sriov_cmd_handler {
24f197a7aaSRajesh Borundia 	int (*fn) (struct qlcnic_bc_trans *, struct qlcnic_cmd_args *);
25f197a7aaSRajesh Borundia };
26f197a7aaSRajesh Borundia 
277cb03b23SRajesh Borundia struct qlcnic_sriov_fw_cmd_handler {
287cb03b23SRajesh Borundia 	u32 cmd;
297cb03b23SRajesh Borundia 	int (*fn) (struct qlcnic_bc_trans *, struct qlcnic_cmd_args *);
307cb03b23SRajesh Borundia };
317cb03b23SRajesh Borundia 
qlcnic_sriov_pf_set_vport_info(struct qlcnic_adapter * adapter,struct qlcnic_info * npar_info,u16 vport_id)3202feda17SRajesh Borundia static int qlcnic_sriov_pf_set_vport_info(struct qlcnic_adapter *adapter,
3302feda17SRajesh Borundia 					  struct qlcnic_info *npar_info,
3402feda17SRajesh Borundia 					  u16 vport_id)
3502feda17SRajesh Borundia {
3602feda17SRajesh Borundia 	struct qlcnic_cmd_args cmd;
3702feda17SRajesh Borundia 	int err;
3802feda17SRajesh Borundia 
3902feda17SRajesh Borundia 	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO))
4002feda17SRajesh Borundia 		return -ENOMEM;
4102feda17SRajesh Borundia 
4202feda17SRajesh Borundia 	cmd.req.arg[1] = (vport_id << 16) | 0x1;
4302feda17SRajesh Borundia 	cmd.req.arg[2] = npar_info->bit_offsets;
4402feda17SRajesh Borundia 	cmd.req.arg[2] |= npar_info->min_tx_bw << 16;
4502feda17SRajesh Borundia 	cmd.req.arg[3] = npar_info->max_tx_bw | (npar_info->max_tx_ques << 16);
4602feda17SRajesh Borundia 	cmd.req.arg[4] = npar_info->max_tx_mac_filters;
4702feda17SRajesh Borundia 	cmd.req.arg[4] |= npar_info->max_rx_mcast_mac_filters << 16;
4802feda17SRajesh Borundia 	cmd.req.arg[5] = npar_info->max_rx_ucast_mac_filters |
4902feda17SRajesh Borundia 			 (npar_info->max_rx_ip_addr << 16);
5002feda17SRajesh Borundia 	cmd.req.arg[6] = npar_info->max_rx_lro_flow |
5102feda17SRajesh Borundia 			 (npar_info->max_rx_status_rings << 16);
5202feda17SRajesh Borundia 	cmd.req.arg[7] = npar_info->max_rx_buf_rings |
5302feda17SRajesh Borundia 			 (npar_info->max_rx_ques << 16);
5402feda17SRajesh Borundia 	cmd.req.arg[8] = npar_info->max_tx_vlan_keys;
5502feda17SRajesh Borundia 	cmd.req.arg[8] |= npar_info->max_local_ipv6_addrs << 16;
5602feda17SRajesh Borundia 	cmd.req.arg[9] = npar_info->max_remote_ipv6_addrs;
5702feda17SRajesh Borundia 
5802feda17SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, &cmd);
5902feda17SRajesh Borundia 	if (err)
6002feda17SRajesh Borundia 		dev_err(&adapter->pdev->dev,
6102feda17SRajesh Borundia 			"Failed to set vport info, err=%d\n", err);
6202feda17SRajesh Borundia 
6302feda17SRajesh Borundia 	qlcnic_free_mbx_args(&cmd);
6402feda17SRajesh Borundia 	return err;
6502feda17SRajesh Borundia }
6602feda17SRajesh Borundia 
qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter * adapter,struct qlcnic_info * info,u16 func)6702feda17SRajesh Borundia static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
6802feda17SRajesh Borundia 					 struct qlcnic_info *info, u16 func)
6902feda17SRajesh Borundia {
7002feda17SRajesh Borundia 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
7102feda17SRajesh Borundia 	struct qlcnic_resources *res = &sriov->ff_max;
72154d0c81SManish Chopra 	u16 num_macs = sriov->num_allowed_vlans + 1;
734000e7a7SRajesh Borundia 	int ret = -EIO, vpid, id;
744000e7a7SRajesh Borundia 	struct qlcnic_vport *vp;
75154d0c81SManish Chopra 	u32 num_vfs, max, temp;
7602feda17SRajesh Borundia 
7702feda17SRajesh Borundia 	vpid = qlcnic_sriov_pf_get_vport_handle(adapter, func);
7802feda17SRajesh Borundia 	if (vpid < 0)
7902feda17SRajesh Borundia 		return -EINVAL;
8002feda17SRajesh Borundia 
8102feda17SRajesh Borundia 	num_vfs = sriov->num_vfs;
8202feda17SRajesh Borundia 	max = num_vfs + 1;
8302feda17SRajesh Borundia 	info->bit_offsets = 0xffff;
8402feda17SRajesh Borundia 	info->max_tx_ques = res->num_tx_queues / max;
85154d0c81SManish Chopra 
86154d0c81SManish Chopra 	if (qlcnic_83xx_pf_check(adapter))
87d747c333SRajesh Borundia 		num_macs = QLCNIC_83XX_SRIOV_VF_MAX_MAC;
8802feda17SRajesh Borundia 
8902feda17SRajesh Borundia 	info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters;
9002feda17SRajesh Borundia 
9102feda17SRajesh Borundia 	if (adapter->ahw->pci_func == func) {
924000e7a7SRajesh Borundia 		info->min_tx_bw = 0;
934000e7a7SRajesh Borundia 		info->max_tx_bw = MAX_BW;
9456a4342dSDavid S. Miller 
95154d0c81SManish Chopra 		temp = res->num_rx_ucast_mac_filters - num_macs * num_vfs;
96154d0c81SManish Chopra 		info->max_rx_ucast_mac_filters = temp;
97154d0c81SManish Chopra 		temp = res->num_tx_mac_filters - num_macs * num_vfs;
98154d0c81SManish Chopra 		info->max_tx_mac_filters = temp;
99154d0c81SManish Chopra 		temp = num_macs * num_vfs * QLCNIC_SRIOV_VF_MAX_MAC;
100154d0c81SManish Chopra 		temp = res->num_rx_mcast_mac_filters - temp;
101154d0c81SManish Chopra 		info->max_rx_mcast_mac_filters = temp;
102154d0c81SManish Chopra 
103f3e3ccf8SManish Chopra 		info->max_tx_ques = res->num_tx_queues - sriov->num_vfs;
10402feda17SRajesh Borundia 	} else {
1054000e7a7SRajesh Borundia 		id = qlcnic_sriov_func_to_index(adapter, func);
1064000e7a7SRajesh Borundia 		if (id < 0)
1074000e7a7SRajesh Borundia 			return id;
1084000e7a7SRajesh Borundia 		vp = sriov->vf_info[id].vp;
1094000e7a7SRajesh Borundia 		info->min_tx_bw = vp->min_tx_bw;
1104000e7a7SRajesh Borundia 		info->max_tx_bw = vp->max_tx_bw;
11156a4342dSDavid S. Miller 
112154d0c81SManish Chopra 		info->max_rx_ucast_mac_filters = num_macs;
113154d0c81SManish Chopra 		info->max_tx_mac_filters = num_macs;
114154d0c81SManish Chopra 		temp = num_macs * QLCNIC_SRIOV_VF_MAX_MAC;
115154d0c81SManish Chopra 		info->max_rx_mcast_mac_filters = temp;
11656a4342dSDavid S. Miller 
117f3e3ccf8SManish Chopra 		info->max_tx_ques = QLCNIC_SINGLE_RING;
11802feda17SRajesh Borundia 	}
11902feda17SRajesh Borundia 
12002feda17SRajesh Borundia 	info->max_rx_ip_addr = res->num_destip / max;
12102feda17SRajesh Borundia 	info->max_rx_status_rings = res->num_rx_status_rings / max;
12202feda17SRajesh Borundia 	info->max_rx_buf_rings = res->num_rx_buf_rings / max;
12302feda17SRajesh Borundia 	info->max_rx_ques = res->num_rx_queues / max;
12402feda17SRajesh Borundia 	info->max_rx_lro_flow = res->num_lro_flows_supported / max;
12502feda17SRajesh Borundia 	info->max_tx_vlan_keys = res->num_txvlan_keys;
12602feda17SRajesh Borundia 	info->max_local_ipv6_addrs = res->max_local_ipv6_addrs;
12702feda17SRajesh Borundia 	info->max_remote_ipv6_addrs = res->max_remote_ipv6_addrs;
12802feda17SRajesh Borundia 
12902feda17SRajesh Borundia 	ret = qlcnic_sriov_pf_set_vport_info(adapter, info, vpid);
13002feda17SRajesh Borundia 	if (ret)
13102feda17SRajesh Borundia 		return ret;
13202feda17SRajesh Borundia 
13302feda17SRajesh Borundia 	return 0;
13402feda17SRajesh Borundia }
13502feda17SRajesh Borundia 
qlcnic_sriov_pf_set_ff_max_res(struct qlcnic_adapter * adapter,struct qlcnic_info * info)13602feda17SRajesh Borundia static void qlcnic_sriov_pf_set_ff_max_res(struct qlcnic_adapter *adapter,
13702feda17SRajesh Borundia 					   struct qlcnic_info *info)
13802feda17SRajesh Borundia {
13902feda17SRajesh Borundia 	struct qlcnic_resources *ff_max = &adapter->ahw->sriov->ff_max;
14002feda17SRajesh Borundia 
14102feda17SRajesh Borundia 	ff_max->num_tx_mac_filters = info->max_tx_mac_filters;
14202feda17SRajesh Borundia 	ff_max->num_rx_ucast_mac_filters = info->max_rx_ucast_mac_filters;
14302feda17SRajesh Borundia 	ff_max->num_rx_mcast_mac_filters = info->max_rx_mcast_mac_filters;
14402feda17SRajesh Borundia 	ff_max->num_txvlan_keys = info->max_tx_vlan_keys;
14502feda17SRajesh Borundia 	ff_max->num_rx_queues = info->max_rx_ques;
14602feda17SRajesh Borundia 	ff_max->num_tx_queues = info->max_tx_ques;
14702feda17SRajesh Borundia 	ff_max->num_lro_flows_supported = info->max_rx_lro_flow;
14802feda17SRajesh Borundia 	ff_max->num_destip = info->max_rx_ip_addr;
14902feda17SRajesh Borundia 	ff_max->num_rx_buf_rings = info->max_rx_buf_rings;
15002feda17SRajesh Borundia 	ff_max->num_rx_status_rings = info->max_rx_status_rings;
15102feda17SRajesh Borundia 	ff_max->max_remote_ipv6_addrs = info->max_remote_ipv6_addrs;
15202feda17SRajesh Borundia 	ff_max->max_local_ipv6_addrs = info->max_local_ipv6_addrs;
15302feda17SRajesh Borundia }
15402feda17SRajesh Borundia 
qlcnic_sriov_set_vf_max_vlan(struct qlcnic_adapter * adapter,struct qlcnic_info * npar_info)155154d0c81SManish Chopra static void qlcnic_sriov_set_vf_max_vlan(struct qlcnic_adapter *adapter,
156154d0c81SManish Chopra 					 struct qlcnic_info *npar_info)
157154d0c81SManish Chopra {
158154d0c81SManish Chopra 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
159154d0c81SManish Chopra 	int temp, total_fn;
160154d0c81SManish Chopra 
161154d0c81SManish Chopra 	temp = npar_info->max_rx_mcast_mac_filters;
162154d0c81SManish Chopra 	total_fn = sriov->num_vfs + 1;
163154d0c81SManish Chopra 
164154d0c81SManish Chopra 	temp = temp / (QLCNIC_SRIOV_VF_MAX_MAC * total_fn);
165154d0c81SManish Chopra 	sriov->num_allowed_vlans = temp - 1;
166154d0c81SManish Chopra 
167154d0c81SManish Chopra 	if (qlcnic_83xx_pf_check(adapter))
168154d0c81SManish Chopra 		sriov->num_allowed_vlans = 1;
169154d0c81SManish Chopra 
170154d0c81SManish Chopra 	netdev_info(adapter->netdev, "Max Guest VLANs supported per VF = %d\n",
171154d0c81SManish Chopra 		    sriov->num_allowed_vlans);
172154d0c81SManish Chopra }
173154d0c81SManish Chopra 
qlcnic_sriov_get_pf_info(struct qlcnic_adapter * adapter,struct qlcnic_info * npar_info)17402feda17SRajesh Borundia static int qlcnic_sriov_get_pf_info(struct qlcnic_adapter *adapter,
17502feda17SRajesh Borundia 				    struct qlcnic_info *npar_info)
17602feda17SRajesh Borundia {
17702feda17SRajesh Borundia 	int err;
17802feda17SRajesh Borundia 	struct qlcnic_cmd_args cmd;
17902feda17SRajesh Borundia 
18002feda17SRajesh Borundia 	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO))
18102feda17SRajesh Borundia 		return -ENOMEM;
18202feda17SRajesh Borundia 
18302feda17SRajesh Borundia 	cmd.req.arg[1] = 0x2;
18402feda17SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, &cmd);
18502feda17SRajesh Borundia 	if (err) {
18602feda17SRajesh Borundia 		dev_err(&adapter->pdev->dev,
18702feda17SRajesh Borundia 			"Failed to get PF info, err=%d\n", err);
18802feda17SRajesh Borundia 		goto out;
18902feda17SRajesh Borundia 	}
19002feda17SRajesh Borundia 
19102feda17SRajesh Borundia 	npar_info->total_pf = cmd.rsp.arg[2] & 0xff;
19202feda17SRajesh Borundia 	npar_info->total_rss_engines = (cmd.rsp.arg[2] >> 8) & 0xff;
19302feda17SRajesh Borundia 	npar_info->max_vports = MSW(cmd.rsp.arg[2]);
19402feda17SRajesh Borundia 	npar_info->max_tx_ques =  LSW(cmd.rsp.arg[3]);
19502feda17SRajesh Borundia 	npar_info->max_tx_mac_filters = MSW(cmd.rsp.arg[3]);
19602feda17SRajesh Borundia 	npar_info->max_rx_mcast_mac_filters = LSW(cmd.rsp.arg[4]);
19702feda17SRajesh Borundia 	npar_info->max_rx_ucast_mac_filters = MSW(cmd.rsp.arg[4]);
19802feda17SRajesh Borundia 	npar_info->max_rx_ip_addr = LSW(cmd.rsp.arg[5]);
19902feda17SRajesh Borundia 	npar_info->max_rx_lro_flow = MSW(cmd.rsp.arg[5]);
20002feda17SRajesh Borundia 	npar_info->max_rx_status_rings = LSW(cmd.rsp.arg[6]);
20102feda17SRajesh Borundia 	npar_info->max_rx_buf_rings = MSW(cmd.rsp.arg[6]);
20202feda17SRajesh Borundia 	npar_info->max_rx_ques = LSW(cmd.rsp.arg[7]);
20302feda17SRajesh Borundia 	npar_info->max_tx_vlan_keys = MSW(cmd.rsp.arg[7]);
20402feda17SRajesh Borundia 	npar_info->max_local_ipv6_addrs = LSW(cmd.rsp.arg[8]);
20502feda17SRajesh Borundia 	npar_info->max_remote_ipv6_addrs = MSW(cmd.rsp.arg[8]);
20602feda17SRajesh Borundia 
207154d0c81SManish Chopra 	qlcnic_sriov_set_vf_max_vlan(adapter, npar_info);
2080c453de6SRajesh Borundia 	qlcnic_sriov_pf_set_ff_max_res(adapter, npar_info);
20902feda17SRajesh Borundia 	dev_info(&adapter->pdev->dev,
21002feda17SRajesh Borundia 		 "\n\ttotal_pf: %d,\n"
21102feda17SRajesh Borundia 		 "\n\ttotal_rss_engines: %d max_vports: %d max_tx_ques %d,\n"
21202feda17SRajesh Borundia 		 "\tmax_tx_mac_filters: %d max_rx_mcast_mac_filters: %d,\n"
21302feda17SRajesh Borundia 		 "\tmax_rx_ucast_mac_filters: 0x%x, max_rx_ip_addr: %d,\n"
21402feda17SRajesh Borundia 		 "\tmax_rx_lro_flow: %d max_rx_status_rings: %d,\n"
21502feda17SRajesh Borundia 		 "\tmax_rx_buf_rings: %d, max_rx_ques: %d, max_tx_vlan_keys %d\n"
21602feda17SRajesh Borundia 		 "\tmax_local_ipv6_addrs: %d, max_remote_ipv6_addrs: %d\n",
21702feda17SRajesh Borundia 		 npar_info->total_pf, npar_info->total_rss_engines,
21802feda17SRajesh Borundia 		 npar_info->max_vports, npar_info->max_tx_ques,
21902feda17SRajesh Borundia 		 npar_info->max_tx_mac_filters,
22002feda17SRajesh Borundia 		 npar_info->max_rx_mcast_mac_filters,
22102feda17SRajesh Borundia 		 npar_info->max_rx_ucast_mac_filters, npar_info->max_rx_ip_addr,
22202feda17SRajesh Borundia 		 npar_info->max_rx_lro_flow, npar_info->max_rx_status_rings,
22302feda17SRajesh Borundia 		 npar_info->max_rx_buf_rings, npar_info->max_rx_ques,
22402feda17SRajesh Borundia 		 npar_info->max_tx_vlan_keys, npar_info->max_local_ipv6_addrs,
22502feda17SRajesh Borundia 		 npar_info->max_remote_ipv6_addrs);
22602feda17SRajesh Borundia 
22702feda17SRajesh Borundia out:
22802feda17SRajesh Borundia 	qlcnic_free_mbx_args(&cmd);
22902feda17SRajesh Borundia 	return err;
23002feda17SRajesh Borundia }
23102feda17SRajesh Borundia 
qlcnic_sriov_pf_reset_vport_handle(struct qlcnic_adapter * adapter,u8 func)23202feda17SRajesh Borundia static void qlcnic_sriov_pf_reset_vport_handle(struct qlcnic_adapter *adapter,
23302feda17SRajesh Borundia 					       u8 func)
23402feda17SRajesh Borundia {
23502feda17SRajesh Borundia 	struct qlcnic_sriov  *sriov = adapter->ahw->sriov;
236f197a7aaSRajesh Borundia 	struct qlcnic_vport *vp;
237f197a7aaSRajesh Borundia 	int index;
23802feda17SRajesh Borundia 
239f197a7aaSRajesh Borundia 	if (adapter->ahw->pci_func == func) {
24002feda17SRajesh Borundia 		sriov->vp_handle = 0;
241f197a7aaSRajesh Borundia 	} else {
242f197a7aaSRajesh Borundia 		index = qlcnic_sriov_func_to_index(adapter, func);
243f197a7aaSRajesh Borundia 		if (index < 0)
244f197a7aaSRajesh Borundia 			return;
245f197a7aaSRajesh Borundia 		vp = sriov->vf_info[index].vp;
246f197a7aaSRajesh Borundia 		vp->handle = 0;
247f197a7aaSRajesh Borundia 	}
24802feda17SRajesh Borundia }
24902feda17SRajesh Borundia 
qlcnic_sriov_pf_set_vport_handle(struct qlcnic_adapter * adapter,u16 vport_handle,u8 func)25002feda17SRajesh Borundia static void qlcnic_sriov_pf_set_vport_handle(struct qlcnic_adapter *adapter,
25102feda17SRajesh Borundia 					     u16 vport_handle, u8 func)
25202feda17SRajesh Borundia {
25302feda17SRajesh Borundia 	struct qlcnic_sriov  *sriov = adapter->ahw->sriov;
254f197a7aaSRajesh Borundia 	struct qlcnic_vport *vp;
255f197a7aaSRajesh Borundia 	int index;
25602feda17SRajesh Borundia 
257f197a7aaSRajesh Borundia 	if (adapter->ahw->pci_func == func) {
25802feda17SRajesh Borundia 		sriov->vp_handle = vport_handle;
259f197a7aaSRajesh Borundia 	} else {
260f197a7aaSRajesh Borundia 		index = qlcnic_sriov_func_to_index(adapter, func);
261f197a7aaSRajesh Borundia 		if (index < 0)
262f197a7aaSRajesh Borundia 			return;
263f197a7aaSRajesh Borundia 		vp = sriov->vf_info[index].vp;
264f197a7aaSRajesh Borundia 		vp->handle = vport_handle;
265f197a7aaSRajesh Borundia 	}
26602feda17SRajesh Borundia }
26702feda17SRajesh Borundia 
qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter * adapter,u8 func)26802feda17SRajesh Borundia static int qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter *adapter,
26902feda17SRajesh Borundia 					    u8 func)
27002feda17SRajesh Borundia {
27102feda17SRajesh Borundia 	struct qlcnic_sriov  *sriov = adapter->ahw->sriov;
272f197a7aaSRajesh Borundia 	struct qlcnic_vf_info *vf_info;
273f197a7aaSRajesh Borundia 	int index;
27402feda17SRajesh Borundia 
275f197a7aaSRajesh Borundia 	if (adapter->ahw->pci_func == func) {
27602feda17SRajesh Borundia 		return sriov->vp_handle;
277f197a7aaSRajesh Borundia 	} else {
278f197a7aaSRajesh Borundia 		index = qlcnic_sriov_func_to_index(adapter, func);
279f197a7aaSRajesh Borundia 		if (index >= 0) {
280f197a7aaSRajesh Borundia 			vf_info = &sriov->vf_info[index];
281f197a7aaSRajesh Borundia 			return vf_info->vp->handle;
282f197a7aaSRajesh Borundia 		}
283f197a7aaSRajesh Borundia 	}
28402feda17SRajesh Borundia 
28502feda17SRajesh Borundia 	return -EINVAL;
28602feda17SRajesh Borundia }
28702feda17SRajesh Borundia 
qlcnic_sriov_pf_config_vport(struct qlcnic_adapter * adapter,u8 flag,u16 func)28802feda17SRajesh Borundia static int qlcnic_sriov_pf_config_vport(struct qlcnic_adapter *adapter,
28902feda17SRajesh Borundia 					u8 flag, u16 func)
29002feda17SRajesh Borundia {
29102feda17SRajesh Borundia 	struct qlcnic_cmd_args cmd;
29202feda17SRajesh Borundia 	int ret;
29302feda17SRajesh Borundia 	int vpid;
29402feda17SRajesh Borundia 
29502feda17SRajesh Borundia 	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_VPORT))
29602feda17SRajesh Borundia 		return -ENOMEM;
29702feda17SRajesh Borundia 
29802feda17SRajesh Borundia 	if (flag) {
29902feda17SRajesh Borundia 		cmd.req.arg[3] = func << 8;
30002feda17SRajesh Borundia 	} else {
30102feda17SRajesh Borundia 		vpid = qlcnic_sriov_pf_get_vport_handle(adapter, func);
30202feda17SRajesh Borundia 		if (vpid < 0) {
30302feda17SRajesh Borundia 			ret = -EINVAL;
30402feda17SRajesh Borundia 			goto out;
30502feda17SRajesh Borundia 		}
30602feda17SRajesh Borundia 		cmd.req.arg[3] = ((vpid & 0xffff) << 8) | 1;
30702feda17SRajesh Borundia 	}
30802feda17SRajesh Borundia 
30902feda17SRajesh Borundia 	ret = qlcnic_issue_cmd(adapter, &cmd);
31002feda17SRajesh Borundia 	if (ret) {
31102feda17SRajesh Borundia 		dev_err(&adapter->pdev->dev,
31202feda17SRajesh Borundia 			"Failed %s vport, err %d for func 0x%x\n",
31302feda17SRajesh Borundia 			(flag ? "enable" : "disable"), ret, func);
31402feda17SRajesh Borundia 		goto out;
31502feda17SRajesh Borundia 	}
31602feda17SRajesh Borundia 
31702feda17SRajesh Borundia 	if (flag) {
31802feda17SRajesh Borundia 		vpid = cmd.rsp.arg[2] & 0xffff;
31902feda17SRajesh Borundia 		qlcnic_sriov_pf_set_vport_handle(adapter, vpid, func);
32002feda17SRajesh Borundia 	} else {
32102feda17SRajesh Borundia 		qlcnic_sriov_pf_reset_vport_handle(adapter, func);
32202feda17SRajesh Borundia 	}
32302feda17SRajesh Borundia 
32402feda17SRajesh Borundia out:
32502feda17SRajesh Borundia 	qlcnic_free_mbx_args(&cmd);
32602feda17SRajesh Borundia 	return ret;
32702feda17SRajesh Borundia }
32802feda17SRajesh Borundia 
qlcnic_sriov_pf_cfg_vlan_filtering(struct qlcnic_adapter * adapter,u8 enable)32991b7282bSRajesh Borundia static int qlcnic_sriov_pf_cfg_vlan_filtering(struct qlcnic_adapter *adapter,
33091b7282bSRajesh Borundia 					      u8 enable)
33191b7282bSRajesh Borundia {
33291b7282bSRajesh Borundia 	struct qlcnic_cmd_args cmd;
33391b7282bSRajesh Borundia 	int err;
33491b7282bSRajesh Borundia 
33591b7282bSRajesh Borundia 	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
33691b7282bSRajesh Borundia 	if (err)
33791b7282bSRajesh Borundia 		return err;
33891b7282bSRajesh Borundia 
33991b7282bSRajesh Borundia 	cmd.req.arg[1] = 0x4;
340cecd59d8SRajesh Borundia 	if (enable) {
341d747c333SRajesh Borundia 		adapter->flags |= QLCNIC_VLAN_FILTERING;
34291b7282bSRajesh Borundia 		cmd.req.arg[1] |= BIT_16;
343cecd59d8SRajesh Borundia 		if (qlcnic_84xx_check(adapter))
344cecd59d8SRajesh Borundia 			cmd.req.arg[1] |= QLC_SRIOV_ALLOW_VLAN0;
345d747c333SRajesh Borundia 	} else {
346d747c333SRajesh Borundia 		adapter->flags &= ~QLCNIC_VLAN_FILTERING;
347cecd59d8SRajesh Borundia 	}
34891b7282bSRajesh Borundia 
34991b7282bSRajesh Borundia 	err = qlcnic_issue_cmd(adapter, &cmd);
35091b7282bSRajesh Borundia 	if (err)
35191b7282bSRajesh Borundia 		dev_err(&adapter->pdev->dev,
35291b7282bSRajesh Borundia 			"Failed to configure VLAN filtering, err=%d\n", err);
35391b7282bSRajesh Borundia 
35491b7282bSRajesh Borundia 	qlcnic_free_mbx_args(&cmd);
35591b7282bSRajesh Borundia 	return err;
35691b7282bSRajesh Borundia }
35791b7282bSRajesh Borundia 
358820b52fdSSucheta Chakraborty /* On configuring VF flood bit, PFD will receive traffic from all VFs */
qlcnic_sriov_pf_cfg_flood(struct qlcnic_adapter * adapter)359820b52fdSSucheta Chakraborty static int qlcnic_sriov_pf_cfg_flood(struct qlcnic_adapter *adapter)
360820b52fdSSucheta Chakraborty {
361820b52fdSSucheta Chakraborty 	struct qlcnic_cmd_args cmd;
362820b52fdSSucheta Chakraborty 	int err;
363820b52fdSSucheta Chakraborty 
364820b52fdSSucheta Chakraborty 	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
365820b52fdSSucheta Chakraborty 	if (err)
366820b52fdSSucheta Chakraborty 		return err;
367820b52fdSSucheta Chakraborty 
368820b52fdSSucheta Chakraborty 	cmd.req.arg[1] = QLC_FLOOD_MODE | QLC_VF_FLOOD_BIT;
369820b52fdSSucheta Chakraborty 
370820b52fdSSucheta Chakraborty 	err = qlcnic_issue_cmd(adapter, &cmd);
371820b52fdSSucheta Chakraborty 	if (err)
372820b52fdSSucheta Chakraborty 		dev_err(&adapter->pdev->dev,
373820b52fdSSucheta Chakraborty 			"Failed to configure VF Flood bit on PF, err=%d\n",
374820b52fdSSucheta Chakraborty 			err);
375820b52fdSSucheta Chakraborty 
376820b52fdSSucheta Chakraborty 	qlcnic_free_mbx_args(&cmd);
377820b52fdSSucheta Chakraborty 	return err;
378820b52fdSSucheta Chakraborty }
379820b52fdSSucheta Chakraborty 
qlcnic_sriov_pf_cfg_eswitch(struct qlcnic_adapter * adapter,u8 func,u8 enable)38002feda17SRajesh Borundia static int qlcnic_sriov_pf_cfg_eswitch(struct qlcnic_adapter *adapter,
38102feda17SRajesh Borundia 				       u8 func, u8 enable)
38202feda17SRajesh Borundia {
38302feda17SRajesh Borundia 	struct qlcnic_cmd_args cmd;
38402feda17SRajesh Borundia 	int err = -EIO;
38502feda17SRajesh Borundia 
38602feda17SRajesh Borundia 	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH))
38702feda17SRajesh Borundia 		return -ENOMEM;
38802feda17SRajesh Borundia 
38902feda17SRajesh Borundia 	cmd.req.arg[0] |= (3 << 29);
39002feda17SRajesh Borundia 	cmd.req.arg[1] = ((func & 0xf) << 2) | BIT_6 | BIT_1;
39102feda17SRajesh Borundia 	if (enable)
39202feda17SRajesh Borundia 		cmd.req.arg[1] |= BIT_0;
39302feda17SRajesh Borundia 
39402feda17SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, &cmd);
39502feda17SRajesh Borundia 
39602feda17SRajesh Borundia 	if (err != QLCNIC_RCODE_SUCCESS) {
39702feda17SRajesh Borundia 		dev_err(&adapter->pdev->dev,
39802feda17SRajesh Borundia 			"Failed to enable sriov eswitch%d\n", err);
39902feda17SRajesh Borundia 		err = -EIO;
40002feda17SRajesh Borundia 	}
40102feda17SRajesh Borundia 
40202feda17SRajesh Borundia 	qlcnic_free_mbx_args(&cmd);
40302feda17SRajesh Borundia 	return err;
40402feda17SRajesh Borundia }
40502feda17SRajesh Borundia 
qlcnic_sriov_pf_del_flr_queue(struct qlcnic_adapter * adapter)40697d8105cSRajesh Borundia static void qlcnic_sriov_pf_del_flr_queue(struct qlcnic_adapter *adapter)
40797d8105cSRajesh Borundia {
40897d8105cSRajesh Borundia 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
40997d8105cSRajesh Borundia 	struct qlcnic_back_channel *bc = &sriov->bc;
41097d8105cSRajesh Borundia 	int i;
41197d8105cSRajesh Borundia 
41297d8105cSRajesh Borundia 	for (i = 0; i < sriov->num_vfs; i++)
41397d8105cSRajesh Borundia 		cancel_work_sync(&sriov->vf_info[i].flr_work);
41497d8105cSRajesh Borundia 
41597d8105cSRajesh Borundia 	destroy_workqueue(bc->bc_flr_wq);
41697d8105cSRajesh Borundia }
41797d8105cSRajesh Borundia 
qlcnic_sriov_pf_create_flr_queue(struct qlcnic_adapter * adapter)41897d8105cSRajesh Borundia static int qlcnic_sriov_pf_create_flr_queue(struct qlcnic_adapter *adapter)
41997d8105cSRajesh Borundia {
42097d8105cSRajesh Borundia 	struct qlcnic_back_channel *bc = &adapter->ahw->sriov->bc;
42197d8105cSRajesh Borundia 	struct workqueue_struct *wq;
42297d8105cSRajesh Borundia 
42397d8105cSRajesh Borundia 	wq = create_singlethread_workqueue("qlcnic-flr");
42497d8105cSRajesh Borundia 	if (wq == NULL) {
42597d8105cSRajesh Borundia 		dev_err(&adapter->pdev->dev, "Cannot create FLR workqueue\n");
42697d8105cSRajesh Borundia 		return -ENOMEM;
42797d8105cSRajesh Borundia 	}
42897d8105cSRajesh Borundia 
42997d8105cSRajesh Borundia 	bc->bc_flr_wq =  wq;
43097d8105cSRajesh Borundia 	return 0;
43197d8105cSRajesh Borundia }
43297d8105cSRajesh Borundia 
qlcnic_sriov_pf_cleanup(struct qlcnic_adapter * adapter)43302feda17SRajesh Borundia void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter)
43402feda17SRajesh Borundia {
43502feda17SRajesh Borundia 	u8 func = adapter->ahw->pci_func;
43602feda17SRajesh Borundia 
43702feda17SRajesh Borundia 	if (!qlcnic_sriov_enable_check(adapter))
43802feda17SRajesh Borundia 		return;
43902feda17SRajesh Borundia 
44097d8105cSRajesh Borundia 	qlcnic_sriov_pf_del_flr_queue(adapter);
441f197a7aaSRajesh Borundia 	qlcnic_sriov_cfg_bc_intr(adapter, 0);
44202feda17SRajesh Borundia 	qlcnic_sriov_pf_config_vport(adapter, 0, func);
44302feda17SRajesh Borundia 	qlcnic_sriov_pf_cfg_eswitch(adapter, func, 0);
44491b7282bSRajesh Borundia 	qlcnic_sriov_pf_cfg_vlan_filtering(adapter, 0);
44502feda17SRajesh Borundia 	__qlcnic_sriov_cleanup(adapter);
44602feda17SRajesh Borundia 	adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
44702feda17SRajesh Borundia 	clear_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
44802feda17SRajesh Borundia }
44902feda17SRajesh Borundia 
qlcnic_sriov_pf_disable(struct qlcnic_adapter * adapter)45002feda17SRajesh Borundia void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter)
45102feda17SRajesh Borundia {
45202feda17SRajesh Borundia 	if (!qlcnic_sriov_pf_check(adapter))
45302feda17SRajesh Borundia 		return;
45402feda17SRajesh Borundia 
45502feda17SRajesh Borundia 	if (!qlcnic_sriov_enable_check(adapter))
45602feda17SRajesh Borundia 		return;
45702feda17SRajesh Borundia 
45802feda17SRajesh Borundia 	pci_disable_sriov(adapter->pdev);
45902feda17SRajesh Borundia 	netdev_info(adapter->netdev,
46002feda17SRajesh Borundia 		    "SR-IOV is disabled successfully on port %d\n",
46102feda17SRajesh Borundia 		    adapter->portnum);
46202feda17SRajesh Borundia }
46302feda17SRajesh Borundia 
qlcnic_pci_sriov_disable(struct qlcnic_adapter * adapter)46402feda17SRajesh Borundia static int qlcnic_pci_sriov_disable(struct qlcnic_adapter *adapter)
46502feda17SRajesh Borundia {
46602feda17SRajesh Borundia 	struct net_device *netdev = adapter->netdev;
46702feda17SRajesh Borundia 
468696f1943SManish Chopra 	if (pci_vfs_assigned(adapter->pdev)) {
469696f1943SManish Chopra 		netdev_err(adapter->netdev,
470696f1943SManish Chopra 			   "SR-IOV VFs belonging to port %d are assigned to VMs. SR-IOV can not be disabled on this port\n",
471696f1943SManish Chopra 			   adapter->portnum);
472696f1943SManish Chopra 		netdev_info(adapter->netdev,
473696f1943SManish Chopra 			    "Please detach SR-IOV VFs belonging to port %d from VMs, and then try to disable SR-IOV on this port\n",
474696f1943SManish Chopra 			    adapter->portnum);
475696f1943SManish Chopra 		return -EPERM;
476696f1943SManish Chopra 	}
477696f1943SManish Chopra 
478132a3f2bSRajesh Borundia 	qlcnic_sriov_pf_disable(adapter);
479132a3f2bSRajesh Borundia 
4801ed98ed5SManish Chopra 	rtnl_lock();
48102feda17SRajesh Borundia 	if (netif_running(netdev))
48202feda17SRajesh Borundia 		__qlcnic_down(adapter, netdev);
48302feda17SRajesh Borundia 
484154d0c81SManish Chopra 	qlcnic_sriov_free_vlans(adapter);
485154d0c81SManish Chopra 
48602feda17SRajesh Borundia 	qlcnic_sriov_pf_cleanup(adapter);
48702feda17SRajesh Borundia 
48802feda17SRajesh Borundia 	/* After disabling SRIOV re-init the driver in default mode
48902feda17SRajesh Borundia 	   configure opmode based on op_mode of function
49002feda17SRajesh Borundia 	 */
4911ed98ed5SManish Chopra 	if (qlcnic_83xx_configure_opmode(adapter)) {
4921ed98ed5SManish Chopra 		rtnl_unlock();
49302feda17SRajesh Borundia 		return -EIO;
4941ed98ed5SManish Chopra 	}
49502feda17SRajesh Borundia 
49602feda17SRajesh Borundia 	if (netif_running(netdev))
49702feda17SRajesh Borundia 		__qlcnic_up(adapter, netdev);
49802feda17SRajesh Borundia 
4991ed98ed5SManish Chopra 	rtnl_unlock();
50002feda17SRajesh Borundia 	return 0;
50102feda17SRajesh Borundia }
50202feda17SRajesh Borundia 
qlcnic_sriov_pf_init(struct qlcnic_adapter * adapter)50302feda17SRajesh Borundia static int qlcnic_sriov_pf_init(struct qlcnic_adapter *adapter)
50402feda17SRajesh Borundia {
50502feda17SRajesh Borundia 	struct qlcnic_hardware_context *ahw = adapter->ahw;
50602feda17SRajesh Borundia 	struct qlcnic_info nic_info, pf_info, vp_info;
50702feda17SRajesh Borundia 	int err;
50802feda17SRajesh Borundia 	u8 func = ahw->pci_func;
50902feda17SRajesh Borundia 
51002feda17SRajesh Borundia 	if (!qlcnic_sriov_enable_check(adapter))
51102feda17SRajesh Borundia 		return 0;
51202feda17SRajesh Borundia 
51391b7282bSRajesh Borundia 	err = qlcnic_sriov_pf_cfg_vlan_filtering(adapter, 1);
51402feda17SRajesh Borundia 	if (err)
51597d8105cSRajesh Borundia 		return err;
51602feda17SRajesh Borundia 
517820b52fdSSucheta Chakraborty 	if (qlcnic_84xx_check(adapter)) {
518820b52fdSSucheta Chakraborty 		err = qlcnic_sriov_pf_cfg_flood(adapter);
519820b52fdSSucheta Chakraborty 		if (err)
520820b52fdSSucheta Chakraborty 			goto disable_vlan_filtering;
521820b52fdSSucheta Chakraborty 	}
522820b52fdSSucheta Chakraborty 
52391b7282bSRajesh Borundia 	err = qlcnic_sriov_pf_cfg_eswitch(adapter, func, 1);
52491b7282bSRajesh Borundia 	if (err)
52591b7282bSRajesh Borundia 		goto disable_vlan_filtering;
52691b7282bSRajesh Borundia 
52702feda17SRajesh Borundia 	err = qlcnic_sriov_pf_config_vport(adapter, 1, func);
52802feda17SRajesh Borundia 	if (err)
52902feda17SRajesh Borundia 		goto disable_eswitch;
53002feda17SRajesh Borundia 
53102feda17SRajesh Borundia 	err = qlcnic_sriov_get_pf_info(adapter, &pf_info);
53202feda17SRajesh Borundia 	if (err)
53302feda17SRajesh Borundia 		goto delete_vport;
53402feda17SRajesh Borundia 
53502feda17SRajesh Borundia 	err = qlcnic_get_nic_info(adapter, &nic_info, func);
53602feda17SRajesh Borundia 	if (err)
53702feda17SRajesh Borundia 		goto delete_vport;
53802feda17SRajesh Borundia 
53902feda17SRajesh Borundia 	err = qlcnic_sriov_pf_cal_res_limit(adapter, &vp_info, func);
54002feda17SRajesh Borundia 	if (err)
54102feda17SRajesh Borundia 		goto delete_vport;
54202feda17SRajesh Borundia 
543f197a7aaSRajesh Borundia 	err = qlcnic_sriov_cfg_bc_intr(adapter, 1);
544f197a7aaSRajesh Borundia 	if (err)
545f197a7aaSRajesh Borundia 		goto delete_vport;
546f197a7aaSRajesh Borundia 
54702feda17SRajesh Borundia 	ahw->physical_port = (u8) nic_info.phys_port;
54802feda17SRajesh Borundia 	ahw->switch_mode = nic_info.switch_mode;
54902feda17SRajesh Borundia 	ahw->max_mtu = nic_info.max_mtu;
55002feda17SRajesh Borundia 	ahw->capabilities = nic_info.capabilities;
55102feda17SRajesh Borundia 	ahw->nic_mode = QLC_83XX_SRIOV_MODE;
55202feda17SRajesh Borundia 	return err;
55302feda17SRajesh Borundia 
55402feda17SRajesh Borundia delete_vport:
55502feda17SRajesh Borundia 	qlcnic_sriov_pf_config_vport(adapter, 0, func);
55602feda17SRajesh Borundia 
55702feda17SRajesh Borundia disable_eswitch:
55802feda17SRajesh Borundia 	qlcnic_sriov_pf_cfg_eswitch(adapter, func, 0);
55902feda17SRajesh Borundia 
56091b7282bSRajesh Borundia disable_vlan_filtering:
56191b7282bSRajesh Borundia 	qlcnic_sriov_pf_cfg_vlan_filtering(adapter, 0);
56291b7282bSRajesh Borundia 
56302feda17SRajesh Borundia 	return err;
56402feda17SRajesh Borundia }
56502feda17SRajesh Borundia 
qlcnic_sriov_pf_enable(struct qlcnic_adapter * adapter,int num_vfs)56602feda17SRajesh Borundia static int qlcnic_sriov_pf_enable(struct qlcnic_adapter *adapter, int num_vfs)
56702feda17SRajesh Borundia {
56802feda17SRajesh Borundia 	int err;
56902feda17SRajesh Borundia 
57002feda17SRajesh Borundia 	if (!qlcnic_sriov_enable_check(adapter))
57102feda17SRajesh Borundia 		return 0;
57202feda17SRajesh Borundia 
57302feda17SRajesh Borundia 	err = pci_enable_sriov(adapter->pdev, num_vfs);
57402feda17SRajesh Borundia 	if (err)
57502feda17SRajesh Borundia 		qlcnic_sriov_pf_cleanup(adapter);
57602feda17SRajesh Borundia 
57702feda17SRajesh Borundia 	return err;
57802feda17SRajesh Borundia }
57902feda17SRajesh Borundia 
__qlcnic_pci_sriov_enable(struct qlcnic_adapter * adapter,int num_vfs)58002feda17SRajesh Borundia static int __qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter,
58102feda17SRajesh Borundia 				     int num_vfs)
58202feda17SRajesh Borundia {
58302feda17SRajesh Borundia 	int err = 0;
58402feda17SRajesh Borundia 
58502feda17SRajesh Borundia 	set_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
58602feda17SRajesh Borundia 	adapter->ahw->op_mode = QLCNIC_SRIOV_PF_FUNC;
58702feda17SRajesh Borundia 
58897d8105cSRajesh Borundia 	err = qlcnic_sriov_init(adapter, num_vfs);
58997d8105cSRajesh Borundia 	if (err)
59097d8105cSRajesh Borundia 		goto clear_op_mode;
59102feda17SRajesh Borundia 
59297d8105cSRajesh Borundia 	err = qlcnic_sriov_pf_create_flr_queue(adapter);
59397d8105cSRajesh Borundia 	if (err)
59497d8105cSRajesh Borundia 		goto sriov_cleanup;
59597d8105cSRajesh Borundia 
59697d8105cSRajesh Borundia 	err = qlcnic_sriov_pf_init(adapter);
59797d8105cSRajesh Borundia 	if (err)
59897d8105cSRajesh Borundia 		goto del_flr_queue;
59902feda17SRajesh Borundia 
60060ec7fcfSJiasheng Jiang 	err = qlcnic_sriov_alloc_vlans(adapter);
60160ec7fcfSJiasheng Jiang 	if (err)
60260ec7fcfSJiasheng Jiang 		goto del_flr_queue;
603154d0c81SManish Chopra 
60402feda17SRajesh Borundia 	return err;
60597d8105cSRajesh Borundia 
60697d8105cSRajesh Borundia del_flr_queue:
60797d8105cSRajesh Borundia 	qlcnic_sriov_pf_del_flr_queue(adapter);
60897d8105cSRajesh Borundia 
60997d8105cSRajesh Borundia sriov_cleanup:
61097d8105cSRajesh Borundia 	__qlcnic_sriov_cleanup(adapter);
61197d8105cSRajesh Borundia 
61297d8105cSRajesh Borundia clear_op_mode:
61397d8105cSRajesh Borundia 	clear_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
61497d8105cSRajesh Borundia 	adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
61597d8105cSRajesh Borundia 	return err;
61602feda17SRajesh Borundia }
61702feda17SRajesh Borundia 
qlcnic_pci_sriov_enable(struct qlcnic_adapter * adapter,int num_vfs)61802feda17SRajesh Borundia static int qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter, int num_vfs)
61902feda17SRajesh Borundia {
62002feda17SRajesh Borundia 	struct net_device *netdev = adapter->netdev;
62102feda17SRajesh Borundia 	int err;
62202feda17SRajesh Borundia 
62302feda17SRajesh Borundia 	if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
62402feda17SRajesh Borundia 		netdev_err(netdev,
62502feda17SRajesh Borundia 			   "SR-IOV cannot be enabled, when legacy interrupts are enabled\n");
62602feda17SRajesh Borundia 		return -EIO;
62702feda17SRajesh Borundia 	}
62802feda17SRajesh Borundia 
6291ed98ed5SManish Chopra 	rtnl_lock();
63002feda17SRajesh Borundia 	if (netif_running(netdev))
63102feda17SRajesh Borundia 		__qlcnic_down(adapter, netdev);
63202feda17SRajesh Borundia 
63302feda17SRajesh Borundia 	err = __qlcnic_pci_sriov_enable(adapter, num_vfs);
634132a3f2bSRajesh Borundia 	if (err)
63502feda17SRajesh Borundia 		goto error;
636132a3f2bSRajesh Borundia 
637132a3f2bSRajesh Borundia 	if (netif_running(netdev))
638132a3f2bSRajesh Borundia 		__qlcnic_up(adapter, netdev);
639132a3f2bSRajesh Borundia 
640132a3f2bSRajesh Borundia 	rtnl_unlock();
641132a3f2bSRajesh Borundia 	err = qlcnic_sriov_pf_enable(adapter, num_vfs);
642132a3f2bSRajesh Borundia 	if (!err) {
64397d8105cSRajesh Borundia 		netdev_info(netdev,
64402feda17SRajesh Borundia 			    "SR-IOV is enabled successfully on port %d\n",
64502feda17SRajesh Borundia 			    adapter->portnum);
64697d8105cSRajesh Borundia 		/* Return number of vfs enabled */
647132a3f2bSRajesh Borundia 		return num_vfs;
64802feda17SRajesh Borundia 	}
649132a3f2bSRajesh Borundia 
650132a3f2bSRajesh Borundia 	rtnl_lock();
65102feda17SRajesh Borundia 	if (netif_running(netdev))
652132a3f2bSRajesh Borundia 		__qlcnic_down(adapter, netdev);
65302feda17SRajesh Borundia 
65402feda17SRajesh Borundia error:
655132a3f2bSRajesh Borundia 	if (!qlcnic_83xx_configure_opmode(adapter)) {
656132a3f2bSRajesh Borundia 		if (netif_running(netdev))
657132a3f2bSRajesh Borundia 			__qlcnic_up(adapter, netdev);
658132a3f2bSRajesh Borundia 	}
659132a3f2bSRajesh Borundia 
6601ed98ed5SManish Chopra 	rtnl_unlock();
661132a3f2bSRajesh Borundia 	netdev_info(netdev, "Failed to enable SR-IOV on port %d\n",
662132a3f2bSRajesh Borundia 		    adapter->portnum);
663132a3f2bSRajesh Borundia 
66402feda17SRajesh Borundia 	return err;
66502feda17SRajesh Borundia }
66602feda17SRajesh Borundia 
qlcnic_pci_sriov_configure(struct pci_dev * dev,int num_vfs)66702feda17SRajesh Borundia int qlcnic_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
66802feda17SRajesh Borundia {
66902feda17SRajesh Borundia 	struct qlcnic_adapter *adapter = pci_get_drvdata(dev);
67002feda17SRajesh Borundia 	int err;
67102feda17SRajesh Borundia 
67202feda17SRajesh Borundia 	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
67302feda17SRajesh Borundia 		return -EBUSY;
67402feda17SRajesh Borundia 
67502feda17SRajesh Borundia 	if (num_vfs == 0)
67602feda17SRajesh Borundia 		err = qlcnic_pci_sriov_disable(adapter);
67702feda17SRajesh Borundia 	else
67802feda17SRajesh Borundia 		err = qlcnic_pci_sriov_enable(adapter, num_vfs);
67902feda17SRajesh Borundia 
68002feda17SRajesh Borundia 	clear_bit(__QLCNIC_RESETTING, &adapter->state);
68102feda17SRajesh Borundia 	return err;
68202feda17SRajesh Borundia }
683f197a7aaSRajesh Borundia 
qlcnic_sriov_set_vf_acl(struct qlcnic_adapter * adapter,u8 func)68491b7282bSRajesh Borundia static int qlcnic_sriov_set_vf_acl(struct qlcnic_adapter *adapter, u8 func)
68591b7282bSRajesh Borundia {
68691b7282bSRajesh Borundia 	struct qlcnic_cmd_args cmd;
68791b7282bSRajesh Borundia 	struct qlcnic_vport *vp;
68891b7282bSRajesh Borundia 	int err, id;
689a80be5a5SRajesh Borundia 	u8 *mac;
69091b7282bSRajesh Borundia 
69191b7282bSRajesh Borundia 	id = qlcnic_sriov_func_to_index(adapter, func);
69291b7282bSRajesh Borundia 	if (id < 0)
69391b7282bSRajesh Borundia 		return id;
69491b7282bSRajesh Borundia 
69591b7282bSRajesh Borundia 	vp = adapter->ahw->sriov->vf_info[id].vp;
69691b7282bSRajesh Borundia 	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
69791b7282bSRajesh Borundia 	if (err)
69891b7282bSRajesh Borundia 		return err;
69991b7282bSRajesh Borundia 
70091b7282bSRajesh Borundia 	cmd.req.arg[1] = 0x3 | func << 16;
701a80be5a5SRajesh Borundia 	if (vp->spoofchk == true) {
702a80be5a5SRajesh Borundia 		mac = vp->mac;
703a80be5a5SRajesh Borundia 		cmd.req.arg[2] |= BIT_1 | BIT_3 | BIT_8;
704a80be5a5SRajesh Borundia 		cmd.req.arg[4] = mac[5] | mac[4] << 8 | mac[3] << 16 |
705a80be5a5SRajesh Borundia 				 mac[2] << 24;
706a80be5a5SRajesh Borundia 		cmd.req.arg[5] = mac[1] | mac[0] << 8;
707a80be5a5SRajesh Borundia 	}
708a80be5a5SRajesh Borundia 
70991b7282bSRajesh Borundia 	if (vp->vlan_mode == QLC_PVID_MODE) {
71091b7282bSRajesh Borundia 		cmd.req.arg[2] |= BIT_6;
711154d0c81SManish Chopra 		cmd.req.arg[3] |= vp->pvid << 8;
71291b7282bSRajesh Borundia 	}
71391b7282bSRajesh Borundia 
71491b7282bSRajesh Borundia 	err = qlcnic_issue_cmd(adapter, &cmd);
71591b7282bSRajesh Borundia 	if (err)
71691b7282bSRajesh Borundia 		dev_err(&adapter->pdev->dev, "Failed to set ACL, err=%d\n",
71791b7282bSRajesh Borundia 			err);
71891b7282bSRajesh Borundia 
71991b7282bSRajesh Borundia 	qlcnic_free_mbx_args(&cmd);
72091b7282bSRajesh Borundia 	return err;
72191b7282bSRajesh Borundia }
72291b7282bSRajesh Borundia 
qlcnic_sriov_set_vf_vport_info(struct qlcnic_adapter * adapter,u16 func)723f197a7aaSRajesh Borundia static int qlcnic_sriov_set_vf_vport_info(struct qlcnic_adapter *adapter,
724f197a7aaSRajesh Borundia 					  u16 func)
725f197a7aaSRajesh Borundia {
726f197a7aaSRajesh Borundia 	struct qlcnic_info defvp_info;
727f197a7aaSRajesh Borundia 	int err;
728f197a7aaSRajesh Borundia 
729f197a7aaSRajesh Borundia 	err = qlcnic_sriov_pf_cal_res_limit(adapter, &defvp_info, func);
730f197a7aaSRajesh Borundia 	if (err)
731f197a7aaSRajesh Borundia 		return -EIO;
732f197a7aaSRajesh Borundia 
73391b7282bSRajesh Borundia 	err = qlcnic_sriov_set_vf_acl(adapter, func);
73491b7282bSRajesh Borundia 	if (err)
73591b7282bSRajesh Borundia 		return err;
73691b7282bSRajesh Borundia 
737f197a7aaSRajesh Borundia 	return 0;
738f197a7aaSRajesh Borundia }
739f197a7aaSRajesh Borundia 
qlcnic_sriov_pf_channel_cfg_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)740f197a7aaSRajesh Borundia static int qlcnic_sriov_pf_channel_cfg_cmd(struct qlcnic_bc_trans *trans,
741f197a7aaSRajesh Borundia 					   struct qlcnic_cmd_args *cmd)
742f197a7aaSRajesh Borundia {
743f197a7aaSRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
7442f0a9afaSManish Chopra 	struct qlcnic_vport *vp = vf->vp;
7452f0a9afaSManish Chopra 	struct qlcnic_adapter *adapter;
746154d0c81SManish Chopra 	struct qlcnic_sriov *sriov;
747f197a7aaSRajesh Borundia 	u16 func = vf->pci_func;
748154d0c81SManish Chopra 	size_t size;
7492f0a9afaSManish Chopra 	int err;
750f197a7aaSRajesh Borundia 
7512f0a9afaSManish Chopra 	adapter = vf->adapter;
752154d0c81SManish Chopra 	sriov = adapter->ahw->sriov;
753f197a7aaSRajesh Borundia 
754f197a7aaSRajesh Borundia 	if (trans->req_hdr->cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) {
755f197a7aaSRajesh Borundia 		err = qlcnic_sriov_pf_config_vport(adapter, 1, func);
756f197a7aaSRajesh Borundia 		if (!err) {
757f197a7aaSRajesh Borundia 			err = qlcnic_sriov_set_vf_vport_info(adapter, func);
758f197a7aaSRajesh Borundia 			if (err)
759f197a7aaSRajesh Borundia 				qlcnic_sriov_pf_config_vport(adapter, 0, func);
760f197a7aaSRajesh Borundia 		}
761f197a7aaSRajesh Borundia 	} else {
762154d0c81SManish Chopra 		if (vp->vlan_mode == QLC_GUEST_VLAN_MODE) {
763154d0c81SManish Chopra 			size = sizeof(*vf->sriov_vlans);
764154d0c81SManish Chopra 			size = size * sriov->num_allowed_vlans;
765154d0c81SManish Chopra 			memset(vf->sriov_vlans, 0, size);
766154d0c81SManish Chopra 		}
767154d0c81SManish Chopra 
768f197a7aaSRajesh Borundia 		err = qlcnic_sriov_pf_config_vport(adapter, 0, func);
769f197a7aaSRajesh Borundia 	}
770f197a7aaSRajesh Borundia 
771f197a7aaSRajesh Borundia 	if (err)
772f197a7aaSRajesh Borundia 		goto err_out;
773f197a7aaSRajesh Borundia 
774f197a7aaSRajesh Borundia 	cmd->rsp.arg[0] |= (1 << 25);
775f197a7aaSRajesh Borundia 
776f197a7aaSRajesh Borundia 	if (trans->req_hdr->cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT)
777f197a7aaSRajesh Borundia 		set_bit(QLC_BC_VF_STATE, &vf->state);
778f197a7aaSRajesh Borundia 	else
779f197a7aaSRajesh Borundia 		clear_bit(QLC_BC_VF_STATE, &vf->state);
780f197a7aaSRajesh Borundia 
781f197a7aaSRajesh Borundia 	return err;
782f197a7aaSRajesh Borundia 
783f197a7aaSRajesh Borundia err_out:
784f197a7aaSRajesh Borundia 	cmd->rsp.arg[0] |= (2 << 25);
785f197a7aaSRajesh Borundia 	return err;
786f197a7aaSRajesh Borundia }
787f197a7aaSRajesh Borundia 
qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter * adapter,struct qlcnic_vf_info * vf,u16 vlan,u8 op)7887cb03b23SRajesh Borundia static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter,
789154d0c81SManish Chopra 				       struct qlcnic_vf_info *vf,
790154d0c81SManish Chopra 				       u16 vlan, u8 op)
7917cb03b23SRajesh Borundia {
79274b7ba1aSRajesh Borundia 	struct qlcnic_cmd_args *cmd;
7937cb03b23SRajesh Borundia 	struct qlcnic_macvlan_mbx mv;
794154d0c81SManish Chopra 	struct qlcnic_vport *vp;
7957cb03b23SRajesh Borundia 	u8 *addr;
7967cb03b23SRajesh Borundia 	int err;
7977cb03b23SRajesh Borundia 	u32 *buf;
7987cb03b23SRajesh Borundia 	int vpid;
7997cb03b23SRajesh Borundia 
800154d0c81SManish Chopra 	vp = vf->vp;
801154d0c81SManish Chopra 
80274b7ba1aSRajesh Borundia 	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
80374b7ba1aSRajesh Borundia 	if (!cmd)
8047cb03b23SRajesh Borundia 		return -ENOMEM;
8057cb03b23SRajesh Borundia 
80674b7ba1aSRajesh Borundia 	err = qlcnic_alloc_mbx_args(cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
80774b7ba1aSRajesh Borundia 	if (err)
80874b7ba1aSRajesh Borundia 		goto free_cmd;
80974b7ba1aSRajesh Borundia 
81074b7ba1aSRajesh Borundia 	cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
811154d0c81SManish Chopra 	vpid = qlcnic_sriov_pf_get_vport_handle(adapter, vf->pci_func);
8127cb03b23SRajesh Borundia 	if (vpid < 0) {
8137cb03b23SRajesh Borundia 		err = -EINVAL;
81474b7ba1aSRajesh Borundia 		goto free_args;
8157cb03b23SRajesh Borundia 	}
8167cb03b23SRajesh Borundia 
8177cb03b23SRajesh Borundia 	if (vlan)
8187cb03b23SRajesh Borundia 		op = ((op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
8197cb03b23SRajesh Borundia 		      QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL);
8207cb03b23SRajesh Borundia 
82174b7ba1aSRajesh Borundia 	cmd->req.arg[1] = op | (1 << 8) | (3 << 6);
82274b7ba1aSRajesh Borundia 	cmd->req.arg[1] |= ((vpid & 0xffff) << 16) | BIT_31;
8237cb03b23SRajesh Borundia 
8247cb03b23SRajesh Borundia 	addr = vp->mac;
825f80bc8feSRajesh Borundia 	mv.vlan = vlan;
8267cb03b23SRajesh Borundia 	mv.mac_addr0 = addr[0];
8277cb03b23SRajesh Borundia 	mv.mac_addr1 = addr[1];
8287cb03b23SRajesh Borundia 	mv.mac_addr2 = addr[2];
8297cb03b23SRajesh Borundia 	mv.mac_addr3 = addr[3];
8307cb03b23SRajesh Borundia 	mv.mac_addr4 = addr[4];
8317cb03b23SRajesh Borundia 	mv.mac_addr5 = addr[5];
83274b7ba1aSRajesh Borundia 	buf = &cmd->req.arg[2];
8337cb03b23SRajesh Borundia 	memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
8347cb03b23SRajesh Borundia 
83574b7ba1aSRajesh Borundia 	err = qlcnic_issue_cmd(adapter, cmd);
8367cb03b23SRajesh Borundia 
83774b7ba1aSRajesh Borundia 	if (!err)
83874b7ba1aSRajesh Borundia 		return err;
8397cb03b23SRajesh Borundia 
84074b7ba1aSRajesh Borundia free_args:
84174b7ba1aSRajesh Borundia 	qlcnic_free_mbx_args(cmd);
84274b7ba1aSRajesh Borundia free_cmd:
84374b7ba1aSRajesh Borundia 	kfree(cmd);
8447cb03b23SRajesh Borundia 	return err;
8457cb03b23SRajesh Borundia }
8467cb03b23SRajesh Borundia 
qlcnic_sriov_validate_create_rx_ctx(struct qlcnic_cmd_args * cmd)8477cb03b23SRajesh Borundia static int qlcnic_sriov_validate_create_rx_ctx(struct qlcnic_cmd_args *cmd)
8487cb03b23SRajesh Borundia {
8497cb03b23SRajesh Borundia 	if ((cmd->req.arg[0] >> 29) != 0x3)
8507cb03b23SRajesh Borundia 		return -EINVAL;
8517cb03b23SRajesh Borundia 
8527cb03b23SRajesh Borundia 	return 0;
8537cb03b23SRajesh Borundia }
8547cb03b23SRajesh Borundia 
qlcnic_83xx_cfg_default_mac_vlan(struct qlcnic_adapter * adapter,struct qlcnic_vf_info * vf,int opcode)855154d0c81SManish Chopra static void qlcnic_83xx_cfg_default_mac_vlan(struct qlcnic_adapter *adapter,
856154d0c81SManish Chopra 					     struct qlcnic_vf_info *vf,
857154d0c81SManish Chopra 					     int opcode)
858154d0c81SManish Chopra {
859154d0c81SManish Chopra 	struct qlcnic_sriov *sriov;
860154d0c81SManish Chopra 	u16 vlan;
861154d0c81SManish Chopra 	int i;
862154d0c81SManish Chopra 
863154d0c81SManish Chopra 	sriov = adapter->ahw->sriov;
864154d0c81SManish Chopra 
86574b7ba1aSRajesh Borundia 	spin_lock_bh(&vf->vlan_list_lock);
866154d0c81SManish Chopra 	if (vf->num_vlan) {
867154d0c81SManish Chopra 		for (i = 0; i < sriov->num_allowed_vlans; i++) {
868154d0c81SManish Chopra 			vlan = vf->sriov_vlans[i];
869154d0c81SManish Chopra 			if (vlan)
870154d0c81SManish Chopra 				qlcnic_sriov_cfg_vf_def_mac(adapter, vf, vlan,
871154d0c81SManish Chopra 							    opcode);
872154d0c81SManish Chopra 		}
873154d0c81SManish Chopra 	}
87474b7ba1aSRajesh Borundia 	spin_unlock_bh(&vf->vlan_list_lock);
875154d0c81SManish Chopra 
876154d0c81SManish Chopra 	if (vf->vp->vlan_mode != QLC_PVID_MODE) {
877154d0c81SManish Chopra 		if (qlcnic_83xx_pf_check(adapter) &&
878154d0c81SManish Chopra 		    qlcnic_sriov_check_any_vlan(vf))
879154d0c81SManish Chopra 			return;
880154d0c81SManish Chopra 		qlcnic_sriov_cfg_vf_def_mac(adapter, vf, 0, opcode);
881154d0c81SManish Chopra 	}
882154d0c81SManish Chopra }
883154d0c81SManish Chopra 
qlcnic_sriov_pf_create_rx_ctx_cmd(struct qlcnic_bc_trans * tran,struct qlcnic_cmd_args * cmd)8847cb03b23SRajesh Borundia static int qlcnic_sriov_pf_create_rx_ctx_cmd(struct qlcnic_bc_trans *tran,
8857cb03b23SRajesh Borundia 					     struct qlcnic_cmd_args *cmd)
8867cb03b23SRajesh Borundia {
8877cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = tran->vf;
8887cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
8897cb03b23SRajesh Borundia 	struct qlcnic_rcv_mbx_out *mbx_out;
8907cb03b23SRajesh Borundia 	int err;
8917cb03b23SRajesh Borundia 
8927cb03b23SRajesh Borundia 	err = qlcnic_sriov_validate_create_rx_ctx(cmd);
8937cb03b23SRajesh Borundia 	if (err) {
8947cb03b23SRajesh Borundia 		cmd->rsp.arg[0] |= (0x6 << 25);
8957cb03b23SRajesh Borundia 		return err;
8967cb03b23SRajesh Borundia 	}
8977cb03b23SRajesh Borundia 
8987cb03b23SRajesh Borundia 	cmd->req.arg[6] = vf->vp->handle;
8997cb03b23SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, cmd);
9007cb03b23SRajesh Borundia 
9017cb03b23SRajesh Borundia 	if (!err) {
9027cb03b23SRajesh Borundia 		mbx_out = (struct qlcnic_rcv_mbx_out *)&cmd->rsp.arg[1];
9037cb03b23SRajesh Borundia 		vf->rx_ctx_id = mbx_out->ctx_id;
904154d0c81SManish Chopra 		qlcnic_83xx_cfg_default_mac_vlan(adapter, vf, QLCNIC_MAC_ADD);
9057cb03b23SRajesh Borundia 	} else {
9067cb03b23SRajesh Borundia 		vf->rx_ctx_id = 0;
9077cb03b23SRajesh Borundia 	}
9087cb03b23SRajesh Borundia 
9097cb03b23SRajesh Borundia 	return err;
9107cb03b23SRajesh Borundia }
9117cb03b23SRajesh Borundia 
qlcnic_sriov_pf_mac_address_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)9127cb03b23SRajesh Borundia static int qlcnic_sriov_pf_mac_address_cmd(struct qlcnic_bc_trans *trans,
9137cb03b23SRajesh Borundia 					   struct qlcnic_cmd_args *cmd)
9147cb03b23SRajesh Borundia {
9157cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
9167cb03b23SRajesh Borundia 	u8 type, *mac;
9177cb03b23SRajesh Borundia 
9187cb03b23SRajesh Borundia 	type = cmd->req.arg[1];
9197cb03b23SRajesh Borundia 	switch (type) {
9207cb03b23SRajesh Borundia 	case QLCNIC_SET_STATION_MAC:
9217cb03b23SRajesh Borundia 	case QLCNIC_SET_FAC_DEF_MAC:
9227cb03b23SRajesh Borundia 		cmd->rsp.arg[0] = (2 << 25);
9237cb03b23SRajesh Borundia 		break;
9247cb03b23SRajesh Borundia 	case QLCNIC_GET_CURRENT_MAC:
9257cb03b23SRajesh Borundia 		cmd->rsp.arg[0] = (1 << 25);
9267cb03b23SRajesh Borundia 		mac = vf->vp->mac;
9277cb03b23SRajesh Borundia 		cmd->rsp.arg[2] = mac[1] | ((mac[0] << 8) & 0xff00);
9287cb03b23SRajesh Borundia 		cmd->rsp.arg[1] = mac[5] | ((mac[4] << 8) & 0xff00) |
9297cb03b23SRajesh Borundia 				  ((mac[3]) << 16 & 0xff0000) |
9307cb03b23SRajesh Borundia 				  ((mac[2]) << 24 & 0xff000000);
9317cb03b23SRajesh Borundia 	}
9327cb03b23SRajesh Borundia 
9337cb03b23SRajesh Borundia 	return 0;
9347cb03b23SRajesh Borundia }
9357cb03b23SRajesh Borundia 
qlcnic_sriov_validate_create_tx_ctx(struct qlcnic_cmd_args * cmd)9367cb03b23SRajesh Borundia static int qlcnic_sriov_validate_create_tx_ctx(struct qlcnic_cmd_args *cmd)
9377cb03b23SRajesh Borundia {
9387cb03b23SRajesh Borundia 	if ((cmd->req.arg[0] >> 29) != 0x3)
9397cb03b23SRajesh Borundia 		return -EINVAL;
9407cb03b23SRajesh Borundia 
9417cb03b23SRajesh Borundia 	return 0;
9427cb03b23SRajesh Borundia }
9437cb03b23SRajesh Borundia 
qlcnic_sriov_pf_create_tx_ctx_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)9447cb03b23SRajesh Borundia static int qlcnic_sriov_pf_create_tx_ctx_cmd(struct qlcnic_bc_trans *trans,
9457cb03b23SRajesh Borundia 					     struct qlcnic_cmd_args *cmd)
9467cb03b23SRajesh Borundia {
9477cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
9487cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
9497cb03b23SRajesh Borundia 	struct qlcnic_tx_mbx_out *mbx_out;
9507cb03b23SRajesh Borundia 	int err;
9517cb03b23SRajesh Borundia 
9527cb03b23SRajesh Borundia 	err = qlcnic_sriov_validate_create_tx_ctx(cmd);
9537cb03b23SRajesh Borundia 	if (err) {
9547cb03b23SRajesh Borundia 		cmd->rsp.arg[0] |= (0x6 << 25);
9557cb03b23SRajesh Borundia 		return err;
9567cb03b23SRajesh Borundia 	}
9577cb03b23SRajesh Borundia 
9587cb03b23SRajesh Borundia 	cmd->req.arg[5] |= vf->vp->handle << 16;
9597cb03b23SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, cmd);
9607cb03b23SRajesh Borundia 	if (!err) {
9617cb03b23SRajesh Borundia 		mbx_out = (struct qlcnic_tx_mbx_out *)&cmd->rsp.arg[2];
9627cb03b23SRajesh Borundia 		vf->tx_ctx_id = mbx_out->ctx_id;
9637cb03b23SRajesh Borundia 	} else {
9647cb03b23SRajesh Borundia 		vf->tx_ctx_id = 0;
9657cb03b23SRajesh Borundia 	}
9667cb03b23SRajesh Borundia 
9677cb03b23SRajesh Borundia 	return err;
9687cb03b23SRajesh Borundia }
9697cb03b23SRajesh Borundia 
qlcnic_sriov_validate_del_rx_ctx(struct qlcnic_vf_info * vf,struct qlcnic_cmd_args * cmd)9707cb03b23SRajesh Borundia static int qlcnic_sriov_validate_del_rx_ctx(struct qlcnic_vf_info *vf,
9717cb03b23SRajesh Borundia 					    struct qlcnic_cmd_args *cmd)
9727cb03b23SRajesh Borundia {
9737cb03b23SRajesh Borundia 	if ((cmd->req.arg[0] >> 29) != 0x3)
9747cb03b23SRajesh Borundia 		return -EINVAL;
9757cb03b23SRajesh Borundia 
9767cb03b23SRajesh Borundia 	if ((cmd->req.arg[1] & 0xffff) != vf->rx_ctx_id)
9777cb03b23SRajesh Borundia 		return -EINVAL;
9787cb03b23SRajesh Borundia 
9797cb03b23SRajesh Borundia 	return 0;
9807cb03b23SRajesh Borundia }
9817cb03b23SRajesh Borundia 
qlcnic_sriov_pf_del_rx_ctx_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)9827cb03b23SRajesh Borundia static int qlcnic_sriov_pf_del_rx_ctx_cmd(struct qlcnic_bc_trans *trans,
9837cb03b23SRajesh Borundia 					  struct qlcnic_cmd_args *cmd)
9847cb03b23SRajesh Borundia {
9857cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
9867cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
9877cb03b23SRajesh Borundia 	int err;
9887cb03b23SRajesh Borundia 
9897cb03b23SRajesh Borundia 	err = qlcnic_sriov_validate_del_rx_ctx(vf, cmd);
9907cb03b23SRajesh Borundia 	if (err) {
9917cb03b23SRajesh Borundia 		cmd->rsp.arg[0] |= (0x6 << 25);
9927cb03b23SRajesh Borundia 		return err;
9937cb03b23SRajesh Borundia 	}
9947cb03b23SRajesh Borundia 
995154d0c81SManish Chopra 	qlcnic_83xx_cfg_default_mac_vlan(adapter, vf, QLCNIC_MAC_DEL);
9967cb03b23SRajesh Borundia 	cmd->req.arg[1] |= vf->vp->handle << 16;
9977cb03b23SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, cmd);
9987cb03b23SRajesh Borundia 
9997cb03b23SRajesh Borundia 	if (!err)
10007cb03b23SRajesh Borundia 		vf->rx_ctx_id = 0;
10017cb03b23SRajesh Borundia 
10027cb03b23SRajesh Borundia 	return err;
10037cb03b23SRajesh Borundia }
10047cb03b23SRajesh Borundia 
qlcnic_sriov_validate_del_tx_ctx(struct qlcnic_vf_info * vf,struct qlcnic_cmd_args * cmd)10057cb03b23SRajesh Borundia static int qlcnic_sriov_validate_del_tx_ctx(struct qlcnic_vf_info *vf,
10067cb03b23SRajesh Borundia 					    struct qlcnic_cmd_args *cmd)
10077cb03b23SRajesh Borundia {
10087cb03b23SRajesh Borundia 	if ((cmd->req.arg[0] >> 29) != 0x3)
10097cb03b23SRajesh Borundia 		return -EINVAL;
10107cb03b23SRajesh Borundia 
10117cb03b23SRajesh Borundia 	if ((cmd->req.arg[1] & 0xffff) != vf->tx_ctx_id)
10127cb03b23SRajesh Borundia 		return -EINVAL;
10137cb03b23SRajesh Borundia 
10147cb03b23SRajesh Borundia 	return 0;
10157cb03b23SRajesh Borundia }
10167cb03b23SRajesh Borundia 
qlcnic_sriov_pf_del_tx_ctx_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)10177cb03b23SRajesh Borundia static int qlcnic_sriov_pf_del_tx_ctx_cmd(struct qlcnic_bc_trans *trans,
10187cb03b23SRajesh Borundia 					  struct qlcnic_cmd_args *cmd)
10197cb03b23SRajesh Borundia {
10207cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
10217cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
10227cb03b23SRajesh Borundia 	int err;
10237cb03b23SRajesh Borundia 
10247cb03b23SRajesh Borundia 	err = qlcnic_sriov_validate_del_tx_ctx(vf, cmd);
10257cb03b23SRajesh Borundia 	if (err) {
10267cb03b23SRajesh Borundia 		cmd->rsp.arg[0] |= (0x6 << 25);
10277cb03b23SRajesh Borundia 		return err;
10287cb03b23SRajesh Borundia 	}
10297cb03b23SRajesh Borundia 
10307cb03b23SRajesh Borundia 	cmd->req.arg[1] |= vf->vp->handle << 16;
10317cb03b23SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, cmd);
10327cb03b23SRajesh Borundia 
10337cb03b23SRajesh Borundia 	if (!err)
10347cb03b23SRajesh Borundia 		vf->tx_ctx_id = 0;
10357cb03b23SRajesh Borundia 
10367cb03b23SRajesh Borundia 	return err;
10377cb03b23SRajesh Borundia }
10387cb03b23SRajesh Borundia 
qlcnic_sriov_validate_cfg_lro(struct qlcnic_vf_info * vf,struct qlcnic_cmd_args * cmd)10397cb03b23SRajesh Borundia static int qlcnic_sriov_validate_cfg_lro(struct qlcnic_vf_info *vf,
10407cb03b23SRajesh Borundia 					 struct qlcnic_cmd_args *cmd)
10417cb03b23SRajesh Borundia {
10427cb03b23SRajesh Borundia 	if ((cmd->req.arg[1] >> 16) != vf->rx_ctx_id)
10437cb03b23SRajesh Borundia 		return -EINVAL;
10447cb03b23SRajesh Borundia 
10457cb03b23SRajesh Borundia 	return 0;
10467cb03b23SRajesh Borundia }
10477cb03b23SRajesh Borundia 
qlcnic_sriov_pf_cfg_lro_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)10487cb03b23SRajesh Borundia static int qlcnic_sriov_pf_cfg_lro_cmd(struct qlcnic_bc_trans *trans,
10497cb03b23SRajesh Borundia 				       struct qlcnic_cmd_args *cmd)
10507cb03b23SRajesh Borundia {
10517cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
10527cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
10537cb03b23SRajesh Borundia 	int err;
10547cb03b23SRajesh Borundia 
10557cb03b23SRajesh Borundia 	err = qlcnic_sriov_validate_cfg_lro(vf, cmd);
10567cb03b23SRajesh Borundia 	if (err) {
10577cb03b23SRajesh Borundia 		cmd->rsp.arg[0] |= (0x6 << 25);
10587cb03b23SRajesh Borundia 		return err;
10597cb03b23SRajesh Borundia 	}
10607cb03b23SRajesh Borundia 
10617cb03b23SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, cmd);
10627cb03b23SRajesh Borundia 	return err;
10637cb03b23SRajesh Borundia }
10647cb03b23SRajesh Borundia 
qlcnic_sriov_pf_cfg_ip_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)10657cb03b23SRajesh Borundia static int qlcnic_sriov_pf_cfg_ip_cmd(struct qlcnic_bc_trans *trans,
10667cb03b23SRajesh Borundia 				      struct qlcnic_cmd_args *cmd)
10677cb03b23SRajesh Borundia {
10687cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
10697cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
10702559d7c4SColin Ian King 	int err;
10717cb03b23SRajesh Borundia 
10727cb03b23SRajesh Borundia 	cmd->req.arg[1] |= vf->vp->handle << 16;
10737cb03b23SRajesh Borundia 	cmd->req.arg[1] |= BIT_31;
10747cb03b23SRajesh Borundia 
10757cb03b23SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, cmd);
10767cb03b23SRajesh Borundia 	return err;
10777cb03b23SRajesh Borundia }
10787cb03b23SRajesh Borundia 
qlcnic_sriov_validate_cfg_intrpt(struct qlcnic_vf_info * vf,struct qlcnic_cmd_args * cmd)10797cb03b23SRajesh Borundia static int qlcnic_sriov_validate_cfg_intrpt(struct qlcnic_vf_info *vf,
10807cb03b23SRajesh Borundia 					    struct qlcnic_cmd_args *cmd)
10817cb03b23SRajesh Borundia {
10827cb03b23SRajesh Borundia 	if (((cmd->req.arg[1] >> 8) & 0xff) != vf->pci_func)
10837cb03b23SRajesh Borundia 		return -EINVAL;
10847cb03b23SRajesh Borundia 
10857cb03b23SRajesh Borundia 	if (!(cmd->req.arg[1] & BIT_16))
10867cb03b23SRajesh Borundia 		return -EINVAL;
10877cb03b23SRajesh Borundia 
10887cb03b23SRajesh Borundia 	if ((cmd->req.arg[1] & 0xff) != 0x1)
10897cb03b23SRajesh Borundia 		return -EINVAL;
10907cb03b23SRajesh Borundia 
10917cb03b23SRajesh Borundia 	return 0;
10927cb03b23SRajesh Borundia }
10937cb03b23SRajesh Borundia 
qlcnic_sriov_pf_cfg_intrpt_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)10947cb03b23SRajesh Borundia static int qlcnic_sriov_pf_cfg_intrpt_cmd(struct qlcnic_bc_trans *trans,
10957cb03b23SRajesh Borundia 					  struct qlcnic_cmd_args *cmd)
10967cb03b23SRajesh Borundia {
10977cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
10987cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
10997cb03b23SRajesh Borundia 	int err;
11007cb03b23SRajesh Borundia 
11017cb03b23SRajesh Borundia 	err = qlcnic_sriov_validate_cfg_intrpt(vf, cmd);
11027cb03b23SRajesh Borundia 	if (err)
11037cb03b23SRajesh Borundia 		cmd->rsp.arg[0] |= (0x6 << 25);
11047cb03b23SRajesh Borundia 	else
11057cb03b23SRajesh Borundia 		err = qlcnic_issue_cmd(adapter, cmd);
11067cb03b23SRajesh Borundia 
11077cb03b23SRajesh Borundia 	return err;
11087cb03b23SRajesh Borundia }
11097cb03b23SRajesh Borundia 
qlcnic_sriov_validate_mtu(struct qlcnic_adapter * adapter,struct qlcnic_vf_info * vf,struct qlcnic_cmd_args * cmd)11107cb03b23SRajesh Borundia static int qlcnic_sriov_validate_mtu(struct qlcnic_adapter *adapter,
11117cb03b23SRajesh Borundia 				     struct qlcnic_vf_info *vf,
11127cb03b23SRajesh Borundia 				     struct qlcnic_cmd_args *cmd)
11137cb03b23SRajesh Borundia {
11147cb03b23SRajesh Borundia 	if (cmd->req.arg[1] != vf->rx_ctx_id)
11157cb03b23SRajesh Borundia 		return -EINVAL;
11167cb03b23SRajesh Borundia 
11177cb03b23SRajesh Borundia 	if (cmd->req.arg[2] > adapter->ahw->max_mtu)
11187cb03b23SRajesh Borundia 		return -EINVAL;
11197cb03b23SRajesh Borundia 
11207cb03b23SRajesh Borundia 	return 0;
11217cb03b23SRajesh Borundia }
11227cb03b23SRajesh Borundia 
qlcnic_sriov_pf_set_mtu_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)11237cb03b23SRajesh Borundia static int qlcnic_sriov_pf_set_mtu_cmd(struct qlcnic_bc_trans *trans,
11247cb03b23SRajesh Borundia 				       struct qlcnic_cmd_args *cmd)
11257cb03b23SRajesh Borundia {
11267cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
11277cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
11287cb03b23SRajesh Borundia 	int err;
11297cb03b23SRajesh Borundia 
11307cb03b23SRajesh Borundia 	err = qlcnic_sriov_validate_mtu(adapter, vf, cmd);
11317cb03b23SRajesh Borundia 	if (err)
11327cb03b23SRajesh Borundia 		cmd->rsp.arg[0] |= (0x6 << 25);
11337cb03b23SRajesh Borundia 	else
11347cb03b23SRajesh Borundia 		err = qlcnic_issue_cmd(adapter, cmd);
11357cb03b23SRajesh Borundia 
11367cb03b23SRajesh Borundia 	return err;
11377cb03b23SRajesh Borundia }
11387cb03b23SRajesh Borundia 
qlcnic_sriov_validate_get_nic_info(struct qlcnic_vf_info * vf,struct qlcnic_cmd_args * cmd)11397cb03b23SRajesh Borundia static int qlcnic_sriov_validate_get_nic_info(struct qlcnic_vf_info *vf,
11407cb03b23SRajesh Borundia 					      struct qlcnic_cmd_args *cmd)
11417cb03b23SRajesh Borundia {
11427cb03b23SRajesh Borundia 	if (cmd->req.arg[1] & BIT_31) {
11437cb03b23SRajesh Borundia 		if (((cmd->req.arg[1] >> 16) & 0x7fff) != vf->pci_func)
11447cb03b23SRajesh Borundia 			return -EINVAL;
11457cb03b23SRajesh Borundia 	} else {
11467cb03b23SRajesh Borundia 		cmd->req.arg[1] |= vf->vp->handle << 16;
11477cb03b23SRajesh Borundia 	}
11487cb03b23SRajesh Borundia 
11497cb03b23SRajesh Borundia 	return 0;
11507cb03b23SRajesh Borundia }
11517cb03b23SRajesh Borundia 
qlcnic_sriov_pf_get_nic_info_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)11527cb03b23SRajesh Borundia static int qlcnic_sriov_pf_get_nic_info_cmd(struct qlcnic_bc_trans *trans,
11537cb03b23SRajesh Borundia 					    struct qlcnic_cmd_args *cmd)
11547cb03b23SRajesh Borundia {
11557cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
11567cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
11577cb03b23SRajesh Borundia 	int err;
11587cb03b23SRajesh Borundia 
11597cb03b23SRajesh Borundia 	err = qlcnic_sriov_validate_get_nic_info(vf, cmd);
11607cb03b23SRajesh Borundia 	if (err) {
11617cb03b23SRajesh Borundia 		cmd->rsp.arg[0] |= (0x6 << 25);
11627cb03b23SRajesh Borundia 		return err;
11637cb03b23SRajesh Borundia 	}
11647cb03b23SRajesh Borundia 
11657cb03b23SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, cmd);
11667cb03b23SRajesh Borundia 	return err;
11677cb03b23SRajesh Borundia }
11687cb03b23SRajesh Borundia 
qlcnic_sriov_validate_cfg_rss(struct qlcnic_vf_info * vf,struct qlcnic_cmd_args * cmd)11697cb03b23SRajesh Borundia static int qlcnic_sriov_validate_cfg_rss(struct qlcnic_vf_info *vf,
11707cb03b23SRajesh Borundia 					 struct qlcnic_cmd_args *cmd)
11717cb03b23SRajesh Borundia {
11727cb03b23SRajesh Borundia 	if (cmd->req.arg[1] != vf->rx_ctx_id)
11737cb03b23SRajesh Borundia 		return -EINVAL;
11747cb03b23SRajesh Borundia 
11757cb03b23SRajesh Borundia 	return 0;
11767cb03b23SRajesh Borundia }
11777cb03b23SRajesh Borundia 
qlcnic_sriov_pf_cfg_rss_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)11787cb03b23SRajesh Borundia static int qlcnic_sriov_pf_cfg_rss_cmd(struct qlcnic_bc_trans *trans,
11797cb03b23SRajesh Borundia 				       struct qlcnic_cmd_args *cmd)
11807cb03b23SRajesh Borundia {
11817cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
11827cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
11837cb03b23SRajesh Borundia 	int err;
11847cb03b23SRajesh Borundia 
11857cb03b23SRajesh Borundia 	err = qlcnic_sriov_validate_cfg_rss(vf, cmd);
11867cb03b23SRajesh Borundia 	if (err)
11877cb03b23SRajesh Borundia 		cmd->rsp.arg[0] |= (0x6 << 25);
11887cb03b23SRajesh Borundia 	else
11897cb03b23SRajesh Borundia 		err = qlcnic_issue_cmd(adapter, cmd);
11907cb03b23SRajesh Borundia 
11917cb03b23SRajesh Borundia 	return err;
11927cb03b23SRajesh Borundia }
11937cb03b23SRajesh Borundia 
qlcnic_sriov_validate_cfg_intrcoal(struct qlcnic_adapter * adapter,struct qlcnic_vf_info * vf,struct qlcnic_cmd_args * cmd)11947cb03b23SRajesh Borundia static int qlcnic_sriov_validate_cfg_intrcoal(struct qlcnic_adapter *adapter,
11957cb03b23SRajesh Borundia 					      struct qlcnic_vf_info *vf,
11967cb03b23SRajesh Borundia 					      struct qlcnic_cmd_args *cmd)
11977cb03b23SRajesh Borundia {
11987cb03b23SRajesh Borundia 	struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
11997cb03b23SRajesh Borundia 	u16 ctx_id, pkts, time;
1200868e9144SSucheta Chakraborty 	int err = -EINVAL;
1201868e9144SSucheta Chakraborty 	u8 type;
12027cb03b23SRajesh Borundia 
1203868e9144SSucheta Chakraborty 	type = cmd->req.arg[1] & QLC_INTR_COAL_TYPE_MASK;
12047cb03b23SRajesh Borundia 	ctx_id = cmd->req.arg[1] >> 16;
12057cb03b23SRajesh Borundia 	pkts = cmd->req.arg[2] & 0xffff;
12067cb03b23SRajesh Borundia 	time = cmd->req.arg[2] >> 16;
12077cb03b23SRajesh Borundia 
1208868e9144SSucheta Chakraborty 	switch (type) {
1209868e9144SSucheta Chakraborty 	case QLCNIC_INTR_COAL_TYPE_RX:
1210868e9144SSucheta Chakraborty 		if (ctx_id != vf->rx_ctx_id || pkts > coal->rx_packets ||
1211868e9144SSucheta Chakraborty 		    time < coal->rx_time_us)
1212868e9144SSucheta Chakraborty 			goto err_label;
1213868e9144SSucheta Chakraborty 		break;
1214868e9144SSucheta Chakraborty 	case QLCNIC_INTR_COAL_TYPE_TX:
1215868e9144SSucheta Chakraborty 		if (ctx_id != vf->tx_ctx_id || pkts > coal->tx_packets ||
1216868e9144SSucheta Chakraborty 		    time < coal->tx_time_us)
1217868e9144SSucheta Chakraborty 			goto err_label;
1218868e9144SSucheta Chakraborty 		break;
1219868e9144SSucheta Chakraborty 	default:
1220868e9144SSucheta Chakraborty 		netdev_err(adapter->netdev, "Invalid coalescing type 0x%x received\n",
1221868e9144SSucheta Chakraborty 			   type);
1222868e9144SSucheta Chakraborty 		return err;
1223868e9144SSucheta Chakraborty 	}
12247cb03b23SRajesh Borundia 
12257cb03b23SRajesh Borundia 	return 0;
1226868e9144SSucheta Chakraborty 
1227868e9144SSucheta Chakraborty err_label:
1228868e9144SSucheta Chakraborty 	netdev_err(adapter->netdev, "Expected: rx_ctx_id 0x%x rx_packets 0x%x rx_time_us 0x%x tx_ctx_id 0x%x tx_packets 0x%x tx_time_us 0x%x\n",
1229868e9144SSucheta Chakraborty 		   vf->rx_ctx_id, coal->rx_packets, coal->rx_time_us,
1230868e9144SSucheta Chakraborty 		   vf->tx_ctx_id, coal->tx_packets, coal->tx_time_us);
1231868e9144SSucheta Chakraborty 	netdev_err(adapter->netdev, "Received: ctx_id 0x%x packets 0x%x time_us 0x%x type 0x%x\n",
1232868e9144SSucheta Chakraborty 		   ctx_id, pkts, time, type);
1233868e9144SSucheta Chakraborty 
1234868e9144SSucheta Chakraborty 	return err;
12357cb03b23SRajesh Borundia }
12367cb03b23SRajesh Borundia 
qlcnic_sriov_pf_cfg_intrcoal_cmd(struct qlcnic_bc_trans * tran,struct qlcnic_cmd_args * cmd)12377cb03b23SRajesh Borundia static int qlcnic_sriov_pf_cfg_intrcoal_cmd(struct qlcnic_bc_trans *tran,
12387cb03b23SRajesh Borundia 					    struct qlcnic_cmd_args *cmd)
12397cb03b23SRajesh Borundia {
12407cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = tran->vf;
12417cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
12427cb03b23SRajesh Borundia 	int err;
12437cb03b23SRajesh Borundia 
12447cb03b23SRajesh Borundia 	err = qlcnic_sriov_validate_cfg_intrcoal(adapter, vf, cmd);
12457cb03b23SRajesh Borundia 	if (err) {
12467cb03b23SRajesh Borundia 		cmd->rsp.arg[0] |= (0x6 << 25);
12477cb03b23SRajesh Borundia 		return err;
12487cb03b23SRajesh Borundia 	}
12497cb03b23SRajesh Borundia 
12507cb03b23SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, cmd);
12517cb03b23SRajesh Borundia 	return err;
12527cb03b23SRajesh Borundia }
12537cb03b23SRajesh Borundia 
qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter * adapter,struct qlcnic_vf_info * vf,struct qlcnic_cmd_args * cmd)12547cb03b23SRajesh Borundia static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter,
12557cb03b23SRajesh Borundia 					     struct qlcnic_vf_info *vf,
12567cb03b23SRajesh Borundia 					     struct qlcnic_cmd_args *cmd)
12577cb03b23SRajesh Borundia {
125891b7282bSRajesh Borundia 	struct qlcnic_vport *vp = vf->vp;
125991b7282bSRajesh Borundia 	u8 op, new_op;
12607cb03b23SRajesh Borundia 
12617cb03b23SRajesh Borundia 	if (!(cmd->req.arg[1] & BIT_8))
12627cb03b23SRajesh Borundia 		return -EINVAL;
12637cb03b23SRajesh Borundia 
12647cb03b23SRajesh Borundia 	cmd->req.arg[1] |= (vf->vp->handle << 16);
12657cb03b23SRajesh Borundia 	cmd->req.arg[1] |= BIT_31;
12667cb03b23SRajesh Borundia 
126791b7282bSRajesh Borundia 	if (vp->vlan_mode == QLC_PVID_MODE) {
126891b7282bSRajesh Borundia 		op = cmd->req.arg[1] & 0x7;
126991b7282bSRajesh Borundia 		cmd->req.arg[1] &= ~0x7;
127091b7282bSRajesh Borundia 		new_op = (op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
127191b7282bSRajesh Borundia 			 QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL;
1272154d0c81SManish Chopra 		cmd->req.arg[3] |= vp->pvid << 16;
127391b7282bSRajesh Borundia 		cmd->req.arg[1] |= new_op;
127491b7282bSRajesh Borundia 	}
127591b7282bSRajesh Borundia 
12767cb03b23SRajesh Borundia 	return 0;
12777cb03b23SRajesh Borundia }
12787cb03b23SRajesh Borundia 
qlcnic_sriov_pf_cfg_macvlan_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)12797cb03b23SRajesh Borundia static int qlcnic_sriov_pf_cfg_macvlan_cmd(struct qlcnic_bc_trans *trans,
12807cb03b23SRajesh Borundia 					   struct qlcnic_cmd_args *cmd)
12817cb03b23SRajesh Borundia {
12827cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
12837cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
12847cb03b23SRajesh Borundia 	int err;
12857cb03b23SRajesh Borundia 
12867cb03b23SRajesh Borundia 	err = qlcnic_sriov_validate_cfg_macvlan(adapter, vf, cmd);
12877cb03b23SRajesh Borundia 	if (err) {
12887cb03b23SRajesh Borundia 		cmd->rsp.arg[0] |= (0x6 << 25);
12897cb03b23SRajesh Borundia 		return err;
12907cb03b23SRajesh Borundia 	}
12917cb03b23SRajesh Borundia 
12927cb03b23SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, cmd);
12937cb03b23SRajesh Borundia 	return err;
12947cb03b23SRajesh Borundia }
12957cb03b23SRajesh Borundia 
qlcnic_sriov_validate_linkevent(struct qlcnic_vf_info * vf,struct qlcnic_cmd_args * cmd)12967cb03b23SRajesh Borundia static int qlcnic_sriov_validate_linkevent(struct qlcnic_vf_info *vf,
12977cb03b23SRajesh Borundia 					   struct qlcnic_cmd_args *cmd)
12987cb03b23SRajesh Borundia {
12997cb03b23SRajesh Borundia 	if ((cmd->req.arg[1] >> 16) != vf->rx_ctx_id)
13007cb03b23SRajesh Borundia 		return -EINVAL;
13017cb03b23SRajesh Borundia 
13027cb03b23SRajesh Borundia 	return 0;
13037cb03b23SRajesh Borundia }
13047cb03b23SRajesh Borundia 
qlcnic_sriov_pf_linkevent_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)13057cb03b23SRajesh Borundia static int qlcnic_sriov_pf_linkevent_cmd(struct qlcnic_bc_trans *trans,
13067cb03b23SRajesh Borundia 					 struct qlcnic_cmd_args *cmd)
13077cb03b23SRajesh Borundia {
13087cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
13097cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
13107cb03b23SRajesh Borundia 	int err;
13117cb03b23SRajesh Borundia 
13127cb03b23SRajesh Borundia 	err = qlcnic_sriov_validate_linkevent(vf, cmd);
13137cb03b23SRajesh Borundia 	if (err) {
13147cb03b23SRajesh Borundia 		cmd->rsp.arg[0] |= (0x6 << 25);
13157cb03b23SRajesh Borundia 		return err;
13167cb03b23SRajesh Borundia 	}
13177cb03b23SRajesh Borundia 
13187cb03b23SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, cmd);
13197cb03b23SRajesh Borundia 	return err;
13207cb03b23SRajesh Borundia }
13217cb03b23SRajesh Borundia 
qlcnic_sriov_pf_cfg_promisc_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)13227cb03b23SRajesh Borundia static int qlcnic_sriov_pf_cfg_promisc_cmd(struct qlcnic_bc_trans *trans,
13237cb03b23SRajesh Borundia 					   struct qlcnic_cmd_args *cmd)
13247cb03b23SRajesh Borundia {
13257cb03b23SRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
13267cb03b23SRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
13277cb03b23SRajesh Borundia 	int err;
13287cb03b23SRajesh Borundia 
13297cb03b23SRajesh Borundia 	cmd->req.arg[1] |= vf->vp->handle << 16;
13307cb03b23SRajesh Borundia 	cmd->req.arg[1] |= BIT_31;
13317cb03b23SRajesh Borundia 	err = qlcnic_issue_cmd(adapter, cmd);
13327cb03b23SRajesh Borundia 	return err;
13337cb03b23SRajesh Borundia }
13347cb03b23SRajesh Borundia 
qlcnic_sriov_pf_get_acl_cmd(struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)133591b7282bSRajesh Borundia static int qlcnic_sriov_pf_get_acl_cmd(struct qlcnic_bc_trans *trans,
133691b7282bSRajesh Borundia 				       struct qlcnic_cmd_args *cmd)
133791b7282bSRajesh Borundia {
133891b7282bSRajesh Borundia 	struct qlcnic_vf_info *vf = trans->vf;
133991b7282bSRajesh Borundia 	struct qlcnic_vport *vp = vf->vp;
13408937388aSYueHaibing 	u8 mode = vp->vlan_mode;
1341991ca269SManish Chopra 	struct qlcnic_adapter *adapter;
1342154d0c81SManish Chopra 	struct qlcnic_sriov *sriov;
1343991ca269SManish Chopra 
1344991ca269SManish Chopra 	adapter = vf->adapter;
1345154d0c81SManish Chopra 	sriov = adapter->ahw->sriov;
134691b7282bSRajesh Borundia 
13476226204bSPratik Pujar 	cmd->rsp.arg[0] |= 1 << 25;
134891b7282bSRajesh Borundia 
1349991ca269SManish Chopra 	/* For 84xx adapter in case of PVID , PFD should send vlan mode as
1350991ca269SManish Chopra 	 * QLC_NO_VLAN_MODE to VFD which is zero in mailbox response
1351991ca269SManish Chopra 	 */
1352991ca269SManish Chopra 	if (qlcnic_84xx_check(adapter) && mode == QLC_PVID_MODE)
1353991ca269SManish Chopra 		return 0;
1354991ca269SManish Chopra 
135591b7282bSRajesh Borundia 	switch (mode) {
135691b7282bSRajesh Borundia 	case QLC_GUEST_VLAN_MODE:
135791b7282bSRajesh Borundia 		cmd->rsp.arg[1] = mode | 1 << 8;
1358154d0c81SManish Chopra 		cmd->rsp.arg[2] = sriov->num_allowed_vlans << 16;
135991b7282bSRajesh Borundia 		break;
136091b7282bSRajesh Borundia 	case QLC_PVID_MODE:
1361154d0c81SManish Chopra 		cmd->rsp.arg[1] = mode | 1 << 8 | vp->pvid << 16;
136291b7282bSRajesh Borundia 		break;
136391b7282bSRajesh Borundia 	}
136491b7282bSRajesh Borundia 
136591b7282bSRajesh Borundia 	return 0;
136691b7282bSRajesh Borundia }
136791b7282bSRajesh Borundia 
qlcnic_sriov_pf_del_guest_vlan(struct qlcnic_adapter * adapter,struct qlcnic_vf_info * vf,struct qlcnic_cmd_args * cmd)136891b7282bSRajesh Borundia static int qlcnic_sriov_pf_del_guest_vlan(struct qlcnic_adapter *adapter,
1369154d0c81SManish Chopra 					  struct qlcnic_vf_info *vf,
1370154d0c81SManish Chopra 					  struct qlcnic_cmd_args *cmd)
137191b7282bSRajesh Borundia {
1372154d0c81SManish Chopra 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
1373154d0c81SManish Chopra 	u16 vlan;
137491b7282bSRajesh Borundia 
1375154d0c81SManish Chopra 	if (!qlcnic_sriov_check_any_vlan(vf))
137691b7282bSRajesh Borundia 		return -EINVAL;
137791b7282bSRajesh Borundia 
1378154d0c81SManish Chopra 	vlan = cmd->req.arg[1] >> 16;
137991b7282bSRajesh Borundia 	if (!vf->rx_ctx_id) {
1380154d0c81SManish Chopra 		qlcnic_sriov_del_vlan_id(sriov, vf, vlan);
138191b7282bSRajesh Borundia 		return 0;
138291b7282bSRajesh Borundia 	}
138391b7282bSRajesh Borundia 
1384154d0c81SManish Chopra 	qlcnic_sriov_cfg_vf_def_mac(adapter, vf, vlan, QLCNIC_MAC_DEL);
1385154d0c81SManish Chopra 	qlcnic_sriov_del_vlan_id(sriov, vf, vlan);
1386154d0c81SManish Chopra 
1387154d0c81SManish Chopra 	if (qlcnic_83xx_pf_check(adapter))
1388154d0c81SManish Chopra 		qlcnic_sriov_cfg_vf_def_mac(adapter, vf,
138991b7282bSRajesh Borundia 					    0, QLCNIC_MAC_ADD);
139091b7282bSRajesh Borundia 	return 0;
139191b7282bSRajesh Borundia }
139291b7282bSRajesh Borundia 
qlcnic_sriov_pf_add_guest_vlan(struct qlcnic_adapter * adapter,struct qlcnic_vf_info * vf,struct qlcnic_cmd_args * cmd)139391b7282bSRajesh Borundia static int qlcnic_sriov_pf_add_guest_vlan(struct qlcnic_adapter *adapter,
139491b7282bSRajesh Borundia 					  struct qlcnic_vf_info *vf,
139591b7282bSRajesh Borundia 					  struct qlcnic_cmd_args *cmd)
139691b7282bSRajesh Borundia {
1397154d0c81SManish Chopra 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
139891b7282bSRajesh Borundia 	int err = -EIO;
1399154d0c81SManish Chopra 	u16 vlan;
140091b7282bSRajesh Borundia 
1401154d0c81SManish Chopra 	if (qlcnic_83xx_pf_check(adapter) && qlcnic_sriov_check_any_vlan(vf))
140291b7282bSRajesh Borundia 		return err;
140391b7282bSRajesh Borundia 
1404154d0c81SManish Chopra 	vlan = cmd->req.arg[1] >> 16;
1405154d0c81SManish Chopra 
140691b7282bSRajesh Borundia 	if (!vf->rx_ctx_id) {
1407154d0c81SManish Chopra 		qlcnic_sriov_add_vlan_id(sriov, vf, vlan);
140891b7282bSRajesh Borundia 		return 0;
140991b7282bSRajesh Borundia 	}
141091b7282bSRajesh Borundia 
1411154d0c81SManish Chopra 	if (qlcnic_83xx_pf_check(adapter)) {
1412154d0c81SManish Chopra 		err = qlcnic_sriov_cfg_vf_def_mac(adapter, vf, 0,
1413154d0c81SManish Chopra 						  QLCNIC_MAC_DEL);
141491b7282bSRajesh Borundia 		if (err)
141591b7282bSRajesh Borundia 			return err;
141691b7282bSRajesh Borundia 	}
141791b7282bSRajesh Borundia 
1418154d0c81SManish Chopra 	err = qlcnic_sriov_cfg_vf_def_mac(adapter, vf, vlan, QLCNIC_MAC_ADD);
1419154d0c81SManish Chopra 
1420154d0c81SManish Chopra 	if (err) {
1421154d0c81SManish Chopra 		if (qlcnic_83xx_pf_check(adapter))
1422154d0c81SManish Chopra 			qlcnic_sriov_cfg_vf_def_mac(adapter, vf, 0,
1423154d0c81SManish Chopra 						    QLCNIC_MAC_ADD);
1424154d0c81SManish Chopra 		return err;
1425154d0c81SManish Chopra 	}
1426154d0c81SManish Chopra 
1427154d0c81SManish Chopra 	qlcnic_sriov_add_vlan_id(sriov, vf, vlan);
142891b7282bSRajesh Borundia 	return err;
142991b7282bSRajesh Borundia }
143091b7282bSRajesh Borundia 
qlcnic_sriov_pf_cfg_guest_vlan_cmd(struct qlcnic_bc_trans * tran,struct qlcnic_cmd_args * cmd)143191b7282bSRajesh Borundia static int qlcnic_sriov_pf_cfg_guest_vlan_cmd(struct qlcnic_bc_trans *tran,
143291b7282bSRajesh Borundia 					      struct qlcnic_cmd_args *cmd)
143391b7282bSRajesh Borundia {
143491b7282bSRajesh Borundia 	struct qlcnic_vf_info  *vf = tran->vf;
143591b7282bSRajesh Borundia 	struct qlcnic_adapter *adapter =  vf->adapter;
143691b7282bSRajesh Borundia 	struct qlcnic_vport *vp = vf->vp;
143791b7282bSRajesh Borundia 	int err = -EIO;
143891b7282bSRajesh Borundia 	u8 op;
143991b7282bSRajesh Borundia 
144091b7282bSRajesh Borundia 	if (vp->vlan_mode != QLC_GUEST_VLAN_MODE) {
144191b7282bSRajesh Borundia 		cmd->rsp.arg[0] |= 2 << 25;
144291b7282bSRajesh Borundia 		return err;
144391b7282bSRajesh Borundia 	}
144491b7282bSRajesh Borundia 
144591b7282bSRajesh Borundia 	op = cmd->req.arg[1] & 0xf;
144691b7282bSRajesh Borundia 
144791b7282bSRajesh Borundia 	if (op)
144891b7282bSRajesh Borundia 		err = qlcnic_sriov_pf_add_guest_vlan(adapter, vf, cmd);
144991b7282bSRajesh Borundia 	else
1450154d0c81SManish Chopra 		err = qlcnic_sriov_pf_del_guest_vlan(adapter, vf, cmd);
145191b7282bSRajesh Borundia 
145291b7282bSRajesh Borundia 	cmd->rsp.arg[0] |= err ? 2 << 25 : 1 << 25;
145391b7282bSRajesh Borundia 	return err;
145491b7282bSRajesh Borundia }
145591b7282bSRajesh Borundia 
14567cb03b23SRajesh Borundia static const int qlcnic_pf_passthru_supp_cmds[] = {
14577cb03b23SRajesh Borundia 	QLCNIC_CMD_GET_STATISTICS,
14587cb03b23SRajesh Borundia 	QLCNIC_CMD_GET_PORT_CONFIG,
14597cb03b23SRajesh Borundia 	QLCNIC_CMD_GET_LINK_STATUS,
14602d8ebcabSSucheta Chakraborty 	QLCNIC_CMD_INIT_NIC_FUNC,
14612d8ebcabSSucheta Chakraborty 	QLCNIC_CMD_STOP_NIC_FUNC,
14627cb03b23SRajesh Borundia };
14637cb03b23SRajesh Borundia 
1464f197a7aaSRajesh Borundia static const struct qlcnic_sriov_cmd_handler qlcnic_pf_bc_cmd_hdlr[] = {
1465f197a7aaSRajesh Borundia 	[QLCNIC_BC_CMD_CHANNEL_INIT] = {&qlcnic_sriov_pf_channel_cfg_cmd},
1466f197a7aaSRajesh Borundia 	[QLCNIC_BC_CMD_CHANNEL_TERM] = {&qlcnic_sriov_pf_channel_cfg_cmd},
146791b7282bSRajesh Borundia 	[QLCNIC_BC_CMD_GET_ACL]	= {&qlcnic_sriov_pf_get_acl_cmd},
146891b7282bSRajesh Borundia 	[QLCNIC_BC_CMD_CFG_GUEST_VLAN]	= {&qlcnic_sriov_pf_cfg_guest_vlan_cmd},
1469f197a7aaSRajesh Borundia };
1470f197a7aaSRajesh Borundia 
14717cb03b23SRajesh Borundia static const struct qlcnic_sriov_fw_cmd_handler qlcnic_pf_fw_cmd_hdlr[] = {
14727cb03b23SRajesh Borundia 	{QLCNIC_CMD_CREATE_RX_CTX, qlcnic_sriov_pf_create_rx_ctx_cmd},
14737cb03b23SRajesh Borundia 	{QLCNIC_CMD_CREATE_TX_CTX, qlcnic_sriov_pf_create_tx_ctx_cmd},
14747cb03b23SRajesh Borundia 	{QLCNIC_CMD_MAC_ADDRESS, qlcnic_sriov_pf_mac_address_cmd},
14757cb03b23SRajesh Borundia 	{QLCNIC_CMD_DESTROY_RX_CTX, qlcnic_sriov_pf_del_rx_ctx_cmd},
14767cb03b23SRajesh Borundia 	{QLCNIC_CMD_DESTROY_TX_CTX, qlcnic_sriov_pf_del_tx_ctx_cmd},
14777cb03b23SRajesh Borundia 	{QLCNIC_CMD_CONFIGURE_HW_LRO, qlcnic_sriov_pf_cfg_lro_cmd},
14787cb03b23SRajesh Borundia 	{QLCNIC_CMD_CONFIGURE_IP_ADDR, qlcnic_sriov_pf_cfg_ip_cmd},
14797cb03b23SRajesh Borundia 	{QLCNIC_CMD_CONFIG_INTRPT, qlcnic_sriov_pf_cfg_intrpt_cmd},
14807cb03b23SRajesh Borundia 	{QLCNIC_CMD_SET_MTU, qlcnic_sriov_pf_set_mtu_cmd},
14817cb03b23SRajesh Borundia 	{QLCNIC_CMD_GET_NIC_INFO, qlcnic_sriov_pf_get_nic_info_cmd},
14827cb03b23SRajesh Borundia 	{QLCNIC_CMD_CONFIGURE_RSS, qlcnic_sriov_pf_cfg_rss_cmd},
14837cb03b23SRajesh Borundia 	{QLCNIC_CMD_CONFIG_INTR_COAL, qlcnic_sriov_pf_cfg_intrcoal_cmd},
14847cb03b23SRajesh Borundia 	{QLCNIC_CMD_CONFIG_MAC_VLAN, qlcnic_sriov_pf_cfg_macvlan_cmd},
14857cb03b23SRajesh Borundia 	{QLCNIC_CMD_GET_LINK_EVENT, qlcnic_sriov_pf_linkevent_cmd},
14867cb03b23SRajesh Borundia 	{QLCNIC_CMD_CONFIGURE_MAC_RX_MODE, qlcnic_sriov_pf_cfg_promisc_cmd},
14877cb03b23SRajesh Borundia };
14887cb03b23SRajesh Borundia 
qlcnic_sriov_pf_process_bc_cmd(struct qlcnic_adapter * adapter,struct qlcnic_bc_trans * trans,struct qlcnic_cmd_args * cmd)1489f197a7aaSRajesh Borundia void qlcnic_sriov_pf_process_bc_cmd(struct qlcnic_adapter *adapter,
1490f197a7aaSRajesh Borundia 				    struct qlcnic_bc_trans *trans,
1491f197a7aaSRajesh Borundia 				    struct qlcnic_cmd_args *cmd)
1492f197a7aaSRajesh Borundia {
1493f197a7aaSRajesh Borundia 	u8 size, cmd_op;
1494f197a7aaSRajesh Borundia 
1495f197a7aaSRajesh Borundia 	cmd_op = trans->req_hdr->cmd_op;
1496f197a7aaSRajesh Borundia 
1497f197a7aaSRajesh Borundia 	if (trans->req_hdr->op_type == QLC_BC_CMD) {
1498f197a7aaSRajesh Borundia 		size = ARRAY_SIZE(qlcnic_pf_bc_cmd_hdlr);
1499f197a7aaSRajesh Borundia 		if (cmd_op < size) {
1500f197a7aaSRajesh Borundia 			qlcnic_pf_bc_cmd_hdlr[cmd_op].fn(trans, cmd);
1501f197a7aaSRajesh Borundia 			return;
1502f197a7aaSRajesh Borundia 		}
15037cb03b23SRajesh Borundia 	} else {
15047cb03b23SRajesh Borundia 		int i;
15057cb03b23SRajesh Borundia 		size = ARRAY_SIZE(qlcnic_pf_fw_cmd_hdlr);
15067cb03b23SRajesh Borundia 		for (i = 0; i < size; i++) {
15077cb03b23SRajesh Borundia 			if (cmd_op == qlcnic_pf_fw_cmd_hdlr[i].cmd) {
15087cb03b23SRajesh Borundia 				qlcnic_pf_fw_cmd_hdlr[i].fn(trans, cmd);
15097cb03b23SRajesh Borundia 				return;
15107cb03b23SRajesh Borundia 			}
15117cb03b23SRajesh Borundia 		}
15127cb03b23SRajesh Borundia 
15137cb03b23SRajesh Borundia 		size = ARRAY_SIZE(qlcnic_pf_passthru_supp_cmds);
15147cb03b23SRajesh Borundia 		for (i = 0; i < size; i++) {
15157cb03b23SRajesh Borundia 			if (cmd_op == qlcnic_pf_passthru_supp_cmds[i]) {
15167cb03b23SRajesh Borundia 				qlcnic_issue_cmd(adapter, cmd);
15177cb03b23SRajesh Borundia 				return;
15187cb03b23SRajesh Borundia 			}
15197cb03b23SRajesh Borundia 		}
1520f197a7aaSRajesh Borundia 	}
1521f197a7aaSRajesh Borundia 
1522f197a7aaSRajesh Borundia 	cmd->rsp.arg[0] |= (0x9 << 25);
1523f197a7aaSRajesh Borundia }
15247cb03b23SRajesh Borundia 
qlcnic_pf_set_interface_id_create_rx_ctx(struct qlcnic_adapter * adapter,u32 * int_id)15257cb03b23SRajesh Borundia void qlcnic_pf_set_interface_id_create_rx_ctx(struct qlcnic_adapter *adapter,
15267cb03b23SRajesh Borundia 					     u32 *int_id)
15277cb03b23SRajesh Borundia {
15287cb03b23SRajesh Borundia 	u16 vpid;
15297cb03b23SRajesh Borundia 
15307cb03b23SRajesh Borundia 	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
15317cb03b23SRajesh Borundia 						adapter->ahw->pci_func);
15327cb03b23SRajesh Borundia 	*int_id |= vpid;
15337cb03b23SRajesh Borundia }
15347cb03b23SRajesh Borundia 
qlcnic_pf_set_interface_id_del_rx_ctx(struct qlcnic_adapter * adapter,u32 * int_id)15357cb03b23SRajesh Borundia void qlcnic_pf_set_interface_id_del_rx_ctx(struct qlcnic_adapter *adapter,
15367cb03b23SRajesh Borundia 					   u32 *int_id)
15377cb03b23SRajesh Borundia {
15387cb03b23SRajesh Borundia 	u16 vpid;
15397cb03b23SRajesh Borundia 
15407cb03b23SRajesh Borundia 	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
15417cb03b23SRajesh Borundia 						adapter->ahw->pci_func);
15427cb03b23SRajesh Borundia 	*int_id |= vpid << 16;
15437cb03b23SRajesh Borundia }
15447cb03b23SRajesh Borundia 
qlcnic_pf_set_interface_id_create_tx_ctx(struct qlcnic_adapter * adapter,u32 * int_id)15457cb03b23SRajesh Borundia void qlcnic_pf_set_interface_id_create_tx_ctx(struct qlcnic_adapter *adapter,
15467cb03b23SRajesh Borundia 					      u32 *int_id)
15477cb03b23SRajesh Borundia {
15487cb03b23SRajesh Borundia 	int vpid;
15497cb03b23SRajesh Borundia 
15507cb03b23SRajesh Borundia 	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
15517cb03b23SRajesh Borundia 						adapter->ahw->pci_func);
15527cb03b23SRajesh Borundia 	*int_id |= vpid << 16;
15537cb03b23SRajesh Borundia }
15547cb03b23SRajesh Borundia 
qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter * adapter,u32 * int_id)15557cb03b23SRajesh Borundia void qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *adapter,
15567cb03b23SRajesh Borundia 					   u32 *int_id)
15577cb03b23SRajesh Borundia {
15587cb03b23SRajesh Borundia 	u16 vpid;
15597cb03b23SRajesh Borundia 
15607cb03b23SRajesh Borundia 	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
15617cb03b23SRajesh Borundia 						adapter->ahw->pci_func);
15627cb03b23SRajesh Borundia 	*int_id |= vpid << 16;
15637cb03b23SRajesh Borundia }
15647cb03b23SRajesh Borundia 
qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter * adapter,u32 * int_id)15657cb03b23SRajesh Borundia void qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *adapter,
15667cb03b23SRajesh Borundia 					u32 *int_id)
15677cb03b23SRajesh Borundia {
15687cb03b23SRajesh Borundia 	u16 vpid;
15697cb03b23SRajesh Borundia 
15707cb03b23SRajesh Borundia 	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
15717cb03b23SRajesh Borundia 						adapter->ahw->pci_func);
15727cb03b23SRajesh Borundia 	*int_id |= (vpid << 16) | BIT_31;
15737cb03b23SRajesh Borundia }
15747cb03b23SRajesh Borundia 
qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter * adapter,u32 * int_id)15757cb03b23SRajesh Borundia void qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *adapter,
15767cb03b23SRajesh Borundia 				       u32 *int_id)
15777cb03b23SRajesh Borundia {
15787cb03b23SRajesh Borundia 	u16 vpid;
15797cb03b23SRajesh Borundia 
15807cb03b23SRajesh Borundia 	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
15817cb03b23SRajesh Borundia 						adapter->ahw->pci_func);
15827cb03b23SRajesh Borundia 	*int_id |= (vpid << 16) | BIT_31;
15837cb03b23SRajesh Borundia }
15847cb03b23SRajesh Borundia 
qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter * adapter,u32 * int_id)15857cb03b23SRajesh Borundia void qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *adapter,
15867cb03b23SRajesh Borundia 					u32 *int_id)
15877cb03b23SRajesh Borundia {
15887cb03b23SRajesh Borundia 	u16 vpid;
15897cb03b23SRajesh Borundia 
15907cb03b23SRajesh Borundia 	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
15917cb03b23SRajesh Borundia 						adapter->ahw->pci_func);
15927cb03b23SRajesh Borundia 	*int_id |= (vpid << 16) | BIT_31;
15937cb03b23SRajesh Borundia }
159497d8105cSRajesh Borundia 
qlcnic_sriov_del_rx_ctx(struct qlcnic_adapter * adapter,struct qlcnic_vf_info * vf)159597d8105cSRajesh Borundia static void qlcnic_sriov_del_rx_ctx(struct qlcnic_adapter *adapter,
159697d8105cSRajesh Borundia 				    struct qlcnic_vf_info *vf)
159797d8105cSRajesh Borundia {
159897d8105cSRajesh Borundia 	struct qlcnic_cmd_args cmd;
159997d8105cSRajesh Borundia 	int vpid;
160097d8105cSRajesh Borundia 
160197d8105cSRajesh Borundia 	if (!vf->rx_ctx_id)
160297d8105cSRajesh Borundia 		return;
160397d8105cSRajesh Borundia 
160497d8105cSRajesh Borundia 	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX))
160597d8105cSRajesh Borundia 		return;
160697d8105cSRajesh Borundia 
160797d8105cSRajesh Borundia 	vpid = qlcnic_sriov_pf_get_vport_handle(adapter, vf->pci_func);
160897d8105cSRajesh Borundia 	if (vpid >= 0) {
160997d8105cSRajesh Borundia 		cmd.req.arg[1] = vf->rx_ctx_id | (vpid & 0xffff) << 16;
161097d8105cSRajesh Borundia 		if (qlcnic_issue_cmd(adapter, &cmd))
161197d8105cSRajesh Borundia 			dev_err(&adapter->pdev->dev,
161297d8105cSRajesh Borundia 				"Failed to delete Tx ctx in firmware for func 0x%x\n",
161397d8105cSRajesh Borundia 				vf->pci_func);
161497d8105cSRajesh Borundia 		else
161597d8105cSRajesh Borundia 			vf->rx_ctx_id = 0;
161697d8105cSRajesh Borundia 	}
161797d8105cSRajesh Borundia 
161897d8105cSRajesh Borundia 	qlcnic_free_mbx_args(&cmd);
161997d8105cSRajesh Borundia }
162097d8105cSRajesh Borundia 
qlcnic_sriov_del_tx_ctx(struct qlcnic_adapter * adapter,struct qlcnic_vf_info * vf)162197d8105cSRajesh Borundia static void qlcnic_sriov_del_tx_ctx(struct qlcnic_adapter *adapter,
162297d8105cSRajesh Borundia 				    struct qlcnic_vf_info *vf)
162397d8105cSRajesh Borundia {
162497d8105cSRajesh Borundia 	struct qlcnic_cmd_args cmd;
162597d8105cSRajesh Borundia 	int vpid;
162697d8105cSRajesh Borundia 
162797d8105cSRajesh Borundia 	if (!vf->tx_ctx_id)
162897d8105cSRajesh Borundia 		return;
162997d8105cSRajesh Borundia 
163097d8105cSRajesh Borundia 	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX))
163197d8105cSRajesh Borundia 		return;
163297d8105cSRajesh Borundia 
163397d8105cSRajesh Borundia 	vpid = qlcnic_sriov_pf_get_vport_handle(adapter, vf->pci_func);
163497d8105cSRajesh Borundia 	if (vpid >= 0) {
163597d8105cSRajesh Borundia 		cmd.req.arg[1] |= vf->tx_ctx_id | (vpid & 0xffff) << 16;
163697d8105cSRajesh Borundia 		if (qlcnic_issue_cmd(adapter, &cmd))
163797d8105cSRajesh Borundia 			dev_err(&adapter->pdev->dev,
163897d8105cSRajesh Borundia 				"Failed to delete Tx ctx in firmware for func 0x%x\n",
163997d8105cSRajesh Borundia 				vf->pci_func);
164097d8105cSRajesh Borundia 		else
164197d8105cSRajesh Borundia 			vf->tx_ctx_id = 0;
164297d8105cSRajesh Borundia 	}
164397d8105cSRajesh Borundia 
164497d8105cSRajesh Borundia 	qlcnic_free_mbx_args(&cmd);
164597d8105cSRajesh Borundia }
164697d8105cSRajesh Borundia 
qlcnic_sriov_add_act_list_irqsave(struct qlcnic_sriov * sriov,struct qlcnic_vf_info * vf,struct qlcnic_bc_trans * trans)164797d8105cSRajesh Borundia static int qlcnic_sriov_add_act_list_irqsave(struct qlcnic_sriov *sriov,
164897d8105cSRajesh Borundia 					     struct qlcnic_vf_info *vf,
164997d8105cSRajesh Borundia 					     struct qlcnic_bc_trans *trans)
165097d8105cSRajesh Borundia {
165197d8105cSRajesh Borundia 	struct qlcnic_trans_list *t_list = &vf->rcv_act;
165297d8105cSRajesh Borundia 	unsigned long flag;
165397d8105cSRajesh Borundia 
165497d8105cSRajesh Borundia 	spin_lock_irqsave(&t_list->lock, flag);
165597d8105cSRajesh Borundia 
165697d8105cSRajesh Borundia 	__qlcnic_sriov_add_act_list(sriov, vf, trans);
165797d8105cSRajesh Borundia 
165897d8105cSRajesh Borundia 	spin_unlock_irqrestore(&t_list->lock, flag);
165997d8105cSRajesh Borundia 	return 0;
166097d8105cSRajesh Borundia }
166197d8105cSRajesh Borundia 
__qlcnic_sriov_process_flr(struct qlcnic_vf_info * vf)166297d8105cSRajesh Borundia static void __qlcnic_sriov_process_flr(struct qlcnic_vf_info *vf)
166397d8105cSRajesh Borundia {
166497d8105cSRajesh Borundia 	struct qlcnic_adapter *adapter = vf->adapter;
166597d8105cSRajesh Borundia 
166697d8105cSRajesh Borundia 	qlcnic_sriov_cleanup_list(&vf->rcv_pend);
166797d8105cSRajesh Borundia 	cancel_work_sync(&vf->trans_work);
166897d8105cSRajesh Borundia 	qlcnic_sriov_cleanup_list(&vf->rcv_act);
166997d8105cSRajesh Borundia 
167097d8105cSRajesh Borundia 	if (test_bit(QLC_BC_VF_SOFT_FLR, &vf->state)) {
167197d8105cSRajesh Borundia 		qlcnic_sriov_del_tx_ctx(adapter, vf);
167297d8105cSRajesh Borundia 		qlcnic_sriov_del_rx_ctx(adapter, vf);
167397d8105cSRajesh Borundia 	}
167497d8105cSRajesh Borundia 
167597d8105cSRajesh Borundia 	qlcnic_sriov_pf_config_vport(adapter, 0, vf->pci_func);
167697d8105cSRajesh Borundia 
167797d8105cSRajesh Borundia 	clear_bit(QLC_BC_VF_FLR, &vf->state);
167897d8105cSRajesh Borundia 	if (test_bit(QLC_BC_VF_SOFT_FLR, &vf->state)) {
167997d8105cSRajesh Borundia 		qlcnic_sriov_add_act_list_irqsave(adapter->ahw->sriov, vf,
168097d8105cSRajesh Borundia 						  vf->flr_trans);
168197d8105cSRajesh Borundia 		clear_bit(QLC_BC_VF_SOFT_FLR, &vf->state);
168297d8105cSRajesh Borundia 		vf->flr_trans = NULL;
168397d8105cSRajesh Borundia 	}
168497d8105cSRajesh Borundia }
168597d8105cSRajesh Borundia 
qlcnic_sriov_pf_process_flr(struct work_struct * work)168697d8105cSRajesh Borundia static void qlcnic_sriov_pf_process_flr(struct work_struct *work)
168797d8105cSRajesh Borundia {
168897d8105cSRajesh Borundia 	struct qlcnic_vf_info *vf;
168997d8105cSRajesh Borundia 
169097d8105cSRajesh Borundia 	vf = container_of(work, struct qlcnic_vf_info, flr_work);
169197d8105cSRajesh Borundia 	__qlcnic_sriov_process_flr(vf);
169297d8105cSRajesh Borundia 	return;
169397d8105cSRajesh Borundia }
169497d8105cSRajesh Borundia 
qlcnic_sriov_schedule_flr(struct qlcnic_sriov * sriov,struct qlcnic_vf_info * vf,work_func_t func)169597d8105cSRajesh Borundia static void qlcnic_sriov_schedule_flr(struct qlcnic_sriov *sriov,
169697d8105cSRajesh Borundia 				      struct qlcnic_vf_info *vf,
169797d8105cSRajesh Borundia 				      work_func_t func)
169897d8105cSRajesh Borundia {
169997d8105cSRajesh Borundia 	if (test_bit(__QLCNIC_RESETTING, &vf->adapter->state))
170097d8105cSRajesh Borundia 		return;
170197d8105cSRajesh Borundia 
170297d8105cSRajesh Borundia 	INIT_WORK(&vf->flr_work, func);
170397d8105cSRajesh Borundia 	queue_work(sriov->bc.bc_flr_wq, &vf->flr_work);
170497d8105cSRajesh Borundia }
170597d8105cSRajesh Borundia 
qlcnic_sriov_handle_soft_flr(struct qlcnic_adapter * adapter,struct qlcnic_bc_trans * trans,struct qlcnic_vf_info * vf)170697d8105cSRajesh Borundia static void qlcnic_sriov_handle_soft_flr(struct qlcnic_adapter *adapter,
170797d8105cSRajesh Borundia 					 struct qlcnic_bc_trans *trans,
170897d8105cSRajesh Borundia 					 struct qlcnic_vf_info *vf)
170997d8105cSRajesh Borundia {
171097d8105cSRajesh Borundia 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
171197d8105cSRajesh Borundia 
171297d8105cSRajesh Borundia 	set_bit(QLC_BC_VF_FLR, &vf->state);
171397d8105cSRajesh Borundia 	clear_bit(QLC_BC_VF_STATE, &vf->state);
171497d8105cSRajesh Borundia 	set_bit(QLC_BC_VF_SOFT_FLR, &vf->state);
171597d8105cSRajesh Borundia 	vf->flr_trans = trans;
171697d8105cSRajesh Borundia 	qlcnic_sriov_schedule_flr(sriov, vf, qlcnic_sriov_pf_process_flr);
171797d8105cSRajesh Borundia 	netdev_info(adapter->netdev, "Software FLR for PCI func %d\n",
171897d8105cSRajesh Borundia 		    vf->pci_func);
171997d8105cSRajesh Borundia }
172097d8105cSRajesh Borundia 
qlcnic_sriov_soft_flr_check(struct qlcnic_adapter * adapter,struct qlcnic_bc_trans * trans,struct qlcnic_vf_info * vf)172197d8105cSRajesh Borundia bool qlcnic_sriov_soft_flr_check(struct qlcnic_adapter *adapter,
172297d8105cSRajesh Borundia 				 struct qlcnic_bc_trans *trans,
172397d8105cSRajesh Borundia 				 struct qlcnic_vf_info *vf)
172497d8105cSRajesh Borundia {
172597d8105cSRajesh Borundia 	struct qlcnic_bc_hdr *hdr = trans->req_hdr;
172697d8105cSRajesh Borundia 
172797d8105cSRajesh Borundia 	if ((hdr->cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) &&
172897d8105cSRajesh Borundia 	    (hdr->op_type == QLC_BC_CMD) &&
172997d8105cSRajesh Borundia 	     test_bit(QLC_BC_VF_STATE, &vf->state)) {
173097d8105cSRajesh Borundia 		qlcnic_sriov_handle_soft_flr(adapter, trans, vf);
173197d8105cSRajesh Borundia 		return true;
173297d8105cSRajesh Borundia 	}
173397d8105cSRajesh Borundia 
173497d8105cSRajesh Borundia 	return false;
173597d8105cSRajesh Borundia }
173697d8105cSRajesh Borundia 
qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov * sriov,struct qlcnic_vf_info * vf)173797d8105cSRajesh Borundia void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *sriov,
173897d8105cSRajesh Borundia 				struct qlcnic_vf_info *vf)
173997d8105cSRajesh Borundia {
174097d8105cSRajesh Borundia 	struct net_device *dev = vf->adapter->netdev;
17412f0a9afaSManish Chopra 	struct qlcnic_vport *vp = vf->vp;
174297d8105cSRajesh Borundia 
174397d8105cSRajesh Borundia 	if (!test_and_clear_bit(QLC_BC_VF_STATE, &vf->state)) {
174497d8105cSRajesh Borundia 		clear_bit(QLC_BC_VF_FLR, &vf->state);
174597d8105cSRajesh Borundia 		return;
174697d8105cSRajesh Borundia 	}
174797d8105cSRajesh Borundia 
174897d8105cSRajesh Borundia 	if (test_and_set_bit(QLC_BC_VF_FLR, &vf->state)) {
174997d8105cSRajesh Borundia 		netdev_info(dev, "FLR for PCI func %d in progress\n",
175097d8105cSRajesh Borundia 			    vf->pci_func);
175197d8105cSRajesh Borundia 		return;
175297d8105cSRajesh Borundia 	}
175397d8105cSRajesh Borundia 
17542f0a9afaSManish Chopra 	if (vp->vlan_mode == QLC_GUEST_VLAN_MODE)
1755154d0c81SManish Chopra 		memset(vf->sriov_vlans, 0,
1756154d0c81SManish Chopra 		       sizeof(*vf->sriov_vlans) * sriov->num_allowed_vlans);
17572f0a9afaSManish Chopra 
175897d8105cSRajesh Borundia 	qlcnic_sriov_schedule_flr(sriov, vf, qlcnic_sriov_pf_process_flr);
175997d8105cSRajesh Borundia 	netdev_info(dev, "FLR received for PCI func %d\n", vf->pci_func);
176097d8105cSRajesh Borundia }
1761f036e4f4SRajesh Borundia 
qlcnic_sriov_pf_reset(struct qlcnic_adapter * adapter)1762f036e4f4SRajesh Borundia void qlcnic_sriov_pf_reset(struct qlcnic_adapter *adapter)
1763f036e4f4SRajesh Borundia {
1764f036e4f4SRajesh Borundia 	struct qlcnic_hardware_context *ahw = adapter->ahw;
1765f036e4f4SRajesh Borundia 	struct qlcnic_sriov *sriov = ahw->sriov;
1766f036e4f4SRajesh Borundia 	struct qlcnic_vf_info *vf;
1767f036e4f4SRajesh Borundia 	u16 num_vfs = sriov->num_vfs;
1768f036e4f4SRajesh Borundia 	int i;
1769f036e4f4SRajesh Borundia 
1770f036e4f4SRajesh Borundia 	for (i = 0; i < num_vfs; i++) {
1771f036e4f4SRajesh Borundia 		vf = &sriov->vf_info[i];
1772f036e4f4SRajesh Borundia 		vf->rx_ctx_id = 0;
1773f036e4f4SRajesh Borundia 		vf->tx_ctx_id = 0;
1774f036e4f4SRajesh Borundia 		cancel_work_sync(&vf->flr_work);
1775f036e4f4SRajesh Borundia 		__qlcnic_sriov_process_flr(vf);
1776f036e4f4SRajesh Borundia 		clear_bit(QLC_BC_VF_STATE, &vf->state);
1777f036e4f4SRajesh Borundia 	}
1778f036e4f4SRajesh Borundia 
1779f036e4f4SRajesh Borundia 	qlcnic_sriov_pf_reset_vport_handle(adapter, ahw->pci_func);
1780f036e4f4SRajesh Borundia 	QLCWRX(ahw, QLCNIC_MBX_INTR_ENBL, (ahw->num_msix - 1) << 8);
1781f036e4f4SRajesh Borundia }
1782f036e4f4SRajesh Borundia 
qlcnic_sriov_pf_reinit(struct qlcnic_adapter * adapter)1783f036e4f4SRajesh Borundia int qlcnic_sriov_pf_reinit(struct qlcnic_adapter *adapter)
1784f036e4f4SRajesh Borundia {
1785f036e4f4SRajesh Borundia 	struct qlcnic_hardware_context *ahw = adapter->ahw;
1786f036e4f4SRajesh Borundia 	int err;
1787f036e4f4SRajesh Borundia 
1788f036e4f4SRajesh Borundia 	if (!qlcnic_sriov_enable_check(adapter))
1789f036e4f4SRajesh Borundia 		return 0;
1790f036e4f4SRajesh Borundia 
1791f036e4f4SRajesh Borundia 	ahw->op_mode = QLCNIC_SRIOV_PF_FUNC;
1792f036e4f4SRajesh Borundia 
1793f036e4f4SRajesh Borundia 	err = qlcnic_sriov_pf_init(adapter);
1794f036e4f4SRajesh Borundia 	if (err)
1795f036e4f4SRajesh Borundia 		return err;
1796f036e4f4SRajesh Borundia 
1797f036e4f4SRajesh Borundia 	dev_info(&adapter->pdev->dev, "%s: op_mode %d\n",
1798f036e4f4SRajesh Borundia 		 __func__, ahw->op_mode);
1799f036e4f4SRajesh Borundia 	return err;
1800f036e4f4SRajesh Borundia }
18014000e7a7SRajesh Borundia 
qlcnic_sriov_set_vf_mac(struct net_device * netdev,int vf,u8 * mac)18024000e7a7SRajesh Borundia int qlcnic_sriov_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
18034000e7a7SRajesh Borundia {
18044000e7a7SRajesh Borundia 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
18054000e7a7SRajesh Borundia 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
1806cab150b5SManish Chopra 	int i, num_vfs;
18074000e7a7SRajesh Borundia 	struct qlcnic_vf_info *vf_info;
18084000e7a7SRajesh Borundia 	u8 *curr_mac;
18094000e7a7SRajesh Borundia 
18104000e7a7SRajesh Borundia 	if (!qlcnic_sriov_pf_check(adapter))
18114000e7a7SRajesh Borundia 		return -EOPNOTSUPP;
18124000e7a7SRajesh Borundia 
1813cab150b5SManish Chopra 	num_vfs = sriov->num_vfs;
1814cab150b5SManish Chopra 
18154000e7a7SRajesh Borundia 	if (!is_valid_ether_addr(mac) || vf >= num_vfs)
18164000e7a7SRajesh Borundia 		return -EINVAL;
18174000e7a7SRajesh Borundia 
18187367d0b5SJoe Perches 	if (ether_addr_equal(adapter->mac_addr, mac)) {
18194000e7a7SRajesh Borundia 		netdev_err(netdev, "MAC address is already in use by the PF\n");
18204000e7a7SRajesh Borundia 		return -EINVAL;
18214000e7a7SRajesh Borundia 	}
18224000e7a7SRajesh Borundia 
18234000e7a7SRajesh Borundia 	for (i = 0; i < num_vfs; i++) {
18244000e7a7SRajesh Borundia 		vf_info = &sriov->vf_info[i];
18257367d0b5SJoe Perches 		if (ether_addr_equal(vf_info->vp->mac, mac)) {
18264000e7a7SRajesh Borundia 			netdev_err(netdev,
18274000e7a7SRajesh Borundia 				   "MAC address is already in use by VF %d\n",
18284000e7a7SRajesh Borundia 				   i);
18294000e7a7SRajesh Borundia 			return -EINVAL;
18304000e7a7SRajesh Borundia 		}
18314000e7a7SRajesh Borundia 	}
18324000e7a7SRajesh Borundia 
18334000e7a7SRajesh Borundia 	vf_info = &sriov->vf_info[vf];
18344000e7a7SRajesh Borundia 	curr_mac = vf_info->vp->mac;
18354000e7a7SRajesh Borundia 
18364000e7a7SRajesh Borundia 	if (test_bit(QLC_BC_VF_STATE, &vf_info->state)) {
18374000e7a7SRajesh Borundia 		netdev_err(netdev,
18384000e7a7SRajesh Borundia 			   "MAC address change failed for VF %d, as VF driver is loaded. Please unload VF driver and retry the operation\n",
18394000e7a7SRajesh Borundia 			   vf);
18404000e7a7SRajesh Borundia 		return -EOPNOTSUPP;
18414000e7a7SRajesh Borundia 	}
18424000e7a7SRajesh Borundia 
18434000e7a7SRajesh Borundia 	memcpy(curr_mac, mac, netdev->addr_len);
18444000e7a7SRajesh Borundia 	netdev_info(netdev, "MAC Address %pM  is configured for VF %d\n",
18454000e7a7SRajesh Borundia 		    mac, vf);
18464000e7a7SRajesh Borundia 	return 0;
18474000e7a7SRajesh Borundia }
18484000e7a7SRajesh Borundia 
qlcnic_sriov_set_vf_tx_rate(struct net_device * netdev,int vf,int min_tx_rate,int max_tx_rate)1849ed616689SSucheta Chakraborty int qlcnic_sriov_set_vf_tx_rate(struct net_device *netdev, int vf,
1850ed616689SSucheta Chakraborty 				int min_tx_rate, int max_tx_rate)
18514000e7a7SRajesh Borundia {
18524000e7a7SRajesh Borundia 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
18534000e7a7SRajesh Borundia 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
18544000e7a7SRajesh Borundia 	struct qlcnic_vf_info *vf_info;
18554000e7a7SRajesh Borundia 	struct qlcnic_info nic_info;
18564000e7a7SRajesh Borundia 	struct qlcnic_vport *vp;
18574000e7a7SRajesh Borundia 	u16 vpid;
18584000e7a7SRajesh Borundia 
18594000e7a7SRajesh Borundia 	if (!qlcnic_sriov_pf_check(adapter))
18604000e7a7SRajesh Borundia 		return -EOPNOTSUPP;
18614000e7a7SRajesh Borundia 
18624000e7a7SRajesh Borundia 	if (vf >= sriov->num_vfs)
18634000e7a7SRajesh Borundia 		return -EINVAL;
18644000e7a7SRajesh Borundia 
18654000e7a7SRajesh Borundia 	vf_info = &sriov->vf_info[vf];
18664000e7a7SRajesh Borundia 	vp = vf_info->vp;
18674000e7a7SRajesh Borundia 	vpid = vp->handle;
18684000e7a7SRajesh Borundia 
1869ed616689SSucheta Chakraborty 	if (!min_tx_rate)
1870ed616689SSucheta Chakraborty 		min_tx_rate = QLC_VF_MIN_TX_RATE;
1871ed616689SSucheta Chakraborty 
1872*10e11aa2SBin Chen 	if (max_tx_rate && max_tx_rate >= 10000) {
1873ed616689SSucheta Chakraborty 		netdev_err(netdev,
1874ed616689SSucheta Chakraborty 			   "Invalid max Tx rate, allowed range is [%d - %d]",
1875ed616689SSucheta Chakraborty 			   min_tx_rate, QLC_VF_MAX_TX_RATE);
1876ed616689SSucheta Chakraborty 		return -EINVAL;
1877ed616689SSucheta Chakraborty 	}
1878ed616689SSucheta Chakraborty 
1879ed616689SSucheta Chakraborty 	if (!max_tx_rate)
1880ed616689SSucheta Chakraborty 		max_tx_rate = 10000;
1881ed616689SSucheta Chakraborty 
1882*10e11aa2SBin Chen 	if (min_tx_rate && min_tx_rate < QLC_VF_MIN_TX_RATE) {
1883ed616689SSucheta Chakraborty 		netdev_err(netdev,
1884ed616689SSucheta Chakraborty 			   "Invalid min Tx rate, allowed range is [%d - %d]",
1885ed616689SSucheta Chakraborty 			   QLC_VF_MIN_TX_RATE, max_tx_rate);
1886ed616689SSucheta Chakraborty 		return -EINVAL;
1887ed616689SSucheta Chakraborty 	}
1888ed616689SSucheta Chakraborty 
18894000e7a7SRajesh Borundia 	if (test_bit(QLC_BC_VF_STATE, &vf_info->state)) {
18904000e7a7SRajesh Borundia 		if (qlcnic_sriov_get_vf_vport_info(adapter, &nic_info, vpid))
18914000e7a7SRajesh Borundia 			return -EIO;
18924000e7a7SRajesh Borundia 
1893ed616689SSucheta Chakraborty 		nic_info.max_tx_bw = max_tx_rate / 100;
1894ed616689SSucheta Chakraborty 		nic_info.min_tx_bw = min_tx_rate / 100;
18954000e7a7SRajesh Borundia 		nic_info.bit_offsets = BIT_0;
18964000e7a7SRajesh Borundia 
18974000e7a7SRajesh Borundia 		if (qlcnic_sriov_pf_set_vport_info(adapter, &nic_info, vpid))
18984000e7a7SRajesh Borundia 			return -EIO;
18994000e7a7SRajesh Borundia 	}
19004000e7a7SRajesh Borundia 
1901ed616689SSucheta Chakraborty 	vp->max_tx_bw = max_tx_rate / 100;
19024000e7a7SRajesh Borundia 	netdev_info(netdev,
1903ed616689SSucheta Chakraborty 		    "Setting Max Tx rate %d (Mbps), %d %% of PF bandwidth, for VF %d\n",
1904ed616689SSucheta Chakraborty 		    max_tx_rate, vp->max_tx_bw, vf);
1905ed616689SSucheta Chakraborty 	vp->min_tx_bw = min_tx_rate / 100;
1906ed616689SSucheta Chakraborty 	netdev_info(netdev,
1907ed616689SSucheta Chakraborty 		    "Setting Min Tx rate %d (Mbps), %d %% of PF bandwidth, for VF %d\n",
1908ed616689SSucheta Chakraborty 		    min_tx_rate, vp->min_tx_bw, vf);
19094000e7a7SRajesh Borundia 	return 0;
19104000e7a7SRajesh Borundia }
19114000e7a7SRajesh Borundia 
qlcnic_sriov_set_vf_vlan(struct net_device * netdev,int vf,u16 vlan,u8 qos,__be16 vlan_proto)191291b7282bSRajesh Borundia int qlcnic_sriov_set_vf_vlan(struct net_device *netdev, int vf,
191379aab093SMoshe Shemesh 			     u16 vlan, u8 qos, __be16 vlan_proto)
191491b7282bSRajesh Borundia {
191591b7282bSRajesh Borundia 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
191691b7282bSRajesh Borundia 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
191791b7282bSRajesh Borundia 	struct qlcnic_vf_info *vf_info;
191891b7282bSRajesh Borundia 	struct qlcnic_vport *vp;
191991b7282bSRajesh Borundia 
192091b7282bSRajesh Borundia 	if (!qlcnic_sriov_pf_check(adapter))
192191b7282bSRajesh Borundia 		return -EOPNOTSUPP;
192291b7282bSRajesh Borundia 
192391b7282bSRajesh Borundia 	if (vf >= sriov->num_vfs || qos > 7)
192491b7282bSRajesh Borundia 		return -EINVAL;
192591b7282bSRajesh Borundia 
192679aab093SMoshe Shemesh 	if (vlan_proto != htons(ETH_P_8021Q))
192779aab093SMoshe Shemesh 		return -EPROTONOSUPPORT;
192879aab093SMoshe Shemesh 
192991b7282bSRajesh Borundia 	if (vlan > MAX_VLAN_ID) {
193091b7282bSRajesh Borundia 		netdev_err(netdev,
193191b7282bSRajesh Borundia 			   "Invalid VLAN ID, allowed range is [0 - %d]\n",
193291b7282bSRajesh Borundia 			   MAX_VLAN_ID);
193391b7282bSRajesh Borundia 		return -EINVAL;
193491b7282bSRajesh Borundia 	}
193591b7282bSRajesh Borundia 
193691b7282bSRajesh Borundia 	vf_info = &sriov->vf_info[vf];
193791b7282bSRajesh Borundia 	vp = vf_info->vp;
193891b7282bSRajesh Borundia 	if (test_bit(QLC_BC_VF_STATE, &vf_info->state)) {
193991b7282bSRajesh Borundia 		netdev_err(netdev,
194091b7282bSRajesh Borundia 			   "VLAN change failed for VF %d, as VF driver is loaded. Please unload VF driver and retry the operation\n",
194191b7282bSRajesh Borundia 			   vf);
194291b7282bSRajesh Borundia 		return -EOPNOTSUPP;
194391b7282bSRajesh Borundia 	}
194491b7282bSRajesh Borundia 
1945154d0c81SManish Chopra 	memset(vf_info->sriov_vlans, 0,
1946154d0c81SManish Chopra 	       sizeof(*vf_info->sriov_vlans) * sriov->num_allowed_vlans);
1947154d0c81SManish Chopra 
194891b7282bSRajesh Borundia 	switch (vlan) {
194991b7282bSRajesh Borundia 	case 4095:
195091b7282bSRajesh Borundia 		vp->vlan_mode = QLC_GUEST_VLAN_MODE;
195191b7282bSRajesh Borundia 		break;
195291b7282bSRajesh Borundia 	case 0:
195391b7282bSRajesh Borundia 		vp->vlan_mode = QLC_NO_VLAN_MODE;
195491b7282bSRajesh Borundia 		vp->qos = 0;
195591b7282bSRajesh Borundia 		break;
195691b7282bSRajesh Borundia 	default:
195791b7282bSRajesh Borundia 		vp->vlan_mode = QLC_PVID_MODE;
1958154d0c81SManish Chopra 		qlcnic_sriov_add_vlan_id(sriov, vf_info, vlan);
195991b7282bSRajesh Borundia 		vp->qos = qos;
1960154d0c81SManish Chopra 		vp->pvid = vlan;
196191b7282bSRajesh Borundia 	}
196291b7282bSRajesh Borundia 
196391b7282bSRajesh Borundia 	netdev_info(netdev, "Setting VLAN %d, QoS %d, for VF %d\n",
196491b7282bSRajesh Borundia 		    vlan, qos, vf);
196591b7282bSRajesh Borundia 	return 0;
196691b7282bSRajesh Borundia }
196791b7282bSRajesh Borundia 
qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter * adapter,struct qlcnic_vport * vp,int vf)196860dcbcb0SManish Chopra static __u32 qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter *adapter,
19697cfc1cebSManish Chopra 				      struct qlcnic_vport *vp, int vf)
19707cfc1cebSManish Chopra {
19717cfc1cebSManish Chopra 	__u32 vlan = 0;
19727cfc1cebSManish Chopra 
19737cfc1cebSManish Chopra 	switch (vp->vlan_mode) {
19747cfc1cebSManish Chopra 	case QLC_PVID_MODE:
1975154d0c81SManish Chopra 		vlan = vp->pvid;
19767cfc1cebSManish Chopra 		break;
19777cfc1cebSManish Chopra 	case QLC_GUEST_VLAN_MODE:
19787cfc1cebSManish Chopra 		vlan = MAX_VLAN_ID;
19797cfc1cebSManish Chopra 		break;
19807cfc1cebSManish Chopra 	case QLC_NO_VLAN_MODE:
19817cfc1cebSManish Chopra 		vlan = 0;
19827cfc1cebSManish Chopra 		break;
19837cfc1cebSManish Chopra 	default:
19847cfc1cebSManish Chopra 		netdev_info(adapter->netdev, "Invalid VLAN mode = %d for VF %d\n",
19857cfc1cebSManish Chopra 			    vp->vlan_mode, vf);
19867cfc1cebSManish Chopra 	}
19877cfc1cebSManish Chopra 
19887cfc1cebSManish Chopra 	return vlan;
19897cfc1cebSManish Chopra }
19907cfc1cebSManish Chopra 
qlcnic_sriov_get_vf_config(struct net_device * netdev,int vf,struct ifla_vf_info * ivi)19914000e7a7SRajesh Borundia int qlcnic_sriov_get_vf_config(struct net_device *netdev,
19924000e7a7SRajesh Borundia 			       int vf, struct ifla_vf_info *ivi)
19934000e7a7SRajesh Borundia {
19944000e7a7SRajesh Borundia 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
19954000e7a7SRajesh Borundia 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
19964000e7a7SRajesh Borundia 	struct qlcnic_vport *vp;
19974000e7a7SRajesh Borundia 
19984000e7a7SRajesh Borundia 	if (!qlcnic_sriov_pf_check(adapter))
19994000e7a7SRajesh Borundia 		return -EOPNOTSUPP;
20004000e7a7SRajesh Borundia 
20014000e7a7SRajesh Borundia 	if (vf >= sriov->num_vfs)
20024000e7a7SRajesh Borundia 		return -EINVAL;
20034000e7a7SRajesh Borundia 
20044000e7a7SRajesh Borundia 	vp = sriov->vf_info[vf].vp;
20054000e7a7SRajesh Borundia 	memcpy(&ivi->mac, vp->mac, ETH_ALEN);
20067cfc1cebSManish Chopra 	ivi->vlan = qlcnic_sriov_get_vf_vlan(adapter, vp, vf);
200791b7282bSRajesh Borundia 	ivi->qos = vp->qos;
2008a80be5a5SRajesh Borundia 	ivi->spoofchk = vp->spoofchk;
20094000e7a7SRajesh Borundia 	if (vp->max_tx_bw == MAX_BW)
2010ed616689SSucheta Chakraborty 		ivi->max_tx_rate = 0;
20114000e7a7SRajesh Borundia 	else
2012ed616689SSucheta Chakraborty 		ivi->max_tx_rate = vp->max_tx_bw * 100;
2013ed616689SSucheta Chakraborty 	if (vp->min_tx_bw == MIN_BW)
2014ed616689SSucheta Chakraborty 		ivi->min_tx_rate = 0;
2015ed616689SSucheta Chakraborty 	else
2016ed616689SSucheta Chakraborty 		ivi->min_tx_rate = vp->min_tx_bw * 100;
20174000e7a7SRajesh Borundia 
20184000e7a7SRajesh Borundia 	ivi->vf = vf;
20194000e7a7SRajesh Borundia 	return 0;
20204000e7a7SRajesh Borundia }
2021a80be5a5SRajesh Borundia 
qlcnic_sriov_set_vf_spoofchk(struct net_device * netdev,int vf,bool chk)2022a80be5a5SRajesh Borundia int qlcnic_sriov_set_vf_spoofchk(struct net_device *netdev, int vf, bool chk)
2023a80be5a5SRajesh Borundia {
2024a80be5a5SRajesh Borundia 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
2025a80be5a5SRajesh Borundia 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
2026a80be5a5SRajesh Borundia 	struct qlcnic_vf_info *vf_info;
2027a80be5a5SRajesh Borundia 	struct qlcnic_vport *vp;
2028a80be5a5SRajesh Borundia 
2029a80be5a5SRajesh Borundia 	if (!qlcnic_sriov_pf_check(adapter))
2030a80be5a5SRajesh Borundia 		return -EOPNOTSUPP;
2031a80be5a5SRajesh Borundia 
2032a80be5a5SRajesh Borundia 	if (vf >= sriov->num_vfs)
2033a80be5a5SRajesh Borundia 		return -EINVAL;
2034a80be5a5SRajesh Borundia 
2035a80be5a5SRajesh Borundia 	vf_info = &sriov->vf_info[vf];
2036a80be5a5SRajesh Borundia 	vp = vf_info->vp;
2037a80be5a5SRajesh Borundia 	if (test_bit(QLC_BC_VF_STATE, &vf_info->state)) {
2038a80be5a5SRajesh Borundia 		netdev_err(netdev,
2039a80be5a5SRajesh Borundia 			   "Spoof check change failed for VF %d, as VF driver is loaded. Please unload VF driver and retry the operation\n",
2040a80be5a5SRajesh Borundia 			   vf);
2041a80be5a5SRajesh Borundia 		return -EOPNOTSUPP;
2042a80be5a5SRajesh Borundia 	}
2043a80be5a5SRajesh Borundia 
2044a80be5a5SRajesh Borundia 	vp->spoofchk = chk;
2045a80be5a5SRajesh Borundia 	return 0;
2046a80be5a5SRajesh Borundia }
2047