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