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