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