1
2
3
4
5
6
7
8#include "qlcnic.h"
9#include "qlcnic_sriov.h"
10#include <linux/if_vlan.h>
11#include <linux/ipv6.h>
12#include <linux/ethtool.h>
13#include <linux/interrupt.h>
14
15#define QLCNIC_MAX_TX_QUEUES 1
16#define RSS_HASHTYPE_IP_TCP 0x3
17#define QLC_83XX_FW_MBX_CMD 0
18
19static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
20 {QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1},
21 {QLCNIC_CMD_CONFIG_INTRPT, 18, 34},
22 {QLCNIC_CMD_CREATE_RX_CTX, 136, 27},
23 {QLCNIC_CMD_DESTROY_RX_CTX, 2, 1},
24 {QLCNIC_CMD_CREATE_TX_CTX, 54, 18},
25 {QLCNIC_CMD_DESTROY_TX_CTX, 2, 1},
26 {QLCNIC_CMD_CONFIGURE_MAC_LEARNING, 2, 1},
27 {QLCNIC_CMD_INTRPT_TEST, 22, 12},
28 {QLCNIC_CMD_SET_MTU, 3, 1},
29 {QLCNIC_CMD_READ_PHY, 4, 2},
30 {QLCNIC_CMD_WRITE_PHY, 5, 1},
31 {QLCNIC_CMD_READ_HW_REG, 4, 1},
32 {QLCNIC_CMD_GET_FLOW_CTL, 4, 2},
33 {QLCNIC_CMD_SET_FLOW_CTL, 4, 1},
34 {QLCNIC_CMD_READ_MAX_MTU, 4, 2},
35 {QLCNIC_CMD_READ_MAX_LRO, 4, 2},
36 {QLCNIC_CMD_MAC_ADDRESS, 4, 3},
37 {QLCNIC_CMD_GET_PCI_INFO, 1, 66},
38 {QLCNIC_CMD_GET_NIC_INFO, 2, 19},
39 {QLCNIC_CMD_SET_NIC_INFO, 32, 1},
40 {QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3},
41 {QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1},
42 {QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3},
43 {QLCNIC_CMD_SET_PORTMIRRORING, 4, 1},
44 {QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1},
45 {QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3},
46 {QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1},
47 {QLCNIC_CMD_CONFIG_PORT, 4, 1},
48 {QLCNIC_CMD_TEMP_SIZE, 1, 4},
49 {QLCNIC_CMD_GET_TEMP_HDR, 5, 5},
50 {QLCNIC_CMD_GET_LINK_EVENT, 2, 1},
51 {QLCNIC_CMD_CONFIG_MAC_VLAN, 4, 3},
52 {QLCNIC_CMD_CONFIG_INTR_COAL, 6, 1},
53 {QLCNIC_CMD_CONFIGURE_RSS, 14, 1},
54 {QLCNIC_CMD_CONFIGURE_LED, 2, 1},
55 {QLCNIC_CMD_CONFIGURE_MAC_RX_MODE, 2, 1},
56 {QLCNIC_CMD_CONFIGURE_HW_LRO, 2, 1},
57 {QLCNIC_CMD_GET_STATISTICS, 2, 80},
58 {QLCNIC_CMD_SET_PORT_CONFIG, 2, 1},
59 {QLCNIC_CMD_GET_PORT_CONFIG, 2, 2},
60 {QLCNIC_CMD_GET_LINK_STATUS, 2, 4},
61 {QLCNIC_CMD_IDC_ACK, 5, 1},
62 {QLCNIC_CMD_INIT_NIC_FUNC, 2, 1},
63 {QLCNIC_CMD_STOP_NIC_FUNC, 2, 1},
64 {QLCNIC_CMD_SET_LED_CONFIG, 5, 1},
65 {QLCNIC_CMD_GET_LED_CONFIG, 1, 5},
66 {QLCNIC_CMD_83XX_SET_DRV_VER, 4, 1},
67 {QLCNIC_CMD_ADD_RCV_RINGS, 130, 26},
68 {QLCNIC_CMD_CONFIG_VPORT, 4, 4},
69 {QLCNIC_CMD_BC_EVENT_SETUP, 2, 1},
70};
71
72const u32 qlcnic_83xx_ext_reg_tbl[] = {
73 0x38CC,
74 0x38F0,
75 0x38FC,
76 0x3038,
77 0x303C,
78 0x355C,
79 0x3560,
80 0x3564,
81 0x1000,
82 0x1200,
83 0x1204,
84 0x3780,
85 0x3784,
86 0x3788,
87 0x378C,
88 0x3790,
89 0x3794,
90 0x3798,
91 0x379C,
92 0x37A0,
93 0x37A4,
94 0x37A8,
95 0x37AC,
96 0x37B0,
97 0x37B4,
98 0x37B8,
99 0x37BC,
100 0x37C0,
101 0x37C4,
102 0x37C8,
103 0x37CC,
104 0x37D0,
105 0x37D4,
106 0x37D8,
107 0x37DC,
108 0x37E0,
109 0x37E4,
110 0x37F0,
111 0x37F4,
112 0x3868,
113 0x386C,
114 0x3504,
115 0x34A4,
116};
117
118const u32 qlcnic_83xx_reg_tbl[] = {
119 0x34A8,
120 0x34AC,
121 0x34B0,
122 0x3500,
123 0x3528,
124 0x3538,
125 0x3540,
126 0x3544,
127 0x3548,
128 0x354C,
129 0x3524,
130 0x3550,
131 0x3554,
132 0x3558,
133 0x359C,
134 0x35FC,
135 0x3650,
136 0x373C,
137 0x37B4,
138 0x356C,
139 0x3570,
140 0x3850,
141 0x3854,
142};
143
144static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
145 .read_crb = qlcnic_83xx_read_crb,
146 .write_crb = qlcnic_83xx_write_crb,
147 .read_reg = qlcnic_83xx_rd_reg_indirect,
148 .write_reg = qlcnic_83xx_wrt_reg_indirect,
149 .get_mac_address = qlcnic_83xx_get_mac_address,
150 .setup_intr = qlcnic_83xx_setup_intr,
151 .alloc_mbx_args = qlcnic_83xx_alloc_mbx_args,
152 .mbx_cmd = qlcnic_83xx_mbx_op,
153 .get_func_no = qlcnic_83xx_get_func_no,
154 .api_lock = qlcnic_83xx_cam_lock,
155 .api_unlock = qlcnic_83xx_cam_unlock,
156 .add_sysfs = qlcnic_83xx_add_sysfs,
157 .remove_sysfs = qlcnic_83xx_remove_sysfs,
158 .process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag,
159 .create_rx_ctx = qlcnic_83xx_create_rx_ctx,
160 .create_tx_ctx = qlcnic_83xx_create_tx_ctx,
161 .del_rx_ctx = qlcnic_83xx_del_rx_ctx,
162 .del_tx_ctx = qlcnic_83xx_del_tx_ctx,
163 .setup_link_event = qlcnic_83xx_setup_link_event,
164 .get_nic_info = qlcnic_83xx_get_nic_info,
165 .get_pci_info = qlcnic_83xx_get_pci_info,
166 .set_nic_info = qlcnic_83xx_set_nic_info,
167 .change_macvlan = qlcnic_83xx_sre_macaddr_change,
168 .napi_enable = qlcnic_83xx_napi_enable,
169 .napi_disable = qlcnic_83xx_napi_disable,
170 .config_intr_coal = qlcnic_83xx_config_intr_coal,
171 .config_rss = qlcnic_83xx_config_rss,
172 .config_hw_lro = qlcnic_83xx_config_hw_lro,
173 .config_promisc_mode = qlcnic_83xx_nic_set_promisc,
174 .change_l2_filter = qlcnic_83xx_change_l2_filter,
175 .get_board_info = qlcnic_83xx_get_port_info,
176 .set_mac_filter_count = qlcnic_83xx_set_mac_filter_count,
177 .free_mac_list = qlcnic_82xx_free_mac_list,
178};
179
180static struct qlcnic_nic_template qlcnic_83xx_ops = {
181 .config_bridged_mode = qlcnic_config_bridged_mode,
182 .config_led = qlcnic_config_led,
183 .request_reset = qlcnic_83xx_idc_request_reset,
184 .cancel_idc_work = qlcnic_83xx_idc_exit,
185 .napi_add = qlcnic_83xx_napi_add,
186 .napi_del = qlcnic_83xx_napi_del,
187 .config_ipaddr = qlcnic_83xx_config_ipaddr,
188 .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr,
189 .shutdown = qlcnic_83xx_shutdown,
190 .resume = qlcnic_83xx_resume,
191};
192
193void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw)
194{
195 ahw->hw_ops = &qlcnic_83xx_hw_ops;
196 ahw->reg_tbl = (u32 *)qlcnic_83xx_reg_tbl;
197 ahw->ext_reg_tbl = (u32 *)qlcnic_83xx_ext_reg_tbl;
198}
199
200int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *adapter)
201{
202 u32 fw_major, fw_minor, fw_build;
203 struct pci_dev *pdev = adapter->pdev;
204
205 fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
206 fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
207 fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
208 adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
209
210 dev_info(&pdev->dev, "Driver v%s, firmware version %d.%d.%d\n",
211 QLCNIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build);
212
213 return adapter->fw_version;
214}
215
216static int __qlcnic_set_win_base(struct qlcnic_adapter *adapter, u32 addr)
217{
218 void __iomem *base;
219 u32 val;
220
221 base = adapter->ahw->pci_base0 +
222 QLC_83XX_CRB_WIN_FUNC(adapter->ahw->pci_func);
223 writel(addr, base);
224 val = readl(base);
225 if (val != addr)
226 return -EIO;
227
228 return 0;
229}
230
231int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
232 int *err)
233{
234 struct qlcnic_hardware_context *ahw = adapter->ahw;
235
236 *err = __qlcnic_set_win_base(adapter, (u32) addr);
237 if (!*err) {
238 return QLCRDX(ahw, QLCNIC_WILDCARD);
239 } else {
240 dev_err(&adapter->pdev->dev,
241 "%s failed, addr = 0x%lx\n", __func__, addr);
242 return -EIO;
243 }
244}
245
246int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
247 u32 data)
248{
249 int err;
250 struct qlcnic_hardware_context *ahw = adapter->ahw;
251
252 err = __qlcnic_set_win_base(adapter, (u32) addr);
253 if (!err) {
254 QLCWRX(ahw, QLCNIC_WILDCARD, data);
255 return 0;
256 } else {
257 dev_err(&adapter->pdev->dev,
258 "%s failed, addr = 0x%x data = 0x%x\n",
259 __func__, (int)addr, data);
260 return err;
261 }
262}
263
264int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
265{
266 int err, i, num_msix;
267 struct qlcnic_hardware_context *ahw = adapter->ahw;
268
269 if (!num_intr)
270 num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;
271 num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
272 num_intr));
273
274 num_msix += 1;
275
276 if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
277 num_msix += adapter->max_drv_tx_rings;
278
279 err = qlcnic_enable_msix(adapter, num_msix);
280 if (err == -ENOMEM)
281 return err;
282 if (adapter->flags & QLCNIC_MSIX_ENABLED)
283 num_msix = adapter->ahw->num_msix;
284 else {
285 if (qlcnic_sriov_vf_check(adapter))
286 return -EINVAL;
287 num_msix = 1;
288 }
289
290 ahw->intr_tbl = vzalloc(num_msix *
291 sizeof(struct qlcnic_intrpt_config));
292 if (!ahw->intr_tbl)
293 return -ENOMEM;
294 if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
295
296 adapter->tgt_status_reg = ahw->pci_base0 + QLC_83XX_INTX_PTR;
297 adapter->tgt_mask_reg = ahw->pci_base0 + QLC_83XX_INTX_MASK;
298 adapter->isr_int_vec = ahw->pci_base0 + QLC_83XX_INTX_TRGR;
299 adapter->msix_entries[0].vector = adapter->pdev->irq;
300 dev_info(&adapter->pdev->dev, "using legacy interrupt\n");
301 }
302
303 for (i = 0; i < num_msix; i++) {
304 if (adapter->flags & QLCNIC_MSIX_ENABLED)
305 ahw->intr_tbl[i].type = QLCNIC_INTRPT_MSIX;
306 else
307 ahw->intr_tbl[i].type = QLCNIC_INTRPT_INTX;
308 ahw->intr_tbl[i].id = i;
309 ahw->intr_tbl[i].src = 0;
310 }
311 return 0;
312}
313
314inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter)
315{
316 writel(0, adapter->tgt_mask_reg);
317}
318
319inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter)
320{
321 writel(1, adapter->tgt_mask_reg);
322}
323
324
325void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter,
326 struct qlcnic_host_sds_ring *sds_ring)
327{
328 writel(0, sds_ring->crb_intr_mask);
329}
330
331
332void qlcnic_83xx_disable_intr(struct qlcnic_adapter *adapter,
333 struct qlcnic_host_sds_ring *sds_ring)
334{
335 writel(1, sds_ring->crb_intr_mask);
336}
337
338inline void qlcnic_83xx_enable_legacy_msix_mbx_intr(struct qlcnic_adapter
339 *adapter)
340{
341 u32 mask;
342
343
344
345
346
347
348 mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
349 writel(0, adapter->ahw->pci_base0 + mask);
350}
351
352void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *adapter)
353{
354 u32 mask;
355
356 mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
357 writel(1, adapter->ahw->pci_base0 + mask);
358 QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, 0);
359}
360
361static inline void qlcnic_83xx_get_mbx_data(struct qlcnic_adapter *adapter,
362 struct qlcnic_cmd_args *cmd)
363{
364 int i;
365 for (i = 0; i < cmd->rsp.num; i++)
366 cmd->rsp.arg[i] = readl(QLCNIC_MBX_FW(adapter->ahw, i));
367}
368
369irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
370{
371 u32 intr_val;
372 struct qlcnic_hardware_context *ahw = adapter->ahw;
373 int retries = 0;
374
375 intr_val = readl(adapter->tgt_status_reg);
376
377 if (!QLC_83XX_VALID_INTX_BIT31(intr_val))
378 return IRQ_NONE;
379
380 if (QLC_83XX_INTX_FUNC(intr_val) != adapter->ahw->pci_func) {
381 adapter->stats.spurious_intr++;
382 return IRQ_NONE;
383 }
384
385 wmb();
386
387
388 writel(0, adapter->isr_int_vec);
389 intr_val = readl(adapter->isr_int_vec);
390 do {
391 intr_val = readl(adapter->tgt_status_reg);
392 if (QLC_83XX_INTX_FUNC(intr_val) != ahw->pci_func)
393 break;
394 retries++;
395 } while (QLC_83XX_VALID_INTX_BIT30(intr_val) &&
396 (retries < QLC_83XX_LEGACY_INTX_MAX_RETRY));
397
398 return IRQ_HANDLED;
399}
400
401static void qlcnic_83xx_poll_process_aen(struct qlcnic_adapter *adapter)
402{
403 u32 resp, event;
404 unsigned long flags;
405
406 spin_lock_irqsave(&adapter->ahw->mbx_lock, flags);
407
408 resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL);
409 if (!(resp & QLCNIC_SET_OWNER))
410 goto out;
411
412 event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
413 if (event & QLCNIC_MBX_ASYNC_EVENT)
414 __qlcnic_83xx_process_aen(adapter);
415
416out:
417 qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
418 spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
419}
420
421irqreturn_t qlcnic_83xx_intr(int irq, void *data)
422{
423 struct qlcnic_adapter *adapter = data;
424 struct qlcnic_host_sds_ring *sds_ring;
425 struct qlcnic_hardware_context *ahw = adapter->ahw;
426
427 if (qlcnic_83xx_clear_legacy_intr(adapter) == IRQ_NONE)
428 return IRQ_NONE;
429
430 qlcnic_83xx_poll_process_aen(adapter);
431
432 if (ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
433 ahw->diag_cnt++;
434 qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
435 return IRQ_HANDLED;
436 }
437
438 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
439 qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
440 } else {
441 sds_ring = &adapter->recv_ctx->sds_rings[0];
442 napi_schedule(&sds_ring->napi);
443 }
444
445 return IRQ_HANDLED;
446}
447
448irqreturn_t qlcnic_83xx_tmp_intr(int irq, void *data)
449{
450 struct qlcnic_host_sds_ring *sds_ring = data;
451 struct qlcnic_adapter *adapter = sds_ring->adapter;
452
453 if (adapter->flags & QLCNIC_MSIX_ENABLED)
454 goto done;
455
456 if (adapter->nic_ops->clear_legacy_intr(adapter) == IRQ_NONE)
457 return IRQ_NONE;
458
459done:
460 adapter->ahw->diag_cnt++;
461 qlcnic_83xx_enable_intr(adapter, sds_ring);
462
463 return IRQ_HANDLED;
464}
465
466void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
467{
468 u32 num_msix;
469
470 if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
471 qlcnic_83xx_set_legacy_intr_mask(adapter);
472
473 qlcnic_83xx_disable_mbx_intr(adapter);
474
475 if (adapter->flags & QLCNIC_MSIX_ENABLED)
476 num_msix = adapter->ahw->num_msix - 1;
477 else
478 num_msix = 0;
479
480 msleep(20);
481 synchronize_irq(adapter->msix_entries[num_msix].vector);
482 free_irq(adapter->msix_entries[num_msix].vector, adapter);
483}
484
485int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
486{
487 irq_handler_t handler;
488 u32 val;
489 int err = 0;
490 unsigned long flags = 0;
491
492 if (!(adapter->flags & QLCNIC_MSI_ENABLED) &&
493 !(adapter->flags & QLCNIC_MSIX_ENABLED))
494 flags |= IRQF_SHARED;
495
496 if (adapter->flags & QLCNIC_MSIX_ENABLED) {
497 handler = qlcnic_83xx_handle_aen;
498 val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector;
499 err = request_irq(val, handler, flags, "qlcnic-MB", adapter);
500 if (err) {
501 dev_err(&adapter->pdev->dev,
502 "failed to register MBX interrupt\n");
503 return err;
504 }
505 } else {
506 handler = qlcnic_83xx_intr;
507 val = adapter->msix_entries[0].vector;
508 err = request_irq(val, handler, flags, "qlcnic", adapter);
509 if (err) {
510 dev_err(&adapter->pdev->dev,
511 "failed to register INTx interrupt\n");
512 return err;
513 }
514 qlcnic_83xx_clear_legacy_intr_mask(adapter);
515 }
516
517
518 qlcnic_83xx_enable_mbx_intrpt(adapter);
519
520 return err;
521}
522
523void qlcnic_83xx_get_func_no(struct qlcnic_adapter *adapter)
524{
525 u32 val = QLCRDX(adapter->ahw, QLCNIC_INFORMANT);
526 adapter->ahw->pci_func = (val >> 24) & 0xff;
527}
528
529int qlcnic_83xx_cam_lock(struct qlcnic_adapter *adapter)
530{
531 void __iomem *addr;
532 u32 val, limit = 0;
533
534 struct qlcnic_hardware_context *ahw = adapter->ahw;
535
536 addr = ahw->pci_base0 + QLC_83XX_SEM_LOCK_FUNC(ahw->pci_func);
537 do {
538 val = readl(addr);
539 if (val) {
540
541 QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER,
542 ahw->pci_func);
543 return 0;
544 }
545 usleep_range(1000, 2000);
546 } while (++limit <= QLCNIC_PCIE_SEM_TIMEOUT);
547
548 return -EIO;
549}
550
551void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *adapter)
552{
553 void __iomem *addr;
554 u32 val;
555 struct qlcnic_hardware_context *ahw = adapter->ahw;
556
557 addr = ahw->pci_base0 + QLC_83XX_SEM_UNLOCK_FUNC(ahw->pci_func);
558 val = readl(addr);
559}
560
561void qlcnic_83xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
562 loff_t offset, size_t size)
563{
564 int ret = 0;
565 u32 data;
566
567 if (qlcnic_api_lock(adapter)) {
568 dev_err(&adapter->pdev->dev,
569 "%s: failed to acquire lock. addr offset 0x%x\n",
570 __func__, (u32)offset);
571 return;
572 }
573
574 data = QLCRD32(adapter, (u32) offset, &ret);
575 qlcnic_api_unlock(adapter);
576
577 if (ret == -EIO) {
578 dev_err(&adapter->pdev->dev,
579 "%s: failed. addr offset 0x%x\n",
580 __func__, (u32)offset);
581 return;
582 }
583 memcpy(buf, &data, size);
584}
585
586void qlcnic_83xx_write_crb(struct qlcnic_adapter *adapter, char *buf,
587 loff_t offset, size_t size)
588{
589 u32 data;
590
591 memcpy(&data, buf, size);
592 qlcnic_83xx_wrt_reg_indirect(adapter, (u32) offset, data);
593}
594
595int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
596{
597 int status;
598
599 status = qlcnic_83xx_get_port_config(adapter);
600 if (status) {
601 dev_err(&adapter->pdev->dev,
602 "Get Port Info failed\n");
603 } else {
604 if (QLC_83XX_SFP_10G_CAPABLE(adapter->ahw->port_config))
605 adapter->ahw->port_type = QLCNIC_XGBE;
606 else
607 adapter->ahw->port_type = QLCNIC_GBE;
608
609 if (QLC_83XX_AUTONEG(adapter->ahw->port_config))
610 adapter->ahw->link_autoneg = AUTONEG_ENABLE;
611 }
612 return status;
613}
614
615void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
616{
617 struct qlcnic_hardware_context *ahw = adapter->ahw;
618 u16 act_pci_fn = ahw->act_pci_func;
619 u16 count;
620
621 ahw->max_mc_count = QLC_83XX_MAX_MC_COUNT;
622 if (act_pci_fn <= 2)
623 count = (QLC_83XX_MAX_UC_COUNT - QLC_83XX_MAX_MC_COUNT) /
624 act_pci_fn;
625 else
626 count = (QLC_83XX_LB_MAX_FILTERS - QLC_83XX_MAX_MC_COUNT) /
627 act_pci_fn;
628 ahw->max_uc_count = count;
629}
630
631void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *adapter)
632{
633 u32 val;
634
635 if (adapter->flags & QLCNIC_MSIX_ENABLED)
636 val = BIT_2 | ((adapter->ahw->num_msix - 1) << 8);
637 else
638 val = BIT_2;
639
640 QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val);
641 qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
642}
643
644void qlcnic_83xx_check_vf(struct qlcnic_adapter *adapter,
645 const struct pci_device_id *ent)
646{
647 u32 op_mode, priv_level;
648 struct qlcnic_hardware_context *ahw = adapter->ahw;
649
650 ahw->fw_hal_version = 2;
651 qlcnic_get_func_no(adapter);
652
653 if (qlcnic_sriov_vf_check(adapter)) {
654 qlcnic_sriov_vf_set_ops(adapter);
655 return;
656 }
657
658
659 op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
660 if (op_mode == QLC_83XX_DEFAULT_OPMODE)
661 priv_level = QLCNIC_MGMT_FUNC;
662 else
663 priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode,
664 ahw->pci_func);
665
666 if (priv_level == QLCNIC_NON_PRIV_FUNC) {
667 ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
668 dev_info(&adapter->pdev->dev,
669 "HAL Version: %d Non Privileged function\n",
670 ahw->fw_hal_version);
671 adapter->nic_ops = &qlcnic_vf_ops;
672 } else {
673 if (pci_find_ext_capability(adapter->pdev,
674 PCI_EXT_CAP_ID_SRIOV))
675 set_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state);
676 adapter->nic_ops = &qlcnic_83xx_ops;
677 }
678}
679
680static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
681 u32 data[]);
682static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter,
683 u32 data[]);
684
685static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
686 struct qlcnic_cmd_args *cmd)
687{
688 int i;
689
690 dev_info(&adapter->pdev->dev,
691 "Host MBX regs(%d)\n", cmd->req.num);
692 for (i = 0; i < cmd->req.num; i++) {
693 if (i && !(i % 8))
694 pr_info("\n");
695 pr_info("%08x ", cmd->req.arg[i]);
696 }
697 pr_info("\n");
698 dev_info(&adapter->pdev->dev,
699 "FW MBX regs(%d)\n", cmd->rsp.num);
700 for (i = 0; i < cmd->rsp.num; i++) {
701 if (i && !(i % 8))
702 pr_info("\n");
703 pr_info("%08x ", cmd->rsp.arg[i]);
704 }
705 pr_info("\n");
706}
707
708
709u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *adapter)
710{
711 u32 fw_data;
712 u8 mac_cmd_rcode;
713
714 fw_data = readl(QLCNIC_MBX_FW(adapter->ahw, 2));
715 mac_cmd_rcode = (u8)fw_data;
716 if (mac_cmd_rcode == QLC_83XX_NO_NIC_RESOURCE ||
717 mac_cmd_rcode == QLC_83XX_MAC_PRESENT ||
718 mac_cmd_rcode == QLC_83XX_MAC_ABSENT)
719 return QLCNIC_RCODE_SUCCESS;
720 return 1;
721}
722
723u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter, u32 *wait_time)
724{
725 u32 data;
726 struct qlcnic_hardware_context *ahw = adapter->ahw;
727
728 do {
729 data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
730 if (++(*wait_time) > QLCNIC_MBX_TIMEOUT) {
731 data = QLCNIC_RCODE_TIMEOUT;
732 break;
733 }
734 mdelay(1);
735 } while (!data);
736 return data;
737}
738
739int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter,
740 struct qlcnic_cmd_args *cmd)
741{
742 int i;
743 u16 opcode;
744 u8 mbx_err_code;
745 unsigned long flags;
746 struct qlcnic_hardware_context *ahw = adapter->ahw;
747 u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, wait_time = 0;
748
749 opcode = LSW(cmd->req.arg[0]);
750 if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) {
751 dev_info(&adapter->pdev->dev,
752 "Mailbox cmd attempted, 0x%x\n", opcode);
753 dev_info(&adapter->pdev->dev, "Mailbox detached\n");
754 return 0;
755 }
756
757 spin_lock_irqsave(&adapter->ahw->mbx_lock, flags);
758 mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
759
760 if (mbx_val) {
761 QLCDB(adapter, DRV,
762 "Mailbox cmd attempted, 0x%x\n", opcode);
763 QLCDB(adapter, DRV,
764 "Mailbox not available, 0x%x, collect FW dump\n",
765 mbx_val);
766 cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
767 spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
768 return cmd->rsp.arg[0];
769 }
770
771
772 mbx_cmd = cmd->req.arg[0];
773 writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
774 for (i = 1; i < cmd->req.num; i++)
775 writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i));
776
777
778 QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
779poll:
780 rsp = qlcnic_83xx_mbx_poll(adapter, &wait_time);
781 if (rsp != QLCNIC_RCODE_TIMEOUT) {
782
783 fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
784 if (fw_data & QLCNIC_MBX_ASYNC_EVENT) {
785 __qlcnic_83xx_process_aen(adapter);
786 goto poll;
787 }
788 mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
789 rsp_num = QLCNIC_MBX_NUM_REGS(fw_data);
790 opcode = QLCNIC_MBX_RSP(fw_data);
791 qlcnic_83xx_get_mbx_data(adapter, cmd);
792
793 switch (mbx_err_code) {
794 case QLCNIC_MBX_RSP_OK:
795 case QLCNIC_MBX_PORT_RSP_OK:
796 rsp = QLCNIC_RCODE_SUCCESS;
797 break;
798 default:
799 if (opcode == QLCNIC_CMD_CONFIG_MAC_VLAN) {
800 rsp = qlcnic_83xx_mac_rcode(adapter);
801 if (!rsp)
802 goto out;
803 }
804 dev_err(&adapter->pdev->dev,
805 "MBX command 0x%x failed with err:0x%x\n",
806 opcode, mbx_err_code);
807 rsp = mbx_err_code;
808 qlcnic_dump_mbx(adapter, cmd);
809 break;
810 }
811 goto out;
812 }
813
814 dev_err(&adapter->pdev->dev, "MBX command 0x%x timed out\n",
815 QLCNIC_MBX_RSP(mbx_cmd));
816 rsp = QLCNIC_RCODE_TIMEOUT;
817out:
818
819 QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
820 spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
821 return rsp;
822}
823
824int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
825 struct qlcnic_adapter *adapter, u32 type)
826{
827 int i, size;
828 u32 temp;
829 const struct qlcnic_mailbox_metadata *mbx_tbl;
830
831 mbx_tbl = qlcnic_83xx_mbx_tbl;
832 size = ARRAY_SIZE(qlcnic_83xx_mbx_tbl);
833 for (i = 0; i < size; i++) {
834 if (type == mbx_tbl[i].cmd) {
835 mbx->op_type = QLC_83XX_FW_MBX_CMD;
836 mbx->req.num = mbx_tbl[i].in_args;
837 mbx->rsp.num = mbx_tbl[i].out_args;
838 mbx->req.arg = kcalloc(mbx->req.num, sizeof(u32),
839 GFP_ATOMIC);
840 if (!mbx->req.arg)
841 return -ENOMEM;
842 mbx->rsp.arg = kcalloc(mbx->rsp.num, sizeof(u32),
843 GFP_ATOMIC);
844 if (!mbx->rsp.arg) {
845 kfree(mbx->req.arg);
846 mbx->req.arg = NULL;
847 return -ENOMEM;
848 }
849 memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num);
850 memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
851 temp = adapter->ahw->fw_hal_version << 29;
852 mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp);
853 return 0;
854 }
855 }
856 return -EINVAL;
857}
858
859void qlcnic_83xx_idc_aen_work(struct work_struct *work)
860{
861 struct qlcnic_adapter *adapter;
862 struct qlcnic_cmd_args cmd;
863 int i, err = 0;
864
865 adapter = container_of(work, struct qlcnic_adapter, idc_aen_work.work);
866 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_IDC_ACK);
867 if (err)
868 return;
869
870 for (i = 1; i < QLC_83XX_MBX_AEN_CNT; i++)
871 cmd.req.arg[i] = adapter->ahw->mbox_aen[i];
872
873 err = qlcnic_issue_cmd(adapter, &cmd);
874 if (err)
875 dev_info(&adapter->pdev->dev,
876 "%s: Mailbox IDC ACK failed.\n", __func__);
877 qlcnic_free_mbx_args(&cmd);
878}
879
880static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter,
881 u32 data[])
882{
883 dev_dbg(&adapter->pdev->dev, "Completion AEN:0x%x.\n",
884 QLCNIC_MBX_RSP(data[0]));
885 clear_bit(QLC_83XX_IDC_COMP_AEN, &adapter->ahw->idc.status);
886 return;
887}
888
889void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
890{
891 u32 event[QLC_83XX_MBX_AEN_CNT];
892 int i;
893 struct qlcnic_hardware_context *ahw = adapter->ahw;
894
895 for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
896 event[i] = readl(QLCNIC_MBX_FW(ahw, i));
897
898 switch (QLCNIC_MBX_RSP(event[0])) {
899
900 case QLCNIC_MBX_LINK_EVENT:
901 qlcnic_83xx_handle_link_aen(adapter, event);
902 break;
903 case QLCNIC_MBX_COMP_EVENT:
904 qlcnic_83xx_handle_idc_comp_aen(adapter, event);
905 break;
906 case QLCNIC_MBX_REQUEST_EVENT:
907 for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
908 adapter->ahw->mbox_aen[i] = QLCNIC_MBX_RSP(event[i]);
909 queue_delayed_work(adapter->qlcnic_wq,
910 &adapter->idc_aen_work, 0);
911 break;
912 case QLCNIC_MBX_TIME_EXTEND_EVENT:
913 break;
914 case QLCNIC_MBX_BC_EVENT:
915 qlcnic_sriov_handle_bc_event(adapter, event[1]);
916 break;
917 case QLCNIC_MBX_SFP_INSERT_EVENT:
918 dev_info(&adapter->pdev->dev, "SFP+ Insert AEN:0x%x.\n",
919 QLCNIC_MBX_RSP(event[0]));
920 break;
921 case QLCNIC_MBX_SFP_REMOVE_EVENT:
922 dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n",
923 QLCNIC_MBX_RSP(event[0]));
924 break;
925 default:
926 dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n",
927 QLCNIC_MBX_RSP(event[0]));
928 break;
929 }
930
931 QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
932}
933
934static void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
935{
936 struct qlcnic_hardware_context *ahw = adapter->ahw;
937 u32 resp, event;
938 unsigned long flags;
939
940 spin_lock_irqsave(&ahw->mbx_lock, flags);
941
942 resp = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
943 if (resp & QLCNIC_SET_OWNER) {
944 event = readl(QLCNIC_MBX_FW(ahw, 0));
945 if (event & QLCNIC_MBX_ASYNC_EVENT)
946 __qlcnic_83xx_process_aen(adapter);
947 }
948
949 spin_unlock_irqrestore(&ahw->mbx_lock, flags);
950}
951
952static void qlcnic_83xx_mbx_poll_work(struct work_struct *work)
953{
954 struct qlcnic_adapter *adapter;
955
956 adapter = container_of(work, struct qlcnic_adapter, mbx_poll_work.work);
957
958 if (!test_bit(__QLCNIC_MBX_POLL_ENABLE, &adapter->state))
959 return;
960
961 qlcnic_83xx_process_aen(adapter);
962 queue_delayed_work(adapter->qlcnic_wq, &adapter->mbx_poll_work,
963 (HZ / 10));
964}
965
966void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *adapter)
967{
968 if (test_and_set_bit(__QLCNIC_MBX_POLL_ENABLE, &adapter->state))
969 return;
970
971 INIT_DELAYED_WORK(&adapter->mbx_poll_work, qlcnic_83xx_mbx_poll_work);
972}
973
974void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *adapter)
975{
976 if (!test_and_clear_bit(__QLCNIC_MBX_POLL_ENABLE, &adapter->state))
977 return;
978 cancel_delayed_work_sync(&adapter->mbx_poll_work);
979}
980
981static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter)
982{
983 int index, i, err, sds_mbx_size;
984 u32 *buf, intrpt_id, intr_mask;
985 u16 context_id;
986 u8 num_sds;
987 struct qlcnic_cmd_args cmd;
988 struct qlcnic_host_sds_ring *sds;
989 struct qlcnic_sds_mbx sds_mbx;
990 struct qlcnic_add_rings_mbx_out *mbx_out;
991 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
992 struct qlcnic_hardware_context *ahw = adapter->ahw;
993
994 sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
995 context_id = recv_ctx->context_id;
996 num_sds = (adapter->max_sds_rings - QLCNIC_MAX_RING_SETS);
997 ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
998 QLCNIC_CMD_ADD_RCV_RINGS);
999 cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16);
1000
1001
1002 index = 2;
1003 for (i = 8; i < adapter->max_sds_rings; i++) {
1004 memset(&sds_mbx, 0, sds_mbx_size);
1005 sds = &recv_ctx->sds_rings[i];
1006 sds->consumer = 0;
1007 memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
1008 sds_mbx.phy_addr_low = LSD(sds->phys_addr);
1009 sds_mbx.phy_addr_high = MSD(sds->phys_addr);
1010 sds_mbx.sds_ring_size = sds->num_desc;
1011
1012 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1013 intrpt_id = ahw->intr_tbl[i].id;
1014 else
1015 intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
1016
1017 if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
1018 sds_mbx.intrpt_id = intrpt_id;
1019 else
1020 sds_mbx.intrpt_id = 0xffff;
1021 sds_mbx.intrpt_val = 0;
1022 buf = &cmd.req.arg[index];
1023 memcpy(buf, &sds_mbx, sds_mbx_size);
1024 index += sds_mbx_size / sizeof(u32);
1025 }
1026
1027
1028 err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
1029 if (err) {
1030 dev_err(&adapter->pdev->dev,
1031 "Failed to add rings %d\n", err);
1032 goto out;
1033 }
1034
1035 mbx_out = (struct qlcnic_add_rings_mbx_out *)&cmd.rsp.arg[1];
1036 index = 0;
1037
1038 for (i = 8; i < adapter->max_sds_rings; i++) {
1039 sds = &recv_ctx->sds_rings[i];
1040 sds->crb_sts_consumer = ahw->pci_base0 +
1041 mbx_out->host_csmr[index];
1042 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1043 intr_mask = ahw->intr_tbl[i].src;
1044 else
1045 intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
1046
1047 sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
1048 index++;
1049 }
1050out:
1051 qlcnic_free_mbx_args(&cmd);
1052 return err;
1053}
1054
1055void qlcnic_83xx_del_rx_ctx(struct qlcnic_adapter *adapter)
1056{
1057 int err;
1058 u32 temp = 0;
1059 struct qlcnic_cmd_args cmd;
1060 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1061
1062 if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX))
1063 return;
1064
1065 if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
1066 cmd.req.arg[0] |= (0x3 << 29);
1067
1068 if (qlcnic_sriov_pf_check(adapter))
1069 qlcnic_pf_set_interface_id_del_rx_ctx(adapter, &temp);
1070
1071 cmd.req.arg[1] = recv_ctx->context_id | temp;
1072 err = qlcnic_issue_cmd(adapter, &cmd);
1073 if (err)
1074 dev_err(&adapter->pdev->dev,
1075 "Failed to destroy rx ctx in firmware\n");
1076
1077 recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED;
1078 qlcnic_free_mbx_args(&cmd);
1079}
1080
1081int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
1082{
1083 int i, err, index, sds_mbx_size, rds_mbx_size;
1084 u8 num_sds, num_rds;
1085 u32 *buf, intrpt_id, intr_mask, cap = 0;
1086 struct qlcnic_host_sds_ring *sds;
1087 struct qlcnic_host_rds_ring *rds;
1088 struct qlcnic_sds_mbx sds_mbx;
1089 struct qlcnic_rds_mbx rds_mbx;
1090 struct qlcnic_cmd_args cmd;
1091 struct qlcnic_rcv_mbx_out *mbx_out;
1092 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1093 struct qlcnic_hardware_context *ahw = adapter->ahw;
1094 num_rds = adapter->max_rds_rings;
1095
1096 if (adapter->max_sds_rings <= QLCNIC_MAX_RING_SETS)
1097 num_sds = adapter->max_sds_rings;
1098 else
1099 num_sds = QLCNIC_MAX_RING_SETS;
1100
1101 sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
1102 rds_mbx_size = sizeof(struct qlcnic_rds_mbx);
1103 cap = QLCNIC_CAP0_LEGACY_CONTEXT;
1104
1105 if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
1106 cap |= QLC_83XX_FW_CAP_LRO_MSS;
1107
1108
1109 err = qlcnic_alloc_mbx_args(&cmd, adapter,
1110 QLCNIC_CMD_CREATE_RX_CTX);
1111 if (err)
1112 return err;
1113
1114 if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
1115 cmd.req.arg[0] |= (0x3 << 29);
1116
1117 cmd.req.arg[1] = cap;
1118 cmd.req.arg[5] = 1 | (num_rds << 5) | (num_sds << 8) |
1119 (QLC_83XX_HOST_RDS_MODE_UNIQUE << 16);
1120
1121 if (qlcnic_sriov_pf_check(adapter))
1122 qlcnic_pf_set_interface_id_create_rx_ctx(adapter,
1123 &cmd.req.arg[6]);
1124
1125 index = QLC_83XX_HOST_SDS_MBX_IDX;
1126 for (i = 0; i < num_sds; i++) {
1127 memset(&sds_mbx, 0, sds_mbx_size);
1128 sds = &recv_ctx->sds_rings[i];
1129 sds->consumer = 0;
1130 memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
1131 sds_mbx.phy_addr_low = LSD(sds->phys_addr);
1132 sds_mbx.phy_addr_high = MSD(sds->phys_addr);
1133 sds_mbx.sds_ring_size = sds->num_desc;
1134 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1135 intrpt_id = ahw->intr_tbl[i].id;
1136 else
1137 intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
1138 if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
1139 sds_mbx.intrpt_id = intrpt_id;
1140 else
1141 sds_mbx.intrpt_id = 0xffff;
1142 sds_mbx.intrpt_val = 0;
1143 buf = &cmd.req.arg[index];
1144 memcpy(buf, &sds_mbx, sds_mbx_size);
1145 index += sds_mbx_size / sizeof(u32);
1146 }
1147
1148 index = QLCNIC_HOST_RDS_MBX_IDX;
1149 rds = &recv_ctx->rds_rings[0];
1150 rds->producer = 0;
1151 memset(&rds_mbx, 0, rds_mbx_size);
1152 rds_mbx.phy_addr_reg_low = LSD(rds->phys_addr);
1153 rds_mbx.phy_addr_reg_high = MSD(rds->phys_addr);
1154 rds_mbx.reg_ring_sz = rds->dma_size;
1155 rds_mbx.reg_ring_len = rds->num_desc;
1156
1157 rds = &recv_ctx->rds_rings[1];
1158 rds->producer = 0;
1159 rds_mbx.phy_addr_jmb_low = LSD(rds->phys_addr);
1160 rds_mbx.phy_addr_jmb_high = MSD(rds->phys_addr);
1161 rds_mbx.jmb_ring_sz = rds->dma_size;
1162 rds_mbx.jmb_ring_len = rds->num_desc;
1163 buf = &cmd.req.arg[index];
1164 memcpy(buf, &rds_mbx, rds_mbx_size);
1165
1166
1167 err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
1168 if (err) {
1169 dev_err(&adapter->pdev->dev,
1170 "Failed to create Rx ctx in firmware%d\n", err);
1171 goto out;
1172 }
1173 mbx_out = (struct qlcnic_rcv_mbx_out *)&cmd.rsp.arg[1];
1174 recv_ctx->context_id = mbx_out->ctx_id;
1175 recv_ctx->state = mbx_out->state;
1176 recv_ctx->virt_port = mbx_out->vport_id;
1177 dev_info(&adapter->pdev->dev, "Rx Context[%d] Created, state:0x%x\n",
1178 recv_ctx->context_id, recv_ctx->state);
1179
1180
1181 rds = &recv_ctx->rds_rings[0];
1182 rds->crb_rcv_producer = ahw->pci_base0 +
1183 mbx_out->host_prod[0].reg_buf;
1184
1185 rds = &recv_ctx->rds_rings[1];
1186 rds->crb_rcv_producer = ahw->pci_base0 +
1187 mbx_out->host_prod[0].jmb_buf;
1188
1189 for (i = 0; i < num_sds; i++) {
1190 sds = &recv_ctx->sds_rings[i];
1191 sds->crb_sts_consumer = ahw->pci_base0 +
1192 mbx_out->host_csmr[i];
1193 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1194 intr_mask = ahw->intr_tbl[i].src;
1195 else
1196 intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
1197 sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
1198 }
1199
1200 if (adapter->max_sds_rings > QLCNIC_MAX_RING_SETS)
1201 err = qlcnic_83xx_add_rings(adapter);
1202out:
1203 qlcnic_free_mbx_args(&cmd);
1204 return err;
1205}
1206
1207void qlcnic_83xx_del_tx_ctx(struct qlcnic_adapter *adapter,
1208 struct qlcnic_host_tx_ring *tx_ring)
1209{
1210 struct qlcnic_cmd_args cmd;
1211 u32 temp = 0;
1212
1213 if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX))
1214 return;
1215
1216 if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
1217 cmd.req.arg[0] |= (0x3 << 29);
1218
1219 if (qlcnic_sriov_pf_check(adapter))
1220 qlcnic_pf_set_interface_id_del_tx_ctx(adapter, &temp);
1221
1222 cmd.req.arg[1] = tx_ring->ctx_id | temp;
1223 if (qlcnic_issue_cmd(adapter, &cmd))
1224 dev_err(&adapter->pdev->dev,
1225 "Failed to destroy tx ctx in firmware\n");
1226 qlcnic_free_mbx_args(&cmd);
1227}
1228
1229int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
1230 struct qlcnic_host_tx_ring *tx, int ring)
1231{
1232 int err;
1233 u16 msix_id;
1234 u32 *buf, intr_mask, temp = 0;
1235 struct qlcnic_cmd_args cmd;
1236 struct qlcnic_tx_mbx mbx;
1237 struct qlcnic_tx_mbx_out *mbx_out;
1238 struct qlcnic_hardware_context *ahw = adapter->ahw;
1239 u32 msix_vector;
1240
1241
1242 tx->producer = 0;
1243 tx->sw_consumer = 0;
1244 *(tx->hw_consumer) = 0;
1245
1246 memset(&mbx, 0, sizeof(struct qlcnic_tx_mbx));
1247
1248
1249 mbx.phys_addr_low = LSD(tx->phys_addr);
1250 mbx.phys_addr_high = MSD(tx->phys_addr);
1251 mbx.cnsmr_index_low = LSD(tx->hw_cons_phys_addr);
1252 mbx.cnsmr_index_high = MSD(tx->hw_cons_phys_addr);
1253 mbx.size = tx->num_desc;
1254 if (adapter->flags & QLCNIC_MSIX_ENABLED) {
1255 if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
1256 msix_vector = adapter->max_sds_rings + ring;
1257 else
1258 msix_vector = adapter->max_sds_rings - 1;
1259 msix_id = ahw->intr_tbl[msix_vector].id;
1260 } else {
1261 msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
1262 }
1263
1264 if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
1265 mbx.intr_id = msix_id;
1266 else
1267 mbx.intr_id = 0xffff;
1268 mbx.src = 0;
1269
1270 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
1271 if (err)
1272 return err;
1273
1274 if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
1275 cmd.req.arg[0] |= (0x3 << 29);
1276
1277 if (qlcnic_sriov_pf_check(adapter))
1278 qlcnic_pf_set_interface_id_create_tx_ctx(adapter, &temp);
1279
1280 cmd.req.arg[1] = QLCNIC_CAP0_LEGACY_CONTEXT;
1281 cmd.req.arg[5] = QLCNIC_MAX_TX_QUEUES | temp;
1282 buf = &cmd.req.arg[6];
1283 memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx));
1284
1285 err = qlcnic_issue_cmd(adapter, &cmd);
1286 if (err) {
1287 dev_err(&adapter->pdev->dev,
1288 "Failed to create Tx ctx in firmware 0x%x\n", err);
1289 goto out;
1290 }
1291 mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2];
1292 tx->crb_cmd_producer = ahw->pci_base0 + mbx_out->host_prod;
1293 tx->ctx_id = mbx_out->ctx_id;
1294 if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
1295 !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
1296 intr_mask = ahw->intr_tbl[adapter->max_sds_rings + ring].src;
1297 tx->crb_intr_mask = ahw->pci_base0 + intr_mask;
1298 }
1299 dev_info(&adapter->pdev->dev, "Tx Context[0x%x] Created, state:0x%x\n",
1300 tx->ctx_id, mbx_out->state);
1301out:
1302 qlcnic_free_mbx_args(&cmd);
1303 return err;
1304}
1305
1306static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
1307 int num_sds_ring)
1308{
1309 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1310 struct qlcnic_host_sds_ring *sds_ring;
1311 struct qlcnic_host_rds_ring *rds_ring;
1312 u16 adapter_state = adapter->is_up;
1313 u8 ring;
1314 int ret;
1315
1316 netif_device_detach(netdev);
1317
1318 if (netif_running(netdev))
1319 __qlcnic_down(adapter, netdev);
1320
1321 qlcnic_detach(adapter);
1322
1323 adapter->max_sds_rings = 1;
1324 adapter->ahw->diag_test = test;
1325 adapter->ahw->linkup = 0;
1326
1327 ret = qlcnic_attach(adapter);
1328 if (ret) {
1329 netif_device_attach(netdev);
1330 return ret;
1331 }
1332
1333 ret = qlcnic_fw_create_ctx(adapter);
1334 if (ret) {
1335 qlcnic_detach(adapter);
1336 if (adapter_state == QLCNIC_ADAPTER_UP_MAGIC) {
1337 adapter->max_sds_rings = num_sds_ring;
1338 qlcnic_attach(adapter);
1339 }
1340 netif_device_attach(netdev);
1341 return ret;
1342 }
1343
1344 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
1345 rds_ring = &adapter->recv_ctx->rds_rings[ring];
1346 qlcnic_post_rx_buffers(adapter, rds_ring, ring);
1347 }
1348
1349 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
1350 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
1351 sds_ring = &adapter->recv_ctx->sds_rings[ring];
1352 qlcnic_83xx_enable_intr(adapter, sds_ring);
1353 }
1354 }
1355
1356 if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
1357
1358 if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
1359 qlcnic_83xx_free_mbx_intr(adapter);
1360 adapter->ahw->loopback_state = 0;
1361 adapter->ahw->hw_ops->setup_link_event(adapter, 1);
1362 }
1363
1364 set_bit(__QLCNIC_DEV_UP, &adapter->state);
1365 return 0;
1366}
1367
1368static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
1369 int max_sds_rings)
1370{
1371 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1372 struct qlcnic_host_sds_ring *sds_ring;
1373 int ring, err;
1374
1375 clear_bit(__QLCNIC_DEV_UP, &adapter->state);
1376 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
1377 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
1378 sds_ring = &adapter->recv_ctx->sds_rings[ring];
1379 qlcnic_83xx_disable_intr(adapter, sds_ring);
1380 }
1381 }
1382
1383 qlcnic_fw_destroy_ctx(adapter);
1384 qlcnic_detach(adapter);
1385
1386 if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
1387 if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
1388 err = qlcnic_83xx_setup_mbx_intr(adapter);
1389 if (err) {
1390 dev_err(&adapter->pdev->dev,
1391 "%s: failed to setup mbx interrupt\n",
1392 __func__);
1393 goto out;
1394 }
1395 }
1396 }
1397 adapter->ahw->diag_test = 0;
1398 adapter->max_sds_rings = max_sds_rings;
1399
1400 if (qlcnic_attach(adapter))
1401 goto out;
1402
1403 if (netif_running(netdev))
1404 __qlcnic_up(adapter, netdev);
1405out:
1406 netif_device_attach(netdev);
1407}
1408
1409int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state,
1410 u32 beacon)
1411{
1412 struct qlcnic_cmd_args cmd;
1413 u32 mbx_in;
1414 int i, status = 0;
1415
1416 if (state) {
1417
1418 status = qlcnic_alloc_mbx_args(&cmd, adapter,
1419 QLCNIC_CMD_GET_LED_CONFIG);
1420 if (status)
1421 return status;
1422
1423 status = qlcnic_issue_cmd(adapter, &cmd);
1424 if (status) {
1425 dev_err(&adapter->pdev->dev,
1426 "Get led config failed.\n");
1427 goto mbx_err;
1428 } else {
1429 for (i = 0; i < 4; i++)
1430 adapter->ahw->mbox_reg[i] = cmd.rsp.arg[i+1];
1431 }
1432 qlcnic_free_mbx_args(&cmd);
1433
1434 mbx_in = (LSW(QLC_83XX_LED_CONFIG) << 16) |
1435 LSW(QLC_83XX_LED_CONFIG);
1436 status = qlcnic_alloc_mbx_args(&cmd, adapter,
1437 QLCNIC_CMD_SET_LED_CONFIG);
1438 if (status)
1439 return status;
1440
1441 cmd.req.arg[1] = mbx_in;
1442 cmd.req.arg[2] = mbx_in;
1443 cmd.req.arg[3] = mbx_in;
1444 if (beacon)
1445 cmd.req.arg[4] = QLC_83XX_ENABLE_BEACON;
1446 status = qlcnic_issue_cmd(adapter, &cmd);
1447 if (status) {
1448 dev_err(&adapter->pdev->dev,
1449 "Set led config failed.\n");
1450 }
1451mbx_err:
1452 qlcnic_free_mbx_args(&cmd);
1453 return status;
1454
1455 } else {
1456
1457 status = qlcnic_alloc_mbx_args(&cmd, adapter,
1458 QLCNIC_CMD_SET_LED_CONFIG);
1459 if (status)
1460 return status;
1461
1462 cmd.req.arg[1] = adapter->ahw->mbox_reg[0];
1463 cmd.req.arg[2] = adapter->ahw->mbox_reg[1];
1464 cmd.req.arg[3] = adapter->ahw->mbox_reg[2];
1465 if (beacon)
1466 cmd.req.arg[4] = adapter->ahw->mbox_reg[3];
1467 status = qlcnic_issue_cmd(adapter, &cmd);
1468 if (status)
1469 dev_err(&adapter->pdev->dev,
1470 "Restoring led config failed.\n");
1471 qlcnic_free_mbx_args(&cmd);
1472 return status;
1473 }
1474}
1475
1476int qlcnic_83xx_set_led(struct net_device *netdev,
1477 enum ethtool_phys_id_state state)
1478{
1479 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1480 int err = -EIO, active = 1;
1481
1482 if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
1483 netdev_warn(netdev,
1484 "LED test is not supported in non-privileged mode\n");
1485 return -EOPNOTSUPP;
1486 }
1487
1488 switch (state) {
1489 case ETHTOOL_ID_ACTIVE:
1490 if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
1491 return -EBUSY;
1492
1493 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
1494 break;
1495
1496 err = qlcnic_83xx_config_led(adapter, active, 0);
1497 if (err)
1498 netdev_err(netdev, "Failed to set LED blink state\n");
1499 break;
1500 case ETHTOOL_ID_INACTIVE:
1501 active = 0;
1502
1503 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
1504 break;
1505
1506 err = qlcnic_83xx_config_led(adapter, active, 0);
1507 if (err)
1508 netdev_err(netdev, "Failed to reset LED blink state\n");
1509 break;
1510
1511 default:
1512 return -EINVAL;
1513 }
1514
1515 if (!active || err)
1516 clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
1517
1518 return err;
1519}
1520
1521void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter,
1522 int enable)
1523{
1524 struct qlcnic_cmd_args cmd;
1525 int status;
1526
1527 if (qlcnic_sriov_vf_check(adapter))
1528 return;
1529
1530 if (enable) {
1531 status = qlcnic_alloc_mbx_args(&cmd, adapter,
1532 QLCNIC_CMD_INIT_NIC_FUNC);
1533 if (status)
1534 return;
1535
1536 cmd.req.arg[1] = BIT_0 | BIT_31;
1537 } else {
1538 status = qlcnic_alloc_mbx_args(&cmd, adapter,
1539 QLCNIC_CMD_STOP_NIC_FUNC);
1540 if (status)
1541 return;
1542
1543 cmd.req.arg[1] = BIT_0 | BIT_31;
1544 }
1545 status = qlcnic_issue_cmd(adapter, &cmd);
1546 if (status)
1547 dev_err(&adapter->pdev->dev,
1548 "Failed to %s in NIC IDC function event.\n",
1549 (enable ? "register" : "unregister"));
1550
1551 qlcnic_free_mbx_args(&cmd);
1552}
1553
1554int qlcnic_83xx_set_port_config(struct qlcnic_adapter *adapter)
1555{
1556 struct qlcnic_cmd_args cmd;
1557 int err;
1558
1559 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORT_CONFIG);
1560 if (err)
1561 return err;
1562
1563 cmd.req.arg[1] = adapter->ahw->port_config;
1564 err = qlcnic_issue_cmd(adapter, &cmd);
1565 if (err)
1566 dev_info(&adapter->pdev->dev, "Set Port Config failed.\n");
1567 qlcnic_free_mbx_args(&cmd);
1568 return err;
1569}
1570
1571int qlcnic_83xx_get_port_config(struct qlcnic_adapter *adapter)
1572{
1573 struct qlcnic_cmd_args cmd;
1574 int err;
1575
1576 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PORT_CONFIG);
1577 if (err)
1578 return err;
1579
1580 err = qlcnic_issue_cmd(adapter, &cmd);
1581 if (err)
1582 dev_info(&adapter->pdev->dev, "Get Port config failed\n");
1583 else
1584 adapter->ahw->port_config = cmd.rsp.arg[1];
1585 qlcnic_free_mbx_args(&cmd);
1586 return err;
1587}
1588
1589int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *adapter, int enable)
1590{
1591 int err;
1592 u32 temp;
1593 struct qlcnic_cmd_args cmd;
1594
1595 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_EVENT);
1596 if (err)
1597 return err;
1598
1599 temp = adapter->recv_ctx->context_id << 16;
1600 cmd.req.arg[1] = (enable ? 1 : 0) | BIT_8 | temp;
1601 err = qlcnic_issue_cmd(adapter, &cmd);
1602 if (err)
1603 dev_info(&adapter->pdev->dev,
1604 "Setup linkevent mailbox failed\n");
1605 qlcnic_free_mbx_args(&cmd);
1606 return err;
1607}
1608
1609static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter,
1610 u32 *interface_id)
1611{
1612 if (qlcnic_sriov_pf_check(adapter)) {
1613 qlcnic_pf_set_interface_id_promisc(adapter, interface_id);
1614 } else {
1615 if (!qlcnic_sriov_vf_check(adapter))
1616 *interface_id = adapter->recv_ctx->context_id << 16;
1617 }
1618}
1619
1620int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
1621{
1622 int err;
1623 u32 temp = 0;
1624 struct qlcnic_cmd_args cmd;
1625
1626 if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
1627 return -EIO;
1628
1629 err = qlcnic_alloc_mbx_args(&cmd, adapter,
1630 QLCNIC_CMD_CONFIGURE_MAC_RX_MODE);
1631 if (err)
1632 return err;
1633
1634 qlcnic_83xx_set_interface_id_promisc(adapter, &temp);
1635 cmd.req.arg[1] = (mode ? 1 : 0) | temp;
1636 err = qlcnic_issue_cmd(adapter, &cmd);
1637 if (err)
1638 dev_info(&adapter->pdev->dev,
1639 "Promiscous mode config failed\n");
1640
1641 qlcnic_free_mbx_args(&cmd);
1642 return err;
1643}
1644
1645int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
1646{
1647 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1648 struct qlcnic_hardware_context *ahw = adapter->ahw;
1649 int ret = 0, loop = 0, max_sds_rings = adapter->max_sds_rings;
1650
1651 if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
1652 netdev_warn(netdev,
1653 "Loopback test not supported in non privileged mode\n");
1654 return ret;
1655 }
1656
1657 if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
1658 netdev_info(netdev, "Device is resetting\n");
1659 return -EBUSY;
1660 }
1661
1662 if (qlcnic_get_diag_lock(adapter)) {
1663 netdev_info(netdev, "Device is in diagnostics mode\n");
1664 return -EBUSY;
1665 }
1666
1667 netdev_info(netdev, "%s loopback test in progress\n",
1668 mode == QLCNIC_ILB_MODE ? "internal" : "external");
1669
1670 ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST,
1671 max_sds_rings);
1672 if (ret)
1673 goto fail_diag_alloc;
1674
1675 ret = qlcnic_83xx_set_lb_mode(adapter, mode);
1676 if (ret)
1677 goto free_diag_res;
1678
1679
1680 do {
1681 msleep(QLC_83XX_LB_MSLEEP_COUNT);
1682 if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
1683 qlcnic_83xx_process_aen(adapter);
1684
1685 if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
1686 netdev_info(netdev,
1687 "Device is resetting, free LB test resources\n");
1688 ret = -EIO;
1689 goto free_diag_res;
1690 }
1691 if (loop++ > QLC_83XX_LB_WAIT_COUNT) {
1692 netdev_info(netdev,
1693 "Firmware didn't sent link up event to loopback request\n");
1694 ret = -QLCNIC_FW_NOT_RESPOND;
1695 qlcnic_83xx_clear_lb_mode(adapter, mode);
1696 goto free_diag_res;
1697 }
1698 } while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
1699
1700
1701 if (netif_running(netdev)) {
1702 netif_carrier_off(netdev);
1703 netif_stop_queue(netdev);
1704 }
1705
1706 ret = qlcnic_do_lb_test(adapter, mode);
1707
1708 qlcnic_83xx_clear_lb_mode(adapter, mode);
1709
1710free_diag_res:
1711 qlcnic_83xx_diag_free_res(netdev, max_sds_rings);
1712
1713fail_diag_alloc:
1714 adapter->max_sds_rings = max_sds_rings;
1715 qlcnic_release_diag_lock(adapter);
1716 return ret;
1717}
1718
1719int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
1720{
1721 struct qlcnic_hardware_context *ahw = adapter->ahw;
1722 struct net_device *netdev = adapter->netdev;
1723 int status = 0, loop = 0;
1724 u32 config;
1725
1726 status = qlcnic_83xx_get_port_config(adapter);
1727 if (status)
1728 return status;
1729
1730 config = ahw->port_config;
1731 set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
1732
1733 if (mode == QLCNIC_ILB_MODE)
1734 ahw->port_config |= QLC_83XX_CFG_LOOPBACK_HSS;
1735 if (mode == QLCNIC_ELB_MODE)
1736 ahw->port_config |= QLC_83XX_CFG_LOOPBACK_EXT;
1737
1738 status = qlcnic_83xx_set_port_config(adapter);
1739 if (status) {
1740 netdev_err(netdev,
1741 "Failed to Set Loopback Mode = 0x%x.\n",
1742 ahw->port_config);
1743 ahw->port_config = config;
1744 clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
1745 return status;
1746 }
1747
1748
1749 do {
1750 msleep(QLC_83XX_LB_MSLEEP_COUNT);
1751 if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
1752 qlcnic_83xx_process_aen(adapter);
1753
1754 if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
1755 netdev_info(netdev,
1756 "Device is resetting, free LB test resources\n");
1757 clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
1758 return -EIO;
1759 }
1760 if (loop++ > QLC_83XX_LB_WAIT_COUNT) {
1761 netdev_err(netdev,
1762 "Did not receive IDC completion AEN\n");
1763 clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
1764 qlcnic_83xx_clear_lb_mode(adapter, mode);
1765 return -EIO;
1766 }
1767 } while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status));
1768
1769 qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0,
1770 QLCNIC_MAC_ADD);
1771 return status;
1772}
1773
1774int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
1775{
1776 struct qlcnic_hardware_context *ahw = adapter->ahw;
1777 struct net_device *netdev = adapter->netdev;
1778 int status = 0, loop = 0;
1779 u32 config = ahw->port_config;
1780
1781 set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
1782 if (mode == QLCNIC_ILB_MODE)
1783 ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_HSS;
1784 if (mode == QLCNIC_ELB_MODE)
1785 ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_EXT;
1786
1787 status = qlcnic_83xx_set_port_config(adapter);
1788 if (status) {
1789 netdev_err(netdev,
1790 "Failed to Clear Loopback Mode = 0x%x.\n",
1791 ahw->port_config);
1792 ahw->port_config = config;
1793 clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
1794 return status;
1795 }
1796
1797
1798 do {
1799 msleep(QLC_83XX_LB_MSLEEP_COUNT);
1800 if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
1801 qlcnic_83xx_process_aen(adapter);
1802
1803 if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
1804 netdev_info(netdev,
1805 "Device is resetting, free LB test resources\n");
1806 clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
1807 return -EIO;
1808 }
1809
1810 if (loop++ > QLC_83XX_LB_WAIT_COUNT) {
1811 netdev_err(netdev,
1812 "Did not receive IDC completion AEN\n");
1813 clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
1814 return -EIO;
1815 }
1816 } while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status));
1817
1818 qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0,
1819 QLCNIC_MAC_DEL);
1820 return status;
1821}
1822
1823static void qlcnic_83xx_set_interface_id_ipaddr(struct qlcnic_adapter *adapter,
1824 u32 *interface_id)
1825{
1826 if (qlcnic_sriov_pf_check(adapter)) {
1827 qlcnic_pf_set_interface_id_ipaddr(adapter, interface_id);
1828 } else {
1829 if (!qlcnic_sriov_vf_check(adapter))
1830 *interface_id = adapter->recv_ctx->context_id << 16;
1831 }
1832}
1833
1834void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip,
1835 int mode)
1836{
1837 int err;
1838 u32 temp = 0, temp_ip;
1839 struct qlcnic_cmd_args cmd;
1840
1841 err = qlcnic_alloc_mbx_args(&cmd, adapter,
1842 QLCNIC_CMD_CONFIGURE_IP_ADDR);
1843 if (err)
1844 return;
1845
1846 qlcnic_83xx_set_interface_id_ipaddr(adapter, &temp);
1847
1848 if (mode == QLCNIC_IP_UP)
1849 cmd.req.arg[1] = 1 | temp;
1850 else
1851 cmd.req.arg[1] = 2 | temp;
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861 temp_ip = swab32(ntohl(ip));
1862 memcpy(&cmd.req.arg[2], &temp_ip, sizeof(u32));
1863 err = qlcnic_issue_cmd(adapter, &cmd);
1864 if (err != QLCNIC_RCODE_SUCCESS)
1865 dev_err(&adapter->netdev->dev,
1866 "could not notify %s IP 0x%x request\n",
1867 (mode == QLCNIC_IP_UP) ? "Add" : "Remove", ip);
1868
1869 qlcnic_free_mbx_args(&cmd);
1870}
1871
1872int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *adapter, int mode)
1873{
1874 int err;
1875 u32 temp, arg1;
1876 struct qlcnic_cmd_args cmd;
1877 int lro_bit_mask;
1878
1879 lro_bit_mask = (mode ? (BIT_0 | BIT_1 | BIT_2 | BIT_3) : 0);
1880
1881 if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
1882 return 0;
1883
1884 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_HW_LRO);
1885 if (err)
1886 return err;
1887
1888 temp = adapter->recv_ctx->context_id << 16;
1889 arg1 = lro_bit_mask | temp;
1890 cmd.req.arg[1] = arg1;
1891
1892 err = qlcnic_issue_cmd(adapter, &cmd);
1893 if (err)
1894 dev_info(&adapter->pdev->dev, "LRO config failed\n");
1895 qlcnic_free_mbx_args(&cmd);
1896
1897 return err;
1898}
1899
1900int qlcnic_83xx_config_rss(struct qlcnic_adapter *adapter, int enable)
1901{
1902 int err;
1903 u32 word;
1904 struct qlcnic_cmd_args cmd;
1905 const u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
1906 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
1907 0x255b0ec26d5a56daULL };
1908
1909 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_RSS);
1910 if (err)
1911 return err;
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921 word = ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) |
1922 ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) |
1923 ((u32)(enable & 0x1) << 8) |
1924 ((0x7ULL) << 16);
1925 cmd.req.arg[1] = (adapter->recv_ctx->context_id);
1926 cmd.req.arg[2] = word;
1927 memcpy(&cmd.req.arg[4], key, sizeof(key));
1928
1929 err = qlcnic_issue_cmd(adapter, &cmd);
1930
1931 if (err)
1932 dev_info(&adapter->pdev->dev, "RSS config failed\n");
1933 qlcnic_free_mbx_args(&cmd);
1934
1935 return err;
1936
1937}
1938
1939static void qlcnic_83xx_set_interface_id_macaddr(struct qlcnic_adapter *adapter,
1940 u32 *interface_id)
1941{
1942 if (qlcnic_sriov_pf_check(adapter)) {
1943 qlcnic_pf_set_interface_id_macaddr(adapter, interface_id);
1944 } else {
1945 if (!qlcnic_sriov_vf_check(adapter))
1946 *interface_id = adapter->recv_ctx->context_id << 16;
1947 }
1948}
1949
1950int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
1951 u16 vlan_id, u8 op)
1952{
1953 int err;
1954 u32 *buf, temp = 0;
1955 struct qlcnic_cmd_args cmd;
1956 struct qlcnic_macvlan_mbx mv;
1957
1958 if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
1959 return -EIO;
1960
1961 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
1962 if (err)
1963 return err;
1964
1965 if (vlan_id)
1966 op = (op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
1967 QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL;
1968
1969 cmd.req.arg[1] = op | (1 << 8);
1970 qlcnic_83xx_set_interface_id_macaddr(adapter, &temp);
1971 cmd.req.arg[1] |= temp;
1972 mv.vlan = vlan_id;
1973 mv.mac_addr0 = addr[0];
1974 mv.mac_addr1 = addr[1];
1975 mv.mac_addr2 = addr[2];
1976 mv.mac_addr3 = addr[3];
1977 mv.mac_addr4 = addr[4];
1978 mv.mac_addr5 = addr[5];
1979 buf = &cmd.req.arg[2];
1980 memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
1981 err = qlcnic_issue_cmd(adapter, &cmd);
1982 if (err)
1983 dev_err(&adapter->pdev->dev,
1984 "MAC-VLAN %s to CAM failed, err=%d.\n",
1985 ((op == 1) ? "add " : "delete "), err);
1986 qlcnic_free_mbx_args(&cmd);
1987 return err;
1988}
1989
1990void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *adapter, u64 *addr,
1991 u16 vlan_id)
1992{
1993 u8 mac[ETH_ALEN];
1994 memcpy(&mac, addr, ETH_ALEN);
1995 qlcnic_83xx_sre_macaddr_change(adapter, mac, vlan_id, QLCNIC_MAC_ADD);
1996}
1997
1998void qlcnic_83xx_configure_mac(struct qlcnic_adapter *adapter, u8 *mac,
1999 u8 type, struct qlcnic_cmd_args *cmd)
2000{
2001 switch (type) {
2002 case QLCNIC_SET_STATION_MAC:
2003 case QLCNIC_SET_FAC_DEF_MAC:
2004 memcpy(&cmd->req.arg[2], mac, sizeof(u32));
2005 memcpy(&cmd->req.arg[3], &mac[4], sizeof(u16));
2006 break;
2007 }
2008 cmd->req.arg[1] = type;
2009}
2010
2011int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
2012{
2013 int err, i;
2014 struct qlcnic_cmd_args cmd;
2015 u32 mac_low, mac_high;
2016
2017 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS);
2018 if (err)
2019 return err;
2020
2021 qlcnic_83xx_configure_mac(adapter, mac, QLCNIC_GET_CURRENT_MAC, &cmd);
2022 err = qlcnic_issue_cmd(adapter, &cmd);
2023
2024 if (err == QLCNIC_RCODE_SUCCESS) {
2025 mac_low = cmd.rsp.arg[1];
2026 mac_high = cmd.rsp.arg[2];
2027
2028 for (i = 0; i < 2; i++)
2029 mac[i] = (u8) (mac_high >> ((1 - i) * 8));
2030 for (i = 2; i < 6; i++)
2031 mac[i] = (u8) (mac_low >> ((5 - i) * 8));
2032 } else {
2033 dev_err(&adapter->pdev->dev, "Failed to get mac address%d\n",
2034 err);
2035 err = -EIO;
2036 }
2037 qlcnic_free_mbx_args(&cmd);
2038 return err;
2039}
2040
2041void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter)
2042{
2043 int err;
2044 u16 temp;
2045 struct qlcnic_cmd_args cmd;
2046 struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
2047
2048 if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
2049 return;
2050
2051 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
2052 if (err)
2053 return;
2054
2055 if (coal->type == QLCNIC_INTR_COAL_TYPE_RX) {
2056 temp = adapter->recv_ctx->context_id;
2057 cmd.req.arg[1] = QLCNIC_INTR_COAL_TYPE_RX | temp << 16;
2058 temp = coal->rx_time_us;
2059 cmd.req.arg[2] = coal->rx_packets | temp << 16;
2060 } else if (coal->type == QLCNIC_INTR_COAL_TYPE_TX) {
2061 temp = adapter->tx_ring->ctx_id;
2062 cmd.req.arg[1] = QLCNIC_INTR_COAL_TYPE_TX | temp << 16;
2063 temp = coal->tx_time_us;
2064 cmd.req.arg[2] = coal->tx_packets | temp << 16;
2065 }
2066 cmd.req.arg[3] = coal->flag;
2067 err = qlcnic_issue_cmd(adapter, &cmd);
2068 if (err != QLCNIC_RCODE_SUCCESS)
2069 dev_info(&adapter->pdev->dev,
2070 "Failed to send interrupt coalescence parameters\n");
2071 qlcnic_free_mbx_args(&cmd);
2072}
2073
2074static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
2075 u32 data[])
2076{
2077 struct qlcnic_hardware_context *ahw = adapter->ahw;
2078 u8 link_status, duplex;
2079
2080 link_status = LSB(data[3]) & 1;
2081 if (link_status) {
2082 ahw->link_speed = MSW(data[2]);
2083 duplex = LSB(MSW(data[3]));
2084 if (duplex)
2085 ahw->link_duplex = DUPLEX_FULL;
2086 else
2087 ahw->link_duplex = DUPLEX_HALF;
2088 } else {
2089 ahw->link_speed = SPEED_UNKNOWN;
2090 ahw->link_duplex = DUPLEX_UNKNOWN;
2091 }
2092
2093 ahw->link_autoneg = MSB(MSW(data[3]));
2094 ahw->module_type = MSB(LSW(data[3]));
2095 ahw->has_link_events = 1;
2096 qlcnic_advert_link_change(adapter, link_status);
2097}
2098
2099irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
2100{
2101 struct qlcnic_adapter *adapter = data;
2102 unsigned long flags;
2103 u32 mask, resp, event;
2104
2105 spin_lock_irqsave(&adapter->ahw->mbx_lock, flags);
2106 resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL);
2107 if (!(resp & QLCNIC_SET_OWNER))
2108 goto out;
2109
2110 event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
2111 if (event & QLCNIC_MBX_ASYNC_EVENT)
2112 __qlcnic_83xx_process_aen(adapter);
2113out:
2114 mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
2115 writel(0, adapter->ahw->pci_base0 + mask);
2116 spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
2117
2118 return IRQ_HANDLED;
2119}
2120
2121int qlcnic_enable_eswitch(struct qlcnic_adapter *adapter, u8 port, u8 enable)
2122{
2123 int err = -EIO;
2124 struct qlcnic_cmd_args cmd;
2125
2126 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
2127 dev_err(&adapter->pdev->dev,
2128 "%s: Error, invoked by non management func\n",
2129 __func__);
2130 return err;
2131 }
2132
2133 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH);
2134 if (err)
2135 return err;
2136
2137 cmd.req.arg[1] = (port & 0xf) | BIT_4;
2138 err = qlcnic_issue_cmd(adapter, &cmd);
2139
2140 if (err != QLCNIC_RCODE_SUCCESS) {
2141 dev_err(&adapter->pdev->dev, "Failed to enable eswitch%d\n",
2142 err);
2143 err = -EIO;
2144 }
2145 qlcnic_free_mbx_args(&cmd);
2146
2147 return err;
2148
2149}
2150
2151int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *adapter,
2152 struct qlcnic_info *nic)
2153{
2154 int i, err = -EIO;
2155 struct qlcnic_cmd_args cmd;
2156
2157 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
2158 dev_err(&adapter->pdev->dev,
2159 "%s: Error, invoked by non management func\n",
2160 __func__);
2161 return err;
2162 }
2163
2164 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
2165 if (err)
2166 return err;
2167
2168 cmd.req.arg[1] = (nic->pci_func << 16);
2169 cmd.req.arg[2] = 0x1 << 16;
2170 cmd.req.arg[3] = nic->phys_port | (nic->switch_mode << 16);
2171 cmd.req.arg[4] = nic->capabilities;
2172 cmd.req.arg[5] = (nic->max_mac_filters & 0xFF) | ((nic->max_mtu) << 16);
2173 cmd.req.arg[6] = (nic->max_tx_ques) | ((nic->max_rx_ques) << 16);
2174 cmd.req.arg[7] = (nic->min_tx_bw) | ((nic->max_tx_bw) << 16);
2175 for (i = 8; i < 32; i++)
2176 cmd.req.arg[i] = 0;
2177
2178 err = qlcnic_issue_cmd(adapter, &cmd);
2179
2180 if (err != QLCNIC_RCODE_SUCCESS) {
2181 dev_err(&adapter->pdev->dev, "Failed to set nic info%d\n",
2182 err);
2183 err = -EIO;
2184 }
2185
2186 qlcnic_free_mbx_args(&cmd);
2187
2188 return err;
2189}
2190
2191int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
2192 struct qlcnic_info *npar_info, u8 func_id)
2193{
2194 int err;
2195 u32 temp;
2196 u8 op = 0;
2197 struct qlcnic_cmd_args cmd;
2198 struct qlcnic_hardware_context *ahw = adapter->ahw;
2199
2200 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
2201 if (err)
2202 return err;
2203
2204 if (func_id != ahw->pci_func) {
2205 temp = func_id << 16;
2206 cmd.req.arg[1] = op | BIT_31 | temp;
2207 } else {
2208 cmd.req.arg[1] = ahw->pci_func << 16;
2209 }
2210 err = qlcnic_issue_cmd(adapter, &cmd);
2211 if (err) {
2212 dev_info(&adapter->pdev->dev,
2213 "Failed to get nic info %d\n", err);
2214 goto out;
2215 }
2216
2217 npar_info->op_type = cmd.rsp.arg[1];
2218 npar_info->pci_func = cmd.rsp.arg[2] & 0xFFFF;
2219 npar_info->op_mode = (cmd.rsp.arg[2] & 0xFFFF0000) >> 16;
2220 npar_info->phys_port = cmd.rsp.arg[3] & 0xFFFF;
2221 npar_info->switch_mode = (cmd.rsp.arg[3] & 0xFFFF0000) >> 16;
2222 npar_info->capabilities = cmd.rsp.arg[4];
2223 npar_info->max_mac_filters = cmd.rsp.arg[5] & 0xFF;
2224 npar_info->max_mtu = (cmd.rsp.arg[5] & 0xFFFF0000) >> 16;
2225 npar_info->max_tx_ques = cmd.rsp.arg[6] & 0xFFFF;
2226 npar_info->max_rx_ques = (cmd.rsp.arg[6] & 0xFFFF0000) >> 16;
2227 npar_info->min_tx_bw = cmd.rsp.arg[7] & 0xFFFF;
2228 npar_info->max_tx_bw = (cmd.rsp.arg[7] & 0xFFFF0000) >> 16;
2229 if (cmd.rsp.arg[8] & 0x1)
2230 npar_info->max_bw_reg_offset = (cmd.rsp.arg[8] & 0x7FFE) >> 1;
2231 if (cmd.rsp.arg[8] & 0x10000) {
2232 temp = (cmd.rsp.arg[8] & 0x7FFE0000) >> 17;
2233 npar_info->max_linkspeed_reg_offset = temp;
2234 }
2235 if (npar_info->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS)
2236 memcpy(ahw->extra_capability, &cmd.rsp.arg[16],
2237 sizeof(ahw->extra_capability));
2238
2239out:
2240 qlcnic_free_mbx_args(&cmd);
2241 return err;
2242}
2243
2244int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
2245 struct qlcnic_pci_info *pci_info)
2246{
2247 struct qlcnic_hardware_context *ahw = adapter->ahw;
2248 struct device *dev = &adapter->pdev->dev;
2249 struct qlcnic_cmd_args cmd;
2250 int i, err = 0, j = 0;
2251 u32 temp;
2252
2253 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
2254 if (err)
2255 return err;
2256
2257 err = qlcnic_issue_cmd(adapter, &cmd);
2258
2259 ahw->act_pci_func = 0;
2260 if (err == QLCNIC_RCODE_SUCCESS) {
2261 ahw->max_pci_func = cmd.rsp.arg[1] & 0xFF;
2262 for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) {
2263 pci_info->id = cmd.rsp.arg[i] & 0xFFFF;
2264 pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
2265 i++;
2266 pci_info->type = cmd.rsp.arg[i] & 0xFFFF;
2267 if (pci_info->type == QLCNIC_TYPE_NIC)
2268 ahw->act_pci_func++;
2269 temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
2270 pci_info->default_port = temp;
2271 i++;
2272 pci_info->tx_min_bw = cmd.rsp.arg[i] & 0xFFFF;
2273 temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
2274 pci_info->tx_max_bw = temp;
2275 i = i + 2;
2276 memcpy(pci_info->mac, &cmd.rsp.arg[i], ETH_ALEN - 2);
2277 i++;
2278 memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2);
2279 i = i + 3;
2280 if (ahw->op_mode == QLCNIC_MGMT_FUNC)
2281 dev_info(dev, "id = %d active = %d type = %d\n"
2282 "\tport = %d min bw = %d max bw = %d\n"
2283 "\tmac_addr = %pM\n", pci_info->id,
2284 pci_info->active, pci_info->type,
2285 pci_info->default_port,
2286 pci_info->tx_min_bw,
2287 pci_info->tx_max_bw, pci_info->mac);
2288 }
2289 if (ahw->op_mode == QLCNIC_MGMT_FUNC)
2290 dev_info(dev, "Max vNIC functions = %d, active vNIC functions = %d\n",
2291 ahw->max_pci_func, ahw->act_pci_func);
2292
2293 } else {
2294 dev_err(dev, "Failed to get PCI Info, error = %d\n", err);
2295 err = -EIO;
2296 }
2297
2298 qlcnic_free_mbx_args(&cmd);
2299
2300 return err;
2301}
2302
2303int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type)
2304{
2305 int i, index, err;
2306 u8 max_ints;
2307 u32 val, temp, type;
2308 struct qlcnic_cmd_args cmd;
2309
2310 max_ints = adapter->ahw->num_msix - 1;
2311 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT);
2312 if (err)
2313 return err;
2314
2315 cmd.req.arg[1] = max_ints;
2316
2317 if (qlcnic_sriov_vf_check(adapter))
2318 cmd.req.arg[1] |= (adapter->ahw->pci_func << 8) | BIT_16;
2319
2320 for (i = 0, index = 2; i < max_ints; i++) {
2321 type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL;
2322 val = type | (adapter->ahw->intr_tbl[i].type << 4);
2323 if (adapter->ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX)
2324 val |= (adapter->ahw->intr_tbl[i].id << 16);
2325 cmd.req.arg[index++] = val;
2326 }
2327 err = qlcnic_issue_cmd(adapter, &cmd);
2328 if (err) {
2329 dev_err(&adapter->pdev->dev,
2330 "Failed to configure interrupts 0x%x\n", err);
2331 goto out;
2332 }
2333
2334 max_ints = cmd.rsp.arg[1];
2335 for (i = 0, index = 2; i < max_ints; i++, index += 2) {
2336 val = cmd.rsp.arg[index];
2337 if (LSB(val)) {
2338 dev_info(&adapter->pdev->dev,
2339 "Can't configure interrupt %d\n",
2340 adapter->ahw->intr_tbl[i].id);
2341 continue;
2342 }
2343 if (op_type) {
2344 adapter->ahw->intr_tbl[i].id = MSW(val);
2345 adapter->ahw->intr_tbl[i].enabled = 1;
2346 temp = cmd.rsp.arg[index + 1];
2347 adapter->ahw->intr_tbl[i].src = temp;
2348 } else {
2349 adapter->ahw->intr_tbl[i].id = i;
2350 adapter->ahw->intr_tbl[i].enabled = 0;
2351 adapter->ahw->intr_tbl[i].src = 0;
2352 }
2353 }
2354out:
2355 qlcnic_free_mbx_args(&cmd);
2356 return err;
2357}
2358
2359int qlcnic_83xx_lock_flash(struct qlcnic_adapter *adapter)
2360{
2361 int id, timeout = 0;
2362 u32 status = 0;
2363
2364 while (status == 0) {
2365 status = QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_LOCK);
2366 if (status)
2367 break;
2368
2369 if (++timeout >= QLC_83XX_FLASH_LOCK_TIMEOUT) {
2370 id = QLC_SHARED_REG_RD32(adapter,
2371 QLCNIC_FLASH_LOCK_OWNER);
2372 dev_err(&adapter->pdev->dev,
2373 "%s: failed, lock held by %d\n", __func__, id);
2374 return -EIO;
2375 }
2376 usleep_range(1000, 2000);
2377 }
2378
2379 QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, adapter->portnum);
2380 return 0;
2381}
2382
2383void qlcnic_83xx_unlock_flash(struct qlcnic_adapter *adapter)
2384{
2385 QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_UNLOCK);
2386 QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, 0xFF);
2387}
2388
2389int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *adapter,
2390 u32 flash_addr, u8 *p_data,
2391 int count)
2392{
2393 u32 word, range, flash_offset, addr = flash_addr, ret;
2394 ulong indirect_add, direct_window;
2395 int i, err = 0;
2396
2397 flash_offset = addr & (QLCNIC_FLASH_SECTOR_SIZE - 1);
2398 if (addr & 0x3) {
2399 dev_err(&adapter->pdev->dev, "Illegal addr = 0x%x\n", addr);
2400 return -EIO;
2401 }
2402
2403 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_DIRECT_WINDOW,
2404 (addr));
2405
2406 range = flash_offset + (count * sizeof(u32));
2407
2408 if (range > (QLCNIC_FLASH_SECTOR_SIZE - 1)) {
2409
2410
2411 for (i = 0; i < count; i++) {
2412 indirect_add = QLC_83XX_FLASH_DIRECT_DATA(addr);
2413 ret = QLCRD32(adapter, indirect_add, &err);
2414 if (err == -EIO)
2415 return err;
2416
2417 word = ret;
2418 *(u32 *)p_data = word;
2419 p_data = p_data + 4;
2420 addr = addr + 4;
2421 flash_offset = flash_offset + 4;
2422
2423 if (flash_offset > (QLCNIC_FLASH_SECTOR_SIZE - 1)) {
2424 direct_window = QLC_83XX_FLASH_DIRECT_WINDOW;
2425
2426 qlcnic_83xx_wrt_reg_indirect(adapter,
2427 direct_window,
2428 (addr));
2429 flash_offset = 0;
2430 }
2431 }
2432 } else {
2433
2434 for (i = 0; i < count; i++) {
2435 indirect_add = QLC_83XX_FLASH_DIRECT_DATA(addr);
2436 ret = QLCRD32(adapter, indirect_add, &err);
2437 if (err == -EIO)
2438 return err;
2439
2440 word = ret;
2441 *(u32 *)p_data = word;
2442 p_data = p_data + 4;
2443 addr = addr + 4;
2444 }
2445 }
2446
2447 return 0;
2448}
2449
2450static int qlcnic_83xx_poll_flash_status_reg(struct qlcnic_adapter *adapter)
2451{
2452 u32 status;
2453 int retries = QLC_83XX_FLASH_READ_RETRY_COUNT;
2454 int err = 0;
2455
2456 do {
2457 status = QLCRD32(adapter, QLC_83XX_FLASH_STATUS, &err);
2458 if (err == -EIO)
2459 return err;
2460
2461 if ((status & QLC_83XX_FLASH_STATUS_READY) ==
2462 QLC_83XX_FLASH_STATUS_READY)
2463 break;
2464
2465 msleep(QLC_83XX_FLASH_STATUS_REG_POLL_DELAY);
2466 } while (--retries);
2467
2468 if (!retries)
2469 return -EIO;
2470
2471 return 0;
2472}
2473
2474int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *adapter)
2475{
2476 int ret;
2477 u32 cmd;
2478 cmd = adapter->ahw->fdt.write_statusreg_cmd;
2479 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2480 (QLC_83XX_FLASH_FDT_WRITE_DEF_SIG | cmd));
2481 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
2482 adapter->ahw->fdt.write_enable_bits);
2483 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2484 QLC_83XX_FLASH_SECOND_ERASE_MS_VAL);
2485 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2486 if (ret)
2487 return -EIO;
2488
2489 return 0;
2490}
2491
2492int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *adapter)
2493{
2494 int ret;
2495
2496 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2497 (QLC_83XX_FLASH_FDT_WRITE_DEF_SIG |
2498 adapter->ahw->fdt.write_statusreg_cmd));
2499 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
2500 adapter->ahw->fdt.write_disable_bits);
2501 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2502 QLC_83XX_FLASH_SECOND_ERASE_MS_VAL);
2503 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2504 if (ret)
2505 return -EIO;
2506
2507 return 0;
2508}
2509
2510int qlcnic_83xx_read_flash_mfg_id(struct qlcnic_adapter *adapter)
2511{
2512 int ret, err = 0;
2513 u32 mfg_id;
2514
2515 if (qlcnic_83xx_lock_flash(adapter))
2516 return -EIO;
2517
2518 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2519 QLC_83XX_FLASH_FDT_READ_MFG_ID_VAL);
2520 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2521 QLC_83XX_FLASH_READ_CTRL);
2522 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2523 if (ret) {
2524 qlcnic_83xx_unlock_flash(adapter);
2525 return -EIO;
2526 }
2527
2528 mfg_id = QLCRD32(adapter, QLC_83XX_FLASH_RDDATA, &err);
2529 if (err == -EIO) {
2530 qlcnic_83xx_unlock_flash(adapter);
2531 return err;
2532 }
2533
2534 adapter->flash_mfg_id = (mfg_id & 0xFF);
2535 qlcnic_83xx_unlock_flash(adapter);
2536
2537 return 0;
2538}
2539
2540int qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *adapter)
2541{
2542 int count, fdt_size, ret = 0;
2543
2544 fdt_size = sizeof(struct qlcnic_fdt);
2545 count = fdt_size / sizeof(u32);
2546
2547 if (qlcnic_83xx_lock_flash(adapter))
2548 return -EIO;
2549
2550 memset(&adapter->ahw->fdt, 0, fdt_size);
2551 ret = qlcnic_83xx_lockless_flash_read32(adapter, QLCNIC_FDT_LOCATION,
2552 (u8 *)&adapter->ahw->fdt,
2553 count);
2554
2555 qlcnic_83xx_unlock_flash(adapter);
2556 return ret;
2557}
2558
2559int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,
2560 u32 sector_start_addr)
2561{
2562 u32 reversed_addr, addr1, addr2, cmd;
2563 int ret = -EIO;
2564
2565 if (qlcnic_83xx_lock_flash(adapter) != 0)
2566 return -EIO;
2567
2568 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
2569 ret = qlcnic_83xx_enable_flash_write(adapter);
2570 if (ret) {
2571 qlcnic_83xx_unlock_flash(adapter);
2572 dev_err(&adapter->pdev->dev,
2573 "%s failed at %d\n",
2574 __func__, __LINE__);
2575 return ret;
2576 }
2577 }
2578
2579 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2580 if (ret) {
2581 qlcnic_83xx_unlock_flash(adapter);
2582 dev_err(&adapter->pdev->dev,
2583 "%s: failed at %d\n", __func__, __LINE__);
2584 return -EIO;
2585 }
2586
2587 addr1 = (sector_start_addr & 0xFF) << 16;
2588 addr2 = (sector_start_addr & 0xFF0000) >> 16;
2589 reversed_addr = addr1 | addr2;
2590
2591 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
2592 reversed_addr);
2593 cmd = QLC_83XX_FLASH_FDT_ERASE_DEF_SIG | adapter->ahw->fdt.erase_cmd;
2594 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id)
2595 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, cmd);
2596 else
2597 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2598 QLC_83XX_FLASH_OEM_ERASE_SIG);
2599 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2600 QLC_83XX_FLASH_LAST_ERASE_MS_VAL);
2601
2602 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2603 if (ret) {
2604 qlcnic_83xx_unlock_flash(adapter);
2605 dev_err(&adapter->pdev->dev,
2606 "%s: failed at %d\n", __func__, __LINE__);
2607 return -EIO;
2608 }
2609
2610 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
2611 ret = qlcnic_83xx_disable_flash_write(adapter);
2612 if (ret) {
2613 qlcnic_83xx_unlock_flash(adapter);
2614 dev_err(&adapter->pdev->dev,
2615 "%s: failed at %d\n", __func__, __LINE__);
2616 return ret;
2617 }
2618 }
2619
2620 qlcnic_83xx_unlock_flash(adapter);
2621
2622 return 0;
2623}
2624
2625int qlcnic_83xx_flash_write32(struct qlcnic_adapter *adapter, u32 addr,
2626 u32 *p_data)
2627{
2628 int ret = -EIO;
2629 u32 addr1 = 0x00800000 | (addr >> 2);
2630
2631 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, addr1);
2632 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data);
2633 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2634 QLC_83XX_FLASH_LAST_ERASE_MS_VAL);
2635 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2636 if (ret) {
2637 dev_err(&adapter->pdev->dev,
2638 "%s: failed at %d\n", __func__, __LINE__);
2639 return -EIO;
2640 }
2641
2642 return 0;
2643}
2644
2645int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
2646 u32 *p_data, int count)
2647{
2648 u32 temp;
2649 int ret = -EIO, err = 0;
2650
2651 if ((count < QLC_83XX_FLASH_WRITE_MIN) ||
2652 (count > QLC_83XX_FLASH_WRITE_MAX)) {
2653 dev_err(&adapter->pdev->dev,
2654 "%s: Invalid word count\n", __func__);
2655 return -EIO;
2656 }
2657
2658 temp = QLCRD32(adapter, QLC_83XX_FLASH_SPI_CONTROL, &err);
2659 if (err == -EIO)
2660 return err;
2661
2662 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_SPI_CONTROL,
2663 (temp | QLC_83XX_FLASH_SPI_CTRL));
2664 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2665 QLC_83XX_FLASH_ADDR_TEMP_VAL);
2666
2667
2668 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data++);
2669 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2670 QLC_83XX_FLASH_FIRST_MS_PATTERN);
2671 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2672 if (ret) {
2673 dev_err(&adapter->pdev->dev,
2674 "%s: failed at %d\n", __func__, __LINE__);
2675 return -EIO;
2676 }
2677
2678 count--;
2679 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2680 QLC_83XX_FLASH_ADDR_SECOND_TEMP_VAL);
2681
2682 while (count != 1) {
2683 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
2684 *p_data++);
2685 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2686 QLC_83XX_FLASH_SECOND_MS_PATTERN);
2687 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2688 if (ret) {
2689 dev_err(&adapter->pdev->dev,
2690 "%s: failed at %d\n", __func__, __LINE__);
2691 return -EIO;
2692 }
2693 count--;
2694 }
2695
2696 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
2697 QLC_83XX_FLASH_ADDR_TEMP_VAL |
2698 (addr >> 2));
2699
2700 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data++);
2701 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
2702 QLC_83XX_FLASH_LAST_MS_PATTERN);
2703 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
2704 if (ret) {
2705 dev_err(&adapter->pdev->dev,
2706 "%s: failed at %d\n", __func__, __LINE__);
2707 return -EIO;
2708 }
2709
2710 ret = QLCRD32(adapter, QLC_83XX_FLASH_SPI_STATUS, &err);
2711 if (err == -EIO)
2712 return err;
2713
2714 if ((ret & QLC_83XX_FLASH_SPI_CTRL) == QLC_83XX_FLASH_SPI_CTRL) {
2715 dev_err(&adapter->pdev->dev, "%s: failed at %d\n",
2716 __func__, __LINE__);
2717
2718 temp = QLCRD32(adapter, QLC_83XX_FLASH_SPI_CONTROL, &err);
2719 if (err == -EIO)
2720 return err;
2721
2722 qlcnic_83xx_wrt_reg_indirect(adapter,
2723 QLC_83XX_FLASH_SPI_CONTROL,
2724 (temp | QLC_83XX_FLASH_SPI_CTRL));
2725 }
2726
2727 return 0;
2728}
2729
2730static void qlcnic_83xx_recover_driver_lock(struct qlcnic_adapter *adapter)
2731{
2732 u32 val, id;
2733
2734 val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK);
2735
2736
2737 if ((val & QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK) == 0) {
2738 val = val & ~0x3F;
2739 val = val | ((adapter->portnum << 2) |
2740 QLC_83XX_NEED_DRV_LOCK_RECOVERY);
2741 QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
2742 dev_info(&adapter->pdev->dev,
2743 "%s: lock recovery initiated\n", __func__);
2744 msleep(QLC_83XX_DRV_LOCK_RECOVERY_DELAY);
2745 val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK);
2746 id = ((val >> 2) & 0xF);
2747 if (id == adapter->portnum) {
2748 val = val & ~QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK;
2749 val = val | QLC_83XX_DRV_LOCK_RECOVERY_IN_PROGRESS;
2750 QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
2751
2752 QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK);
2753
2754 val = val & ~0x3F;
2755 QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
2756 dev_info(&adapter->pdev->dev,
2757 "%s: lock recovery completed\n", __func__);
2758 } else {
2759 dev_info(&adapter->pdev->dev,
2760 "%s: func %d to resume lock recovery process\n",
2761 __func__, id);
2762 }
2763 } else {
2764 dev_info(&adapter->pdev->dev,
2765 "%s: lock recovery initiated by other functions\n",
2766 __func__);
2767 }
2768}
2769
2770int qlcnic_83xx_lock_driver(struct qlcnic_adapter *adapter)
2771{
2772 u32 lock_alive_counter, val, id, i = 0, status = 0, temp = 0;
2773 int max_attempt = 0;
2774
2775 while (status == 0) {
2776 status = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK);
2777 if (status)
2778 break;
2779
2780 msleep(QLC_83XX_DRV_LOCK_WAIT_DELAY);
2781 i++;
2782
2783 if (i == 1)
2784 temp = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
2785
2786 if (i == QLC_83XX_DRV_LOCK_WAIT_COUNTER) {
2787 val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
2788 if (val == temp) {
2789 id = val & 0xFF;
2790 dev_info(&adapter->pdev->dev,
2791 "%s: lock to be recovered from %d\n",
2792 __func__, id);
2793 qlcnic_83xx_recover_driver_lock(adapter);
2794 i = 0;
2795 max_attempt++;
2796 } else {
2797 dev_err(&adapter->pdev->dev,
2798 "%s: failed to get lock\n", __func__);
2799 return -EIO;
2800 }
2801 }
2802
2803
2804 if (max_attempt == QLC_83XX_MAX_DRV_LOCK_RECOVERY_ATTEMPT) {
2805 dev_err(&adapter->pdev->dev,
2806 "%s: failed to get lock\n", __func__);
2807 return -EIO;
2808 }
2809 }
2810
2811 val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
2812 lock_alive_counter = val >> 8;
2813 lock_alive_counter++;
2814 val = lock_alive_counter << 8 | adapter->portnum;
2815 QLCWRX(adapter->ahw, QLC_83XX_DRV_LOCK_ID, val);
2816
2817 return 0;
2818}
2819
2820void qlcnic_83xx_unlock_driver(struct qlcnic_adapter *adapter)
2821{
2822 u32 val, lock_alive_counter, id;
2823
2824 val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
2825 id = val & 0xFF;
2826 lock_alive_counter = val >> 8;
2827
2828 if (id != adapter->portnum)
2829 dev_err(&adapter->pdev->dev,
2830 "%s:Warning func %d is unlocking lock owned by %d\n",
2831 __func__, adapter->portnum, id);
2832
2833 val = (lock_alive_counter << 8) | 0xFF;
2834 QLCWRX(adapter->ahw, QLC_83XX_DRV_LOCK_ID, val);
2835 QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK);
2836}
2837
2838int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *adapter, u64 addr,
2839 u32 *data, u32 count)
2840{
2841 int i, j, ret = 0;
2842 u32 temp;
2843 int err = 0;
2844
2845
2846 if (addr & 0xF)
2847 return -EIO;
2848
2849 mutex_lock(&adapter->ahw->mem_lock);
2850 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_ADDR_HI, 0);
2851
2852 for (i = 0; i < count; i++, addr += 16) {
2853 if (!((ADDR_IN_RANGE(addr, QLCNIC_ADDR_QDR_NET,
2854 QLCNIC_ADDR_QDR_NET_MAX)) ||
2855 (ADDR_IN_RANGE(addr, QLCNIC_ADDR_DDR_NET,
2856 QLCNIC_ADDR_DDR_NET_MAX)))) {
2857 mutex_unlock(&adapter->ahw->mem_lock);
2858 return -EIO;
2859 }
2860
2861 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_ADDR_LO, addr);
2862 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_LO,
2863 *data++);
2864 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_HI,
2865 *data++);
2866 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_ULO,
2867 *data++);
2868 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_UHI,
2869 *data++);
2870 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_CTRL,
2871 QLCNIC_TA_WRITE_ENABLE);
2872 qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_CTRL,
2873 QLCNIC_TA_WRITE_START);
2874
2875 for (j = 0; j < MAX_CTL_CHECK; j++) {
2876 temp = QLCRD32(adapter, QLCNIC_MS_CTRL, &err);
2877 if (err == -EIO) {
2878 mutex_unlock(&adapter->ahw->mem_lock);
2879 return err;
2880 }
2881
2882 if ((temp & TA_CTL_BUSY) == 0)
2883 break;
2884 }
2885
2886
2887 if (j >= MAX_CTL_CHECK) {
2888 printk_ratelimited(KERN_WARNING
2889 "MS memory write failed\n");
2890 mutex_unlock(&adapter->ahw->mem_lock);
2891 return -EIO;
2892 }
2893 }
2894
2895 mutex_unlock(&adapter->ahw->mem_lock);
2896
2897 return ret;
2898}
2899
2900int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
2901 u8 *p_data, int count)
2902{
2903 u32 word, addr = flash_addr, ret;
2904 ulong indirect_addr;
2905 int i, err = 0;
2906
2907 if (qlcnic_83xx_lock_flash(adapter) != 0)
2908 return -EIO;
2909
2910 if (addr & 0x3) {
2911 dev_err(&adapter->pdev->dev, "Illegal addr = 0x%x\n", addr);
2912 qlcnic_83xx_unlock_flash(adapter);
2913 return -EIO;
2914 }
2915
2916 for (i = 0; i < count; i++) {
2917 if (qlcnic_83xx_wrt_reg_indirect(adapter,
2918 QLC_83XX_FLASH_DIRECT_WINDOW,
2919 (addr))) {
2920 qlcnic_83xx_unlock_flash(adapter);
2921 return -EIO;
2922 }
2923
2924 indirect_addr = QLC_83XX_FLASH_DIRECT_DATA(addr);
2925 ret = QLCRD32(adapter, indirect_addr, &err);
2926 if (err == -EIO)
2927 return err;
2928
2929 word = ret;
2930 *(u32 *)p_data = word;
2931 p_data = p_data + 4;
2932 addr = addr + 4;
2933 }
2934
2935 qlcnic_83xx_unlock_flash(adapter);
2936
2937 return 0;
2938}
2939
2940int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
2941{
2942 u8 pci_func;
2943 int err;
2944 u32 config = 0, state;
2945 struct qlcnic_cmd_args cmd;
2946 struct qlcnic_hardware_context *ahw = adapter->ahw;
2947
2948 if (qlcnic_sriov_vf_check(adapter))
2949 pci_func = adapter->portnum;
2950 else
2951 pci_func = ahw->pci_func;
2952
2953 state = readl(ahw->pci_base0 + QLC_83XX_LINK_STATE(pci_func));
2954 if (!QLC_83xx_FUNC_VAL(state, pci_func)) {
2955 dev_info(&adapter->pdev->dev, "link state down\n");
2956 return config;
2957 }
2958
2959 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS);
2960 if (err)
2961 return err;
2962
2963 err = qlcnic_issue_cmd(adapter, &cmd);
2964 if (err) {
2965 dev_info(&adapter->pdev->dev,
2966 "Get Link Status Command failed: 0x%x\n", err);
2967 goto out;
2968 } else {
2969 config = cmd.rsp.arg[1];
2970 switch (QLC_83XX_CURRENT_LINK_SPEED(config)) {
2971 case QLC_83XX_10M_LINK:
2972 ahw->link_speed = SPEED_10;
2973 break;
2974 case QLC_83XX_100M_LINK:
2975 ahw->link_speed = SPEED_100;
2976 break;
2977 case QLC_83XX_1G_LINK:
2978 ahw->link_speed = SPEED_1000;
2979 break;
2980 case QLC_83XX_10G_LINK:
2981 ahw->link_speed = SPEED_10000;
2982 break;
2983 default:
2984 ahw->link_speed = 0;
2985 break;
2986 }
2987 config = cmd.rsp.arg[3];
2988 if (QLC_83XX_SFP_PRESENT(config)) {
2989 switch (ahw->module_type) {
2990 case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
2991 case LINKEVENT_MODULE_OPTICAL_SRLR:
2992 case LINKEVENT_MODULE_OPTICAL_LRM:
2993 case LINKEVENT_MODULE_OPTICAL_SFP_1G:
2994 ahw->supported_type = PORT_FIBRE;
2995 break;
2996 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
2997 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
2998 case LINKEVENT_MODULE_TWINAX:
2999 ahw->supported_type = PORT_TP;
3000 break;
3001 default:
3002 ahw->supported_type = PORT_OTHER;
3003 }
3004 }
3005 if (config & 1)
3006 err = 1;
3007 }
3008out:
3009 qlcnic_free_mbx_args(&cmd);
3010 return config;
3011}
3012
3013int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
3014 struct ethtool_cmd *ecmd)
3015{
3016 u32 config = 0;
3017 int status = 0;
3018 struct qlcnic_hardware_context *ahw = adapter->ahw;
3019
3020
3021 status = qlcnic_83xx_get_port_info(adapter);
3022
3023 config = qlcnic_83xx_test_link(adapter);
3024 ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config);
3025
3026 ahw->board_type = QLCNIC_BRDTYPE_83XX_10G;
3027
3028 if (netif_running(adapter->netdev) && ahw->has_link_events) {
3029 ethtool_cmd_speed_set(ecmd, ahw->link_speed);
3030 ecmd->duplex = ahw->link_duplex;
3031 ecmd->autoneg = ahw->link_autoneg;
3032 } else {
3033 ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
3034 ecmd->duplex = DUPLEX_UNKNOWN;
3035 ecmd->autoneg = AUTONEG_DISABLE;
3036 }
3037
3038 if (ahw->port_type == QLCNIC_XGBE) {
3039 ecmd->supported = SUPPORTED_10000baseT_Full;
3040 ecmd->advertising = ADVERTISED_10000baseT_Full;
3041 } else {
3042 ecmd->supported = (SUPPORTED_10baseT_Half |
3043 SUPPORTED_10baseT_Full |
3044 SUPPORTED_100baseT_Half |
3045 SUPPORTED_100baseT_Full |
3046 SUPPORTED_1000baseT_Half |
3047 SUPPORTED_1000baseT_Full);
3048 ecmd->advertising = (ADVERTISED_100baseT_Half |
3049 ADVERTISED_100baseT_Full |
3050 ADVERTISED_1000baseT_Half |
3051 ADVERTISED_1000baseT_Full);
3052 }
3053
3054 switch (ahw->supported_type) {
3055 case PORT_FIBRE:
3056 ecmd->supported |= SUPPORTED_FIBRE;
3057 ecmd->advertising |= ADVERTISED_FIBRE;
3058 ecmd->port = PORT_FIBRE;
3059 ecmd->transceiver = XCVR_EXTERNAL;
3060 break;
3061 case PORT_TP:
3062 ecmd->supported |= SUPPORTED_TP;
3063 ecmd->advertising |= ADVERTISED_TP;
3064 ecmd->port = PORT_TP;
3065 ecmd->transceiver = XCVR_INTERNAL;
3066 break;
3067 default:
3068 ecmd->supported |= SUPPORTED_FIBRE;
3069 ecmd->advertising |= ADVERTISED_FIBRE;
3070 ecmd->port = PORT_OTHER;
3071 ecmd->transceiver = XCVR_EXTERNAL;
3072 break;
3073 }
3074 ecmd->phy_address = ahw->physical_port;
3075 return status;
3076}
3077
3078int qlcnic_83xx_set_settings(struct qlcnic_adapter *adapter,
3079 struct ethtool_cmd *ecmd)
3080{
3081 int status = 0;
3082 u32 config = adapter->ahw->port_config;
3083
3084 if (ecmd->autoneg)
3085 adapter->ahw->port_config |= BIT_15;
3086
3087 switch (ethtool_cmd_speed(ecmd)) {
3088 case SPEED_10:
3089 adapter->ahw->port_config |= BIT_8;
3090 break;
3091 case SPEED_100:
3092 adapter->ahw->port_config |= BIT_9;
3093 break;
3094 case SPEED_1000:
3095 adapter->ahw->port_config |= BIT_10;
3096 break;
3097 case SPEED_10000:
3098 adapter->ahw->port_config |= BIT_11;
3099 break;
3100 default:
3101 return -EINVAL;
3102 }
3103
3104 status = qlcnic_83xx_set_port_config(adapter);
3105 if (status) {
3106 dev_info(&adapter->pdev->dev,
3107 "Faild to Set Link Speed and autoneg.\n");
3108 adapter->ahw->port_config = config;
3109 }
3110 return status;
3111}
3112
3113static inline u64 *qlcnic_83xx_copy_stats(struct qlcnic_cmd_args *cmd,
3114 u64 *data, int index)
3115{
3116 u32 low, hi;
3117 u64 val;
3118
3119 low = cmd->rsp.arg[index];
3120 hi = cmd->rsp.arg[index + 1];
3121 val = (((u64) low) | (((u64) hi) << 32));
3122 *data++ = val;
3123 return data;
3124}
3125
3126static u64 *qlcnic_83xx_fill_stats(struct qlcnic_adapter *adapter,
3127 struct qlcnic_cmd_args *cmd, u64 *data,
3128 int type, int *ret)
3129{
3130 int err, k, total_regs;
3131
3132 *ret = 0;
3133 err = qlcnic_issue_cmd(adapter, cmd);
3134 if (err != QLCNIC_RCODE_SUCCESS) {
3135 dev_info(&adapter->pdev->dev,
3136 "Error in get statistics mailbox command\n");
3137 *ret = -EIO;
3138 return data;
3139 }
3140 total_regs = cmd->rsp.num;
3141 switch (type) {
3142 case QLC_83XX_STAT_MAC:
3143
3144 for (k = 2; k < 28; k += 2)
3145 data = qlcnic_83xx_copy_stats(cmd, data, k);
3146
3147
3148 for (k += 6; k < 60; k += 2)
3149 data = qlcnic_83xx_copy_stats(cmd, data, k);
3150
3151
3152 for (k += 6; k < 80; k += 2)
3153 data = qlcnic_83xx_copy_stats(cmd, data, k);
3154
3155 for (; k < total_regs; k += 2)
3156 data = qlcnic_83xx_copy_stats(cmd, data, k);
3157 break;
3158 case QLC_83XX_STAT_RX:
3159 for (k = 2; k < 8; k += 2)
3160 data = qlcnic_83xx_copy_stats(cmd, data, k);
3161
3162 for (k += 2; k < 24; k += 2)
3163 data = qlcnic_83xx_copy_stats(cmd, data, k);
3164
3165 for (k += 2; k < total_regs; k += 2)
3166 data = qlcnic_83xx_copy_stats(cmd, data, k);
3167 break;
3168 case QLC_83XX_STAT_TX:
3169 for (k = 2; k < 10; k += 2)
3170 data = qlcnic_83xx_copy_stats(cmd, data, k);
3171
3172 for (k += 2; k < total_regs; k += 2)
3173 data = qlcnic_83xx_copy_stats(cmd, data, k);
3174 break;
3175 default:
3176 dev_warn(&adapter->pdev->dev, "Unknown get statistics mode\n");
3177 *ret = -EIO;
3178 }
3179 return data;
3180}
3181
3182void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data)
3183{
3184 struct qlcnic_cmd_args cmd;
3185 struct net_device *netdev = adapter->netdev;
3186 int ret = 0;
3187
3188 ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_STATISTICS);
3189 if (ret)
3190 return;
3191
3192 cmd.req.arg[1] = BIT_1 | (adapter->tx_ring->ctx_id << 16);
3193 cmd.rsp.num = QLC_83XX_TX_STAT_REGS;
3194 data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
3195 QLC_83XX_STAT_TX, &ret);
3196 if (ret) {
3197 netdev_err(netdev, "Error getting Tx stats\n");
3198 goto out;
3199 }
3200
3201 cmd.req.arg[1] = BIT_2 | (adapter->portnum << 16);
3202 cmd.rsp.num = QLC_83XX_MAC_STAT_REGS;
3203 memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num);
3204 data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
3205 QLC_83XX_STAT_MAC, &ret);
3206 if (ret) {
3207 netdev_err(netdev, "Error getting MAC stats\n");
3208 goto out;
3209 }
3210
3211 cmd.req.arg[1] = adapter->recv_ctx->context_id << 16;
3212 cmd.rsp.num = QLC_83XX_RX_STAT_REGS;
3213 memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num);
3214 data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
3215 QLC_83XX_STAT_RX, &ret);
3216 if (ret)
3217 netdev_err(netdev, "Error getting Rx stats\n");
3218out:
3219 qlcnic_free_mbx_args(&cmd);
3220}
3221
3222int qlcnic_83xx_reg_test(struct qlcnic_adapter *adapter)
3223{
3224 u32 major, minor, sub;
3225
3226 major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
3227 minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
3228 sub = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
3229
3230 if (adapter->fw_version != QLCNIC_VERSION_CODE(major, minor, sub)) {
3231 dev_info(&adapter->pdev->dev, "%s: Reg test failed\n",
3232 __func__);
3233 return 1;
3234 }
3235 return 0;
3236}
3237
3238int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *adapter)
3239{
3240 return (ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl) *
3241 sizeof(adapter->ahw->ext_reg_tbl)) +
3242 (ARRAY_SIZE(qlcnic_83xx_reg_tbl) +
3243 sizeof(adapter->ahw->reg_tbl));
3244}
3245
3246int qlcnic_83xx_get_registers(struct qlcnic_adapter *adapter, u32 *regs_buff)
3247{
3248 int i, j = 0;
3249
3250 for (i = QLCNIC_DEV_INFO_SIZE + 1;
3251 j < ARRAY_SIZE(qlcnic_83xx_reg_tbl); i++, j++)
3252 regs_buff[i] = QLC_SHARED_REG_RD32(adapter, j);
3253
3254 for (j = 0; j < ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl); j++)
3255 regs_buff[i++] = QLCRDX(adapter->ahw, j);
3256 return i;
3257}
3258
3259int qlcnic_83xx_interrupt_test(struct net_device *netdev)
3260{
3261 struct qlcnic_adapter *adapter = netdev_priv(netdev);
3262 struct qlcnic_hardware_context *ahw = adapter->ahw;
3263 struct qlcnic_cmd_args cmd;
3264 u32 data;
3265 u16 intrpt_id, id;
3266 u8 val;
3267 int ret, max_sds_rings = adapter->max_sds_rings;
3268
3269 if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
3270 netdev_info(netdev, "Device is resetting\n");
3271 return -EBUSY;
3272 }
3273
3274 if (qlcnic_get_diag_lock(adapter)) {
3275 netdev_info(netdev, "Device in diagnostics mode\n");
3276 return -EBUSY;
3277 }
3278
3279 ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST,
3280 max_sds_rings);
3281 if (ret)
3282 goto fail_diag_irq;
3283
3284 ahw->diag_cnt = 0;
3285 ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
3286 if (ret)
3287 goto fail_diag_irq;
3288
3289 if (adapter->flags & QLCNIC_MSIX_ENABLED)
3290 intrpt_id = ahw->intr_tbl[0].id;
3291 else
3292 intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
3293
3294 cmd.req.arg[1] = 1;
3295 cmd.req.arg[2] = intrpt_id;
3296 cmd.req.arg[3] = BIT_0;
3297
3298 ret = qlcnic_issue_cmd(adapter, &cmd);
3299 data = cmd.rsp.arg[2];
3300 id = LSW(data);
3301 val = LSB(MSW(data));
3302 if (id != intrpt_id)
3303 dev_info(&adapter->pdev->dev,
3304 "Interrupt generated: 0x%x, requested:0x%x\n",
3305 id, intrpt_id);
3306 if (val)
3307 dev_err(&adapter->pdev->dev,
3308 "Interrupt test error: 0x%x\n", val);
3309 if (ret)
3310 goto done;
3311
3312 msleep(20);
3313 ret = !ahw->diag_cnt;
3314
3315done:
3316 qlcnic_free_mbx_args(&cmd);
3317 qlcnic_83xx_diag_free_res(netdev, max_sds_rings);
3318
3319fail_diag_irq:
3320 adapter->max_sds_rings = max_sds_rings;
3321 qlcnic_release_diag_lock(adapter);
3322 return ret;
3323}
3324
3325void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *adapter,
3326 struct ethtool_pauseparam *pause)
3327{
3328 struct qlcnic_hardware_context *ahw = adapter->ahw;
3329 int status = 0;
3330 u32 config;
3331
3332 status = qlcnic_83xx_get_port_config(adapter);
3333 if (status) {
3334 dev_err(&adapter->pdev->dev,
3335 "%s: Get Pause Config failed\n", __func__);
3336 return;
3337 }
3338 config = ahw->port_config;
3339 if (config & QLC_83XX_CFG_STD_PAUSE) {
3340 if (config & QLC_83XX_CFG_STD_TX_PAUSE)
3341 pause->tx_pause = 1;
3342 if (config & QLC_83XX_CFG_STD_RX_PAUSE)
3343 pause->rx_pause = 1;
3344 }
3345
3346 if (QLC_83XX_AUTONEG(config))
3347 pause->autoneg = 1;
3348}
3349
3350int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *adapter,
3351 struct ethtool_pauseparam *pause)
3352{
3353 struct qlcnic_hardware_context *ahw = adapter->ahw;
3354 int status = 0;
3355 u32 config;
3356
3357 status = qlcnic_83xx_get_port_config(adapter);
3358 if (status) {
3359 dev_err(&adapter->pdev->dev,
3360 "%s: Get Pause Config failed.\n", __func__);
3361 return status;
3362 }
3363 config = ahw->port_config;
3364
3365 if (ahw->port_type == QLCNIC_GBE) {
3366 if (pause->autoneg)
3367 ahw->port_config |= QLC_83XX_ENABLE_AUTONEG;
3368 if (!pause->autoneg)
3369 ahw->port_config &= ~QLC_83XX_ENABLE_AUTONEG;
3370 } else if ((ahw->port_type == QLCNIC_XGBE) && (pause->autoneg)) {
3371 return -EOPNOTSUPP;
3372 }
3373
3374 if (!(config & QLC_83XX_CFG_STD_PAUSE))
3375 ahw->port_config |= QLC_83XX_CFG_STD_PAUSE;
3376
3377 if (pause->rx_pause && pause->tx_pause) {
3378 ahw->port_config |= QLC_83XX_CFG_STD_TX_RX_PAUSE;
3379 } else if (pause->rx_pause && !pause->tx_pause) {
3380 ahw->port_config &= ~QLC_83XX_CFG_STD_TX_PAUSE;
3381 ahw->port_config |= QLC_83XX_CFG_STD_RX_PAUSE;
3382 } else if (pause->tx_pause && !pause->rx_pause) {
3383 ahw->port_config &= ~QLC_83XX_CFG_STD_RX_PAUSE;
3384 ahw->port_config |= QLC_83XX_CFG_STD_TX_PAUSE;
3385 } else if (!pause->rx_pause && !pause->tx_pause) {
3386 ahw->port_config &= ~QLC_83XX_CFG_STD_TX_RX_PAUSE;
3387 }
3388 status = qlcnic_83xx_set_port_config(adapter);
3389 if (status) {
3390 dev_err(&adapter->pdev->dev,
3391 "%s: Set Pause Config failed.\n", __func__);
3392 ahw->port_config = config;
3393 }
3394 return status;
3395}
3396
3397static int qlcnic_83xx_read_flash_status_reg(struct qlcnic_adapter *adapter)
3398{
3399 int ret, err = 0;
3400 u32 temp;
3401
3402 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
3403 QLC_83XX_FLASH_OEM_READ_SIG);
3404 qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
3405 QLC_83XX_FLASH_READ_CTRL);
3406 ret = qlcnic_83xx_poll_flash_status_reg(adapter);
3407 if (ret)
3408 return -EIO;
3409
3410 temp = QLCRD32(adapter, QLC_83XX_FLASH_RDDATA, &err);
3411 if (err == -EIO)
3412 return err;
3413
3414 return temp & 0xFF;
3415}
3416
3417int qlcnic_83xx_flash_test(struct qlcnic_adapter *adapter)
3418{
3419 int status;
3420
3421 status = qlcnic_83xx_read_flash_status_reg(adapter);
3422 if (status == -EIO) {
3423 dev_info(&adapter->pdev->dev, "%s: EEPROM test failed.\n",
3424 __func__);
3425 return 1;
3426 }
3427 return 0;
3428}
3429
3430int qlcnic_83xx_shutdown(struct pci_dev *pdev)
3431{
3432 struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
3433 struct net_device *netdev = adapter->netdev;
3434 int retval;
3435
3436 netif_device_detach(netdev);
3437 qlcnic_cancel_idc_work(adapter);
3438
3439 if (netif_running(netdev))
3440 qlcnic_down(adapter, netdev);
3441
3442 qlcnic_83xx_disable_mbx_intr(adapter);
3443 cancel_delayed_work_sync(&adapter->idc_aen_work);
3444
3445 retval = pci_save_state(pdev);
3446 if (retval)
3447 return retval;
3448
3449 return 0;
3450}
3451
3452int qlcnic_83xx_resume(struct qlcnic_adapter *adapter)
3453{
3454 struct qlcnic_hardware_context *ahw = adapter->ahw;
3455 struct qlc_83xx_idc *idc = &ahw->idc;
3456 int err = 0;
3457
3458 err = qlcnic_83xx_idc_init(adapter);
3459 if (err)
3460 return err;
3461
3462 if (ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) {
3463 if (ahw->op_mode == QLCNIC_MGMT_FUNC) {
3464 qlcnic_83xx_set_vnic_opmode(adapter);
3465 } else {
3466 err = qlcnic_83xx_check_vnic_state(adapter);
3467 if (err)
3468 return err;
3469 }
3470 }
3471
3472 err = qlcnic_83xx_idc_reattach_driver(adapter);
3473 if (err)
3474 return err;
3475
3476 qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
3477 idc->delay);
3478 return err;
3479}
3480