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, lock: 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_config_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(msecs: 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, info: &nic_info, id: 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 | |