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 <linux/types.h> |
8 | |
9 | #include "qlcnic_sriov.h" |
10 | #include "qlcnic.h" |
11 | #include "qlcnic_83xx_hw.h" |
12 | |
13 | #define QLC_BC_COMMAND 0 |
14 | #define QLC_BC_RESPONSE 1 |
15 | |
16 | #define QLC_MBOX_RESP_TIMEOUT (10 * HZ) |
17 | #define QLC_MBOX_CH_FREE_TIMEOUT (10 * HZ) |
18 | |
19 | #define QLC_BC_MSG 0 |
20 | #define QLC_BC_CFREE 1 |
21 | #define QLC_BC_FLR 2 |
22 | #define QLC_BC_HDR_SZ 16 |
23 | #define QLC_BC_PAYLOAD_SZ (1024 - QLC_BC_HDR_SZ) |
24 | |
25 | #define QLC_DEFAULT_RCV_DESCRIPTORS_SRIOV_VF 2048 |
26 | #define QLC_DEFAULT_JUMBO_RCV_DESCRIPTORS_SRIOV_VF 512 |
27 | |
28 | #define QLC_83XX_VF_RESET_FAIL_THRESH 8 |
29 | #define QLC_BC_CMD_MAX_RETRY_CNT 5 |
30 | |
31 | static void qlcnic_sriov_handle_async_issue_cmd(struct work_struct *work); |
32 | static void qlcnic_sriov_vf_free_mac_list(struct qlcnic_adapter *); |
33 | static int qlcnic_sriov_alloc_bc_mbx_args(struct qlcnic_cmd_args *, u32); |
34 | static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *); |
35 | static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *); |
36 | static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *); |
37 | static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *, |
38 | struct qlcnic_cmd_args *); |
39 | static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *, u8); |
40 | static void qlcnic_sriov_process_bc_cmd(struct work_struct *); |
41 | static int qlcnic_sriov_vf_shutdown(struct pci_dev *); |
42 | static int qlcnic_sriov_vf_resume(struct qlcnic_adapter *); |
43 | static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *, |
44 | struct qlcnic_cmd_args *); |
45 | |
46 | static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { |
47 | .read_crb = qlcnic_83xx_read_crb, |
48 | .write_crb = qlcnic_83xx_write_crb, |
49 | .read_reg = qlcnic_83xx_rd_reg_indirect, |
50 | .write_reg = qlcnic_83xx_wrt_reg_indirect, |
51 | .get_mac_address = qlcnic_83xx_get_mac_address, |
52 | .setup_intr = qlcnic_83xx_setup_intr, |
53 | .alloc_mbx_args = qlcnic_83xx_alloc_mbx_args, |
54 | .mbx_cmd = qlcnic_sriov_issue_cmd, |
55 | .get_func_no = qlcnic_83xx_get_func_no, |
56 | .api_lock = qlcnic_83xx_cam_lock, |
57 | .api_unlock = qlcnic_83xx_cam_unlock, |
58 | .process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag, |
59 | .create_rx_ctx = qlcnic_83xx_create_rx_ctx, |
60 | .create_tx_ctx = qlcnic_83xx_create_tx_ctx, |
61 | .del_rx_ctx = qlcnic_83xx_del_rx_ctx, |
62 | .del_tx_ctx = qlcnic_83xx_del_tx_ctx, |
63 | .setup_link_event = qlcnic_83xx_setup_link_event, |
64 | .get_nic_info = qlcnic_83xx_get_nic_info, |
65 | .get_pci_info = qlcnic_83xx_get_pci_info, |
66 | .set_nic_info = qlcnic_83xx_set_nic_info, |
67 | .change_macvlan = qlcnic_83xx_sre_macaddr_change, |
68 | .napi_enable = qlcnic_83xx_napi_enable, |
69 | .napi_disable = qlcnic_83xx_napi_disable, |
70 | .config_intr_coal = qlcnic_83xx_config_intr_coal, |
71 | .config_rss = qlcnic_83xx_config_rss, |
72 | .config_hw_lro = qlcnic_83xx_config_hw_lro, |
73 | .config_promisc_mode = qlcnic_83xx_nic_set_promisc, |
74 | .change_l2_filter = qlcnic_83xx_change_l2_filter, |
75 | .get_board_info = qlcnic_83xx_get_port_info, |
76 | .free_mac_list = qlcnic_sriov_vf_free_mac_list, |
77 | .enable_sds_intr = qlcnic_83xx_enable_sds_intr, |
78 | .disable_sds_intr = qlcnic_83xx_disable_sds_intr, |
79 | .encap_rx_offload = qlcnic_83xx_encap_rx_offload, |
80 | .encap_tx_offload = qlcnic_83xx_encap_tx_offload, |
81 | }; |
82 | |
83 | static struct qlcnic_nic_template qlcnic_sriov_vf_ops = { |
84 | .config_bridged_mode = qlcnic_config_bridged_mode, |
85 | .config_led = qlcnic_config_led, |
86 | .cancel_idc_work = qlcnic_sriov_vf_cancel_fw_work, |
87 | .napi_add = qlcnic_83xx_napi_add, |
88 | .napi_del = qlcnic_83xx_napi_del, |
89 | .shutdown = qlcnic_sriov_vf_shutdown, |
90 | .resume = qlcnic_sriov_vf_resume, |
91 | .config_ipaddr = qlcnic_83xx_config_ipaddr, |
92 | .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr, |
93 | }; |
94 | |
95 | static const struct qlcnic_mailbox_metadata qlcnic_sriov_bc_mbx_tbl[] = { |
96 | {QLCNIC_BC_CMD_CHANNEL_INIT, 2, 2}, |
97 | {QLCNIC_BC_CMD_CHANNEL_TERM, 2, 2}, |
98 | {QLCNIC_BC_CMD_GET_ACL, 3, 14}, |
99 | {QLCNIC_BC_CMD_CFG_GUEST_VLAN, 2, 2}, |
100 | }; |
101 | |
102 | static inline bool qlcnic_sriov_bc_msg_check(u32 val) |
103 | { |
104 | return (val & (1 << QLC_BC_MSG)) ? true : false; |
105 | } |
106 | |
107 | static inline bool qlcnic_sriov_channel_free_check(u32 val) |
108 | { |
109 | return (val & (1 << QLC_BC_CFREE)) ? true : false; |
110 | } |
111 | |
112 | static inline bool qlcnic_sriov_flr_check(u32 val) |
113 | { |
114 | return (val & (1 << QLC_BC_FLR)) ? true : false; |
115 | } |
116 | |
117 | static inline u8 qlcnic_sriov_target_func_id(u32 val) |
118 | { |
119 | return (val >> 4) & 0xff; |
120 | } |
121 | |
122 | static int qlcnic_sriov_virtid_fn(struct qlcnic_adapter *adapter, int vf_id) |
123 | { |
124 | struct pci_dev *dev = adapter->pdev; |
125 | int pos; |
126 | u16 stride, offset; |
127 | |
128 | if (qlcnic_sriov_vf_check(adapter)) |
129 | return 0; |
130 | |
131 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); |
132 | if (!pos) |
133 | return 0; |
134 | pci_read_config_word(dev, where: pos + PCI_SRIOV_VF_OFFSET, val: &offset); |
135 | pci_read_config_word(dev, where: pos + PCI_SRIOV_VF_STRIDE, val: &stride); |
136 | |
137 | return (dev->devfn + offset + stride * vf_id) & 0xff; |
138 | } |
139 | |
140 | int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs) |
141 | { |
142 | struct qlcnic_sriov *sriov; |
143 | struct qlcnic_back_channel *bc; |
144 | struct workqueue_struct *wq; |
145 | struct qlcnic_vport *vp; |
146 | struct qlcnic_vf_info *vf; |
147 | int err, i; |
148 | |
149 | if (!qlcnic_sriov_enable_check(adapter)) |
150 | return -EIO; |
151 | |
152 | sriov = kzalloc(size: sizeof(struct qlcnic_sriov), GFP_KERNEL); |
153 | if (!sriov) |
154 | return -ENOMEM; |
155 | |
156 | adapter->ahw->sriov = sriov; |
157 | sriov->num_vfs = num_vfs; |
158 | bc = &sriov->bc; |
159 | sriov->vf_info = kcalloc(n: num_vfs, size: sizeof(struct qlcnic_vf_info), |
160 | GFP_KERNEL); |
161 | if (!sriov->vf_info) { |
162 | err = -ENOMEM; |
163 | goto qlcnic_free_sriov; |
164 | } |
165 | |
166 | wq = create_singlethread_workqueue("bc-trans" ); |
167 | if (wq == NULL) { |
168 | err = -ENOMEM; |
169 | dev_err(&adapter->pdev->dev, |
170 | "Cannot create bc-trans workqueue\n" ); |
171 | goto qlcnic_free_vf_info; |
172 | } |
173 | |
174 | bc->bc_trans_wq = wq; |
175 | |
176 | wq = create_singlethread_workqueue("async" ); |
177 | if (wq == NULL) { |
178 | err = -ENOMEM; |
179 | dev_err(&adapter->pdev->dev, "Cannot create async workqueue\n" ); |
180 | goto qlcnic_destroy_trans_wq; |
181 | } |
182 | |
183 | bc->bc_async_wq = wq; |
184 | INIT_LIST_HEAD(list: &bc->async_cmd_list); |
185 | INIT_WORK(&bc->vf_async_work, qlcnic_sriov_handle_async_issue_cmd); |
186 | spin_lock_init(&bc->queue_lock); |
187 | bc->adapter = adapter; |
188 | |
189 | for (i = 0; i < num_vfs; i++) { |
190 | vf = &sriov->vf_info[i]; |
191 | vf->adapter = adapter; |
192 | vf->pci_func = qlcnic_sriov_virtid_fn(adapter, vf_id: i); |
193 | mutex_init(&vf->send_cmd_lock); |
194 | spin_lock_init(&vf->vlan_list_lock); |
195 | INIT_LIST_HEAD(list: &vf->rcv_act.wait_list); |
196 | INIT_LIST_HEAD(list: &vf->rcv_pend.wait_list); |
197 | spin_lock_init(&vf->rcv_act.lock); |
198 | spin_lock_init(&vf->rcv_pend.lock); |
199 | init_completion(x: &vf->ch_free_cmpl); |
200 | |
201 | INIT_WORK(&vf->trans_work, qlcnic_sriov_process_bc_cmd); |
202 | |
203 | if (qlcnic_sriov_pf_check(adapter)) { |
204 | vp = kzalloc(size: sizeof(struct qlcnic_vport), GFP_KERNEL); |
205 | if (!vp) { |
206 | err = -ENOMEM; |
207 | goto qlcnic_destroy_async_wq; |
208 | } |
209 | sriov->vf_info[i].vp = vp; |
210 | vp->vlan_mode = QLC_GUEST_VLAN_MODE; |
211 | vp->max_tx_bw = MAX_BW; |
212 | vp->min_tx_bw = MIN_BW; |
213 | vp->spoofchk = false; |
214 | eth_random_addr(addr: vp->mac); |
215 | dev_info(&adapter->pdev->dev, |
216 | "MAC Address %pM is configured for VF %d\n" , |
217 | vp->mac, i); |
218 | } |
219 | } |
220 | |
221 | return 0; |
222 | |
223 | qlcnic_destroy_async_wq: |
224 | while (i--) |
225 | kfree(objp: sriov->vf_info[i].vp); |
226 | destroy_workqueue(wq: bc->bc_async_wq); |
227 | |
228 | qlcnic_destroy_trans_wq: |
229 | destroy_workqueue(wq: bc->bc_trans_wq); |
230 | |
231 | qlcnic_free_vf_info: |
232 | kfree(objp: sriov->vf_info); |
233 | |
234 | qlcnic_free_sriov: |
235 | kfree(objp: adapter->ahw->sriov); |
236 | return err; |
237 | } |
238 | |
239 | void qlcnic_sriov_cleanup_list(struct qlcnic_trans_list *t_list) |
240 | { |
241 | struct qlcnic_bc_trans *trans; |
242 | struct qlcnic_cmd_args cmd; |
243 | unsigned long flags; |
244 | |
245 | spin_lock_irqsave(&t_list->lock, flags); |
246 | |
247 | while (!list_empty(head: &t_list->wait_list)) { |
248 | trans = list_first_entry(&t_list->wait_list, |
249 | struct qlcnic_bc_trans, list); |
250 | list_del(entry: &trans->list); |
251 | t_list->count--; |
252 | cmd.req.arg = (u32 *)trans->req_pay; |
253 | cmd.rsp.arg = (u32 *)trans->rsp_pay; |
254 | qlcnic_free_mbx_args(cmd: &cmd); |
255 | qlcnic_sriov_cleanup_transaction(trans); |
256 | } |
257 | |
258 | spin_unlock_irqrestore(lock: &t_list->lock, flags); |
259 | } |
260 | |
261 | void __qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter) |
262 | { |
263 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
264 | struct qlcnic_back_channel *bc = &sriov->bc; |
265 | struct qlcnic_vf_info *vf; |
266 | int i; |
267 | |
268 | if (!qlcnic_sriov_enable_check(adapter)) |
269 | return; |
270 | |
271 | qlcnic_sriov_cleanup_async_list(bc); |
272 | destroy_workqueue(wq: bc->bc_async_wq); |
273 | |
274 | for (i = 0; i < sriov->num_vfs; i++) { |
275 | vf = &sriov->vf_info[i]; |
276 | qlcnic_sriov_cleanup_list(t_list: &vf->rcv_pend); |
277 | cancel_work_sync(work: &vf->trans_work); |
278 | qlcnic_sriov_cleanup_list(t_list: &vf->rcv_act); |
279 | } |
280 | |
281 | destroy_workqueue(wq: bc->bc_trans_wq); |
282 | |
283 | for (i = 0; i < sriov->num_vfs; i++) |
284 | kfree(objp: sriov->vf_info[i].vp); |
285 | |
286 | kfree(objp: sriov->vf_info); |
287 | kfree(objp: adapter->ahw->sriov); |
288 | } |
289 | |
290 | static void qlcnic_sriov_vf_cleanup(struct qlcnic_adapter *adapter) |
291 | { |
292 | qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_TERM); |
293 | qlcnic_sriov_cfg_bc_intr(adapter, 0); |
294 | __qlcnic_sriov_cleanup(adapter); |
295 | } |
296 | |
297 | void qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter) |
298 | { |
299 | if (!test_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state)) |
300 | return; |
301 | |
302 | qlcnic_sriov_free_vlans(adapter); |
303 | |
304 | if (qlcnic_sriov_pf_check(adapter)) |
305 | qlcnic_sriov_pf_cleanup(adapter); |
306 | |
307 | if (qlcnic_sriov_vf_check(adapter)) |
308 | qlcnic_sriov_vf_cleanup(adapter); |
309 | } |
310 | |
311 | static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr, |
312 | u32 *pay, u8 pci_func, u8 size) |
313 | { |
314 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
315 | struct qlcnic_mailbox *mbx = ahw->mailbox; |
316 | struct qlcnic_cmd_args cmd; |
317 | unsigned long timeout; |
318 | int err; |
319 | |
320 | memset(&cmd, 0, sizeof(struct qlcnic_cmd_args)); |
321 | cmd.hdr = hdr; |
322 | cmd.pay = pay; |
323 | cmd.pay_size = size; |
324 | cmd.func_num = pci_func; |
325 | cmd.op_type = QLC_83XX_MBX_POST_BC_OP; |
326 | cmd.cmd_op = ((struct qlcnic_bc_hdr *)hdr)->cmd_op; |
327 | |
328 | err = mbx->ops->enqueue_cmd(adapter, &cmd, &timeout); |
329 | if (err) { |
330 | dev_err(&adapter->pdev->dev, |
331 | "%s: Mailbox not available, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n" , |
332 | __func__, cmd.cmd_op, cmd.type, ahw->pci_func, |
333 | ahw->op_mode); |
334 | return err; |
335 | } |
336 | |
337 | if (!wait_for_completion_timeout(x: &cmd.completion, timeout)) { |
338 | dev_err(&adapter->pdev->dev, |
339 | "%s: Mailbox command timed out, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n" , |
340 | __func__, cmd.cmd_op, cmd.type, ahw->pci_func, |
341 | ahw->op_mode); |
342 | flush_workqueue(mbx->work_q); |
343 | } |
344 | |
345 | return cmd.rsp_opcode; |
346 | } |
347 | |
348 | static void qlcnic_sriov_vf_cfg_buff_desc(struct qlcnic_adapter *adapter) |
349 | { |
350 | adapter->num_rxd = QLC_DEFAULT_RCV_DESCRIPTORS_SRIOV_VF; |
351 | adapter->max_rxd = MAX_RCV_DESCRIPTORS_10G; |
352 | adapter->num_jumbo_rxd = QLC_DEFAULT_JUMBO_RCV_DESCRIPTORS_SRIOV_VF; |
353 | adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; |
354 | adapter->num_txd = MAX_CMD_DESCRIPTORS; |
355 | adapter->max_rds_rings = MAX_RDS_RINGS; |
356 | } |
357 | |
358 | int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *adapter, |
359 | struct qlcnic_info *npar_info, u16 vport_id) |
360 | { |
361 | struct device *dev = &adapter->pdev->dev; |
362 | struct qlcnic_cmd_args cmd; |
363 | int err; |
364 | u32 status; |
365 | |
366 | err = qlcnic_alloc_mbx_args(mbx: &cmd, adapter, QLCNIC_CMD_GET_NIC_INFO); |
367 | if (err) |
368 | return err; |
369 | |
370 | cmd.req.arg[1] = vport_id << 16 | 0x1; |
371 | err = qlcnic_issue_cmd(adapter, cmd: &cmd); |
372 | if (err) { |
373 | dev_err(&adapter->pdev->dev, |
374 | "Failed to get vport info, err=%d\n" , err); |
375 | qlcnic_free_mbx_args(cmd: &cmd); |
376 | return err; |
377 | } |
378 | |
379 | status = cmd.rsp.arg[2] & 0xffff; |
380 | if (status & BIT_0) |
381 | npar_info->min_tx_bw = MSW(cmd.rsp.arg[2]); |
382 | if (status & BIT_1) |
383 | npar_info->max_tx_bw = LSW(cmd.rsp.arg[3]); |
384 | if (status & BIT_2) |
385 | npar_info->max_tx_ques = MSW(cmd.rsp.arg[3]); |
386 | if (status & BIT_3) |
387 | npar_info->max_tx_mac_filters = LSW(cmd.rsp.arg[4]); |
388 | if (status & BIT_4) |
389 | npar_info->max_rx_mcast_mac_filters = MSW(cmd.rsp.arg[4]); |
390 | if (status & BIT_5) |
391 | npar_info->max_rx_ucast_mac_filters = LSW(cmd.rsp.arg[5]); |
392 | if (status & BIT_6) |
393 | npar_info->max_rx_ip_addr = MSW(cmd.rsp.arg[5]); |
394 | if (status & BIT_7) |
395 | npar_info->max_rx_lro_flow = LSW(cmd.rsp.arg[6]); |
396 | if (status & BIT_8) |
397 | npar_info->max_rx_status_rings = MSW(cmd.rsp.arg[6]); |
398 | if (status & BIT_9) |
399 | npar_info->max_rx_buf_rings = LSW(cmd.rsp.arg[7]); |
400 | |
401 | npar_info->max_rx_ques = MSW(cmd.rsp.arg[7]); |
402 | npar_info->max_tx_vlan_keys = LSW(cmd.rsp.arg[8]); |
403 | npar_info->max_local_ipv6_addrs = MSW(cmd.rsp.arg[8]); |
404 | npar_info->max_remote_ipv6_addrs = LSW(cmd.rsp.arg[9]); |
405 | |
406 | dev_info(dev, "\n\tmin_tx_bw: %d, max_tx_bw: %d max_tx_ques: %d,\n" |
407 | "\tmax_tx_mac_filters: %d max_rx_mcast_mac_filters: %d,\n" |
408 | "\tmax_rx_ucast_mac_filters: 0x%x, max_rx_ip_addr: %d,\n" |
409 | "\tmax_rx_lro_flow: %d max_rx_status_rings: %d,\n" |
410 | "\tmax_rx_buf_rings: %d, max_rx_ques: %d, max_tx_vlan_keys %d\n" |
411 | "\tlocal_ipv6_addr: %d, remote_ipv6_addr: %d\n" , |
412 | npar_info->min_tx_bw, npar_info->max_tx_bw, |
413 | npar_info->max_tx_ques, npar_info->max_tx_mac_filters, |
414 | npar_info->max_rx_mcast_mac_filters, |
415 | npar_info->max_rx_ucast_mac_filters, npar_info->max_rx_ip_addr, |
416 | npar_info->max_rx_lro_flow, npar_info->max_rx_status_rings, |
417 | npar_info->max_rx_buf_rings, npar_info->max_rx_ques, |
418 | npar_info->max_tx_vlan_keys, npar_info->max_local_ipv6_addrs, |
419 | npar_info->max_remote_ipv6_addrs); |
420 | |
421 | qlcnic_free_mbx_args(cmd: &cmd); |
422 | return err; |
423 | } |
424 | |
425 | static int qlcnic_sriov_set_pvid_mode(struct qlcnic_adapter *adapter, |
426 | struct qlcnic_cmd_args *cmd) |
427 | { |
428 | adapter->rx_pvid = MSW(cmd->rsp.arg[1]) & 0xffff; |
429 | adapter->flags &= ~QLCNIC_TAGGING_ENABLED; |
430 | return 0; |
431 | } |
432 | |
433 | static int qlcnic_sriov_set_guest_vlan_mode(struct qlcnic_adapter *adapter, |
434 | struct qlcnic_cmd_args *cmd) |
435 | { |
436 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
437 | int i, num_vlans, ret; |
438 | u16 *vlans; |
439 | |
440 | if (sriov->allowed_vlans) |
441 | return 0; |
442 | |
443 | sriov->any_vlan = cmd->rsp.arg[2] & 0xf; |
444 | sriov->num_allowed_vlans = cmd->rsp.arg[2] >> 16; |
445 | dev_info(&adapter->pdev->dev, "Number of allowed Guest VLANs = %d\n" , |
446 | sriov->num_allowed_vlans); |
447 | |
448 | ret = qlcnic_sriov_alloc_vlans(adapter); |
449 | if (ret) |
450 | return ret; |
451 | |
452 | if (!sriov->any_vlan) |
453 | return 0; |
454 | |
455 | num_vlans = sriov->num_allowed_vlans; |
456 | sriov->allowed_vlans = kcalloc(n: num_vlans, size: sizeof(u16), GFP_KERNEL); |
457 | if (!sriov->allowed_vlans) |
458 | return -ENOMEM; |
459 | |
460 | vlans = (u16 *)&cmd->rsp.arg[3]; |
461 | for (i = 0; i < num_vlans; i++) |
462 | sriov->allowed_vlans[i] = vlans[i]; |
463 | |
464 | return 0; |
465 | } |
466 | |
467 | static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter) |
468 | { |
469 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
470 | struct qlcnic_cmd_args cmd; |
471 | int ret = 0; |
472 | |
473 | memset(&cmd, 0, sizeof(cmd)); |
474 | ret = qlcnic_sriov_alloc_bc_mbx_args(&cmd, QLCNIC_BC_CMD_GET_ACL); |
475 | if (ret) |
476 | return ret; |
477 | |
478 | ret = qlcnic_issue_cmd(adapter, cmd: &cmd); |
479 | if (ret) { |
480 | dev_err(&adapter->pdev->dev, "Failed to get ACL, err=%d\n" , |
481 | ret); |
482 | } else { |
483 | sriov->vlan_mode = cmd.rsp.arg[1] & 0x3; |
484 | switch (sriov->vlan_mode) { |
485 | case QLC_GUEST_VLAN_MODE: |
486 | ret = qlcnic_sriov_set_guest_vlan_mode(adapter, cmd: &cmd); |
487 | break; |
488 | case QLC_PVID_MODE: |
489 | ret = qlcnic_sriov_set_pvid_mode(adapter, cmd: &cmd); |
490 | break; |
491 | } |
492 | } |
493 | |
494 | qlcnic_free_mbx_args(cmd: &cmd); |
495 | return ret; |
496 | } |
497 | |
498 | static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter) |
499 | { |
500 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
501 | struct qlcnic_info nic_info; |
502 | int err; |
503 | |
504 | err = qlcnic_sriov_get_vf_vport_info(adapter, npar_info: &nic_info, vport_id: 0); |
505 | if (err) |
506 | return err; |
507 | |
508 | ahw->max_mc_count = nic_info.max_rx_mcast_mac_filters; |
509 | |
510 | err = qlcnic_get_nic_info(adapter, info: &nic_info, id: ahw->pci_func); |
511 | if (err) |
512 | return -EIO; |
513 | |
514 | if (qlcnic_83xx_get_port_info(adapter)) |
515 | return -EIO; |
516 | |
517 | qlcnic_sriov_vf_cfg_buff_desc(adapter); |
518 | adapter->flags |= QLCNIC_ADAPTER_INITIALIZED; |
519 | dev_info(&adapter->pdev->dev, "HAL Version: %d\n" , |
520 | adapter->ahw->fw_hal_version); |
521 | |
522 | ahw->physical_port = (u8) nic_info.phys_port; |
523 | ahw->switch_mode = nic_info.switch_mode; |
524 | ahw->max_mtu = nic_info.max_mtu; |
525 | ahw->op_mode = nic_info.op_mode; |
526 | ahw->capabilities = nic_info.capabilities; |
527 | return 0; |
528 | } |
529 | |
530 | static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter) |
531 | { |
532 | int err; |
533 | |
534 | adapter->flags |= QLCNIC_VLAN_FILTERING; |
535 | adapter->ahw->total_nic_func = 1; |
536 | INIT_LIST_HEAD(list: &adapter->vf_mc_list); |
537 | if (!qlcnic_use_msi_x && !!qlcnic_use_msi) |
538 | dev_warn(&adapter->pdev->dev, |
539 | "Device does not support MSI interrupts\n" ); |
540 | |
541 | /* compute and set default and max tx/sds rings */ |
542 | qlcnic_set_tx_ring_count(adapter, QLCNIC_SINGLE_RING); |
543 | qlcnic_set_sds_ring_count(adapter, QLCNIC_SINGLE_RING); |
544 | |
545 | err = qlcnic_setup_intr(adapter); |
546 | if (err) { |
547 | dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n" ); |
548 | goto err_out_disable_msi; |
549 | } |
550 | |
551 | err = qlcnic_83xx_setup_mbx_intr(adapter); |
552 | if (err) |
553 | goto err_out_disable_msi; |
554 | |
555 | err = qlcnic_sriov_init(adapter, num_vfs: 1); |
556 | if (err) |
557 | goto err_out_disable_mbx_intr; |
558 | |
559 | err = qlcnic_sriov_cfg_bc_intr(adapter, 1); |
560 | if (err) |
561 | goto err_out_cleanup_sriov; |
562 | |
563 | err = qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_INIT); |
564 | if (err) |
565 | goto err_out_disable_bc_intr; |
566 | |
567 | err = qlcnic_sriov_vf_init_driver(adapter); |
568 | if (err) |
569 | goto err_out_send_channel_term; |
570 | |
571 | err = qlcnic_sriov_get_vf_acl(adapter); |
572 | if (err) |
573 | goto err_out_send_channel_term; |
574 | |
575 | err = qlcnic_setup_netdev(adapter, adapter->netdev); |
576 | if (err) |
577 | goto err_out_send_channel_term; |
578 | |
579 | pci_set_drvdata(pdev: adapter->pdev, data: adapter); |
580 | dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n" , |
581 | adapter->netdev->name); |
582 | |
583 | qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state, |
584 | adapter->ahw->idc.delay); |
585 | return 0; |
586 | |
587 | err_out_send_channel_term: |
588 | qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_TERM); |
589 | |
590 | err_out_disable_bc_intr: |
591 | qlcnic_sriov_cfg_bc_intr(adapter, 0); |
592 | |
593 | err_out_cleanup_sriov: |
594 | __qlcnic_sriov_cleanup(adapter); |
595 | |
596 | err_out_disable_mbx_intr: |
597 | qlcnic_83xx_free_mbx_intr(adapter); |
598 | |
599 | err_out_disable_msi: |
600 | qlcnic_teardown_intr(adapter); |
601 | return err; |
602 | } |
603 | |
604 | static int qlcnic_sriov_check_dev_ready(struct qlcnic_adapter *adapter) |
605 | { |
606 | u32 state; |
607 | |
608 | do { |
609 | msleep(msecs: 20); |
610 | if (++adapter->fw_fail_cnt > QLC_BC_CMD_MAX_RETRY_CNT) |
611 | return -EIO; |
612 | state = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE); |
613 | } while (state != QLC_83XX_IDC_DEV_READY); |
614 | |
615 | return 0; |
616 | } |
617 | |
618 | int qlcnic_sriov_vf_init(struct qlcnic_adapter *adapter) |
619 | { |
620 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
621 | int err; |
622 | |
623 | set_bit(QLC_83XX_MODULE_LOADED, addr: &ahw->idc.status); |
624 | ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY; |
625 | ahw->reset_context = 0; |
626 | adapter->fw_fail_cnt = 0; |
627 | ahw->msix_supported = 1; |
628 | adapter->need_fw_reset = 0; |
629 | adapter->flags |= QLCNIC_TX_INTR_SHARED; |
630 | |
631 | err = qlcnic_sriov_check_dev_ready(adapter); |
632 | if (err) |
633 | return err; |
634 | |
635 | err = qlcnic_sriov_setup_vf(adapter); |
636 | if (err) |
637 | return err; |
638 | |
639 | if (qlcnic_read_mac_addr(adapter)) |
640 | dev_warn(&adapter->pdev->dev, "failed to read mac addr\n" ); |
641 | |
642 | INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work); |
643 | |
644 | clear_bit(__QLCNIC_RESETTING, addr: &adapter->state); |
645 | return 0; |
646 | } |
647 | |
648 | void qlcnic_sriov_vf_set_ops(struct qlcnic_adapter *adapter) |
649 | { |
650 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
651 | |
652 | ahw->op_mode = QLCNIC_SRIOV_VF_FUNC; |
653 | dev_info(&adapter->pdev->dev, |
654 | "HAL Version: %d Non Privileged SRIOV function\n" , |
655 | ahw->fw_hal_version); |
656 | adapter->nic_ops = &qlcnic_sriov_vf_ops; |
657 | set_bit(__QLCNIC_SRIOV_ENABLE, addr: &adapter->state); |
658 | return; |
659 | } |
660 | |
661 | void qlcnic_sriov_vf_register_map(struct qlcnic_hardware_context *ahw) |
662 | { |
663 | ahw->hw_ops = &qlcnic_sriov_vf_hw_ops; |
664 | ahw->reg_tbl = (u32 *)qlcnic_83xx_reg_tbl; |
665 | ahw->ext_reg_tbl = (u32 *)qlcnic_83xx_ext_reg_tbl; |
666 | } |
667 | |
668 | static u32 qlcnic_sriov_get_bc_paysize(u32 real_pay_size, u8 curr_frag) |
669 | { |
670 | u32 pay_size; |
671 | |
672 | pay_size = real_pay_size / ((curr_frag + 1) * QLC_BC_PAYLOAD_SZ); |
673 | |
674 | if (pay_size) |
675 | pay_size = QLC_BC_PAYLOAD_SZ; |
676 | else |
677 | pay_size = real_pay_size % QLC_BC_PAYLOAD_SZ; |
678 | |
679 | return pay_size; |
680 | } |
681 | |
682 | int qlcnic_sriov_func_to_index(struct qlcnic_adapter *adapter, u8 pci_func) |
683 | { |
684 | struct qlcnic_vf_info *vf_info = adapter->ahw->sriov->vf_info; |
685 | u8 i; |
686 | |
687 | if (qlcnic_sriov_vf_check(adapter)) |
688 | return 0; |
689 | |
690 | for (i = 0; i < adapter->ahw->sriov->num_vfs; i++) { |
691 | if (vf_info[i].pci_func == pci_func) |
692 | return i; |
693 | } |
694 | |
695 | return -EINVAL; |
696 | } |
697 | |
698 | static inline int qlcnic_sriov_alloc_bc_trans(struct qlcnic_bc_trans **trans) |
699 | { |
700 | *trans = kzalloc(size: sizeof(struct qlcnic_bc_trans), GFP_ATOMIC); |
701 | if (!*trans) |
702 | return -ENOMEM; |
703 | |
704 | init_completion(x: &(*trans)->resp_cmpl); |
705 | return 0; |
706 | } |
707 | |
708 | static inline int qlcnic_sriov_alloc_bc_msg(struct qlcnic_bc_hdr **hdr, |
709 | u32 size) |
710 | { |
711 | *hdr = kcalloc(n: size, size: sizeof(struct qlcnic_bc_hdr), GFP_ATOMIC); |
712 | if (!*hdr) |
713 | return -ENOMEM; |
714 | |
715 | return 0; |
716 | } |
717 | |
718 | static int qlcnic_sriov_alloc_bc_mbx_args(struct qlcnic_cmd_args *mbx, u32 type) |
719 | { |
720 | const struct qlcnic_mailbox_metadata *mbx_tbl; |
721 | int i, size; |
722 | |
723 | mbx_tbl = qlcnic_sriov_bc_mbx_tbl; |
724 | size = ARRAY_SIZE(qlcnic_sriov_bc_mbx_tbl); |
725 | |
726 | for (i = 0; i < size; i++) { |
727 | if (type == mbx_tbl[i].cmd) { |
728 | mbx->op_type = QLC_BC_CMD; |
729 | mbx->req.num = mbx_tbl[i].in_args; |
730 | mbx->rsp.num = mbx_tbl[i].out_args; |
731 | mbx->req.arg = kcalloc(n: mbx->req.num, size: sizeof(u32), |
732 | GFP_ATOMIC); |
733 | if (!mbx->req.arg) |
734 | return -ENOMEM; |
735 | mbx->rsp.arg = kcalloc(n: mbx->rsp.num, size: sizeof(u32), |
736 | GFP_ATOMIC); |
737 | if (!mbx->rsp.arg) { |
738 | kfree(objp: mbx->req.arg); |
739 | mbx->req.arg = NULL; |
740 | return -ENOMEM; |
741 | } |
742 | mbx->req.arg[0] = (type | (mbx->req.num << 16) | |
743 | (3 << 29)); |
744 | mbx->rsp.arg[0] = (type & 0xffff) | mbx->rsp.num << 16; |
745 | return 0; |
746 | } |
747 | } |
748 | return -EINVAL; |
749 | } |
750 | |
751 | static int qlcnic_sriov_prepare_bc_hdr(struct qlcnic_bc_trans *trans, |
752 | struct qlcnic_cmd_args *cmd, |
753 | u16 seq, u8 msg_type) |
754 | { |
755 | struct qlcnic_bc_hdr *hdr; |
756 | int i; |
757 | u32 num_regs, bc_pay_sz; |
758 | u16 remainder; |
759 | u8 cmd_op, num_frags, t_num_frags; |
760 | |
761 | bc_pay_sz = QLC_BC_PAYLOAD_SZ; |
762 | if (msg_type == QLC_BC_COMMAND) { |
763 | trans->req_pay = (struct qlcnic_bc_payload *)cmd->req.arg; |
764 | trans->rsp_pay = (struct qlcnic_bc_payload *)cmd->rsp.arg; |
765 | num_regs = cmd->req.num; |
766 | trans->req_pay_size = (num_regs * 4); |
767 | num_regs = cmd->rsp.num; |
768 | trans->rsp_pay_size = (num_regs * 4); |
769 | cmd_op = cmd->req.arg[0] & 0xff; |
770 | remainder = (trans->req_pay_size) % (bc_pay_sz); |
771 | num_frags = (trans->req_pay_size) / (bc_pay_sz); |
772 | if (remainder) |
773 | num_frags++; |
774 | t_num_frags = num_frags; |
775 | if (qlcnic_sriov_alloc_bc_msg(hdr: &trans->req_hdr, size: num_frags)) |
776 | return -ENOMEM; |
777 | remainder = (trans->rsp_pay_size) % (bc_pay_sz); |
778 | num_frags = (trans->rsp_pay_size) / (bc_pay_sz); |
779 | if (remainder) |
780 | num_frags++; |
781 | if (qlcnic_sriov_alloc_bc_msg(hdr: &trans->rsp_hdr, size: num_frags)) |
782 | return -ENOMEM; |
783 | num_frags = t_num_frags; |
784 | hdr = trans->req_hdr; |
785 | } else { |
786 | cmd->req.arg = (u32 *)trans->req_pay; |
787 | cmd->rsp.arg = (u32 *)trans->rsp_pay; |
788 | cmd_op = cmd->req.arg[0] & 0xff; |
789 | cmd->cmd_op = cmd_op; |
790 | remainder = (trans->rsp_pay_size) % (bc_pay_sz); |
791 | num_frags = (trans->rsp_pay_size) / (bc_pay_sz); |
792 | if (remainder) |
793 | num_frags++; |
794 | cmd->req.num = trans->req_pay_size / 4; |
795 | cmd->rsp.num = trans->rsp_pay_size / 4; |
796 | hdr = trans->rsp_hdr; |
797 | cmd->op_type = trans->req_hdr->op_type; |
798 | } |
799 | |
800 | trans->trans_id = seq; |
801 | trans->cmd_id = cmd_op; |
802 | for (i = 0; i < num_frags; i++) { |
803 | hdr[i].version = 2; |
804 | hdr[i].msg_type = msg_type; |
805 | hdr[i].op_type = cmd->op_type; |
806 | hdr[i].num_cmds = 1; |
807 | hdr[i].num_frags = num_frags; |
808 | hdr[i].frag_num = i + 1; |
809 | hdr[i].cmd_op = cmd_op; |
810 | hdr[i].seq_id = seq; |
811 | } |
812 | return 0; |
813 | } |
814 | |
815 | static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *trans) |
816 | { |
817 | if (!trans) |
818 | return; |
819 | kfree(objp: trans->req_hdr); |
820 | kfree(objp: trans->rsp_hdr); |
821 | kfree(objp: trans); |
822 | } |
823 | |
824 | static int qlcnic_sriov_clear_trans(struct qlcnic_vf_info *vf, |
825 | struct qlcnic_bc_trans *trans, u8 type) |
826 | { |
827 | struct qlcnic_trans_list *t_list; |
828 | unsigned long flags; |
829 | int ret = 0; |
830 | |
831 | if (type == QLC_BC_RESPONSE) { |
832 | t_list = &vf->rcv_act; |
833 | spin_lock_irqsave(&t_list->lock, flags); |
834 | t_list->count--; |
835 | list_del(entry: &trans->list); |
836 | if (t_list->count > 0) |
837 | ret = 1; |
838 | spin_unlock_irqrestore(lock: &t_list->lock, flags); |
839 | } |
840 | if (type == QLC_BC_COMMAND) { |
841 | while (test_and_set_bit(nr: QLC_BC_VF_SEND, addr: &vf->state)) |
842 | msleep(msecs: 100); |
843 | vf->send_cmd = NULL; |
844 | clear_bit(nr: QLC_BC_VF_SEND, addr: &vf->state); |
845 | } |
846 | return ret; |
847 | } |
848 | |
849 | static void qlcnic_sriov_schedule_bc_cmd(struct qlcnic_sriov *sriov, |
850 | struct qlcnic_vf_info *vf, |
851 | work_func_t func) |
852 | { |
853 | if (test_bit(QLC_BC_VF_FLR, &vf->state) || |
854 | vf->adapter->need_fw_reset) |
855 | return; |
856 | |
857 | queue_work(wq: sriov->bc.bc_trans_wq, work: &vf->trans_work); |
858 | } |
859 | |
860 | static inline void qlcnic_sriov_wait_for_resp(struct qlcnic_bc_trans *trans) |
861 | { |
862 | struct completion *cmpl = &trans->resp_cmpl; |
863 | |
864 | if (wait_for_completion_timeout(x: cmpl, QLC_MBOX_RESP_TIMEOUT)) |
865 | trans->trans_state = QLC_END; |
866 | else |
867 | trans->trans_state = QLC_ABORT; |
868 | |
869 | return; |
870 | } |
871 | |
872 | static void qlcnic_sriov_handle_multi_frags(struct qlcnic_bc_trans *trans, |
873 | u8 type) |
874 | { |
875 | if (type == QLC_BC_RESPONSE) { |
876 | trans->curr_rsp_frag++; |
877 | if (trans->curr_rsp_frag < trans->rsp_hdr->num_frags) |
878 | trans->trans_state = QLC_INIT; |
879 | else |
880 | trans->trans_state = QLC_END; |
881 | } else { |
882 | trans->curr_req_frag++; |
883 | if (trans->curr_req_frag < trans->req_hdr->num_frags) |
884 | trans->trans_state = QLC_INIT; |
885 | else |
886 | trans->trans_state = QLC_WAIT_FOR_RESP; |
887 | } |
888 | } |
889 | |
890 | static void qlcnic_sriov_wait_for_channel_free(struct qlcnic_bc_trans *trans, |
891 | u8 type) |
892 | { |
893 | struct qlcnic_vf_info *vf = trans->vf; |
894 | struct completion *cmpl = &vf->ch_free_cmpl; |
895 | |
896 | if (!wait_for_completion_timeout(x: cmpl, QLC_MBOX_CH_FREE_TIMEOUT)) { |
897 | trans->trans_state = QLC_ABORT; |
898 | return; |
899 | } |
900 | |
901 | clear_bit(nr: QLC_BC_VF_CHANNEL, addr: &vf->state); |
902 | qlcnic_sriov_handle_multi_frags(trans, type); |
903 | } |
904 | |
905 | static void qlcnic_sriov_pull_bc_msg(struct qlcnic_adapter *adapter, |
906 | u32 *hdr, u32 *pay, u32 size) |
907 | { |
908 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
909 | u8 i, max = 2, hdr_size, j; |
910 | |
911 | hdr_size = (sizeof(struct qlcnic_bc_hdr) / sizeof(u32)); |
912 | max = (size / sizeof(u32)) + hdr_size; |
913 | |
914 | for (i = 2, j = 0; j < hdr_size; i++, j++) |
915 | *(hdr++) = readl(QLCNIC_MBX_FW(ahw, i)); |
916 | for (; j < max; i++, j++) |
917 | *(pay++) = readl(QLCNIC_MBX_FW(ahw, i)); |
918 | } |
919 | |
920 | static int __qlcnic_sriov_issue_bc_post(struct qlcnic_vf_info *vf) |
921 | { |
922 | int ret = -EBUSY; |
923 | u32 timeout = 10000; |
924 | |
925 | do { |
926 | if (!test_and_set_bit(nr: QLC_BC_VF_CHANNEL, addr: &vf->state)) { |
927 | ret = 0; |
928 | break; |
929 | } |
930 | mdelay(1); |
931 | } while (--timeout); |
932 | |
933 | return ret; |
934 | } |
935 | |
936 | static int qlcnic_sriov_issue_bc_post(struct qlcnic_bc_trans *trans, u8 type) |
937 | { |
938 | struct qlcnic_vf_info *vf = trans->vf; |
939 | u32 pay_size; |
940 | u32 *hdr, *pay; |
941 | int ret; |
942 | u8 pci_func = trans->func_id; |
943 | |
944 | if (__qlcnic_sriov_issue_bc_post(vf)) |
945 | return -EBUSY; |
946 | |
947 | if (type == QLC_BC_COMMAND) { |
948 | hdr = (u32 *)(trans->req_hdr + trans->curr_req_frag); |
949 | pay = (u32 *)(trans->req_pay + trans->curr_req_frag); |
950 | pay_size = qlcnic_sriov_get_bc_paysize(real_pay_size: trans->req_pay_size, |
951 | curr_frag: trans->curr_req_frag); |
952 | pay_size = (pay_size / sizeof(u32)); |
953 | } else { |
954 | hdr = (u32 *)(trans->rsp_hdr + trans->curr_rsp_frag); |
955 | pay = (u32 *)(trans->rsp_pay + trans->curr_rsp_frag); |
956 | pay_size = qlcnic_sriov_get_bc_paysize(real_pay_size: trans->rsp_pay_size, |
957 | curr_frag: trans->curr_rsp_frag); |
958 | pay_size = (pay_size / sizeof(u32)); |
959 | } |
960 | |
961 | ret = qlcnic_sriov_post_bc_msg(adapter: vf->adapter, hdr, pay, |
962 | pci_func, size: pay_size); |
963 | return ret; |
964 | } |
965 | |
966 | static int __qlcnic_sriov_send_bc_msg(struct qlcnic_bc_trans *trans, |
967 | struct qlcnic_vf_info *vf, u8 type) |
968 | { |
969 | bool flag = true; |
970 | int err = -EIO; |
971 | |
972 | while (flag) { |
973 | if (test_bit(QLC_BC_VF_FLR, &vf->state) || |
974 | vf->adapter->need_fw_reset) |
975 | trans->trans_state = QLC_ABORT; |
976 | |
977 | switch (trans->trans_state) { |
978 | case QLC_INIT: |
979 | trans->trans_state = QLC_WAIT_FOR_CHANNEL_FREE; |
980 | if (qlcnic_sriov_issue_bc_post(trans, type)) |
981 | trans->trans_state = QLC_ABORT; |
982 | break; |
983 | case QLC_WAIT_FOR_CHANNEL_FREE: |
984 | qlcnic_sriov_wait_for_channel_free(trans, type); |
985 | break; |
986 | case QLC_WAIT_FOR_RESP: |
987 | qlcnic_sriov_wait_for_resp(trans); |
988 | break; |
989 | case QLC_END: |
990 | err = 0; |
991 | flag = false; |
992 | break; |
993 | case QLC_ABORT: |
994 | err = -EIO; |
995 | flag = false; |
996 | clear_bit(nr: QLC_BC_VF_CHANNEL, addr: &vf->state); |
997 | break; |
998 | default: |
999 | err = -EIO; |
1000 | flag = false; |
1001 | } |
1002 | } |
1003 | return err; |
1004 | } |
1005 | |
1006 | static int qlcnic_sriov_send_bc_cmd(struct qlcnic_adapter *adapter, |
1007 | struct qlcnic_bc_trans *trans, int pci_func) |
1008 | { |
1009 | struct qlcnic_vf_info *vf; |
1010 | int err, index = qlcnic_sriov_func_to_index(adapter, pci_func); |
1011 | |
1012 | if (index < 0) |
1013 | return -EIO; |
1014 | |
1015 | vf = &adapter->ahw->sriov->vf_info[index]; |
1016 | trans->vf = vf; |
1017 | trans->func_id = pci_func; |
1018 | |
1019 | if (!test_bit(QLC_BC_VF_STATE, &vf->state)) { |
1020 | if (qlcnic_sriov_pf_check(adapter)) |
1021 | return -EIO; |
1022 | if (qlcnic_sriov_vf_check(adapter) && |
1023 | trans->cmd_id != QLCNIC_BC_CMD_CHANNEL_INIT) |
1024 | return -EIO; |
1025 | } |
1026 | |
1027 | mutex_lock(&vf->send_cmd_lock); |
1028 | vf->send_cmd = trans; |
1029 | err = __qlcnic_sriov_send_bc_msg(trans, vf, QLC_BC_COMMAND); |
1030 | qlcnic_sriov_clear_trans(vf, trans, QLC_BC_COMMAND); |
1031 | mutex_unlock(lock: &vf->send_cmd_lock); |
1032 | return err; |
1033 | } |
1034 | |
1035 | static void __qlcnic_sriov_process_bc_cmd(struct qlcnic_adapter *adapter, |
1036 | struct qlcnic_bc_trans *trans, |
1037 | struct qlcnic_cmd_args *cmd) |
1038 | { |
1039 | #ifdef CONFIG_QLCNIC_SRIOV |
1040 | if (qlcnic_sriov_pf_check(adapter)) { |
1041 | qlcnic_sriov_pf_process_bc_cmd(adapter, trans, cmd); |
1042 | return; |
1043 | } |
1044 | #endif |
1045 | cmd->rsp.arg[0] |= (0x9 << 25); |
1046 | return; |
1047 | } |
1048 | |
1049 | static void qlcnic_sriov_process_bc_cmd(struct work_struct *work) |
1050 | { |
1051 | struct qlcnic_vf_info *vf = container_of(work, struct qlcnic_vf_info, |
1052 | trans_work); |
1053 | struct qlcnic_bc_trans *trans = NULL; |
1054 | struct qlcnic_adapter *adapter = vf->adapter; |
1055 | struct qlcnic_cmd_args cmd; |
1056 | u8 req; |
1057 | |
1058 | if (adapter->need_fw_reset) |
1059 | return; |
1060 | |
1061 | if (test_bit(QLC_BC_VF_FLR, &vf->state)) |
1062 | return; |
1063 | |
1064 | memset(&cmd, 0, sizeof(struct qlcnic_cmd_args)); |
1065 | trans = list_first_entry(&vf->rcv_act.wait_list, |
1066 | struct qlcnic_bc_trans, list); |
1067 | adapter = vf->adapter; |
1068 | |
1069 | if (qlcnic_sriov_prepare_bc_hdr(trans, cmd: &cmd, seq: trans->req_hdr->seq_id, |
1070 | QLC_BC_RESPONSE)) |
1071 | goto cleanup_trans; |
1072 | |
1073 | __qlcnic_sriov_process_bc_cmd(adapter, trans, cmd: &cmd); |
1074 | trans->trans_state = QLC_INIT; |
1075 | __qlcnic_sriov_send_bc_msg(trans, vf, QLC_BC_RESPONSE); |
1076 | |
1077 | cleanup_trans: |
1078 | qlcnic_free_mbx_args(cmd: &cmd); |
1079 | req = qlcnic_sriov_clear_trans(vf, trans, QLC_BC_RESPONSE); |
1080 | qlcnic_sriov_cleanup_transaction(trans); |
1081 | if (req) |
1082 | qlcnic_sriov_schedule_bc_cmd(sriov: adapter->ahw->sriov, vf, |
1083 | func: qlcnic_sriov_process_bc_cmd); |
1084 | } |
1085 | |
1086 | static void qlcnic_sriov_handle_bc_resp(struct qlcnic_bc_hdr *hdr, |
1087 | struct qlcnic_vf_info *vf) |
1088 | { |
1089 | struct qlcnic_bc_trans *trans; |
1090 | u32 pay_size; |
1091 | |
1092 | if (test_and_set_bit(nr: QLC_BC_VF_SEND, addr: &vf->state)) |
1093 | return; |
1094 | |
1095 | trans = vf->send_cmd; |
1096 | |
1097 | if (trans == NULL) |
1098 | goto clear_send; |
1099 | |
1100 | if (trans->trans_id != hdr->seq_id) |
1101 | goto clear_send; |
1102 | |
1103 | pay_size = qlcnic_sriov_get_bc_paysize(real_pay_size: trans->rsp_pay_size, |
1104 | curr_frag: trans->curr_rsp_frag); |
1105 | qlcnic_sriov_pull_bc_msg(adapter: vf->adapter, |
1106 | hdr: (u32 *)(trans->rsp_hdr + trans->curr_rsp_frag), |
1107 | pay: (u32 *)(trans->rsp_pay + trans->curr_rsp_frag), |
1108 | size: pay_size); |
1109 | if (++trans->curr_rsp_frag < trans->rsp_hdr->num_frags) |
1110 | goto clear_send; |
1111 | |
1112 | complete(&trans->resp_cmpl); |
1113 | |
1114 | clear_send: |
1115 | clear_bit(nr: QLC_BC_VF_SEND, addr: &vf->state); |
1116 | } |
1117 | |
1118 | int __qlcnic_sriov_add_act_list(struct qlcnic_sriov *sriov, |
1119 | struct qlcnic_vf_info *vf, |
1120 | struct qlcnic_bc_trans *trans) |
1121 | { |
1122 | struct qlcnic_trans_list *t_list = &vf->rcv_act; |
1123 | |
1124 | t_list->count++; |
1125 | list_add_tail(new: &trans->list, head: &t_list->wait_list); |
1126 | if (t_list->count == 1) |
1127 | qlcnic_sriov_schedule_bc_cmd(sriov, vf, |
1128 | func: qlcnic_sriov_process_bc_cmd); |
1129 | return 0; |
1130 | } |
1131 | |
1132 | static int qlcnic_sriov_add_act_list(struct qlcnic_sriov *sriov, |
1133 | struct qlcnic_vf_info *vf, |
1134 | struct qlcnic_bc_trans *trans) |
1135 | { |
1136 | struct qlcnic_trans_list *t_list = &vf->rcv_act; |
1137 | |
1138 | spin_lock(lock: &t_list->lock); |
1139 | |
1140 | __qlcnic_sriov_add_act_list(sriov, vf, trans); |
1141 | |
1142 | spin_unlock(lock: &t_list->lock); |
1143 | return 0; |
1144 | } |
1145 | |
1146 | static void qlcnic_sriov_handle_pending_trans(struct qlcnic_sriov *sriov, |
1147 | struct qlcnic_vf_info *vf, |
1148 | struct qlcnic_bc_hdr *hdr) |
1149 | { |
1150 | struct qlcnic_bc_trans *trans = NULL; |
1151 | struct list_head *node; |
1152 | u32 pay_size, curr_frag; |
1153 | u8 found = 0, active = 0; |
1154 | |
1155 | spin_lock(lock: &vf->rcv_pend.lock); |
1156 | if (vf->rcv_pend.count > 0) { |
1157 | list_for_each(node, &vf->rcv_pend.wait_list) { |
1158 | trans = list_entry(node, struct qlcnic_bc_trans, list); |
1159 | if (trans->trans_id == hdr->seq_id) { |
1160 | found = 1; |
1161 | break; |
1162 | } |
1163 | } |
1164 | } |
1165 | |
1166 | if (found) { |
1167 | curr_frag = trans->curr_req_frag; |
1168 | pay_size = qlcnic_sriov_get_bc_paysize(real_pay_size: trans->req_pay_size, |
1169 | curr_frag); |
1170 | qlcnic_sriov_pull_bc_msg(adapter: vf->adapter, |
1171 | hdr: (u32 *)(trans->req_hdr + curr_frag), |
1172 | pay: (u32 *)(trans->req_pay + curr_frag), |
1173 | size: pay_size); |
1174 | trans->curr_req_frag++; |
1175 | if (trans->curr_req_frag >= hdr->num_frags) { |
1176 | vf->rcv_pend.count--; |
1177 | list_del(entry: &trans->list); |
1178 | active = 1; |
1179 | } |
1180 | } |
1181 | spin_unlock(lock: &vf->rcv_pend.lock); |
1182 | |
1183 | if (active) |
1184 | if (qlcnic_sriov_add_act_list(sriov, vf, trans)) |
1185 | qlcnic_sriov_cleanup_transaction(trans); |
1186 | |
1187 | return; |
1188 | } |
1189 | |
1190 | static void qlcnic_sriov_handle_bc_cmd(struct qlcnic_sriov *sriov, |
1191 | struct qlcnic_bc_hdr *hdr, |
1192 | struct qlcnic_vf_info *vf) |
1193 | { |
1194 | struct qlcnic_bc_trans *trans; |
1195 | struct qlcnic_adapter *adapter = vf->adapter; |
1196 | struct qlcnic_cmd_args cmd; |
1197 | u32 pay_size; |
1198 | int err; |
1199 | u8 cmd_op; |
1200 | |
1201 | if (adapter->need_fw_reset) |
1202 | return; |
1203 | |
1204 | if (!test_bit(QLC_BC_VF_STATE, &vf->state) && |
1205 | hdr->op_type != QLC_BC_CMD && |
1206 | hdr->cmd_op != QLCNIC_BC_CMD_CHANNEL_INIT) |
1207 | return; |
1208 | |
1209 | if (hdr->frag_num > 1) { |
1210 | qlcnic_sriov_handle_pending_trans(sriov, vf, hdr); |
1211 | return; |
1212 | } |
1213 | |
1214 | memset(&cmd, 0, sizeof(struct qlcnic_cmd_args)); |
1215 | cmd_op = hdr->cmd_op; |
1216 | if (qlcnic_sriov_alloc_bc_trans(trans: &trans)) |
1217 | return; |
1218 | |
1219 | if (hdr->op_type == QLC_BC_CMD) |
1220 | err = qlcnic_sriov_alloc_bc_mbx_args(mbx: &cmd, type: cmd_op); |
1221 | else |
1222 | err = qlcnic_alloc_mbx_args(mbx: &cmd, adapter, arg: cmd_op); |
1223 | |
1224 | if (err) { |
1225 | qlcnic_sriov_cleanup_transaction(trans); |
1226 | return; |
1227 | } |
1228 | |
1229 | cmd.op_type = hdr->op_type; |
1230 | if (qlcnic_sriov_prepare_bc_hdr(trans, cmd: &cmd, seq: hdr->seq_id, |
1231 | QLC_BC_COMMAND)) { |
1232 | qlcnic_free_mbx_args(cmd: &cmd); |
1233 | qlcnic_sriov_cleanup_transaction(trans); |
1234 | return; |
1235 | } |
1236 | |
1237 | pay_size = qlcnic_sriov_get_bc_paysize(real_pay_size: trans->req_pay_size, |
1238 | curr_frag: trans->curr_req_frag); |
1239 | qlcnic_sriov_pull_bc_msg(adapter: vf->adapter, |
1240 | hdr: (u32 *)(trans->req_hdr + trans->curr_req_frag), |
1241 | pay: (u32 *)(trans->req_pay + trans->curr_req_frag), |
1242 | size: pay_size); |
1243 | trans->func_id = vf->pci_func; |
1244 | trans->vf = vf; |
1245 | trans->trans_id = hdr->seq_id; |
1246 | trans->curr_req_frag++; |
1247 | |
1248 | if (qlcnic_sriov_soft_flr_check(adapter, trans, vf)) |
1249 | return; |
1250 | |
1251 | if (trans->curr_req_frag == trans->req_hdr->num_frags) { |
1252 | if (qlcnic_sriov_add_act_list(sriov, vf, trans)) { |
1253 | qlcnic_free_mbx_args(cmd: &cmd); |
1254 | qlcnic_sriov_cleanup_transaction(trans); |
1255 | } |
1256 | } else { |
1257 | spin_lock(lock: &vf->rcv_pend.lock); |
1258 | list_add_tail(new: &trans->list, head: &vf->rcv_pend.wait_list); |
1259 | vf->rcv_pend.count++; |
1260 | spin_unlock(lock: &vf->rcv_pend.lock); |
1261 | } |
1262 | } |
1263 | |
1264 | static void qlcnic_sriov_handle_msg_event(struct qlcnic_sriov *sriov, |
1265 | struct qlcnic_vf_info *vf) |
1266 | { |
1267 | struct qlcnic_bc_hdr hdr; |
1268 | u32 *ptr = (u32 *)&hdr; |
1269 | u8 msg_type, i; |
1270 | |
1271 | for (i = 2; i < 6; i++) |
1272 | ptr[i - 2] = readl(QLCNIC_MBX_FW(vf->adapter->ahw, i)); |
1273 | msg_type = hdr.msg_type; |
1274 | |
1275 | switch (msg_type) { |
1276 | case QLC_BC_COMMAND: |
1277 | qlcnic_sriov_handle_bc_cmd(sriov, hdr: &hdr, vf); |
1278 | break; |
1279 | case QLC_BC_RESPONSE: |
1280 | qlcnic_sriov_handle_bc_resp(hdr: &hdr, vf); |
1281 | break; |
1282 | } |
1283 | } |
1284 | |
1285 | static void qlcnic_sriov_handle_flr_event(struct qlcnic_sriov *sriov, |
1286 | struct qlcnic_vf_info *vf) |
1287 | { |
1288 | struct qlcnic_adapter *adapter = vf->adapter; |
1289 | |
1290 | if (qlcnic_sriov_pf_check(adapter)) |
1291 | qlcnic_sriov_pf_handle_flr(sriov, vf); |
1292 | else |
1293 | dev_err(&adapter->pdev->dev, |
1294 | "Invalid event to VF. VF should not get FLR event\n" ); |
1295 | } |
1296 | |
1297 | void qlcnic_sriov_handle_bc_event(struct qlcnic_adapter *adapter, u32 event) |
1298 | { |
1299 | struct qlcnic_vf_info *vf; |
1300 | struct qlcnic_sriov *sriov; |
1301 | int index; |
1302 | u8 pci_func; |
1303 | |
1304 | sriov = adapter->ahw->sriov; |
1305 | pci_func = qlcnic_sriov_target_func_id(val: event); |
1306 | index = qlcnic_sriov_func_to_index(adapter, pci_func); |
1307 | |
1308 | if (index < 0) |
1309 | return; |
1310 | |
1311 | vf = &sriov->vf_info[index]; |
1312 | vf->pci_func = pci_func; |
1313 | |
1314 | if (qlcnic_sriov_channel_free_check(val: event)) |
1315 | complete(&vf->ch_free_cmpl); |
1316 | |
1317 | if (qlcnic_sriov_flr_check(val: event)) { |
1318 | qlcnic_sriov_handle_flr_event(sriov, vf); |
1319 | return; |
1320 | } |
1321 | |
1322 | if (qlcnic_sriov_bc_msg_check(val: event)) |
1323 | qlcnic_sriov_handle_msg_event(sriov, vf); |
1324 | } |
1325 | |
1326 | int qlcnic_sriov_cfg_bc_intr(struct qlcnic_adapter *adapter, u8 enable) |
1327 | { |
1328 | struct qlcnic_cmd_args cmd; |
1329 | int err; |
1330 | |
1331 | if (!test_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state)) |
1332 | return 0; |
1333 | |
1334 | if (qlcnic_alloc_mbx_args(mbx: &cmd, adapter, QLCNIC_CMD_BC_EVENT_SETUP)) |
1335 | return -ENOMEM; |
1336 | |
1337 | if (enable) |
1338 | cmd.req.arg[1] = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7); |
1339 | |
1340 | err = qlcnic_83xx_issue_cmd(adapter, &cmd); |
1341 | |
1342 | if (err != QLCNIC_RCODE_SUCCESS) { |
1343 | dev_err(&adapter->pdev->dev, |
1344 | "Failed to %s bc events, err=%d\n" , |
1345 | (enable ? "enable" : "disable" ), err); |
1346 | } |
1347 | |
1348 | qlcnic_free_mbx_args(cmd: &cmd); |
1349 | return err; |
1350 | } |
1351 | |
1352 | static int qlcnic_sriov_retry_bc_cmd(struct qlcnic_adapter *adapter, |
1353 | struct qlcnic_bc_trans *trans) |
1354 | { |
1355 | u8 max = QLC_BC_CMD_MAX_RETRY_CNT; |
1356 | u32 state; |
1357 | |
1358 | state = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE); |
1359 | if (state == QLC_83XX_IDC_DEV_READY) { |
1360 | msleep(msecs: 20); |
1361 | clear_bit(nr: QLC_BC_VF_CHANNEL, addr: &trans->vf->state); |
1362 | trans->trans_state = QLC_INIT; |
1363 | if (++adapter->fw_fail_cnt > max) |
1364 | return -EIO; |
1365 | else |
1366 | return 0; |
1367 | } |
1368 | |
1369 | return -EIO; |
1370 | } |
1371 | |
1372 | static int __qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter, |
1373 | struct qlcnic_cmd_args *cmd) |
1374 | { |
1375 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1376 | struct qlcnic_mailbox *mbx = ahw->mailbox; |
1377 | struct device *dev = &adapter->pdev->dev; |
1378 | struct qlcnic_bc_trans *trans; |
1379 | int err; |
1380 | u32 rsp_data, opcode, mbx_err_code, rsp; |
1381 | u16 seq = ++adapter->ahw->sriov->bc.trans_counter; |
1382 | u8 func = ahw->pci_func; |
1383 | |
1384 | rsp = qlcnic_sriov_alloc_bc_trans(trans: &trans); |
1385 | if (rsp) |
1386 | goto free_cmd; |
1387 | |
1388 | rsp = qlcnic_sriov_prepare_bc_hdr(trans, cmd, seq, QLC_BC_COMMAND); |
1389 | if (rsp) |
1390 | goto cleanup_transaction; |
1391 | |
1392 | retry: |
1393 | if (!test_bit(QLC_83XX_MBX_READY, &mbx->status)) { |
1394 | rsp = -EIO; |
1395 | QLCDB(adapter, DRV, "MBX not Ready!(cmd 0x%x) for VF 0x%x\n" , |
1396 | QLCNIC_MBX_RSP(cmd->req.arg[0]), func); |
1397 | goto err_out; |
1398 | } |
1399 | |
1400 | err = qlcnic_sriov_send_bc_cmd(adapter, trans, pci_func: func); |
1401 | if (err) { |
1402 | dev_err(dev, "MBX command 0x%x timed out for VF %d\n" , |
1403 | (cmd->req.arg[0] & 0xffff), func); |
1404 | rsp = QLCNIC_RCODE_TIMEOUT; |
1405 | |
1406 | /* After adapter reset PF driver may take some time to |
1407 | * respond to VF's request. Retry request till maximum retries. |
1408 | */ |
1409 | if ((trans->req_hdr->cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) && |
1410 | !qlcnic_sriov_retry_bc_cmd(adapter, trans)) |
1411 | goto retry; |
1412 | |
1413 | goto err_out; |
1414 | } |
1415 | |
1416 | rsp_data = cmd->rsp.arg[0]; |
1417 | mbx_err_code = QLCNIC_MBX_STATUS(rsp_data); |
1418 | opcode = QLCNIC_MBX_RSP(cmd->req.arg[0]); |
1419 | |
1420 | if ((mbx_err_code == QLCNIC_MBX_RSP_OK) || |
1421 | (mbx_err_code == QLCNIC_MBX_PORT_RSP_OK)) { |
1422 | rsp = QLCNIC_RCODE_SUCCESS; |
1423 | } else { |
1424 | if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT) { |
1425 | rsp = QLCNIC_RCODE_SUCCESS; |
1426 | } else { |
1427 | rsp = mbx_err_code; |
1428 | if (!rsp) |
1429 | rsp = 1; |
1430 | |
1431 | dev_err(dev, |
1432 | "MBX command 0x%x failed with err:0x%x for VF %d\n" , |
1433 | opcode, mbx_err_code, func); |
1434 | } |
1435 | } |
1436 | |
1437 | err_out: |
1438 | if (rsp == QLCNIC_RCODE_TIMEOUT) { |
1439 | ahw->reset_context = 1; |
1440 | adapter->need_fw_reset = 1; |
1441 | clear_bit(QLC_83XX_MBX_READY, addr: &mbx->status); |
1442 | } |
1443 | |
1444 | cleanup_transaction: |
1445 | qlcnic_sriov_cleanup_transaction(trans); |
1446 | |
1447 | free_cmd: |
1448 | if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT) { |
1449 | qlcnic_free_mbx_args(cmd); |
1450 | kfree(objp: cmd); |
1451 | } |
1452 | |
1453 | return rsp; |
1454 | } |
1455 | |
1456 | |
1457 | static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter, |
1458 | struct qlcnic_cmd_args *cmd) |
1459 | { |
1460 | if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT) |
1461 | return qlcnic_sriov_async_issue_cmd(adapter, cmd); |
1462 | else |
1463 | return __qlcnic_sriov_issue_cmd(adapter, cmd); |
1464 | } |
1465 | |
1466 | static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_op) |
1467 | { |
1468 | struct qlcnic_cmd_args cmd; |
1469 | struct qlcnic_vf_info *vf = &adapter->ahw->sriov->vf_info[0]; |
1470 | int ret; |
1471 | |
1472 | memset(&cmd, 0, sizeof(cmd)); |
1473 | if (qlcnic_sriov_alloc_bc_mbx_args(mbx: &cmd, type: cmd_op)) |
1474 | return -ENOMEM; |
1475 | |
1476 | ret = qlcnic_issue_cmd(adapter, cmd: &cmd); |
1477 | if (ret) { |
1478 | dev_err(&adapter->pdev->dev, |
1479 | "Failed bc channel %s %d\n" , cmd_op ? "term" : "init" , |
1480 | ret); |
1481 | goto out; |
1482 | } |
1483 | |
1484 | cmd_op = (cmd.rsp.arg[0] & 0xff); |
1485 | if (cmd.rsp.arg[0] >> 25 == 2) |
1486 | return 2; |
1487 | if (cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) |
1488 | set_bit(nr: QLC_BC_VF_STATE, addr: &vf->state); |
1489 | else |
1490 | clear_bit(nr: QLC_BC_VF_STATE, addr: &vf->state); |
1491 | |
1492 | out: |
1493 | qlcnic_free_mbx_args(cmd: &cmd); |
1494 | return ret; |
1495 | } |
1496 | |
1497 | static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac, |
1498 | enum qlcnic_mac_type mac_type) |
1499 | { |
1500 | struct qlcnic_adapter *adapter = netdev_priv(dev: netdev); |
1501 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
1502 | struct qlcnic_vf_info *vf; |
1503 | u16 vlan_id; |
1504 | int i; |
1505 | |
1506 | vf = &adapter->ahw->sriov->vf_info[0]; |
1507 | |
1508 | if (!qlcnic_sriov_check_any_vlan(vf)) { |
1509 | qlcnic_nic_add_mac(adapter, mac, 0, mac_type); |
1510 | } else { |
1511 | spin_lock(lock: &vf->vlan_list_lock); |
1512 | for (i = 0; i < sriov->num_allowed_vlans; i++) { |
1513 | vlan_id = vf->sriov_vlans[i]; |
1514 | if (vlan_id) |
1515 | qlcnic_nic_add_mac(adapter, mac, vlan_id, |
1516 | mac_type); |
1517 | } |
1518 | spin_unlock(lock: &vf->vlan_list_lock); |
1519 | if (qlcnic_84xx_check(adapter)) |
1520 | qlcnic_nic_add_mac(adapter, mac, 0, mac_type); |
1521 | } |
1522 | } |
1523 | |
1524 | void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc) |
1525 | { |
1526 | struct list_head *head = &bc->async_cmd_list; |
1527 | struct qlcnic_async_cmd *entry; |
1528 | |
1529 | flush_workqueue(bc->bc_async_wq); |
1530 | cancel_work_sync(work: &bc->vf_async_work); |
1531 | |
1532 | spin_lock(lock: &bc->queue_lock); |
1533 | while (!list_empty(head)) { |
1534 | entry = list_entry(head->next, struct qlcnic_async_cmd, |
1535 | list); |
1536 | list_del(entry: &entry->list); |
1537 | kfree(objp: entry->cmd); |
1538 | kfree(objp: entry); |
1539 | } |
1540 | spin_unlock(lock: &bc->queue_lock); |
1541 | } |
1542 | |
1543 | void qlcnic_sriov_vf_set_multi(struct net_device *netdev) |
1544 | { |
1545 | struct qlcnic_adapter *adapter = netdev_priv(dev: netdev); |
1546 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1547 | static const u8 bcast_addr[ETH_ALEN] = { |
1548 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff |
1549 | }; |
1550 | struct netdev_hw_addr *ha; |
1551 | u32 mode = VPORT_MISS_MODE_DROP; |
1552 | |
1553 | if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) |
1554 | return; |
1555 | |
1556 | if (netdev->flags & IFF_PROMISC) { |
1557 | if (!(adapter->flags & QLCNIC_PROMISC_DISABLED)) |
1558 | mode = VPORT_MISS_MODE_ACCEPT_ALL; |
1559 | } else if ((netdev->flags & IFF_ALLMULTI) || |
1560 | (netdev_mc_count(netdev) > ahw->max_mc_count)) { |
1561 | mode = VPORT_MISS_MODE_ACCEPT_MULTI; |
1562 | } else { |
1563 | qlcnic_vf_add_mc_list(netdev, mac: bcast_addr, mac_type: QLCNIC_BROADCAST_MAC); |
1564 | if (!netdev_mc_empty(netdev)) { |
1565 | qlcnic_flush_mcast_mac(adapter); |
1566 | netdev_for_each_mc_addr(ha, netdev) |
1567 | qlcnic_vf_add_mc_list(netdev, mac: ha->addr, |
1568 | mac_type: QLCNIC_MULTICAST_MAC); |
1569 | } |
1570 | } |
1571 | |
1572 | /* configure unicast MAC address, if there is not sufficient space |
1573 | * to store all the unicast addresses then enable promiscuous mode |
1574 | */ |
1575 | if (netdev_uc_count(netdev) > ahw->max_uc_count) { |
1576 | mode = VPORT_MISS_MODE_ACCEPT_ALL; |
1577 | } else if (!netdev_uc_empty(netdev)) { |
1578 | netdev_for_each_uc_addr(ha, netdev) |
1579 | qlcnic_vf_add_mc_list(netdev, mac: ha->addr, |
1580 | mac_type: QLCNIC_UNICAST_MAC); |
1581 | } |
1582 | |
1583 | if (adapter->pdev->is_virtfn) { |
1584 | if (mode == VPORT_MISS_MODE_ACCEPT_ALL && |
1585 | !adapter->fdb_mac_learn) { |
1586 | qlcnic_alloc_lb_filters_mem(adapter); |
1587 | adapter->drv_mac_learn = true; |
1588 | adapter->rx_mac_learn = true; |
1589 | } else { |
1590 | adapter->drv_mac_learn = false; |
1591 | adapter->rx_mac_learn = false; |
1592 | } |
1593 | } |
1594 | |
1595 | qlcnic_nic_set_promisc(adapter, mode); |
1596 | } |
1597 | |
1598 | static void qlcnic_sriov_handle_async_issue_cmd(struct work_struct *work) |
1599 | { |
1600 | struct qlcnic_async_cmd *entry, *tmp; |
1601 | struct qlcnic_back_channel *bc; |
1602 | struct qlcnic_cmd_args *cmd; |
1603 | struct list_head *head; |
1604 | LIST_HEAD(del_list); |
1605 | |
1606 | bc = container_of(work, struct qlcnic_back_channel, vf_async_work); |
1607 | head = &bc->async_cmd_list; |
1608 | |
1609 | spin_lock(lock: &bc->queue_lock); |
1610 | list_splice_init(list: head, head: &del_list); |
1611 | spin_unlock(lock: &bc->queue_lock); |
1612 | |
1613 | list_for_each_entry_safe(entry, tmp, &del_list, list) { |
1614 | list_del(entry: &entry->list); |
1615 | cmd = entry->cmd; |
1616 | __qlcnic_sriov_issue_cmd(adapter: bc->adapter, cmd); |
1617 | kfree(objp: entry); |
1618 | } |
1619 | |
1620 | if (!list_empty(head)) |
1621 | queue_work(wq: bc->bc_async_wq, work: &bc->vf_async_work); |
1622 | |
1623 | return; |
1624 | } |
1625 | |
1626 | static struct qlcnic_async_cmd * |
1627 | qlcnic_sriov_alloc_async_cmd(struct qlcnic_back_channel *bc, |
1628 | struct qlcnic_cmd_args *cmd) |
1629 | { |
1630 | struct qlcnic_async_cmd *entry = NULL; |
1631 | |
1632 | entry = kzalloc(size: sizeof(*entry), GFP_ATOMIC); |
1633 | if (!entry) |
1634 | return NULL; |
1635 | |
1636 | entry->cmd = cmd; |
1637 | |
1638 | spin_lock(lock: &bc->queue_lock); |
1639 | list_add_tail(new: &entry->list, head: &bc->async_cmd_list); |
1640 | spin_unlock(lock: &bc->queue_lock); |
1641 | |
1642 | return entry; |
1643 | } |
1644 | |
1645 | static void qlcnic_sriov_schedule_async_cmd(struct qlcnic_back_channel *bc, |
1646 | struct qlcnic_cmd_args *cmd) |
1647 | { |
1648 | struct qlcnic_async_cmd *entry = NULL; |
1649 | |
1650 | entry = qlcnic_sriov_alloc_async_cmd(bc, cmd); |
1651 | if (!entry) { |
1652 | qlcnic_free_mbx_args(cmd); |
1653 | kfree(objp: cmd); |
1654 | return; |
1655 | } |
1656 | |
1657 | queue_work(wq: bc->bc_async_wq, work: &bc->vf_async_work); |
1658 | } |
1659 | |
1660 | static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *adapter, |
1661 | struct qlcnic_cmd_args *cmd) |
1662 | { |
1663 | |
1664 | struct qlcnic_back_channel *bc = &adapter->ahw->sriov->bc; |
1665 | |
1666 | if (adapter->need_fw_reset) |
1667 | return -EIO; |
1668 | |
1669 | qlcnic_sriov_schedule_async_cmd(bc, cmd); |
1670 | |
1671 | return 0; |
1672 | } |
1673 | |
1674 | static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter) |
1675 | { |
1676 | int err; |
1677 | |
1678 | adapter->need_fw_reset = 0; |
1679 | qlcnic_83xx_reinit_mbx_work(mbx: adapter->ahw->mailbox); |
1680 | qlcnic_83xx_enable_mbx_interrupt(adapter); |
1681 | |
1682 | err = qlcnic_sriov_cfg_bc_intr(adapter, enable: 1); |
1683 | if (err) |
1684 | return err; |
1685 | |
1686 | err = qlcnic_sriov_channel_cfg_cmd(adapter, cmd_op: QLCNIC_BC_CMD_CHANNEL_INIT); |
1687 | if (err) |
1688 | goto err_out_cleanup_bc_intr; |
1689 | |
1690 | err = qlcnic_sriov_vf_init_driver(adapter); |
1691 | if (err) |
1692 | goto err_out_term_channel; |
1693 | |
1694 | return 0; |
1695 | |
1696 | err_out_term_channel: |
1697 | qlcnic_sriov_channel_cfg_cmd(adapter, cmd_op: QLCNIC_BC_CMD_CHANNEL_TERM); |
1698 | |
1699 | err_out_cleanup_bc_intr: |
1700 | qlcnic_sriov_cfg_bc_intr(adapter, enable: 0); |
1701 | return err; |
1702 | } |
1703 | |
1704 | static void qlcnic_sriov_vf_attach(struct qlcnic_adapter *adapter) |
1705 | { |
1706 | struct net_device *netdev = adapter->netdev; |
1707 | |
1708 | if (netif_running(dev: netdev)) { |
1709 | if (!qlcnic_up(adapter, netdev)) |
1710 | qlcnic_restore_indev_addr(netdev, NETDEV_UP); |
1711 | } |
1712 | |
1713 | netif_device_attach(dev: netdev); |
1714 | } |
1715 | |
1716 | static void qlcnic_sriov_vf_detach(struct qlcnic_adapter *adapter) |
1717 | { |
1718 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1719 | struct qlcnic_intrpt_config *intr_tbl = ahw->intr_tbl; |
1720 | struct net_device *netdev = adapter->netdev; |
1721 | u8 i, max_ints = ahw->num_msix - 1; |
1722 | |
1723 | netif_device_detach(dev: netdev); |
1724 | qlcnic_83xx_detach_mailbox_work(adapter); |
1725 | qlcnic_83xx_disable_mbx_intr(adapter); |
1726 | |
1727 | if (netif_running(dev: netdev)) |
1728 | qlcnic_down(adapter, netdev); |
1729 | |
1730 | for (i = 0; i < max_ints; i++) { |
1731 | intr_tbl[i].id = i; |
1732 | intr_tbl[i].enabled = 0; |
1733 | intr_tbl[i].src = 0; |
1734 | } |
1735 | ahw->reset_context = 0; |
1736 | } |
1737 | |
1738 | static int qlcnic_sriov_vf_handle_dev_ready(struct qlcnic_adapter *adapter) |
1739 | { |
1740 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1741 | struct device *dev = &adapter->pdev->dev; |
1742 | struct qlc_83xx_idc *idc = &ahw->idc; |
1743 | u8 func = ahw->pci_func; |
1744 | u32 state; |
1745 | |
1746 | if ((idc->prev_state == QLC_83XX_IDC_DEV_NEED_RESET) || |
1747 | (idc->prev_state == QLC_83XX_IDC_DEV_INIT)) { |
1748 | if (!qlcnic_sriov_vf_reinit_driver(adapter)) { |
1749 | qlcnic_sriov_vf_attach(adapter); |
1750 | adapter->fw_fail_cnt = 0; |
1751 | dev_info(dev, |
1752 | "%s: Reinitialization of VF 0x%x done after FW reset\n" , |
1753 | __func__, func); |
1754 | } else { |
1755 | dev_err(dev, |
1756 | "%s: Reinitialization of VF 0x%x failed after FW reset\n" , |
1757 | __func__, func); |
1758 | state = QLCRDX(ahw, QLC_83XX_IDC_DEV_STATE); |
1759 | dev_info(dev, "Current state 0x%x after FW reset\n" , |
1760 | state); |
1761 | } |
1762 | } |
1763 | |
1764 | return 0; |
1765 | } |
1766 | |
1767 | static int qlcnic_sriov_vf_handle_context_reset(struct qlcnic_adapter *adapter) |
1768 | { |
1769 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1770 | struct qlcnic_mailbox *mbx = ahw->mailbox; |
1771 | struct device *dev = &adapter->pdev->dev; |
1772 | struct qlc_83xx_idc *idc = &ahw->idc; |
1773 | u8 func = ahw->pci_func; |
1774 | u32 state; |
1775 | |
1776 | adapter->reset_ctx_cnt++; |
1777 | |
1778 | /* Skip the context reset and check if FW is hung */ |
1779 | if (adapter->reset_ctx_cnt < 3) { |
1780 | adapter->need_fw_reset = 1; |
1781 | clear_bit(QLC_83XX_MBX_READY, addr: &mbx->status); |
1782 | dev_info(dev, |
1783 | "Resetting context, wait here to check if FW is in failed state\n" ); |
1784 | return 0; |
1785 | } |
1786 | |
1787 | /* Check if number of resets exceed the threshold. |
1788 | * If it exceeds the threshold just fail the VF. |
1789 | */ |
1790 | if (adapter->reset_ctx_cnt > QLC_83XX_VF_RESET_FAIL_THRESH) { |
1791 | clear_bit(QLC_83XX_MODULE_LOADED, addr: &idc->status); |
1792 | adapter->tx_timeo_cnt = 0; |
1793 | adapter->fw_fail_cnt = 0; |
1794 | adapter->reset_ctx_cnt = 0; |
1795 | qlcnic_sriov_vf_detach(adapter); |
1796 | dev_err(dev, |
1797 | "Device context resets have exceeded the threshold, device interface will be shutdown\n" ); |
1798 | return -EIO; |
1799 | } |
1800 | |
1801 | dev_info(dev, "Resetting context of VF 0x%x\n" , func); |
1802 | dev_info(dev, "%s: Context reset count %d for VF 0x%x\n" , |
1803 | __func__, adapter->reset_ctx_cnt, func); |
1804 | set_bit(__QLCNIC_RESETTING, addr: &adapter->state); |
1805 | adapter->need_fw_reset = 1; |
1806 | clear_bit(QLC_83XX_MBX_READY, addr: &mbx->status); |
1807 | qlcnic_sriov_vf_detach(adapter); |
1808 | adapter->need_fw_reset = 0; |
1809 | |
1810 | if (!qlcnic_sriov_vf_reinit_driver(adapter)) { |
1811 | qlcnic_sriov_vf_attach(adapter); |
1812 | adapter->tx_timeo_cnt = 0; |
1813 | adapter->reset_ctx_cnt = 0; |
1814 | adapter->fw_fail_cnt = 0; |
1815 | dev_info(dev, "Done resetting context for VF 0x%x\n" , func); |
1816 | } else { |
1817 | dev_err(dev, "%s: Reinitialization of VF 0x%x failed\n" , |
1818 | __func__, func); |
1819 | state = QLCRDX(ahw, QLC_83XX_IDC_DEV_STATE); |
1820 | dev_info(dev, "%s: Current state 0x%x\n" , __func__, state); |
1821 | } |
1822 | |
1823 | return 0; |
1824 | } |
1825 | |
1826 | static int qlcnic_sriov_vf_idc_ready_state(struct qlcnic_adapter *adapter) |
1827 | { |
1828 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1829 | int ret = 0; |
1830 | |
1831 | if (ahw->idc.prev_state != QLC_83XX_IDC_DEV_READY) |
1832 | ret = qlcnic_sriov_vf_handle_dev_ready(adapter); |
1833 | else if (ahw->reset_context) |
1834 | ret = qlcnic_sriov_vf_handle_context_reset(adapter); |
1835 | |
1836 | clear_bit(__QLCNIC_RESETTING, addr: &adapter->state); |
1837 | return ret; |
1838 | } |
1839 | |
1840 | static int qlcnic_sriov_vf_idc_failed_state(struct qlcnic_adapter *adapter) |
1841 | { |
1842 | struct qlc_83xx_idc *idc = &adapter->ahw->idc; |
1843 | |
1844 | dev_err(&adapter->pdev->dev, "Device is in failed state\n" ); |
1845 | if (idc->prev_state == QLC_83XX_IDC_DEV_READY) |
1846 | qlcnic_sriov_vf_detach(adapter); |
1847 | |
1848 | clear_bit(QLC_83XX_MODULE_LOADED, addr: &idc->status); |
1849 | clear_bit(__QLCNIC_RESETTING, addr: &adapter->state); |
1850 | return -EIO; |
1851 | } |
1852 | |
1853 | static int |
1854 | qlcnic_sriov_vf_idc_need_quiescent_state(struct qlcnic_adapter *adapter) |
1855 | { |
1856 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; |
1857 | struct qlc_83xx_idc *idc = &adapter->ahw->idc; |
1858 | |
1859 | dev_info(&adapter->pdev->dev, "Device is in quiescent state\n" ); |
1860 | if (idc->prev_state == QLC_83XX_IDC_DEV_READY) { |
1861 | set_bit(__QLCNIC_RESETTING, addr: &adapter->state); |
1862 | adapter->tx_timeo_cnt = 0; |
1863 | adapter->reset_ctx_cnt = 0; |
1864 | clear_bit(QLC_83XX_MBX_READY, addr: &mbx->status); |
1865 | qlcnic_sriov_vf_detach(adapter); |
1866 | } |
1867 | |
1868 | return 0; |
1869 | } |
1870 | |
1871 | static int qlcnic_sriov_vf_idc_init_reset_state(struct qlcnic_adapter *adapter) |
1872 | { |
1873 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; |
1874 | struct qlc_83xx_idc *idc = &adapter->ahw->idc; |
1875 | u8 func = adapter->ahw->pci_func; |
1876 | |
1877 | if (idc->prev_state == QLC_83XX_IDC_DEV_READY) { |
1878 | dev_err(&adapter->pdev->dev, |
1879 | "Firmware hang detected by VF 0x%x\n" , func); |
1880 | set_bit(__QLCNIC_RESETTING, addr: &adapter->state); |
1881 | adapter->tx_timeo_cnt = 0; |
1882 | adapter->reset_ctx_cnt = 0; |
1883 | clear_bit(QLC_83XX_MBX_READY, addr: &mbx->status); |
1884 | qlcnic_sriov_vf_detach(adapter); |
1885 | } |
1886 | return 0; |
1887 | } |
1888 | |
1889 | static int qlcnic_sriov_vf_idc_unknown_state(struct qlcnic_adapter *adapter) |
1890 | { |
1891 | dev_err(&adapter->pdev->dev, "%s: Device in unknown state\n" , __func__); |
1892 | return 0; |
1893 | } |
1894 | |
1895 | static void qlcnic_sriov_vf_periodic_tasks(struct qlcnic_adapter *adapter) |
1896 | { |
1897 | if (adapter->fhash.fnum) |
1898 | qlcnic_prune_lb_filters(adapter); |
1899 | } |
1900 | |
1901 | static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *work) |
1902 | { |
1903 | struct qlcnic_adapter *adapter; |
1904 | struct qlc_83xx_idc *idc; |
1905 | int ret = 0; |
1906 | |
1907 | adapter = container_of(work, struct qlcnic_adapter, fw_work.work); |
1908 | idc = &adapter->ahw->idc; |
1909 | idc->curr_state = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE); |
1910 | |
1911 | switch (idc->curr_state) { |
1912 | case QLC_83XX_IDC_DEV_READY: |
1913 | ret = qlcnic_sriov_vf_idc_ready_state(adapter); |
1914 | break; |
1915 | case QLC_83XX_IDC_DEV_NEED_RESET: |
1916 | case QLC_83XX_IDC_DEV_INIT: |
1917 | ret = qlcnic_sriov_vf_idc_init_reset_state(adapter); |
1918 | break; |
1919 | case QLC_83XX_IDC_DEV_NEED_QUISCENT: |
1920 | ret = qlcnic_sriov_vf_idc_need_quiescent_state(adapter); |
1921 | break; |
1922 | case QLC_83XX_IDC_DEV_FAILED: |
1923 | ret = qlcnic_sriov_vf_idc_failed_state(adapter); |
1924 | break; |
1925 | case QLC_83XX_IDC_DEV_QUISCENT: |
1926 | break; |
1927 | default: |
1928 | ret = qlcnic_sriov_vf_idc_unknown_state(adapter); |
1929 | } |
1930 | |
1931 | idc->prev_state = idc->curr_state; |
1932 | qlcnic_sriov_vf_periodic_tasks(adapter); |
1933 | |
1934 | if (!ret && test_bit(QLC_83XX_MODULE_LOADED, &idc->status)) |
1935 | qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state, |
1936 | idc->delay); |
1937 | } |
1938 | |
1939 | static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *adapter) |
1940 | { |
1941 | while (test_and_set_bit(__QLCNIC_RESETTING, addr: &adapter->state)) |
1942 | msleep(msecs: 20); |
1943 | |
1944 | clear_bit(QLC_83XX_MODULE_LOADED, addr: &adapter->ahw->idc.status); |
1945 | clear_bit(__QLCNIC_RESETTING, addr: &adapter->state); |
1946 | cancel_delayed_work_sync(dwork: &adapter->fw_work); |
1947 | } |
1948 | |
1949 | static int qlcnic_sriov_check_vlan_id(struct qlcnic_sriov *sriov, |
1950 | struct qlcnic_vf_info *vf, u16 vlan_id) |
1951 | { |
1952 | int i, err = -EINVAL; |
1953 | |
1954 | if (!vf->sriov_vlans) |
1955 | return err; |
1956 | |
1957 | spin_lock_bh(lock: &vf->vlan_list_lock); |
1958 | |
1959 | for (i = 0; i < sriov->num_allowed_vlans; i++) { |
1960 | if (vf->sriov_vlans[i] == vlan_id) { |
1961 | err = 0; |
1962 | break; |
1963 | } |
1964 | } |
1965 | |
1966 | spin_unlock_bh(lock: &vf->vlan_list_lock); |
1967 | return err; |
1968 | } |
1969 | |
1970 | static int qlcnic_sriov_validate_num_vlans(struct qlcnic_sriov *sriov, |
1971 | struct qlcnic_vf_info *vf) |
1972 | { |
1973 | int err = 0; |
1974 | |
1975 | spin_lock_bh(lock: &vf->vlan_list_lock); |
1976 | |
1977 | if (vf->num_vlan >= sriov->num_allowed_vlans) |
1978 | err = -EINVAL; |
1979 | |
1980 | spin_unlock_bh(lock: &vf->vlan_list_lock); |
1981 | return err; |
1982 | } |
1983 | |
1984 | static int qlcnic_sriov_validate_vlan_cfg(struct qlcnic_adapter *adapter, |
1985 | u16 vid, u8 enable) |
1986 | { |
1987 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
1988 | struct qlcnic_vf_info *vf; |
1989 | bool vlan_exist; |
1990 | u8 allowed = 0; |
1991 | int i; |
1992 | |
1993 | vf = &adapter->ahw->sriov->vf_info[0]; |
1994 | vlan_exist = qlcnic_sriov_check_any_vlan(vf); |
1995 | if (sriov->vlan_mode != QLC_GUEST_VLAN_MODE) |
1996 | return -EINVAL; |
1997 | |
1998 | if (enable) { |
1999 | if (qlcnic_83xx_vf_check(adapter) && vlan_exist) |
2000 | return -EINVAL; |
2001 | |
2002 | if (qlcnic_sriov_validate_num_vlans(sriov, vf)) |
2003 | return -EINVAL; |
2004 | |
2005 | if (sriov->any_vlan) { |
2006 | for (i = 0; i < sriov->num_allowed_vlans; i++) { |
2007 | if (sriov->allowed_vlans[i] == vid) |
2008 | allowed = 1; |
2009 | } |
2010 | |
2011 | if (!allowed) |
2012 | return -EINVAL; |
2013 | } |
2014 | } else { |
2015 | if (!vlan_exist || qlcnic_sriov_check_vlan_id(sriov, vf, vlan_id: vid)) |
2016 | return -EINVAL; |
2017 | } |
2018 | |
2019 | return 0; |
2020 | } |
2021 | |
2022 | static void qlcnic_sriov_vlan_operation(struct qlcnic_vf_info *vf, u16 vlan_id, |
2023 | enum qlcnic_vlan_operations opcode) |
2024 | { |
2025 | struct qlcnic_adapter *adapter = vf->adapter; |
2026 | struct qlcnic_sriov *sriov; |
2027 | |
2028 | sriov = adapter->ahw->sriov; |
2029 | |
2030 | if (!vf->sriov_vlans) |
2031 | return; |
2032 | |
2033 | spin_lock_bh(lock: &vf->vlan_list_lock); |
2034 | |
2035 | switch (opcode) { |
2036 | case QLC_VLAN_ADD: |
2037 | qlcnic_sriov_add_vlan_id(sriov, vf, vlan_id); |
2038 | break; |
2039 | case QLC_VLAN_DELETE: |
2040 | qlcnic_sriov_del_vlan_id(sriov, vf, vlan_id); |
2041 | break; |
2042 | default: |
2043 | netdev_err(dev: adapter->netdev, format: "Invalid VLAN operation\n" ); |
2044 | } |
2045 | |
2046 | spin_unlock_bh(lock: &vf->vlan_list_lock); |
2047 | return; |
2048 | } |
2049 | |
2050 | int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter, |
2051 | u16 vid, u8 enable) |
2052 | { |
2053 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
2054 | struct net_device *netdev = adapter->netdev; |
2055 | struct qlcnic_vf_info *vf; |
2056 | struct qlcnic_cmd_args cmd; |
2057 | int ret; |
2058 | |
2059 | memset(&cmd, 0, sizeof(cmd)); |
2060 | if (vid == 0) |
2061 | return 0; |
2062 | |
2063 | vf = &adapter->ahw->sriov->vf_info[0]; |
2064 | ret = qlcnic_sriov_validate_vlan_cfg(adapter, vid, enable); |
2065 | if (ret) |
2066 | return ret; |
2067 | |
2068 | ret = qlcnic_sriov_alloc_bc_mbx_args(mbx: &cmd, |
2069 | type: QLCNIC_BC_CMD_CFG_GUEST_VLAN); |
2070 | if (ret) |
2071 | return ret; |
2072 | |
2073 | cmd.req.arg[1] = (enable & 1) | vid << 16; |
2074 | |
2075 | qlcnic_sriov_cleanup_async_list(bc: &sriov->bc); |
2076 | ret = qlcnic_issue_cmd(adapter, cmd: &cmd); |
2077 | if (ret) { |
2078 | dev_err(&adapter->pdev->dev, |
2079 | "Failed to configure guest VLAN, err=%d\n" , ret); |
2080 | } else { |
2081 | netif_addr_lock_bh(dev: netdev); |
2082 | qlcnic_free_mac_list(adapter); |
2083 | netif_addr_unlock_bh(dev: netdev); |
2084 | |
2085 | if (enable) |
2086 | qlcnic_sriov_vlan_operation(vf, vlan_id: vid, opcode: QLC_VLAN_ADD); |
2087 | else |
2088 | qlcnic_sriov_vlan_operation(vf, vlan_id: vid, opcode: QLC_VLAN_DELETE); |
2089 | |
2090 | netif_addr_lock_bh(dev: netdev); |
2091 | qlcnic_set_multi(netdev); |
2092 | netif_addr_unlock_bh(dev: netdev); |
2093 | } |
2094 | |
2095 | qlcnic_free_mbx_args(cmd: &cmd); |
2096 | return ret; |
2097 | } |
2098 | |
2099 | static void qlcnic_sriov_vf_free_mac_list(struct qlcnic_adapter *adapter) |
2100 | { |
2101 | struct list_head *head = &adapter->mac_list; |
2102 | struct qlcnic_mac_vlan_list *cur; |
2103 | |
2104 | while (!list_empty(head)) { |
2105 | cur = list_entry(head->next, struct qlcnic_mac_vlan_list, list); |
2106 | qlcnic_sre_macaddr_change(adapter, addr: cur->mac_addr, id: cur->vlan_id, |
2107 | QLCNIC_MAC_DEL); |
2108 | list_del(entry: &cur->list); |
2109 | kfree(objp: cur); |
2110 | } |
2111 | } |
2112 | |
2113 | |
2114 | static int qlcnic_sriov_vf_shutdown(struct pci_dev *pdev) |
2115 | { |
2116 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); |
2117 | struct net_device *netdev = adapter->netdev; |
2118 | |
2119 | netif_device_detach(dev: netdev); |
2120 | qlcnic_cancel_idc_work(adapter); |
2121 | |
2122 | if (netif_running(dev: netdev)) |
2123 | qlcnic_down(adapter, netdev); |
2124 | |
2125 | qlcnic_sriov_channel_cfg_cmd(adapter, cmd_op: QLCNIC_BC_CMD_CHANNEL_TERM); |
2126 | qlcnic_sriov_cfg_bc_intr(adapter, enable: 0); |
2127 | qlcnic_83xx_disable_mbx_intr(adapter); |
2128 | cancel_delayed_work_sync(dwork: &adapter->idc_aen_work); |
2129 | |
2130 | return pci_save_state(dev: pdev); |
2131 | } |
2132 | |
2133 | static int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter) |
2134 | { |
2135 | struct qlc_83xx_idc *idc = &adapter->ahw->idc; |
2136 | struct net_device *netdev = adapter->netdev; |
2137 | int err; |
2138 | |
2139 | set_bit(QLC_83XX_MODULE_LOADED, addr: &idc->status); |
2140 | qlcnic_83xx_enable_mbx_interrupt(adapter); |
2141 | err = qlcnic_sriov_cfg_bc_intr(adapter, enable: 1); |
2142 | if (err) |
2143 | return err; |
2144 | |
2145 | err = qlcnic_sriov_channel_cfg_cmd(adapter, cmd_op: QLCNIC_BC_CMD_CHANNEL_INIT); |
2146 | if (!err) { |
2147 | if (netif_running(dev: netdev)) { |
2148 | err = qlcnic_up(adapter, netdev); |
2149 | if (!err) |
2150 | qlcnic_restore_indev_addr(netdev, NETDEV_UP); |
2151 | } |
2152 | } |
2153 | |
2154 | netif_device_attach(dev: netdev); |
2155 | qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state, |
2156 | idc->delay); |
2157 | return err; |
2158 | } |
2159 | |
2160 | int qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *adapter) |
2161 | { |
2162 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
2163 | struct qlcnic_vf_info *vf; |
2164 | int i; |
2165 | |
2166 | for (i = 0; i < sriov->num_vfs; i++) { |
2167 | vf = &sriov->vf_info[i]; |
2168 | vf->sriov_vlans = kcalloc(n: sriov->num_allowed_vlans, |
2169 | size: sizeof(*vf->sriov_vlans), GFP_KERNEL); |
2170 | if (!vf->sriov_vlans) |
2171 | return -ENOMEM; |
2172 | } |
2173 | |
2174 | return 0; |
2175 | } |
2176 | |
2177 | void qlcnic_sriov_free_vlans(struct qlcnic_adapter *adapter) |
2178 | { |
2179 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
2180 | struct qlcnic_vf_info *vf; |
2181 | int i; |
2182 | |
2183 | for (i = 0; i < sriov->num_vfs; i++) { |
2184 | vf = &sriov->vf_info[i]; |
2185 | kfree(objp: vf->sriov_vlans); |
2186 | vf->sriov_vlans = NULL; |
2187 | } |
2188 | } |
2189 | |
2190 | void qlcnic_sriov_add_vlan_id(struct qlcnic_sriov *sriov, |
2191 | struct qlcnic_vf_info *vf, u16 vlan_id) |
2192 | { |
2193 | int i; |
2194 | |
2195 | for (i = 0; i < sriov->num_allowed_vlans; i++) { |
2196 | if (!vf->sriov_vlans[i]) { |
2197 | vf->sriov_vlans[i] = vlan_id; |
2198 | vf->num_vlan++; |
2199 | return; |
2200 | } |
2201 | } |
2202 | } |
2203 | |
2204 | void qlcnic_sriov_del_vlan_id(struct qlcnic_sriov *sriov, |
2205 | struct qlcnic_vf_info *vf, u16 vlan_id) |
2206 | { |
2207 | int i; |
2208 | |
2209 | for (i = 0; i < sriov->num_allowed_vlans; i++) { |
2210 | if (vf->sriov_vlans[i] == vlan_id) { |
2211 | vf->sriov_vlans[i] = 0; |
2212 | vf->num_vlan--; |
2213 | return; |
2214 | } |
2215 | } |
2216 | } |
2217 | |
2218 | bool qlcnic_sriov_check_any_vlan(struct qlcnic_vf_info *vf) |
2219 | { |
2220 | bool err = false; |
2221 | |
2222 | spin_lock_bh(lock: &vf->vlan_list_lock); |
2223 | |
2224 | if (vf->num_vlan) |
2225 | err = true; |
2226 | |
2227 | spin_unlock_bh(lock: &vf->vlan_list_lock); |
2228 | return err; |
2229 | } |
2230 | |