6d4d792e56d24966826a7aa2c98f1dba863fd32d
[pandora-kernel.git] / drivers / net / ethernet / qlogic / qlcnic / qlcnic_83xx_hw.c
1 #include "qlcnic.h"
2 #include <linux/if_vlan.h>
3 #include <linux/ipv6.h>
4 #include <linux/ethtool.h>
5 #include <linux/interrupt.h>
6
7 #define QLCNIC_MAX_TX_QUEUES            1
8
9 #define QLCNIC_MBX_RSP(reg)             LSW(reg)
10 #define QLCNIC_MBX_NUM_REGS(reg)        (MSW(reg) & 0x1FF)
11 #define QLCNIC_MBX_STATUS(reg)          (((reg) >> 25) & 0x7F)
12 #define QLCNIC_MBX_HOST(ahw, i) ((ahw)->pci_base0 + ((i) * 4))
13 #define QLCNIC_MBX_FW(ahw, i)           ((ahw)->pci_base0 + 0x800 + ((i) * 4))
14
15 #define RSS_HASHTYPE_IP_TCP             0x3
16
17 /* status descriptor mailbox data
18  * @phy_addr: physical address of buffer
19  * @sds_ring_size: buffer size
20  * @intrpt_id: interrupt id
21  * @intrpt_val: source of interrupt
22  */
23 struct qlcnic_sds_mbx {
24         u64     phy_addr;
25         u8      rsvd1[16];
26         u16     sds_ring_size;
27         u16     rsvd2[3];
28         u16     intrpt_id;
29         u8      intrpt_val;
30         u8      rsvd3[5];
31 } __packed;
32
33 /* receive descriptor buffer data
34  * phy_addr_reg: physical address of regular buffer
35  * phy_addr_jmb: physical address of jumbo buffer
36  * reg_ring_sz: size of regular buffer
37  * reg_ring_len: no. of entries in regular buffer
38  * jmb_ring_len: no. of entries in jumbo buffer
39  * jmb_ring_sz: size of jumbo buffer
40  */
41 struct qlcnic_rds_mbx {
42         u64     phy_addr_reg;
43         u64     phy_addr_jmb;
44         u16     reg_ring_sz;
45         u16     reg_ring_len;
46         u16     jmb_ring_sz;
47         u16     jmb_ring_len;
48 } __packed;
49
50 /* host producers for regular and jumbo rings */
51 struct __host_producer_mbx {
52         u32     reg_buf;
53         u32     jmb_buf;
54 } __packed;
55
56 /* Receive context mailbox data outbox registers
57  * @state: state of the context
58  * @vport_id: virtual port id
59  * @context_id: receive context id
60  * @num_pci_func: number of pci functions of the port
61  * @phy_port: physical port id
62  */
63 struct qlcnic_rcv_mbx_out {
64         u8      rcv_num;
65         u8      sts_num;
66         u16     ctx_id;
67         u8      state;
68         u8      num_pci_func;
69         u8      phy_port;
70         u8      vport_id;
71         u32     host_csmr[QLCNIC_MAX_RING_SETS];
72         struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
73 } __packed;
74
75 struct qlcnic_add_rings_mbx_out {
76         u8      rcv_num;
77         u8      sts_num;
78         u16  ctx_id;
79         u32  host_csmr[QLCNIC_MAX_RING_SETS];
80         struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
81 } __packed;
82
83 /* Transmit context mailbox inbox registers
84  * @phys_addr: DMA address of the transmit buffer
85  * @cnsmr_index: host consumer index
86  * @size: legth of transmit buffer ring
87  * @intr_id: interrput id
88  * @src: src of interrupt
89  */
90 struct qlcnic_tx_mbx {
91         u64     phys_addr;
92         u64     cnsmr_index;
93         u16     size;
94         u16     intr_id;
95         u8      src;
96         u8      rsvd[3];
97 } __packed;
98
99 /* Transmit context mailbox outbox registers
100  * @host_prod: host producer index
101  * @ctx_id: transmit context id
102  * @state: state of the transmit context
103  */
104 struct qlcnic_tx_mbx_out {
105         u32     host_prod;
106         u16     ctx_id;
107         u8      state;
108         u8      rsvd;
109 } __packed;
110
111 static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
112         {QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1},
113         {QLCNIC_CMD_CONFIG_INTRPT, 18, 34},
114         {QLCNIC_CMD_CREATE_RX_CTX, 136, 27},
115         {QLCNIC_CMD_DESTROY_RX_CTX, 2, 1},
116         {QLCNIC_CMD_CREATE_TX_CTX, 54, 18},
117         {QLCNIC_CMD_DESTROY_TX_CTX, 2, 1},
118         {QLCNIC_CMD_CONFIGURE_MAC_LEARNING, 2, 1},
119         {QLCNIC_CMD_INTRPT_TEST, 22, 12},
120         {QLCNIC_CMD_SET_MTU, 3, 1},
121         {QLCNIC_CMD_READ_PHY, 4, 2},
122         {QLCNIC_CMD_WRITE_PHY, 5, 1},
123         {QLCNIC_CMD_READ_HW_REG, 4, 1},
124         {QLCNIC_CMD_GET_FLOW_CTL, 4, 2},
125         {QLCNIC_CMD_SET_FLOW_CTL, 4, 1},
126         {QLCNIC_CMD_READ_MAX_MTU, 4, 2},
127         {QLCNIC_CMD_READ_MAX_LRO, 4, 2},
128         {QLCNIC_CMD_MAC_ADDRESS, 4, 3},
129         {QLCNIC_CMD_GET_PCI_INFO, 1, 66},
130         {QLCNIC_CMD_GET_NIC_INFO, 2, 19},
131         {QLCNIC_CMD_SET_NIC_INFO, 32, 1},
132         {QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3},
133         {QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1},
134         {QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3},
135         {QLCNIC_CMD_SET_PORTMIRRORING, 4, 1},
136         {QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1},
137         {QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3},
138         {QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1},
139         {QLCNIC_CMD_CONFIG_PORT, 4, 1},
140         {QLCNIC_CMD_TEMP_SIZE, 1, 4},
141         {QLCNIC_CMD_GET_TEMP_HDR, 5, 5},
142         {QLCNIC_CMD_GET_LINK_EVENT, 2, 1},
143         {QLCNIC_CMD_CONFIG_MAC_VLAN, 4, 3},
144         {QLCNIC_CMD_CONFIG_INTR_COAL, 6, 1},
145         {QLCNIC_CMD_CONFIGURE_RSS, 14, 1},
146         {QLCNIC_CMD_CONFIGURE_LED, 2, 1},
147         {QLCNIC_CMD_CONFIGURE_MAC_RX_MODE, 2, 1},
148         {QLCNIC_CMD_CONFIGURE_HW_LRO, 2, 1},
149         {QLCNIC_CMD_GET_STATISTICS, 2, 80},
150         {QLCNIC_CMD_SET_PORT_CONFIG, 2, 1},
151         {QLCNIC_CMD_GET_PORT_CONFIG, 2, 2},
152         {QLCNIC_CMD_GET_LINK_STATUS, 2, 4},
153         {QLCNIC_CMD_IDC_ACK, 5, 1},
154         {QLCNIC_CMD_INIT_NIC_FUNC, 2, 1},
155         {QLCNIC_CMD_STOP_NIC_FUNC, 2, 1},
156         {QLCNIC_CMD_SET_LED_CONFIG, 5, 1},
157         {QLCNIC_CMD_GET_LED_CONFIG, 1, 5},
158         {QLCNIC_CMD_ADD_RCV_RINGS, 130, 26},
159 };
160
161 static const u32 qlcnic_83xx_ext_reg_tbl[] = {
162         0x38CC,         /* Global Reset */
163         0x38F0,         /* Wildcard */
164         0x38FC,         /* Informant */
165         0x3038,         /* Host MBX ctrl */
166         0x303C,         /* FW MBX ctrl */
167         0x355C,         /* BOOT LOADER ADDRESS REG */
168         0x3560,         /* BOOT LOADER SIZE REG */
169         0x3564,         /* FW IMAGE ADDR REG */
170         0x1000,         /* MBX intr enable */
171         0x1200,         /* Default Intr mask */
172         0x1204,         /* Default Interrupt ID */
173         0x3780,         /* QLC_83XX_IDC_MAJ_VERSION */
174         0x3784,         /* QLC_83XX_IDC_DEV_STATE */
175         0x3788,         /* QLC_83XX_IDC_DRV_PRESENCE */
176         0x378C,         /* QLC_83XX_IDC_DRV_ACK */
177         0x3790,         /* QLC_83XX_IDC_CTRL */
178         0x3794,         /* QLC_83XX_IDC_DRV_AUDIT */
179         0x3798,         /* QLC_83XX_IDC_MIN_VERSION */
180         0x379C,         /* QLC_83XX_RECOVER_DRV_LOCK */
181         0x37A0,         /* QLC_83XX_IDC_PF_0 */
182         0x37A4,         /* QLC_83XX_IDC_PF_1 */
183         0x37A8,         /* QLC_83XX_IDC_PF_2 */
184         0x37AC,         /* QLC_83XX_IDC_PF_3 */
185         0x37B0,         /* QLC_83XX_IDC_PF_4 */
186         0x37B4,         /* QLC_83XX_IDC_PF_5 */
187         0x37B8,         /* QLC_83XX_IDC_PF_6 */
188         0x37BC,         /* QLC_83XX_IDC_PF_7 */
189         0x37C0,         /* QLC_83XX_IDC_PF_8 */
190         0x37C4,         /* QLC_83XX_IDC_PF_9 */
191         0x37C8,         /* QLC_83XX_IDC_PF_10 */
192         0x37CC,         /* QLC_83XX_IDC_PF_11 */
193         0x37D0,         /* QLC_83XX_IDC_PF_12 */
194         0x37D4,         /* QLC_83XX_IDC_PF_13 */
195         0x37D8,         /* QLC_83XX_IDC_PF_14 */
196         0x37DC,         /* QLC_83XX_IDC_PF_15 */
197         0x37E0,         /* QLC_83XX_IDC_DEV_PARTITION_INFO_1 */
198         0x37E4,         /* QLC_83XX_IDC_DEV_PARTITION_INFO_2 */
199         0x37F0,         /* QLC_83XX_DRV_OP_MODE */
200         0x37F4,         /* QLC_83XX_VNIC_STATE */
201         0x3868,         /* QLC_83XX_DRV_LOCK */
202         0x386C,         /* QLC_83XX_DRV_UNLOCK */
203         0x3504,         /* QLC_83XX_DRV_LOCK_ID */
204         0x34A4,         /* QLC_83XX_ASIC_TEMP */
205 };
206
207 static const u32 qlcnic_83xx_reg_tbl[] = {
208         0x34A8,         /* PEG_HALT_STAT1 */
209         0x34AC,         /* PEG_HALT_STAT2 */
210         0x34B0,         /* FW_HEARTBEAT */
211         0x3500,         /* FLASH LOCK_ID */
212         0x3528,         /* FW_CAPABILITIES */
213         0x3538,         /* Driver active, DRV_REG0 */
214         0x3540,         /* Device state, DRV_REG1 */
215         0x3544,         /* Driver state, DRV_REG2 */
216         0x3548,         /* Driver scratch, DRV_REG3 */
217         0x354C,         /* Device partiton info, DRV_REG4 */
218         0x3524,         /* Driver IDC ver, DRV_REG5 */
219         0x3550,         /* FW_VER_MAJOR */
220         0x3554,         /* FW_VER_MINOR */
221         0x3558,         /* FW_VER_SUB */
222         0x359C,         /* NPAR STATE */
223         0x35FC,         /* FW_IMG_VALID */
224         0x3650,         /* CMD_PEG_STATE */
225         0x373C,         /* RCV_PEG_STATE */
226         0x37B4,         /* ASIC TEMP */
227         0x356C,         /* FW API */
228         0x3570,         /* DRV OP MODE */
229         0x3850,         /* FLASH LOCK */
230         0x3854,         /* FLASH UNLOCK */
231 };
232
233 static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
234         .read_crb                       = qlcnic_83xx_read_crb,
235         .write_crb                      = qlcnic_83xx_write_crb,
236         .read_reg                       = qlcnic_83xx_rd_reg_indirect,
237         .write_reg                      = qlcnic_83xx_wrt_reg_indirect,
238         .get_mac_address                = qlcnic_83xx_get_mac_address,
239         .setup_intr                     = qlcnic_83xx_setup_intr,
240         .alloc_mbx_args                 = qlcnic_83xx_alloc_mbx_args,
241         .mbx_cmd                        = qlcnic_83xx_mbx_op,
242         .get_func_no                    = qlcnic_83xx_get_func_no,
243         .api_lock                       = qlcnic_83xx_cam_lock,
244         .api_unlock                     = qlcnic_83xx_cam_unlock,
245         .add_sysfs                      = qlcnic_83xx_add_sysfs,
246         .remove_sysfs                   = qlcnic_83xx_remove_sysfs,
247         .process_lb_rcv_ring_diag       = qlcnic_83xx_process_rcv_ring_diag,
248         .create_rx_ctx                  = qlcnic_83xx_create_rx_ctx,
249         .create_tx_ctx                  = qlcnic_83xx_create_tx_ctx,
250         .setup_link_event               = qlcnic_83xx_setup_link_event,
251         .get_nic_info                   = qlcnic_83xx_get_nic_info,
252         .get_pci_info                   = qlcnic_83xx_get_pci_info,
253         .set_nic_info                   = qlcnic_83xx_set_nic_info,
254         .change_macvlan                 = qlcnic_83xx_sre_macaddr_change,
255         .napi_enable                    = qlcnic_83xx_napi_enable,
256         .napi_disable                   = qlcnic_83xx_napi_disable,
257         .config_intr_coal               = qlcnic_83xx_config_intr_coal,
258         .config_rss                     = qlcnic_83xx_config_rss,
259         .config_hw_lro                  = qlcnic_83xx_config_hw_lro,
260         .config_loopback                = qlcnic_83xx_set_lb_mode,
261         .clear_loopback                 = qlcnic_83xx_clear_lb_mode,
262         .config_promisc_mode            = qlcnic_83xx_nic_set_promisc,
263         .change_l2_filter               = qlcnic_83xx_change_l2_filter,
264         .get_board_info                 = qlcnic_83xx_get_port_info,
265 };
266
267 static struct qlcnic_nic_template qlcnic_83xx_ops = {
268         .config_bridged_mode    = qlcnic_config_bridged_mode,
269         .config_led             = qlcnic_config_led,
270         .napi_add               = qlcnic_83xx_napi_add,
271         .napi_del               = qlcnic_83xx_napi_del,
272         .config_ipaddr          = qlcnic_83xx_config_ipaddr,
273         .clear_legacy_intr      = qlcnic_83xx_clear_legacy_intr,
274 };
275
276 void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw)
277 {
278         ahw->hw_ops             = &qlcnic_83xx_hw_ops;
279         ahw->reg_tbl            = (u32 *)qlcnic_83xx_reg_tbl;
280         ahw->ext_reg_tbl        = (u32 *)qlcnic_83xx_ext_reg_tbl;
281 }
282
283 int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *adapter)
284 {
285         u32 fw_major, fw_minor, fw_build;
286         struct pci_dev *pdev = adapter->pdev;
287
288         fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
289         fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
290         fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
291         adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
292
293         dev_info(&pdev->dev, "Driver v%s, firmware version %d.%d.%d\n",
294                  QLCNIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build);
295
296         return adapter->fw_version;
297 }
298
299 static int __qlcnic_set_win_base(struct qlcnic_adapter *adapter, u32 addr)
300 {
301         void __iomem *base;
302         u32 val;
303
304         base = adapter->ahw->pci_base0 +
305                QLC_83XX_CRB_WIN_FUNC(adapter->ahw->pci_func);
306         writel(addr, base);
307         val = readl(base);
308         if (val != addr)
309                 return -EIO;
310
311         return 0;
312 }
313
314 int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *adapter, ulong addr)
315 {
316         int ret;
317         struct qlcnic_hardware_context *ahw = adapter->ahw;
318
319         ret = __qlcnic_set_win_base(adapter, (u32) addr);
320         if (!ret) {
321                 return QLCRDX(ahw, QLCNIC_WILDCARD);
322         } else {
323                 dev_err(&adapter->pdev->dev,
324                         "%s failed, addr = 0x%x\n", __func__, (int)addr);
325                 return -EIO;
326         }
327 }
328
329 int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
330                                  u32 data)
331 {
332         int err;
333         struct qlcnic_hardware_context *ahw = adapter->ahw;
334
335         err = __qlcnic_set_win_base(adapter, (u32) addr);
336         if (!err) {
337                 QLCWRX(ahw, QLCNIC_WILDCARD, data);
338                 return 0;
339         } else {
340                 dev_err(&adapter->pdev->dev,
341                         "%s failed, addr = 0x%x data = 0x%x\n",
342                         __func__, (int)addr, data);
343                 return err;
344         }
345 }
346
347 int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
348 {
349         int err, i, num_msix;
350         struct qlcnic_hardware_context *ahw = adapter->ahw;
351
352         if (!num_intr)
353                 num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;
354         num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
355                                               num_intr));
356         /* account for AEN interrupt MSI-X based interrupts */
357         num_msix += 1;
358         num_msix += adapter->max_drv_tx_rings;
359         err = qlcnic_enable_msix(adapter, num_msix);
360         if (err == -ENOMEM)
361                 return err;
362         if (adapter->flags & QLCNIC_MSIX_ENABLED)
363                 num_msix = adapter->ahw->num_msix;
364         else
365                 num_msix = 1;
366         /* setup interrupt mapping table for fw */
367         ahw->intr_tbl = vzalloc(num_msix *
368                                 sizeof(struct qlcnic_intrpt_config));
369         if (!ahw->intr_tbl)
370                 return -ENOMEM;
371         if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
372                 /* MSI-X enablement failed, use legacy interrupt */
373                 adapter->tgt_status_reg = ahw->pci_base0 + QLC_83XX_INTX_PTR;
374                 adapter->tgt_mask_reg = ahw->pci_base0 + QLC_83XX_INTX_MASK;
375                 adapter->isr_int_vec = ahw->pci_base0 + QLC_83XX_INTX_TRGR;
376                 adapter->msix_entries[0].vector = adapter->pdev->irq;
377                 dev_info(&adapter->pdev->dev, "using legacy interrupt\n");
378         }
379
380         for (i = 0; i < num_msix; i++) {
381                 if (adapter->flags & QLCNIC_MSIX_ENABLED)
382                         ahw->intr_tbl[i].type = QLCNIC_INTRPT_MSIX;
383                 else
384                         ahw->intr_tbl[i].type = QLCNIC_INTRPT_INTX;
385                 ahw->intr_tbl[i].id = i;
386                 ahw->intr_tbl[i].src = 0;
387         }
388         return 0;
389 }
390
391 inline void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter,
392                                     struct qlcnic_host_sds_ring *sds_ring)
393 {
394         writel(0, sds_ring->crb_intr_mask);
395         if (!QLCNIC_IS_MSI_FAMILY(adapter))
396                 writel(0, adapter->tgt_mask_reg);
397 }
398
399 static inline void qlcnic_83xx_get_mbx_data(struct qlcnic_adapter *adapter,
400                                      struct qlcnic_cmd_args *cmd)
401 {
402         int i;
403         for (i = 0; i < cmd->rsp.num; i++)
404                 cmd->rsp.arg[i] = readl(QLCNIC_MBX_FW(adapter->ahw, i));
405 }
406
407 irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
408 {
409         u32 intr_val;
410         struct qlcnic_hardware_context *ahw = adapter->ahw;
411         int retries = 0;
412
413         intr_val = readl(adapter->tgt_status_reg);
414
415         if (!QLC_83XX_VALID_INTX_BIT31(intr_val))
416                 return IRQ_NONE;
417
418         if (QLC_83XX_INTX_FUNC(intr_val) != adapter->ahw->pci_func) {
419                 adapter->stats.spurious_intr++;
420                 return IRQ_NONE;
421         }
422         /* clear the interrupt trigger control register */
423         writel(0, adapter->isr_int_vec);
424         do {
425                 intr_val = readl(adapter->tgt_status_reg);
426                 if (QLC_83XX_INTX_FUNC(intr_val) != ahw->pci_func)
427                         break;
428                 retries++;
429         } while (QLC_83XX_VALID_INTX_BIT30(intr_val) &&
430                  (retries < QLC_83XX_LEGACY_INTX_MAX_RETRY));
431
432         if (retries == QLC_83XX_LEGACY_INTX_MAX_RETRY) {
433                 dev_info(&adapter->pdev->dev,
434                          "Reached maximum retries to clear legacy interrupt\n");
435                 return IRQ_NONE;
436         }
437
438         mdelay(QLC_83XX_LEGACY_INTX_DELAY);
439
440         return IRQ_HANDLED;
441 }
442
443 irqreturn_t qlcnic_83xx_tmp_intr(int irq, void *data)
444 {
445         struct qlcnic_host_sds_ring *sds_ring = data;
446         struct qlcnic_adapter *adapter = sds_ring->adapter;
447
448         if (adapter->flags & QLCNIC_MSIX_ENABLED)
449                 goto done;
450
451         if (adapter->nic_ops->clear_legacy_intr(adapter) == IRQ_NONE)
452                 return IRQ_NONE;
453
454 done:
455         adapter->ahw->diag_cnt++;
456         qlcnic_83xx_enable_intr(adapter, sds_ring);
457
458         return IRQ_HANDLED;
459 }
460
461 void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
462 {
463         u32 val = 0;
464         u32 num_msix = adapter->ahw->num_msix - 1;
465
466         val = (num_msix << 8);
467
468         QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val);
469         if (adapter->flags & QLCNIC_MSIX_ENABLED)
470                 free_irq(adapter->msix_entries[num_msix].vector, adapter);
471 }
472
473 int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
474 {
475         irq_handler_t handler;
476         u32 val;
477         char name[32];
478         int err = 0;
479         unsigned long flags = 0;
480
481         if (!(adapter->flags & QLCNIC_MSI_ENABLED) &&
482             !(adapter->flags & QLCNIC_MSIX_ENABLED))
483                 flags |= IRQF_SHARED;
484
485         if (adapter->flags & QLCNIC_MSIX_ENABLED) {
486                 handler = qlcnic_83xx_handle_aen;
487                 val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector;
488                 snprintf(name, (IFNAMSIZ + 4),
489                          "%s[%s]", adapter->netdev->name, "aen");
490                 err = request_irq(val, handler, flags, name, adapter);
491                 if (err) {
492                         dev_err(&adapter->pdev->dev,
493                                 "failed to register MBX interrupt\n");
494                         return err;
495                 }
496         }
497
498         /* Enable mailbox interrupt */
499         qlcnic_83xx_enable_mbx_intrpt(adapter);
500         if (adapter->flags & QLCNIC_MSIX_ENABLED)
501                 err = qlcnic_83xx_config_intrpt(adapter, 1);
502
503         return err;
504 }
505
506 void qlcnic_83xx_get_func_no(struct qlcnic_adapter *adapter)
507 {
508         u32 val = QLCRDX(adapter->ahw, QLCNIC_INFORMANT);
509         adapter->ahw->pci_func = val & 0xf;
510 }
511
512 int qlcnic_83xx_cam_lock(struct qlcnic_adapter *adapter)
513 {
514         void __iomem *addr;
515         u32 val, limit = 0;
516
517         struct qlcnic_hardware_context *ahw = adapter->ahw;
518
519         addr = ahw->pci_base0 + QLC_83XX_SEM_LOCK_FUNC(ahw->pci_func);
520         do {
521                 val = readl(addr);
522                 if (val) {
523                         /* write the function number to register */
524                         QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER,
525                                             ahw->pci_func);
526                         return 0;
527                 }
528                 usleep_range(1000, 2000);
529         } while (++limit <= QLCNIC_PCIE_SEM_TIMEOUT);
530
531         return -EIO;
532 }
533
534 void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *adapter)
535 {
536         void __iomem *addr;
537         u32 val;
538         struct qlcnic_hardware_context *ahw = adapter->ahw;
539
540         addr = ahw->pci_base0 + QLC_83XX_SEM_UNLOCK_FUNC(ahw->pci_func);
541         val = readl(addr);
542 }
543
544 void qlcnic_83xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
545                           loff_t offset, size_t size)
546 {
547         int ret;
548         u32 data;
549
550         if (qlcnic_api_lock(adapter)) {
551                 dev_err(&adapter->pdev->dev,
552                         "%s: failed to acquire lock. addr offset 0x%x\n",
553                         __func__, (u32)offset);
554                 return;
555         }
556
557         ret = qlcnic_83xx_rd_reg_indirect(adapter, (u32) offset);
558         qlcnic_api_unlock(adapter);
559
560         if (ret == -EIO) {
561                 dev_err(&adapter->pdev->dev,
562                         "%s: failed. addr offset 0x%x\n",
563                         __func__, (u32)offset);
564                 return;
565         }
566         data = ret;
567         memcpy(buf, &data, size);
568 }
569
570 void qlcnic_83xx_write_crb(struct qlcnic_adapter *adapter, char *buf,
571                            loff_t offset, size_t size)
572 {
573         u32 data;
574
575         memcpy(&data, buf, size);
576         qlcnic_83xx_wrt_reg_indirect(adapter, (u32) offset, data);
577 }
578
579 int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
580 {
581         int status;
582
583         status = qlcnic_83xx_get_port_config(adapter);
584         if (status) {
585                 dev_err(&adapter->pdev->dev,
586                         "Get Port Info failed\n");
587         } else {
588                 if (QLC_83XX_SFP_10G_CAPABLE(adapter->ahw->port_config))
589                         adapter->ahw->port_type = QLCNIC_XGBE;
590                 else
591                         adapter->ahw->port_type = QLCNIC_GBE;
592                 if (QLC_83XX_AUTONEG(adapter->ahw->port_config))
593                         adapter->ahw->link_autoneg = AUTONEG_ENABLE;
594         }
595         return status;
596 }
597
598 void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *adapter)
599 {
600         u32 val;
601
602         if (adapter->flags & QLCNIC_MSIX_ENABLED)
603                 val = BIT_2 | ((adapter->ahw->num_msix - 1) << 8);
604         else
605                 val = BIT_2;
606         QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val);
607 }
608
609 void qlcnic_83xx_check_vf(struct qlcnic_adapter *adapter,
610                           const struct pci_device_id *ent)
611 {
612         u32 op_mode, priv_level;
613         struct qlcnic_hardware_context *ahw = adapter->ahw;
614
615         /* Determine FW API version */
616         ahw->fw_hal_version = 2;
617         /* Find PCI function number */
618         qlcnic_get_func_no(adapter);
619
620         /* Determine function privilege level */
621         op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
622         if (op_mode == QLC_83XX_DEFAULT_OPMODE)
623                 priv_level = QLCNIC_MGMT_FUNC;
624         else
625                 priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode,
626                                                          ahw->pci_func);
627
628         if (priv_level == QLCNIC_NON_PRIV_FUNC) {
629                 ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
630                 dev_info(&adapter->pdev->dev,
631                          "HAL Version: %d Non Privileged function\n",
632                          ahw->fw_hal_version);
633                 adapter->nic_ops = &qlcnic_vf_ops;
634         } else {
635                 adapter->nic_ops = &qlcnic_83xx_ops;
636         }
637 }
638
639 static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
640                                         u32 data[]);
641 static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter,
642                                             u32 data[]);
643
644 static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
645                             struct qlcnic_cmd_args *cmd)
646 {
647         int i;
648
649         dev_info(&adapter->pdev->dev,
650                  "Host MBX regs(%d)\n", cmd->req.num);
651         for (i = 0; i < cmd->req.num; i++) {
652                 if (i && !(i % 8))
653                         pr_info("\n");
654                 pr_info("%08x ", cmd->req.arg[i]);
655         }
656         pr_info("\n");
657         dev_info(&adapter->pdev->dev,
658                  "FW MBX regs(%d)\n", cmd->rsp.num);
659         for (i = 0; i < cmd->rsp.num; i++) {
660                 if (i && !(i % 8))
661                         pr_info("\n");
662                 pr_info("%08x ", cmd->rsp.arg[i]);
663         }
664         pr_info("\n");
665 }
666
667 static u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter)
668 {
669         u32 data;
670         unsigned long wait_time = 0;
671         struct qlcnic_hardware_context *ahw = adapter->ahw;
672         /* wait for mailbox completion */
673         do {
674                 data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
675                 if (++wait_time > QLCNIC_MBX_TIMEOUT) {
676                         data = QLCNIC_RCODE_TIMEOUT;
677                         break;
678                 }
679                 mdelay(1);
680         } while (!data);
681         return data;
682 }
683
684 int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter,
685                        struct qlcnic_cmd_args *cmd)
686 {
687         int i;
688         u16 opcode;
689         u8 mbx_err_code, mac_cmd_rcode;
690         u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, temp, fw[8];
691         struct qlcnic_hardware_context *ahw = adapter->ahw;
692
693         opcode = LSW(cmd->req.arg[0]);
694         spin_lock(&ahw->mbx_lock);
695         mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
696
697         if (mbx_val) {
698                 QLCDB(adapter, DRV,
699                       "Mailbox cmd attempted, 0x%x\n", opcode);
700                 QLCDB(adapter, DRV,
701                       "Mailbox not available, 0x%x, collect FW dump\n",
702                       mbx_val);
703                 cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
704                 spin_unlock(&ahw->mbx_lock);
705                 return cmd->rsp.arg[0];
706         }
707
708         /* Fill in mailbox registers */
709         mbx_cmd = cmd->req.arg[0];
710         writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
711         for (i = 1; i < cmd->req.num; i++)
712                 writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i));
713
714         /* Signal FW about the impending command */
715         QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
716 poll:
717         rsp = qlcnic_83xx_mbx_poll(adapter);
718         /* Get the FW response data */
719         fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
720         mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
721         rsp_num = QLCNIC_MBX_NUM_REGS(fw_data);
722         opcode = QLCNIC_MBX_RSP(fw_data);
723
724         if (rsp != QLCNIC_RCODE_TIMEOUT) {
725                 if (opcode == QLCNIC_MBX_LINK_EVENT) {
726                         for (i = 0; i < rsp_num; i++) {
727                                 temp = readl(QLCNIC_MBX_FW(ahw, i));
728                                 fw[i] = temp;
729                         }
730                         qlcnic_83xx_handle_link_aen(adapter, fw);
731                         /* clear fw mbx control register */
732                         QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
733                         mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
734                         if (mbx_val)
735                                 goto poll;
736                 } else if (opcode == QLCNIC_MBX_COMP_EVENT) {
737                         for (i = 0; i < rsp_num; i++) {
738                                 temp = readl(QLCNIC_MBX_FW(ahw, i));
739                                 fw[i] = temp;
740                         }
741                         qlcnic_83xx_handle_idc_comp_aen(adapter, fw);
742                         /* clear fw mbx control register */
743                         QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
744                         mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
745                         if (mbx_val)
746                                 goto poll;
747                 } else if (opcode == QLCNIC_MBX_REQUEST_EVENT) {
748                         /* IDC Request Notification */
749                         for (i = 0; i < rsp_num; i++) {
750                                 temp = readl(QLCNIC_MBX_FW(ahw, i));
751                                 fw[i] = temp;
752                         }
753                         for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++) {
754                                 temp = QLCNIC_MBX_RSP(fw[i]);
755                                 adapter->ahw->mbox_aen[i] = temp;
756                         }
757                         queue_delayed_work(adapter->qlcnic_wq,
758                                            &adapter->idc_aen_work, 0);
759                         /* clear fw mbx control register */
760                         QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
761                         mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
762                         if (mbx_val)
763                                 goto poll;
764                 } else if ((mbx_err_code == QLCNIC_MBX_RSP_OK) ||
765                            (mbx_err_code == QLCNIC_MBX_PORT_RSP_OK)) {
766                         qlcnic_83xx_get_mbx_data(adapter, cmd);
767                         rsp = QLCNIC_RCODE_SUCCESS;
768                 } else {
769                         qlcnic_83xx_get_mbx_data(adapter, cmd);
770                         if (opcode == QLCNIC_CMD_CONFIG_MAC_VLAN) {
771                                 fw_data = readl(QLCNIC_MBX_FW(ahw, 2));
772                                 mac_cmd_rcode = (u8)fw_data;
773                                 if (mac_cmd_rcode == QLC_83XX_NO_NIC_RESOURCE ||
774                                     mac_cmd_rcode == QLC_83XX_MAC_PRESENT ||
775                                     mac_cmd_rcode == QLC_83XX_MAC_ABSENT) {
776                                         rsp = QLCNIC_RCODE_SUCCESS;
777                                         goto out;
778                                 }
779                         }
780                         dev_info(&adapter->pdev->dev,
781                                  "MBX command 0x%x failed with err:0x%x\n",
782                                  opcode, mbx_err_code);
783                         rsp = mbx_err_code;
784                         qlcnic_dump_mbx(adapter, cmd);
785                 }
786         } else {
787                 dev_info(&adapter->pdev->dev,
788                          "MBX command 0x%x timed out\n", opcode);
789                 qlcnic_dump_mbx(adapter, cmd);
790         }
791 out:
792         /* clear fw mbx control register */
793         QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
794         spin_unlock(&ahw->mbx_lock);
795         return rsp;
796 }
797
798 int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
799                                struct qlcnic_adapter *adapter, u32 type)
800 {
801         int i, size;
802         u32 temp;
803         const struct qlcnic_mailbox_metadata *mbx_tbl;
804
805         mbx_tbl = qlcnic_83xx_mbx_tbl;
806         size = ARRAY_SIZE(qlcnic_83xx_mbx_tbl);
807         for (i = 0; i < size; i++) {
808                 if (type == mbx_tbl[i].cmd) {
809                         mbx->req.num = mbx_tbl[i].in_args;
810                         mbx->rsp.num = mbx_tbl[i].out_args;
811                         mbx->req.arg = kcalloc(mbx->req.num, sizeof(u32),
812                                                GFP_ATOMIC);
813                         if (!mbx->req.arg)
814                                 return -ENOMEM;
815                         mbx->rsp.arg = kcalloc(mbx->rsp.num, sizeof(u32),
816                                                GFP_ATOMIC);
817                         if (!mbx->rsp.arg) {
818                                 kfree(mbx->req.arg);
819                                 mbx->req.arg = NULL;
820                                 return -ENOMEM;
821                         }
822                         memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num);
823                         memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
824                         temp = adapter->ahw->fw_hal_version << 29;
825                         mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp);
826                         break;
827                 }
828         }
829         return 0;
830 }
831
832 void qlcnic_83xx_idc_aen_work(struct work_struct *work)
833 {
834         struct qlcnic_adapter *adapter;
835         struct qlcnic_cmd_args cmd;
836         int i, err = 0;
837
838         adapter = container_of(work, struct qlcnic_adapter, idc_aen_work.work);
839         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_IDC_ACK);
840
841         for (i = 1; i < QLC_83XX_MBX_AEN_CNT; i++)
842                 cmd.req.arg[i] = adapter->ahw->mbox_aen[i];
843
844         err = qlcnic_issue_cmd(adapter, &cmd);
845         if (err)
846                 dev_info(&adapter->pdev->dev,
847                          "%s: Mailbox IDC ACK failed.\n", __func__);
848         qlcnic_free_mbx_args(&cmd);
849 }
850
851 static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter,
852                                             u32 data[])
853 {
854         dev_dbg(&adapter->pdev->dev, "Completion AEN:0x%x.\n",
855                 QLCNIC_MBX_RSP(data[0]));
856         return;
857 }
858
859 void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
860 {
861         u32 mask, resp, event[QLC_83XX_MBX_AEN_CNT];
862         int i;
863         struct qlcnic_hardware_context *ahw = adapter->ahw;
864
865         if (!spin_trylock(&ahw->mbx_lock)) {
866                 mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
867                 writel(0, adapter->ahw->pci_base0 + mask);
868                 return;
869         }
870         resp = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
871
872         if (!(resp & QLCNIC_SET_OWNER))
873                 goto out;
874
875         for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
876                 event[i] = readl(QLCNIC_MBX_FW(ahw, i));
877
878         switch (QLCNIC_MBX_RSP(event[0])) {
879
880         case QLCNIC_MBX_LINK_EVENT:
881                 qlcnic_83xx_handle_link_aen(adapter, event);
882                 break;
883         case QLCNIC_MBX_COMP_EVENT:
884                 qlcnic_83xx_handle_idc_comp_aen(adapter, event);
885                 break;
886         case QLCNIC_MBX_REQUEST_EVENT:
887                 for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
888                         adapter->ahw->mbox_aen[i] = QLCNIC_MBX_RSP(event[i]);
889                 queue_delayed_work(adapter->qlcnic_wq,
890                                    &adapter->idc_aen_work, 0);
891                 break;
892         case QLCNIC_MBX_TIME_EXTEND_EVENT:
893                 break;
894         case QLCNIC_MBX_SFP_INSERT_EVENT:
895                 dev_info(&adapter->pdev->dev, "SFP+ Insert AEN:0x%x.\n",
896                          QLCNIC_MBX_RSP(event[0]));
897                 break;
898         case QLCNIC_MBX_SFP_REMOVE_EVENT:
899                 dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n",
900                          QLCNIC_MBX_RSP(event[0]));
901                 break;
902         default:
903                 dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n",
904                         QLCNIC_MBX_RSP(event[0]));
905                 break;
906         }
907
908         QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
909 out:
910         mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
911         writel(0, adapter->ahw->pci_base0 + mask);
912         spin_unlock(&ahw->mbx_lock);
913 }
914
915 static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter)
916 {
917         int index, i, err, sds_mbx_size;
918         u32 *buf, intrpt_id, intr_mask;
919         u16 context_id;
920         u8 num_sds;
921         struct qlcnic_cmd_args cmd;
922         struct qlcnic_host_sds_ring *sds;
923         struct qlcnic_sds_mbx sds_mbx;
924         struct qlcnic_add_rings_mbx_out *mbx_out;
925         struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
926         struct qlcnic_hardware_context *ahw = adapter->ahw;
927
928         sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
929         context_id = recv_ctx->context_id;
930         num_sds = (adapter->max_sds_rings - QLCNIC_MAX_RING_SETS);
931         ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
932                                     QLCNIC_CMD_ADD_RCV_RINGS);
933         cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16);
934
935         /* set up status rings, mbx 2-81 */
936         index = 2;
937         for (i = 8; i < adapter->max_sds_rings; i++) {
938                 memset(&sds_mbx, 0, sds_mbx_size);
939                 sds = &recv_ctx->sds_rings[i];
940                 sds->consumer = 0;
941                 memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
942                 sds_mbx.phy_addr = sds->phys_addr;
943                 sds_mbx.sds_ring_size = sds->num_desc;
944
945                 if (adapter->flags & QLCNIC_MSIX_ENABLED)
946                         intrpt_id = ahw->intr_tbl[i].id;
947                 else
948                         intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
949
950                 if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
951                         sds_mbx.intrpt_id = intrpt_id;
952                 else
953                         sds_mbx.intrpt_id = 0xffff;
954                 sds_mbx.intrpt_val = 0;
955                 buf = &cmd.req.arg[index];
956                 memcpy(buf, &sds_mbx, sds_mbx_size);
957                 index += sds_mbx_size / sizeof(u32);
958         }
959
960         /* send the mailbox command */
961         err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
962         if (err) {
963                 dev_err(&adapter->pdev->dev,
964                         "Failed to add rings %d\n", err);
965                 goto out;
966         }
967
968         mbx_out = (struct qlcnic_add_rings_mbx_out *)&cmd.rsp.arg[1];
969         index = 0;
970         /* status descriptor ring */
971         for (i = 8; i < adapter->max_sds_rings; i++) {
972                 sds = &recv_ctx->sds_rings[i];
973                 sds->crb_sts_consumer = ahw->pci_base0 +
974                                         mbx_out->host_csmr[index];
975                 if (adapter->flags & QLCNIC_MSIX_ENABLED)
976                         intr_mask = ahw->intr_tbl[i].src;
977                 else
978                         intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
979
980                 sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
981                 index++;
982         }
983 out:
984         qlcnic_free_mbx_args(&cmd);
985         return err;
986 }
987
988 int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
989 {
990         int i, err, index, sds_mbx_size, rds_mbx_size;
991         u8 num_sds, num_rds;
992         u32 *buf, intrpt_id, intr_mask, cap = 0;
993         struct qlcnic_host_sds_ring *sds;
994         struct qlcnic_host_rds_ring *rds;
995         struct qlcnic_sds_mbx sds_mbx;
996         struct qlcnic_rds_mbx rds_mbx;
997         struct qlcnic_cmd_args cmd;
998         struct qlcnic_rcv_mbx_out *mbx_out;
999         struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1000         struct qlcnic_hardware_context *ahw = adapter->ahw;
1001         num_rds = adapter->max_rds_rings;
1002
1003         if (adapter->max_sds_rings <= QLCNIC_MAX_RING_SETS)
1004                 num_sds = adapter->max_sds_rings;
1005         else
1006                 num_sds = QLCNIC_MAX_RING_SETS;
1007
1008         sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
1009         rds_mbx_size = sizeof(struct qlcnic_rds_mbx);
1010         cap = QLCNIC_CAP0_LEGACY_CONTEXT;
1011
1012         if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
1013                 cap |= QLC_83XX_FW_CAP_LRO_MSS;
1014
1015         /* set mailbox hdr and capabilities */
1016         qlcnic_alloc_mbx_args(&cmd, adapter,
1017                               QLCNIC_CMD_CREATE_RX_CTX);
1018         cmd.req.arg[1] = cap;
1019         cmd.req.arg[5] = 1 | (num_rds << 5) | (num_sds << 8) |
1020                          (QLC_83XX_HOST_RDS_MODE_UNIQUE << 16);
1021         /* set up status rings, mbx 8-57/87 */
1022         index = QLC_83XX_HOST_SDS_MBX_IDX;
1023         for (i = 0; i < num_sds; i++) {
1024                 memset(&sds_mbx, 0, sds_mbx_size);
1025                 sds = &recv_ctx->sds_rings[i];
1026                 sds->consumer = 0;
1027                 memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
1028                 sds_mbx.phy_addr = sds->phys_addr;
1029                 sds_mbx.sds_ring_size = sds->num_desc;
1030                 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1031                         intrpt_id = ahw->intr_tbl[i].id;
1032                 else
1033                         intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
1034                 if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
1035                         sds_mbx.intrpt_id = intrpt_id;
1036                 else
1037                         sds_mbx.intrpt_id = 0xffff;
1038                 sds_mbx.intrpt_val = 0;
1039                 buf = &cmd.req.arg[index];
1040                 memcpy(buf, &sds_mbx, sds_mbx_size);
1041                 index += sds_mbx_size / sizeof(u32);
1042         }
1043         /* set up receive rings, mbx 88-111/135 */
1044         index = QLCNIC_HOST_RDS_MBX_IDX;
1045         rds = &recv_ctx->rds_rings[0];
1046         rds->producer = 0;
1047         memset(&rds_mbx, 0, rds_mbx_size);
1048         rds_mbx.phy_addr_reg = rds->phys_addr;
1049         rds_mbx.reg_ring_sz = rds->dma_size;
1050         rds_mbx.reg_ring_len = rds->num_desc;
1051         /* Jumbo ring */
1052         rds = &recv_ctx->rds_rings[1];
1053         rds->producer = 0;
1054         rds_mbx.phy_addr_jmb = rds->phys_addr;
1055         rds_mbx.jmb_ring_sz = rds->dma_size;
1056         rds_mbx.jmb_ring_len = rds->num_desc;
1057         buf = &cmd.req.arg[index];
1058         memcpy(buf, &rds_mbx, rds_mbx_size);
1059
1060         /* send the mailbox command */
1061         err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
1062         if (err) {
1063                 dev_err(&adapter->pdev->dev,
1064                         "Failed to create Rx ctx in firmware%d\n", err);
1065                 goto out;
1066         }
1067         mbx_out = (struct qlcnic_rcv_mbx_out *)&cmd.rsp.arg[1];
1068         recv_ctx->context_id = mbx_out->ctx_id;
1069         recv_ctx->state = mbx_out->state;
1070         recv_ctx->virt_port = mbx_out->vport_id;
1071         dev_info(&adapter->pdev->dev, "Rx Context[%d] Created, state:0x%x\n",
1072                  recv_ctx->context_id, recv_ctx->state);
1073         /* Receive descriptor ring */
1074         /* Standard ring */
1075         rds = &recv_ctx->rds_rings[0];
1076         rds->crb_rcv_producer = ahw->pci_base0 +
1077                                 mbx_out->host_prod[0].reg_buf;
1078         /* Jumbo ring */
1079         rds = &recv_ctx->rds_rings[1];
1080         rds->crb_rcv_producer = ahw->pci_base0 +
1081                                 mbx_out->host_prod[0].jmb_buf;
1082         /* status descriptor ring */
1083         for (i = 0; i < num_sds; i++) {
1084                 sds = &recv_ctx->sds_rings[i];
1085                 sds->crb_sts_consumer = ahw->pci_base0 +
1086                                         mbx_out->host_csmr[i];
1087                 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1088                         intr_mask = ahw->intr_tbl[i].src;
1089                 else
1090                         intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
1091                 sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
1092         }
1093
1094         if (adapter->max_sds_rings > QLCNIC_MAX_RING_SETS)
1095                 err = qlcnic_83xx_add_rings(adapter);
1096 out:
1097         qlcnic_free_mbx_args(&cmd);
1098         return err;
1099 }
1100
1101 int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
1102                               struct qlcnic_host_tx_ring *tx, int ring)
1103 {
1104         int err;
1105         u16 msix_id;
1106         u32 *buf, intr_mask;
1107         struct qlcnic_cmd_args cmd;
1108         struct qlcnic_tx_mbx mbx;
1109         struct qlcnic_tx_mbx_out *mbx_out;
1110         struct qlcnic_hardware_context *ahw = adapter->ahw;
1111
1112         /* Reset host resources */
1113         tx->producer = 0;
1114         tx->sw_consumer = 0;
1115         *(tx->hw_consumer) = 0;
1116
1117         memset(&mbx, 0, sizeof(struct qlcnic_tx_mbx));
1118
1119         /* setup mailbox inbox registerss */
1120         mbx.phys_addr = tx->phys_addr;
1121         mbx.cnsmr_index = tx->hw_cons_phys_addr;
1122         mbx.size = tx->num_desc;
1123         if (adapter->flags & QLCNIC_MSIX_ENABLED)
1124                 msix_id = ahw->intr_tbl[adapter->max_sds_rings + ring].id;
1125         else
1126                 msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
1127         if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
1128                 mbx.intr_id = msix_id;
1129         else
1130                 mbx.intr_id = 0xffff;
1131         mbx.src = 0;
1132
1133         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
1134         cmd.req.arg[1] = QLCNIC_CAP0_LEGACY_CONTEXT;
1135         cmd.req.arg[5] = QLCNIC_MAX_TX_QUEUES;
1136         buf = &cmd.req.arg[6];
1137         memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx));
1138         /* send the mailbox command*/
1139         err = qlcnic_issue_cmd(adapter, &cmd);
1140         if (err) {
1141                 dev_err(&adapter->pdev->dev,
1142                         "Failed to create Tx ctx in firmware 0x%x\n", err);
1143                 goto out;
1144         }
1145         mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2];
1146         tx->crb_cmd_producer = ahw->pci_base0 + mbx_out->host_prod;
1147         tx->ctx_id = mbx_out->ctx_id;
1148         if (adapter->flags & QLCNIC_MSIX_ENABLED) {
1149                 intr_mask = ahw->intr_tbl[adapter->max_sds_rings + ring].src;
1150                 tx->crb_intr_mask = ahw->pci_base0 + intr_mask;
1151         }
1152         dev_info(&adapter->pdev->dev, "Tx Context[0x%x] Created, state:0x%x\n",
1153                  tx->ctx_id, mbx_out->state);
1154 out:
1155         qlcnic_free_mbx_args(&cmd);
1156         return err;
1157 }
1158
1159 int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state,
1160                            u32 beacon)
1161 {
1162         struct qlcnic_cmd_args cmd;
1163         u32 mbx_in;
1164         int i, status = 0;
1165
1166         if (state) {
1167                 /* Get LED configuration */
1168                 qlcnic_alloc_mbx_args(&cmd, adapter,
1169                                       QLCNIC_CMD_GET_LED_CONFIG);
1170                 status = qlcnic_issue_cmd(adapter, &cmd);
1171                 if (status) {
1172                         dev_err(&adapter->pdev->dev,
1173                                 "Get led config failed.\n");
1174                         goto mbx_err;
1175                 } else {
1176                         for (i = 0; i < 4; i++)
1177                                 adapter->ahw->mbox_reg[i] = cmd.rsp.arg[i+1];
1178                 }
1179                 qlcnic_free_mbx_args(&cmd);
1180                 /* Set LED Configuration */
1181                 mbx_in = (LSW(QLC_83XX_LED_CONFIG) << 16) |
1182                           LSW(QLC_83XX_LED_CONFIG);
1183                 qlcnic_alloc_mbx_args(&cmd, adapter,
1184                                       QLCNIC_CMD_SET_LED_CONFIG);
1185                 cmd.req.arg[1] = mbx_in;
1186                 cmd.req.arg[2] = mbx_in;
1187                 cmd.req.arg[3] = mbx_in;
1188                 if (beacon)
1189                         cmd.req.arg[4] = QLC_83XX_ENABLE_BEACON;
1190                 status = qlcnic_issue_cmd(adapter, &cmd);
1191                 if (status) {
1192                         dev_err(&adapter->pdev->dev,
1193                                 "Set led config failed.\n");
1194                 }
1195 mbx_err:
1196                 qlcnic_free_mbx_args(&cmd);
1197                 return status;
1198
1199         } else {
1200                 /* Restoring default LED configuration */
1201                 qlcnic_alloc_mbx_args(&cmd, adapter,
1202                                       QLCNIC_CMD_SET_LED_CONFIG);
1203                 cmd.req.arg[1] = adapter->ahw->mbox_reg[0];
1204                 cmd.req.arg[2] = adapter->ahw->mbox_reg[1];
1205                 cmd.req.arg[3] = adapter->ahw->mbox_reg[2];
1206                 if (beacon)
1207                         cmd.req.arg[4] = adapter->ahw->mbox_reg[3];
1208                 status = qlcnic_issue_cmd(adapter, &cmd);
1209                 if (status)
1210                         dev_err(&adapter->pdev->dev,
1211                                 "Restoring led config failed.\n");
1212                 qlcnic_free_mbx_args(&cmd);
1213                 return status;
1214         }
1215 }
1216
1217 void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter,
1218                                        int enable)
1219 {
1220         struct qlcnic_cmd_args cmd;
1221         int status;
1222
1223         if (enable) {
1224                 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INIT_NIC_FUNC);
1225                 cmd.req.arg[1] = 1 | BIT_0;
1226         } else {
1227                 qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_STOP_NIC_FUNC);
1228                 cmd.req.arg[1] = 0 | BIT_0;
1229         }
1230         status = qlcnic_issue_cmd(adapter, &cmd);
1231         if (status)
1232                 dev_err(&adapter->pdev->dev,
1233                         "Failed to %s in NIC IDC function event.\n",
1234                         (enable ? "register" : "unregister"));
1235
1236         qlcnic_free_mbx_args(&cmd);
1237 }
1238
1239 int qlcnic_83xx_set_port_config(struct qlcnic_adapter *adapter)
1240 {
1241         struct qlcnic_cmd_args cmd;
1242         int err;
1243
1244         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORT_CONFIG);
1245         cmd.req.arg[1] = adapter->ahw->port_config;
1246         err = qlcnic_issue_cmd(adapter, &cmd);
1247         if (err)
1248                 dev_info(&adapter->pdev->dev, "Set Port Config failed.\n");
1249         qlcnic_free_mbx_args(&cmd);
1250         return err;
1251 }
1252
1253 int qlcnic_83xx_get_port_config(struct qlcnic_adapter *adapter)
1254 {
1255         struct qlcnic_cmd_args cmd;
1256         int err;
1257
1258         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PORT_CONFIG);
1259         err = qlcnic_issue_cmd(adapter, &cmd);
1260         if (err)
1261                 dev_info(&adapter->pdev->dev, "Get Port config failed\n");
1262         else
1263                 adapter->ahw->port_config = cmd.rsp.arg[1];
1264         qlcnic_free_mbx_args(&cmd);
1265         return err;
1266 }
1267
1268 int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *adapter, int enable)
1269 {
1270         int err;
1271         u32 temp;
1272         struct qlcnic_cmd_args cmd;
1273
1274         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_EVENT);
1275         temp = adapter->recv_ctx->context_id << 16;
1276         cmd.req.arg[1] = (enable ? 1 : 0) | BIT_8 | temp;
1277         err = qlcnic_issue_cmd(adapter, &cmd);
1278         if (err)
1279                 dev_info(&adapter->pdev->dev,
1280                          "Setup linkevent mailbox failed\n");
1281         qlcnic_free_mbx_args(&cmd);
1282         return err;
1283 }
1284
1285 int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
1286 {
1287         int err;
1288         u32 temp;
1289         struct qlcnic_cmd_args cmd;
1290
1291         if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
1292                 return -EIO;
1293
1294         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_MAC_RX_MODE);
1295         temp = adapter->recv_ctx->context_id << 16;
1296         cmd.req.arg[1] = (mode ? 1 : 0) | temp;
1297         err = qlcnic_issue_cmd(adapter, &cmd);
1298         if (err)
1299                 dev_info(&adapter->pdev->dev,
1300                          "Promiscous mode config failed\n");
1301         qlcnic_free_mbx_args(&cmd);
1302
1303         return err;
1304 }
1305
1306 int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
1307 {
1308         struct qlcnic_hardware_context *ahw = adapter->ahw;
1309         int status = 0;
1310         u32 config;
1311
1312         status = qlcnic_83xx_get_port_config(adapter);
1313         if (status)
1314                 return status;
1315
1316         config = ahw->port_config;
1317
1318         if (mode == QLCNIC_ILB_MODE)
1319                 ahw->port_config |= QLC_83XX_CFG_LOOPBACK_HSS;
1320         if (mode == QLCNIC_ELB_MODE)
1321                 ahw->port_config |= QLC_83XX_CFG_LOOPBACK_EXT;
1322
1323         status = qlcnic_83xx_set_port_config(adapter);
1324         if (status) {
1325                 dev_err(&adapter->pdev->dev,
1326                         "Failed to Set Loopback Mode = 0x%x.\n",
1327                         ahw->port_config);
1328                 ahw->port_config = config;
1329                 return status;
1330         }
1331
1332         qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0,
1333                                   QLCNIC_MAC_ADD);
1334         return status;
1335 }
1336
1337 int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
1338 {
1339         struct qlcnic_hardware_context *ahw = adapter->ahw;
1340         int status = 0;
1341         u32 config = ahw->port_config;
1342
1343         if (mode == QLCNIC_ILB_MODE)
1344                 ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_HSS;
1345         if (mode == QLCNIC_ELB_MODE)
1346                 ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_EXT;
1347
1348         status = qlcnic_83xx_set_port_config(adapter);
1349         if (status) {
1350                 dev_err(&adapter->pdev->dev,
1351                         "Failed to Clear Loopback Mode = 0x%x.\n",
1352                         ahw->port_config);
1353                 ahw->port_config = config;
1354                 return status;
1355         }
1356
1357         qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0,
1358                                   QLCNIC_MAC_DEL);
1359         return status;
1360 }
1361
1362 void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip,
1363                                int mode)
1364 {
1365         int err;
1366         u32 temp;
1367         struct qlcnic_cmd_args cmd;
1368
1369         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_IP_ADDR);
1370         if (mode == QLCNIC_IP_UP) {
1371                 temp = adapter->recv_ctx->context_id << 16;
1372                 cmd.req.arg[1] = 1 | temp;
1373         } else {
1374                 temp = adapter->recv_ctx->context_id << 16;
1375                 cmd.req.arg[1] = 2 | temp;
1376         }
1377         cmd.req.arg[2] = ntohl(ip);
1378
1379         err = qlcnic_issue_cmd(adapter, &cmd);
1380         if (err != QLCNIC_RCODE_SUCCESS)
1381                 dev_err(&adapter->netdev->dev,
1382                         "could not notify %s IP 0x%x request\n",
1383                         (mode == QLCNIC_IP_UP) ? "Add" : "Remove", ip);
1384         qlcnic_free_mbx_args(&cmd);
1385 }
1386
1387 int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *adapter, int mode)
1388 {
1389         int err;
1390         u32 temp, arg1;
1391         struct qlcnic_cmd_args cmd;
1392
1393         if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
1394                 return 0;
1395
1396         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_HW_LRO);
1397         temp = adapter->recv_ctx->context_id << 16;
1398         arg1 = (mode ? (BIT_0 | BIT_1 | BIT_3) : 0) | temp;
1399         cmd.req.arg[1] = arg1;
1400
1401         err = qlcnic_issue_cmd(adapter, &cmd);
1402         if (err)
1403                 dev_info(&adapter->pdev->dev, "LRO config failed\n");
1404         qlcnic_free_mbx_args(&cmd);
1405
1406         return err;
1407 }
1408
1409 int qlcnic_83xx_config_rss(struct qlcnic_adapter *adapter, int enable)
1410 {
1411         int err;
1412         u32 word;
1413         struct qlcnic_cmd_args cmd;
1414         const u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
1415                             0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
1416                             0x255b0ec26d5a56daULL };
1417
1418         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_RSS);
1419
1420         /*
1421          * RSS request:
1422          * bits 3-0: Rsvd
1423          *      5-4: hash_type_ipv4
1424          *      7-6: hash_type_ipv6
1425          *        8: enable
1426          *        9: use indirection table
1427          *    16-31: indirection table mask
1428          */
1429         word =  ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) |
1430                 ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) |
1431                 ((u32)(enable & 0x1) << 8) |
1432                 ((0x7ULL) << 16);
1433         cmd.req.arg[1] = (adapter->recv_ctx->context_id);
1434         cmd.req.arg[2] = word;
1435         memcpy(&cmd.req.arg[4], key, sizeof(key));
1436
1437         err = qlcnic_issue_cmd(adapter, &cmd);
1438
1439         if (err)
1440                 dev_info(&adapter->pdev->dev, "RSS config failed\n");
1441         qlcnic_free_mbx_args(&cmd);
1442
1443         return err;
1444
1445 }
1446
1447 int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
1448                                    __le16 vlan_id, u8 op)
1449 {
1450         int err;
1451         u32 *buf;
1452         struct qlcnic_cmd_args cmd;
1453         struct qlcnic_macvlan_mbx mv;
1454
1455         if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
1456                 return -EIO;
1457
1458         err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
1459         if (err)
1460                 return err;
1461         cmd.req.arg[1] = op | (1 << 8) |
1462                         (adapter->recv_ctx->context_id << 16);
1463
1464         mv.vlan = le16_to_cpu(vlan_id);
1465         memcpy(&mv.mac, addr, ETH_ALEN);
1466         buf = &cmd.req.arg[2];
1467         memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
1468         err = qlcnic_issue_cmd(adapter, &cmd);
1469         if (err)
1470                 dev_err(&adapter->pdev->dev,
1471                         "MAC-VLAN %s to CAM failed, err=%d.\n",
1472                         ((op == 1) ? "add " : "delete "), err);
1473         qlcnic_free_mbx_args(&cmd);
1474         return err;
1475 }
1476
1477 void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *adapter, u64 *addr,
1478                                   __le16 vlan_id)
1479 {
1480         u8 mac[ETH_ALEN];
1481         memcpy(&mac, addr, ETH_ALEN);
1482         qlcnic_83xx_sre_macaddr_change(adapter, mac, vlan_id, QLCNIC_MAC_ADD);
1483 }
1484
1485 void qlcnic_83xx_configure_mac(struct qlcnic_adapter *adapter, u8 *mac,
1486                                u8 type, struct qlcnic_cmd_args *cmd)
1487 {
1488         switch (type) {
1489         case QLCNIC_SET_STATION_MAC:
1490         case QLCNIC_SET_FAC_DEF_MAC:
1491                 memcpy(&cmd->req.arg[2], mac, sizeof(u32));
1492                 memcpy(&cmd->req.arg[3], &mac[4], sizeof(u16));
1493                 break;
1494         }
1495         cmd->req.arg[1] = type;
1496 }
1497
1498 int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
1499 {
1500         int err, i;
1501         struct qlcnic_cmd_args cmd;
1502         u32 mac_low, mac_high;
1503
1504         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS);
1505         qlcnic_83xx_configure_mac(adapter, mac, QLCNIC_GET_CURRENT_MAC, &cmd);
1506         err = qlcnic_issue_cmd(adapter, &cmd);
1507
1508         if (err == QLCNIC_RCODE_SUCCESS) {
1509                 mac_low = cmd.rsp.arg[1];
1510                 mac_high = cmd.rsp.arg[2];
1511
1512                 for (i = 0; i < 2; i++)
1513                         mac[i] = (u8) (mac_high >> ((1 - i) * 8));
1514                 for (i = 2; i < 6; i++)
1515                         mac[i] = (u8) (mac_low >> ((5 - i) * 8));
1516         } else {
1517                 dev_err(&adapter->pdev->dev, "Failed to get mac address%d\n",
1518                         err);
1519                 err = -EIO;
1520         }
1521         qlcnic_free_mbx_args(&cmd);
1522         return err;
1523 }
1524
1525 void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter)
1526 {
1527         int err;
1528         u32 temp;
1529         struct qlcnic_cmd_args cmd;
1530         struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
1531
1532         if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
1533                 return;
1534
1535         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
1536         cmd.req.arg[1] = 1 | (adapter->recv_ctx->context_id << 16);
1537         cmd.req.arg[3] = coal->flag;
1538         temp = coal->rx_time_us << 16;
1539         cmd.req.arg[2] = coal->rx_packets | temp;
1540         err = qlcnic_issue_cmd(adapter, &cmd);
1541         if (err != QLCNIC_RCODE_SUCCESS)
1542                 dev_info(&adapter->pdev->dev,
1543                          "Failed to send interrupt coalescence parameters\n");
1544         qlcnic_free_mbx_args(&cmd);
1545 }
1546
1547 static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
1548                                         u32 data[])
1549 {
1550         u8 link_status, duplex;
1551         /* link speed */
1552         link_status = LSB(data[3]) & 1;
1553         adapter->ahw->link_speed = MSW(data[2]);
1554         adapter->ahw->link_autoneg = MSB(MSW(data[3]));
1555         adapter->ahw->module_type = MSB(LSW(data[3]));
1556         duplex = LSB(MSW(data[3]));
1557         if (duplex)
1558                 adapter->ahw->link_duplex = DUPLEX_FULL;
1559         else
1560                 adapter->ahw->link_duplex = DUPLEX_HALF;
1561         adapter->ahw->has_link_events = 1;
1562         qlcnic_advert_link_change(adapter, link_status);
1563 }
1564
1565 irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
1566 {
1567         struct qlcnic_adapter *adapter = data;
1568         qlcnic_83xx_process_aen(adapter);
1569         return IRQ_HANDLED;
1570 }
1571
1572 int qlcnic_enable_eswitch(struct qlcnic_adapter *adapter, u8 port, u8 enable)
1573 {
1574         int err = -EIO;
1575         struct qlcnic_cmd_args cmd;
1576
1577         if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
1578                 dev_err(&adapter->pdev->dev,
1579                         "%s: Error, invoked by non management func\n",
1580                         __func__);
1581                 return err;
1582         }
1583
1584         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH);
1585         cmd.req.arg[1] = (port & 0xf) | BIT_4;
1586         err = qlcnic_issue_cmd(adapter, &cmd);
1587
1588         if (err != QLCNIC_RCODE_SUCCESS) {
1589                 dev_err(&adapter->pdev->dev, "Failed to enable eswitch%d\n",
1590                         err);
1591                 err = -EIO;
1592         }
1593         qlcnic_free_mbx_args(&cmd);
1594
1595         return err;
1596
1597 }
1598
1599 int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *adapter,
1600                              struct qlcnic_info *nic)
1601 {
1602         int i, err = -EIO;
1603         struct qlcnic_cmd_args cmd;
1604
1605         if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
1606                 dev_err(&adapter->pdev->dev,
1607                         "%s: Error, invoked by non management func\n",
1608                         __func__);
1609                 return err;
1610         }
1611
1612         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
1613         cmd.req.arg[1] = (nic->pci_func << 16);
1614         cmd.req.arg[2] = 0x1 << 16;
1615         cmd.req.arg[3] = nic->phys_port | (nic->switch_mode << 16);
1616         cmd.req.arg[4] = nic->capabilities;
1617         cmd.req.arg[5] = (nic->max_mac_filters & 0xFF) | ((nic->max_mtu) << 16);
1618         cmd.req.arg[6] = (nic->max_tx_ques) | ((nic->max_rx_ques) << 16);
1619         cmd.req.arg[7] = (nic->min_tx_bw) | ((nic->max_tx_bw) << 16);
1620         for (i = 8; i < 32; i++)
1621                 cmd.req.arg[i] = 0;
1622
1623         err = qlcnic_issue_cmd(adapter, &cmd);
1624
1625         if (err != QLCNIC_RCODE_SUCCESS) {
1626                 dev_err(&adapter->pdev->dev, "Failed to set nic info%d\n",
1627                         err);
1628                 err = -EIO;
1629         }
1630
1631         qlcnic_free_mbx_args(&cmd);
1632
1633         return err;
1634 }
1635
1636 int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
1637                              struct qlcnic_info *npar_info, u8 func_id)
1638 {
1639         int err;
1640         u32 temp;
1641         u8 op = 0;
1642         struct qlcnic_cmd_args cmd;
1643
1644         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
1645         if (func_id != adapter->ahw->pci_func) {
1646                 temp = func_id << 16;
1647                 cmd.req.arg[1] = op | BIT_31 | temp;
1648         } else {
1649                 cmd.req.arg[1] = adapter->ahw->pci_func << 16;
1650         }
1651         err = qlcnic_issue_cmd(adapter, &cmd);
1652         if (err) {
1653                 dev_info(&adapter->pdev->dev,
1654                          "Failed to get nic info %d\n", err);
1655                 goto out;
1656         }
1657
1658         npar_info->op_type = cmd.rsp.arg[1];
1659         npar_info->pci_func = cmd.rsp.arg[2] & 0xFFFF;
1660         npar_info->op_mode = (cmd.rsp.arg[2] & 0xFFFF0000) >> 16;
1661         npar_info->phys_port = cmd.rsp.arg[3] & 0xFFFF;
1662         npar_info->switch_mode = (cmd.rsp.arg[3] & 0xFFFF0000) >> 16;
1663         npar_info->capabilities = cmd.rsp.arg[4];
1664         npar_info->max_mac_filters = cmd.rsp.arg[5] & 0xFF;
1665         npar_info->max_mtu = (cmd.rsp.arg[5] & 0xFFFF0000) >> 16;
1666         npar_info->max_tx_ques = cmd.rsp.arg[6] & 0xFFFF;
1667         npar_info->max_rx_ques = (cmd.rsp.arg[6] & 0xFFFF0000) >> 16;
1668         npar_info->min_tx_bw = cmd.rsp.arg[7] & 0xFFFF;
1669         npar_info->max_tx_bw = (cmd.rsp.arg[7] & 0xFFFF0000) >> 16;
1670         if (cmd.rsp.arg[8] & 0x1)
1671                 npar_info->max_bw_reg_offset = (cmd.rsp.arg[8] & 0x7FFE) >> 1;
1672         if (cmd.rsp.arg[8] & 0x10000) {
1673                 temp = (cmd.rsp.arg[8] & 0x7FFE0000) >> 17;
1674                 npar_info->max_linkspeed_reg_offset = temp;
1675         }
1676
1677 out:
1678         qlcnic_free_mbx_args(&cmd);
1679         return err;
1680 }
1681
1682 int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
1683                              struct qlcnic_pci_info *pci_info)
1684 {
1685         int i, err = 0, j = 0;
1686         u32 temp;
1687         struct qlcnic_cmd_args cmd;
1688
1689         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
1690         err = qlcnic_issue_cmd(adapter, &cmd);
1691
1692         adapter->ahw->act_pci_func = 0;
1693         if (err == QLCNIC_RCODE_SUCCESS) {
1694                 pci_info->func_count = cmd.rsp.arg[1] & 0xFF;
1695                 dev_info(&adapter->pdev->dev,
1696                          "%s: total functions = %d\n",
1697                          __func__, pci_info->func_count);
1698                 for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) {
1699                         pci_info->id = cmd.rsp.arg[i] & 0xFFFF;
1700                         pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
1701                         i++;
1702                         pci_info->type = cmd.rsp.arg[i] & 0xFFFF;
1703                         if (pci_info->type == QLCNIC_TYPE_NIC)
1704                                 adapter->ahw->act_pci_func++;
1705                         temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
1706                         pci_info->default_port = temp;
1707                         i++;
1708                         pci_info->tx_min_bw = cmd.rsp.arg[i] & 0xFFFF;
1709                         temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
1710                         pci_info->tx_max_bw = temp;
1711                         i = i + 2;
1712                         memcpy(pci_info->mac, &cmd.rsp.arg[i], ETH_ALEN - 2);
1713                         i++;
1714                         memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2);
1715                         i = i + 3;
1716
1717                         dev_info(&adapter->pdev->dev, "%s:\n"
1718                                  "\tid = %d active = %d type = %d\n"
1719                                  "\tport = %d min bw = %d max bw = %d\n"
1720                                  "\tmac_addr =  %pM\n", __func__,
1721                                  pci_info->id, pci_info->active, pci_info->type,
1722                                  pci_info->default_port, pci_info->tx_min_bw,
1723                                  pci_info->tx_max_bw, pci_info->mac);
1724                 }
1725         } else {
1726                 dev_err(&adapter->pdev->dev, "Failed to get PCI Info%d\n",
1727                         err);
1728                 err = -EIO;
1729         }
1730
1731         qlcnic_free_mbx_args(&cmd);
1732
1733         return err;
1734 }
1735
1736 int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type)
1737 {
1738         int i, index, err;
1739         bool type;
1740         u8 max_ints;
1741         u32 val, temp;
1742         struct qlcnic_cmd_args cmd;
1743
1744         max_ints = adapter->ahw->num_msix;
1745         qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT);
1746         cmd.req.arg[1] = max_ints;
1747         for (i = 0, index = 2; i < max_ints; i++) {
1748                 type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL;
1749                 val = type | (adapter->ahw->intr_tbl[i].type << 4);
1750                 if (adapter->ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX)
1751                         val |= (adapter->ahw->intr_tbl[i].id << 16);
1752                 cmd.req.arg[index++] = val;
1753         }
1754         err = qlcnic_issue_cmd(adapter, &cmd);
1755         if (err) {
1756                 dev_err(&adapter->pdev->dev,
1757                         "Failed to configure interrupts 0x%x\n", err);
1758                 goto out;
1759         }
1760
1761         max_ints = cmd.rsp.arg[1];
1762         for (i = 0, index = 2; i < max_ints; i++, index += 2) {
1763                 val = cmd.rsp.arg[index];
1764                 if (LSB(val)) {
1765                         dev_info(&adapter->pdev->dev,
1766                                  "Can't configure interrupt %d\n",
1767                                  adapter->ahw->intr_tbl[i].id);
1768                         continue;
1769                 }
1770                 if (op_type) {
1771                         adapter->ahw->intr_tbl[i].id = MSW(val);
1772                         adapter->ahw->intr_tbl[i].enabled = 1;
1773                         temp = cmd.rsp.arg[index + 1];
1774                         adapter->ahw->intr_tbl[i].src = temp;
1775                 } else {
1776                         adapter->ahw->intr_tbl[i].id = i;
1777                         adapter->ahw->intr_tbl[i].enabled = 0;
1778                         adapter->ahw->intr_tbl[i].src = 0;
1779                 }
1780         }
1781 out:
1782         qlcnic_free_mbx_args(&cmd);
1783         return err;
1784 }