xref: /linux/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c (revision ec8a42e7343234802b9054874fe01810880289ce)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * QLogic qlcnic NIC Driver
4  * Copyright (c) 2009-2013 QLogic Corporation
5  */
6 
7 #include "qlcnic.h"
8 #include "qlcnic_hw.h"
9 
10 static int qlcnic_83xx_enable_vnic_mode(struct qlcnic_adapter *adapter, int lock)
11 {
12 	if (lock) {
13 		if (qlcnic_83xx_lock_driver(adapter))
14 			return -EBUSY;
15 	}
16 	QLCWRX(adapter->ahw, QLC_83XX_VNIC_STATE, QLCNIC_DEV_NPAR_OPER);
17 	if (lock)
18 		qlcnic_83xx_unlock_driver(adapter);
19 
20 	return 0;
21 }
22 
23 int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *adapter, int lock)
24 {
25 	struct qlcnic_hardware_context *ahw = adapter->ahw;
26 
27 	if (lock) {
28 		if (qlcnic_83xx_lock_driver(adapter))
29 			return -EBUSY;
30 	}
31 
32 	QLCWRX(adapter->ahw, QLC_83XX_VNIC_STATE, QLCNIC_DEV_NPAR_NON_OPER);
33 	ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
34 
35 	if (lock)
36 		qlcnic_83xx_unlock_driver(adapter);
37 
38 	return 0;
39 }
40 
41 int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter)
42 {
43 	u8 id;
44 	int ret = -EBUSY;
45 	u32 data = QLCNIC_MGMT_FUNC;
46 	struct qlcnic_hardware_context *ahw = adapter->ahw;
47 
48 	if (qlcnic_83xx_lock_driver(adapter))
49 		return ret;
50 
51 	id = ahw->pci_func;
52 	data = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
53 	data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, id)) |
54 	       QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC, id);
55 
56 	QLCWRX(adapter->ahw, QLC_83XX_DRV_OP_MODE, data);
57 
58 	qlcnic_83xx_unlock_driver(adapter);
59 
60 	return 0;
61 }
62 
63 static void
64 qlcnic_83xx_config_vnic_buff_descriptors(struct qlcnic_adapter *adapter)
65 {
66 	struct qlcnic_hardware_context *ahw = adapter->ahw;
67 
68 	if (ahw->port_type == QLCNIC_XGBE) {
69 		adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF;
70 		adapter->max_rxd = MAX_RCV_DESCRIPTORS_VF;
71 		adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
72 		adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
73 
74 	} else if (ahw->port_type == QLCNIC_GBE) {
75 		adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
76 		adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
77 		adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
78 		adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;
79 	}
80 	adapter->num_txd = MAX_CMD_DESCRIPTORS;
81 	adapter->max_rds_rings = MAX_RDS_RINGS;
82 }
83 
84 
85 /**
86  * qlcnic_83xx_init_mgmt_vnic
87  *
88  * @adapter: adapter structure
89  * Management virtual NIC sets the operational mode of other vNIC's and
90  * configures embedded switch (ESWITCH).
91  * Returns: Success(0) or error code.
92  *
93  **/
94 static int qlcnic_83xx_init_mgmt_vnic(struct qlcnic_adapter *adapter)
95 {
96 	struct qlcnic_hardware_context *ahw = adapter->ahw;
97 	struct device *dev = &adapter->pdev->dev;
98 	struct qlcnic_npar_info *npar;
99 	int i, err = -EIO;
100 
101 	qlcnic_83xx_get_minidump_template(adapter);
102 
103 	if (!(adapter->flags & QLCNIC_ADAPTER_INITIALIZED)) {
104 		if (qlcnic_init_pci_info(adapter))
105 			return err;
106 
107 		npar = adapter->npars;
108 
109 		for (i = 0; i < ahw->total_nic_func; i++, npar++) {
110 			dev_info(dev, "id:%d active:%d type:%d port:%d min_bw:%d max_bw:%d mac_addr:%pM\n",
111 				 npar->pci_func, npar->active, npar->type,
112 				 npar->phy_port, npar->min_bw, npar->max_bw,
113 				 npar->mac);
114 		}
115 
116 		dev_info(dev, "Max functions = %d, active functions = %d\n",
117 			 ahw->max_pci_func, ahw->total_nic_func);
118 
119 		if (qlcnic_83xx_set_vnic_opmode(adapter))
120 			return err;
121 
122 		if (qlcnic_set_default_offload_settings(adapter))
123 			return err;
124 	} else {
125 		if (qlcnic_reset_npar_config(adapter))
126 			return err;
127 	}
128 
129 	if (qlcnic_83xx_get_port_info(adapter))
130 		return err;
131 
132 	qlcnic_83xx_config_vnic_buff_descriptors(adapter);
133 	ahw->msix_supported = qlcnic_use_msi_x ? 1 : 0;
134 	adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
135 	qlcnic_83xx_enable_vnic_mode(adapter, 1);
136 
137 	dev_info(dev, "HAL Version: %d, Management function\n",
138 		 ahw->fw_hal_version);
139 
140 	return 0;
141 }
142 
143 static int qlcnic_83xx_init_privileged_vnic(struct qlcnic_adapter *adapter)
144 {
145 	int err = -EIO;
146 
147 	qlcnic_83xx_get_minidump_template(adapter);
148 	if (qlcnic_83xx_get_port_info(adapter))
149 		return err;
150 
151 	qlcnic_83xx_config_vnic_buff_descriptors(adapter);
152 	adapter->ahw->msix_supported = !!qlcnic_use_msi_x;
153 	adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
154 
155 	dev_info(&adapter->pdev->dev,
156 		 "HAL Version: %d, Privileged function\n",
157 		 adapter->ahw->fw_hal_version);
158 	return 0;
159 }
160 
161 static int qlcnic_83xx_init_non_privileged_vnic(struct qlcnic_adapter *adapter)
162 {
163 	int err = -EIO;
164 
165 	qlcnic_83xx_get_fw_version(adapter);
166 	if (qlcnic_set_eswitch_port_config(adapter))
167 		return err;
168 
169 	if (qlcnic_83xx_get_port_info(adapter))
170 		return err;
171 
172 	qlcnic_83xx_config_vnic_buff_descriptors(adapter);
173 	adapter->ahw->msix_supported = !!qlcnic_use_msi_x;
174 	adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
175 
176 	dev_info(&adapter->pdev->dev, "HAL Version: %d, Virtual function\n",
177 		 adapter->ahw->fw_hal_version);
178 
179 	return 0;
180 }
181 
182 /**
183  * qlcnic_83xx_vnic_opmode
184  *
185  * @adapter: adapter structure
186  * Identify virtual NIC operational modes.
187  *
188  * Returns: Success(0) or error code.
189  *
190  **/
191 int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
192 {
193 	u32 op_mode, priv_level;
194 	struct qlcnic_hardware_context *ahw = adapter->ahw;
195 	struct qlcnic_nic_template *nic_ops = adapter->nic_ops;
196 
197 	qlcnic_get_func_no(adapter);
198 	op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
199 
200 	if (op_mode == QLC_83XX_DEFAULT_OPMODE)
201 		priv_level = QLCNIC_MGMT_FUNC;
202 	else
203 		priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode,
204 							 ahw->pci_func);
205 	switch (priv_level) {
206 	case QLCNIC_NON_PRIV_FUNC:
207 		ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
208 		ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
209 		nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic;
210 		break;
211 	case QLCNIC_PRIV_FUNC:
212 		ahw->op_mode = QLCNIC_PRIV_FUNC;
213 		ahw->idc.state_entry = qlcnic_83xx_idc_vnic_pf_entry;
214 		nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic;
215 		break;
216 	case QLCNIC_MGMT_FUNC:
217 		ahw->op_mode = QLCNIC_MGMT_FUNC;
218 		ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
219 		nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic;
220 		break;
221 	default:
222 		dev_err(&adapter->pdev->dev, "Invalid Virtual NIC opmode\n");
223 		return -EIO;
224 	}
225 
226 	if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) {
227 		adapter->flags |= QLCNIC_ESWITCH_ENABLED;
228 		if (adapter->drv_mac_learn)
229 			adapter->rx_mac_learn = true;
230 	} else {
231 		adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
232 		adapter->rx_mac_learn = false;
233 	}
234 
235 	ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
236 	ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO;
237 
238 	return 0;
239 }
240 
241 int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter)
242 {
243 	struct qlcnic_hardware_context *ahw = adapter->ahw;
244 	struct qlc_83xx_idc *idc = &ahw->idc;
245 	u32 state;
246 
247 	state = QLCRDX(ahw, QLC_83XX_VNIC_STATE);
248 	while (state != QLCNIC_DEV_NPAR_OPER && idc->vnic_wait_limit) {
249 		idc->vnic_wait_limit--;
250 		msleep(1000);
251 		state = QLCRDX(ahw, QLC_83XX_VNIC_STATE);
252 	}
253 
254 	if (state != QLCNIC_DEV_NPAR_OPER) {
255 		dev_err(&adapter->pdev->dev,
256 			"vNIC mode not operational, state check timed out.\n");
257 		return -EIO;
258 	}
259 
260 	return 0;
261 }
262 
263 int qlcnic_83xx_set_port_eswitch_status(struct qlcnic_adapter *adapter,
264 					int func, int *port_id)
265 {
266 	struct qlcnic_info nic_info;
267 	int err = 0;
268 
269 	memset(&nic_info, 0, sizeof(struct qlcnic_info));
270 
271 	err = qlcnic_get_nic_info(adapter, &nic_info, func);
272 	if (err)
273 		return err;
274 
275 	if (nic_info.capabilities & QLC_83XX_ESWITCH_CAPABILITY)
276 		*port_id = nic_info.phys_port;
277 	else
278 		err = -EIO;
279 
280 	if (!err)
281 		adapter->eswitch[*port_id].flags |= QLCNIC_SWITCH_ENABLE;
282 
283 	return err;
284 }
285