]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - sys/dev/qlxgbe/ql_hw.c
MFC 250661,251076,251605,252580,254976,255003,258155
[FreeBSD/stable/9.git] / sys / dev / qlxgbe / ql_hw.c
1 /*
2  * Copyright (c) 2013-2014 Qlogic Corporation
3  * All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions
7  *  are met:
8  *
9  *  1. Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  *  POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 /*
29  * File: ql_hw.c
30  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
31  * Content: Contains Hardware dependant functions
32  */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include "ql_os.h"
38 #include "ql_hw.h"
39 #include "ql_def.h"
40 #include "ql_inline.h"
41 #include "ql_ver.h"
42 #include "ql_glbl.h"
43 #include "ql_dbg.h"
44
45 /*
46  * Static Functions
47  */
48
49 static void qla_del_rcv_cntxt(qla_host_t *ha);
50 static int qla_init_rcv_cntxt(qla_host_t *ha);
51 static void qla_del_xmt_cntxt(qla_host_t *ha);
52 static int qla_init_xmt_cntxt(qla_host_t *ha);
53 static void qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx);
54 static int qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
55         uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause);
56 static int qla_config_intr_cntxt(qla_host_t *ha, uint32_t num_intrs,
57         uint32_t create);
58 static int qla_get_nic_partition(qla_host_t *ha);
59 static int qla_config_rss(qla_host_t *ha, uint16_t cntxt_id);
60 static int qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id,
61         int tenable);
62 static int qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode);
63 static int qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id);
64
65 static int qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd,
66                 uint8_t *hdr);
67 static int qla_hw_add_all_mcast(qla_host_t *ha);
68 static int qla_hw_del_all_mcast(qla_host_t *ha);
69 static int qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx);
70
71 static int qla_minidump_init(qla_host_t *ha);
72 static void qla_minidump_free(qla_host_t *ha);
73
74
75 static int
76 qla_sysctl_get_drvr_stats(SYSCTL_HANDLER_ARGS)
77 {
78         int err = 0, ret;
79         qla_host_t *ha;
80         uint32_t i;
81
82         err = sysctl_handle_int(oidp, &ret, 0, req);
83
84         if (err || !req->newptr)
85                 return (err);
86
87         if (ret == 1) {
88
89                 ha = (qla_host_t *)arg1;
90
91                 for (i = 0; i < ha->hw.num_sds_rings; i++) 
92                         device_printf(ha->pci_dev,
93                                 "%s: sds_ring[%d] = %p\n", __func__,i,
94                                 (void *)ha->hw.sds[i].intr_count);
95
96                 for (i = 0; i < ha->hw.num_tx_rings; i++) 
97                         device_printf(ha->pci_dev,
98                                 "%s: tx[%d] = %p\n", __func__,i,
99                                 (void *)ha->tx_ring[i].count);
100
101                 for (i = 0; i < ha->hw.num_rds_rings; i++)
102                         device_printf(ha->pci_dev,
103                                 "%s: rds_ring[%d] = %p\n", __func__,i,
104                                 (void *)ha->hw.rds[i].count);
105
106                 device_printf(ha->pci_dev, "%s: lro_pkt_count = %p\n", __func__,
107                         (void *)ha->lro_pkt_count);
108
109                 device_printf(ha->pci_dev, "%s: lro_bytes = %p\n", __func__,
110                         (void *)ha->lro_bytes);
111         }
112         return (err);
113 }
114
115 #ifdef QL_DBG
116
117 static void
118 qla_stop_pegs(qla_host_t *ha)
119 {
120         uint32_t val = 1;
121
122         ql_rdwr_indreg32(ha, Q8_CRB_PEG_0, &val, 0);
123         ql_rdwr_indreg32(ha, Q8_CRB_PEG_1, &val, 0);
124         ql_rdwr_indreg32(ha, Q8_CRB_PEG_2, &val, 0);
125         ql_rdwr_indreg32(ha, Q8_CRB_PEG_3, &val, 0);
126         ql_rdwr_indreg32(ha, Q8_CRB_PEG_4, &val, 0);
127         device_printf(ha->pci_dev, "%s PEGS HALTED!!!!!\n", __func__);
128 }
129
130 static int
131 qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS)
132 {
133         int err, ret = 0;
134         qla_host_t *ha;
135         
136         err = sysctl_handle_int(oidp, &ret, 0, req);
137
138
139         if (err || !req->newptr)
140                 return (err);
141
142         if (ret == 1) {
143                 ha = (qla_host_t *)arg1;
144                 (void)QLA_LOCK(ha, __func__, 0);
145                 qla_stop_pegs(ha);      
146                 QLA_UNLOCK(ha, __func__);
147         }
148
149         return err;
150 }
151 #endif /* #ifdef QL_DBG */
152
153 /*
154  * Name: ql_hw_add_sysctls
155  * Function: Add P3Plus specific sysctls
156  */
157 void
158 ql_hw_add_sysctls(qla_host_t *ha)
159 {
160         device_t        dev;
161
162         dev = ha->pci_dev;
163
164         ha->hw.num_sds_rings = MAX_SDS_RINGS;
165         ha->hw.num_rds_rings = MAX_RDS_RINGS;
166         ha->hw.num_tx_rings = NUM_TX_RINGS;
167
168         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
169                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
170                 OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings,
171                 ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings");
172
173         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
174                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
175                 OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings,
176                 ha->hw.num_sds_rings, "Number of Status Descriptor Rings");
177
178         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
179                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
180                 OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings,
181                 ha->hw.num_tx_rings, "Number of Transmit Rings");
182
183         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
184                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
185                 OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx,
186                 ha->txr_idx, "Tx Ring Used");
187
188         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
189                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
190                 OID_AUTO, "drvr_stats", CTLTYPE_INT | CTLFLAG_RW,
191                 (void *)ha, 0,
192                 qla_sysctl_get_drvr_stats, "I", "Driver Maintained Statistics");
193
194         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
195                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
196                 OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs,
197                 ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt");
198
199         ha->hw.sds_cidx_thres = 32;
200         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
201                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
202                 OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres,
203                 ha->hw.sds_cidx_thres,
204                 "Number of SDS entries to process before updating"
205                 " SDS Ring Consumer Index");
206
207         ha->hw.rds_pidx_thres = 32;
208         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
209                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
210                 OID_AUTO, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres,
211                 ha->hw.rds_pidx_thres,
212                 "Number of Rcv Rings Entries to post before updating"
213                 " RDS Ring Producer Index");
214
215         ha->hw.min_lro_pkt_size = 512;
216         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
217                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
218                 OID_AUTO, "min_lro_pkt_size", CTLFLAG_RD, &ha->hw.min_lro_pkt_size,
219                 ha->hw.min_lro_pkt_size, "minimum packet size to trigger lro");
220
221         ha->hw.mdump_active = 0;
222         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
223                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
224                 OID_AUTO, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active,
225                 ha->hw.mdump_active,
226                 "Minidump Utility is Active \n"
227                 "\t 0 = Minidump Utility is not active\n"
228                 "\t 1 = Minidump Utility is retrieved on this port\n"
229                 "\t 2 = Minidump Utility is retrieved on the other port\n");
230
231         ha->hw.mdump_start = 0;
232         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
233                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
234                 OID_AUTO, "minidump_start", CTLFLAG_RW,
235                 &ha->hw.mdump_start, ha->hw.mdump_start,
236                 "Minidump Utility can start minidump process");
237 #ifdef QL_DBG
238
239         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
240                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
241                 OID_AUTO, "err_inject",
242                 CTLFLAG_RW, &ha->err_inject, ha->err_inject,
243                 "Error to be injected\n"
244                 "\t\t\t 0: No Errors\n"
245                 "\t\t\t 1: rcv: rxb struct invalid\n"
246                 "\t\t\t 2: rcv: mp == NULL\n"
247                 "\t\t\t 3: lro: rxb struct invalid\n"
248                 "\t\t\t 4: lro: mp == NULL\n"
249                 "\t\t\t 5: rcv: num handles invalid\n"
250                 "\t\t\t 6: reg: indirect reg rd_wr failure\n"
251                 "\t\t\t 7: ocm: offchip memory rd_wr failure\n"
252                 "\t\t\t 8: mbx: mailbox command failure\n"
253                 "\t\t\t 9: heartbeat failure\n"
254                 "\t\t\t A: temperature failure\n" );
255
256         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
257                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
258                 OID_AUTO, "peg_stop", CTLTYPE_INT | CTLFLAG_RW,
259                 (void *)ha, 0,
260                 qla_sysctl_stop_pegs, "I", "Peg Stop");
261
262 #endif /* #ifdef QL_DBG */
263
264 }
265
266 void
267 ql_hw_link_status(qla_host_t *ha)
268 {
269         device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui);
270
271         if (ha->hw.link_up) {
272                 device_printf(ha->pci_dev, "link Up\n");
273         } else {
274                 device_printf(ha->pci_dev, "link Down\n");
275         }
276
277         if (ha->hw.flags.fduplex) {
278                 device_printf(ha->pci_dev, "Full Duplex\n");
279         } else {
280                 device_printf(ha->pci_dev, "Half Duplex\n");
281         }
282
283         if (ha->hw.flags.autoneg) {
284                 device_printf(ha->pci_dev, "Auto Negotiation Enabled\n");
285         } else {
286                 device_printf(ha->pci_dev, "Auto Negotiation Disabled\n");
287         }
288
289         switch (ha->hw.link_speed) {
290         case 0x710:
291                 device_printf(ha->pci_dev, "link speed\t\t 10Gps\n");
292                 break;
293
294         case 0x3E8:
295                 device_printf(ha->pci_dev, "link speed\t\t 1Gps\n");
296                 break;
297
298         case 0x64:
299                 device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n");
300                 break;
301
302         default:
303                 device_printf(ha->pci_dev, "link speed\t\t Unknown\n");
304                 break;
305         }
306
307         switch (ha->hw.module_type) {
308
309         case 0x01:
310                 device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n");
311                 break;
312
313         case 0x02:
314                 device_printf(ha->pci_dev, "Module Type 10GBase-LR\n");
315                 break;
316
317         case 0x03:
318                 device_printf(ha->pci_dev, "Module Type 10GBase-SR\n");
319                 break;
320
321         case 0x04:
322                 device_printf(ha->pci_dev,
323                         "Module Type 10GE Passive Copper(Compliant)[%d m]\n",
324                         ha->hw.cable_length);
325                 break;
326
327         case 0x05:
328                 device_printf(ha->pci_dev, "Module Type 10GE Active"
329                         " Limiting Copper(Compliant)[%d m]\n",
330                         ha->hw.cable_length);
331                 break;
332
333         case 0x06:
334                 device_printf(ha->pci_dev,
335                         "Module Type 10GE Passive Copper"
336                         " (Legacy, Best Effort)[%d m]\n",
337                         ha->hw.cable_length);
338                 break;
339
340         case 0x07:
341                 device_printf(ha->pci_dev, "Module Type 1000Base-SX\n");
342                 break;
343
344         case 0x08:
345                 device_printf(ha->pci_dev, "Module Type 1000Base-LX\n");
346                 break;
347
348         case 0x09:
349                 device_printf(ha->pci_dev, "Module Type 1000Base-CX\n");
350                 break;
351
352         case 0x0A:
353                 device_printf(ha->pci_dev, "Module Type 1000Base-T\n");
354                 break;
355
356         case 0x0B:
357                 device_printf(ha->pci_dev, "Module Type 1GE Passive Copper"
358                         "(Legacy, Best Effort)\n");
359                 break;
360
361         default:
362                 device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n",
363                         ha->hw.module_type);
364                 break;
365         }
366
367         if (ha->hw.link_faults == 1)
368                 device_printf(ha->pci_dev, "SFP Power Fault\n");
369 }
370
371 /*
372  * Name: ql_free_dma
373  * Function: Frees the DMA'able memory allocated in ql_alloc_dma()
374  */
375 void
376 ql_free_dma(qla_host_t *ha)
377 {
378         uint32_t i;
379
380         if (ha->hw.dma_buf.flags.sds_ring) {
381                 for (i = 0; i < ha->hw.num_sds_rings; i++) {
382                         ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]);
383                 }
384                 ha->hw.dma_buf.flags.sds_ring = 0;
385         }
386
387         if (ha->hw.dma_buf.flags.rds_ring) {
388                 for (i = 0; i < ha->hw.num_rds_rings; i++) {
389                         ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]);
390                 }
391                 ha->hw.dma_buf.flags.rds_ring = 0;
392         }
393
394         if (ha->hw.dma_buf.flags.tx_ring) {
395                 ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring);
396                 ha->hw.dma_buf.flags.tx_ring = 0;
397         }
398         qla_minidump_free(ha);
399 }
400
401 /*
402  * Name: ql_alloc_dma
403  * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts.
404  */
405 int
406 ql_alloc_dma(qla_host_t *ha)
407 {
408         device_t                dev;
409         uint32_t                i, j, size, tx_ring_size;
410         qla_hw_t                *hw;
411         qla_hw_tx_cntxt_t       *tx_cntxt;
412         uint8_t                 *vaddr;
413         bus_addr_t              paddr;
414
415         dev = ha->pci_dev;
416
417         QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
418
419         hw = &ha->hw;
420         /*
421          * Allocate Transmit Ring
422          */
423         tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS);
424         size = (tx_ring_size * ha->hw.num_tx_rings);
425
426         hw->dma_buf.tx_ring.alignment = 8;
427         hw->dma_buf.tx_ring.size = size + PAGE_SIZE;
428         
429         if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) {
430                 device_printf(dev, "%s: tx ring alloc failed\n", __func__);
431                 goto ql_alloc_dma_exit;
432         }
433
434         vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b;
435         paddr = hw->dma_buf.tx_ring.dma_addr;
436         
437         for (i = 0; i < ha->hw.num_tx_rings; i++) {
438                 tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
439
440                 tx_cntxt->tx_ring_base = (q80_tx_cmd_t *)vaddr;
441                 tx_cntxt->tx_ring_paddr = paddr;
442
443                 vaddr += tx_ring_size;
444                 paddr += tx_ring_size;
445         }
446
447         for (i = 0; i < ha->hw.num_tx_rings; i++) {
448                 tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
449
450                 tx_cntxt->tx_cons = (uint32_t *)vaddr;
451                 tx_cntxt->tx_cons_paddr = paddr;
452
453                 vaddr += sizeof (uint32_t);
454                 paddr += sizeof (uint32_t);
455         }
456
457         ha->hw.dma_buf.flags.tx_ring = 1;
458
459         QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n",
460                 __func__, (void *)(hw->dma_buf.tx_ring.dma_addr),
461                 hw->dma_buf.tx_ring.dma_b));
462         /*
463          * Allocate Receive Descriptor Rings
464          */
465
466         for (i = 0; i < hw->num_rds_rings; i++) {
467
468                 hw->dma_buf.rds_ring[i].alignment = 8;
469                 hw->dma_buf.rds_ring[i].size =
470                         (sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS;
471
472                 if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) {
473                         device_printf(dev, "%s: rds ring[%d] alloc failed\n",
474                                 __func__, i);
475
476                         for (j = 0; j < i; j++)
477                                 ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]);
478
479                         goto ql_alloc_dma_exit;
480                 }
481                 QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n",
482                         __func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr),
483                         hw->dma_buf.rds_ring[i].dma_b));
484         }
485
486         hw->dma_buf.flags.rds_ring = 1;
487
488         /*
489          * Allocate Status Descriptor Rings
490          */
491
492         for (i = 0; i < hw->num_sds_rings; i++) {
493                 hw->dma_buf.sds_ring[i].alignment = 8;
494                 hw->dma_buf.sds_ring[i].size =
495                         (sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS;
496
497                 if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) {
498                         device_printf(dev, "%s: sds ring alloc failed\n",
499                                 __func__);
500
501                         for (j = 0; j < i; j++)
502                                 ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]);
503
504                         goto ql_alloc_dma_exit;
505                 }
506                 QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n",
507                         __func__, i,
508                         (void *)(hw->dma_buf.sds_ring[i].dma_addr),
509                         hw->dma_buf.sds_ring[i].dma_b));
510         }
511         for (i = 0; i < hw->num_sds_rings; i++) {
512                 hw->sds[i].sds_ring_base =
513                         (q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b;
514         }
515
516         hw->dma_buf.flags.sds_ring = 1;
517
518         return 0;
519
520 ql_alloc_dma_exit:
521         ql_free_dma(ha);
522         return -1;
523 }
524
525 #define Q8_MBX_MSEC_DELAY       5000
526
527 static int
528 qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
529         uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause)
530 {
531         uint32_t i;
532         uint32_t data;
533         int ret = 0;
534
535         if (QL_ERR_INJECT(ha, INJCT_MBX_CMD_FAILURE)) {
536                 ret = -3;
537                 ha->qla_initiate_recovery = 1;
538                 goto exit_qla_mbx_cmd;
539         }
540
541         if (no_pause)
542                 i = 1000;
543         else
544                 i = Q8_MBX_MSEC_DELAY;
545
546         while (i) {
547                 data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL);
548                 if (data == 0)
549                         break;
550                 if (no_pause) {
551                         DELAY(1000);
552                 } else {
553                         qla_mdelay(__func__, 1);
554                 }
555                 i--;
556         }
557
558         if (i == 0) {
559                 device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n",
560                         __func__, data);
561                 ret = -1;
562                 ha->qla_initiate_recovery = 1;
563                 goto exit_qla_mbx_cmd;
564         }
565
566         for (i = 0; i < n_hmbox; i++) {
567                 WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox);
568                 h_mbox++;
569         }
570
571         WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1);
572
573
574         i = Q8_MBX_MSEC_DELAY;
575         while (i) {
576                 data = READ_REG32(ha, Q8_FW_MBOX_CNTRL);
577
578                 if ((data & 0x3) == 1) {
579                         data = READ_REG32(ha, Q8_FW_MBOX0);
580                         if ((data & 0xF000) != 0x8000)
581                                 break;
582                 }
583                 if (no_pause) {
584                         DELAY(1000);
585                 } else {
586                         qla_mdelay(__func__, 1);
587                 }
588                 i--;
589         }
590         if (i == 0) {
591                 device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n",
592                         __func__, data);
593                 ret = -2;
594                 ha->qla_initiate_recovery = 1;
595                 goto exit_qla_mbx_cmd;
596         }
597
598         for (i = 0; i < n_fwmbox; i++) {
599                 *fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2)));
600         }
601
602         WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0);
603         WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
604
605 exit_qla_mbx_cmd:
606         return (ret);
607 }
608
609 static int
610 qla_get_nic_partition(qla_host_t *ha)
611 {
612         uint32_t *mbox, err;
613         device_t dev = ha->pci_dev;
614
615         bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX));
616
617         mbox = ha->hw.mbox;
618
619         mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29); 
620
621         if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) {
622                 device_printf(dev, "%s: failed0\n", __func__);
623                 return (-1);
624         }
625         err = mbox[0] >> 25; 
626
627         if ((err != 1) && (err != 0)) {
628                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
629                 return (-1);
630         }
631         return 0;
632 }
633
634 static int
635 qla_config_intr_cntxt(qla_host_t *ha, uint32_t num_intrs, uint32_t create)
636 {
637         uint32_t i, err;
638         device_t dev = ha->pci_dev;
639         q80_config_intr_t *c_intr;
640         q80_config_intr_rsp_t *c_intr_rsp;
641
642         c_intr = (q80_config_intr_t *)ha->hw.mbox;
643         bzero(c_intr, (sizeof (q80_config_intr_t)));
644
645         c_intr->opcode = Q8_MBX_CONFIG_INTR;
646
647         c_intr->count_version = (sizeof (q80_config_intr_t) >> 2);
648         c_intr->count_version |= Q8_MBX_CMD_VERSION;
649
650         c_intr->nentries = num_intrs;
651
652         for (i = 0; i < num_intrs; i++) {
653                 if (create) {
654                         c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE;
655                         c_intr->intr[i].msix_index = i + 1;
656                 } else {
657                         c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE;
658                         c_intr->intr[i].msix_index = ha->hw.intr_id[i];
659                 }
660
661                 c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X;
662         }
663
664         if (qla_mbx_cmd(ha, (uint32_t *)c_intr,
665                 (sizeof (q80_config_intr_t) >> 2),
666                 ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) {
667                 device_printf(dev, "%s: failed0\n", __func__);
668                 return (-1);
669         }
670
671         c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox;
672
673         err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status);
674
675         if (err) {
676                 device_printf(dev, "%s: failed1 [0x%08x, %d]\n", __func__, err,
677                         c_intr_rsp->nentries);
678
679                 for (i = 0; i < c_intr_rsp->nentries; i++) {
680                         device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n",
681                                 __func__, i, 
682                                 c_intr_rsp->intr[i].status,
683                                 c_intr_rsp->intr[i].intr_id,
684                                 c_intr_rsp->intr[i].intr_src);
685                 }
686
687                 return (-1);
688         }
689
690         for (i = 0; ((i < num_intrs) && create); i++) {
691                 if (!c_intr_rsp->intr[i].status) {
692                         ha->hw.intr_id[i] = c_intr_rsp->intr[i].intr_id;
693                         ha->hw.intr_src[i] = c_intr_rsp->intr[i].intr_src;
694                 }
695         }
696
697         return (0);
698 }
699
700 /*
701  * Name: qla_config_rss
702  * Function: Configure RSS for the context/interface.
703  */
704 static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL,
705                         0x8030f20c77cb2da3ULL,
706                         0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
707                         0x255b0ec26d5a56daULL };
708
709 static int
710 qla_config_rss(qla_host_t *ha, uint16_t cntxt_id)
711 {
712         q80_config_rss_t        *c_rss;
713         q80_config_rss_rsp_t    *c_rss_rsp;
714         uint32_t                err, i;
715         device_t                dev = ha->pci_dev;
716
717         c_rss = (q80_config_rss_t *)ha->hw.mbox;
718         bzero(c_rss, (sizeof (q80_config_rss_t)));
719
720         c_rss->opcode = Q8_MBX_CONFIG_RSS;
721
722         c_rss->count_version = (sizeof (q80_config_rss_t) >> 2);
723         c_rss->count_version |= Q8_MBX_CMD_VERSION;
724
725         c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP |
726                                 Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP);
727
728         c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS;
729         c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE;
730
731         c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK;
732
733         c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID;
734         c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS;
735
736         c_rss->cntxt_id = cntxt_id;
737
738         for (i = 0; i < 5; i++) {
739                 c_rss->rss_key[i] = rss_key[i];
740         }
741
742         if (qla_mbx_cmd(ha, (uint32_t *)c_rss,
743                 (sizeof (q80_config_rss_t) >> 2),
744                 ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) {
745                 device_printf(dev, "%s: failed0\n", __func__);
746                 return (-1);
747         }
748         c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox;
749
750         err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status);
751
752         if (err) {
753                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
754                 return (-1);
755         }
756         return 0;
757 }
758
759 static uint8_t rss_ind_default_table[Q8_RSS_IND_TBL_SIZE];
760
761 static int
762 qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count,
763         uint16_t cntxt_id, uint8_t *ind_table)
764 {
765         q80_config_rss_ind_table_t      *c_rss_ind;
766         q80_config_rss_ind_table_rsp_t  *c_rss_ind_rsp;
767         uint32_t                        err;
768         device_t                        dev = ha->pci_dev;
769
770         if ((count > Q8_RSS_IND_TBL_SIZE) ||
771                 ((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) {
772                 device_printf(dev, "%s: illegal count [%d, %d]\n", __func__,
773                         start_idx, count);
774                 return (-1);
775         }
776
777         c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox;
778         bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t));
779
780         c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE;
781         c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2);
782         c_rss_ind->count_version |= Q8_MBX_CMD_VERSION;
783
784         c_rss_ind->start_idx = start_idx;
785         c_rss_ind->end_idx = start_idx + count - 1;
786         c_rss_ind->cntxt_id = cntxt_id;
787         bcopy(ind_table, c_rss_ind->ind_table, count);
788
789         if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind,
790                 (sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox,
791                 (sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) {
792                 device_printf(dev, "%s: failed0\n", __func__);
793                 return (-1);
794         }
795
796         c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox;
797         err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status);
798
799         if (err) {
800                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
801                 return (-1);
802         }
803         return 0;
804 }
805
806 /*
807  * Name: qla_config_intr_coalesce
808  * Function: Configure Interrupt Coalescing.
809  */
810 static int
811 qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable)
812 {
813         q80_config_intr_coalesc_t       *intrc;
814         q80_config_intr_coalesc_rsp_t   *intrc_rsp;
815         uint32_t                        err, i;
816         device_t                        dev = ha->pci_dev;
817         
818         intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox;
819         bzero(intrc, (sizeof (q80_config_intr_coalesc_t)));
820
821         intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE;
822         intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2);
823         intrc->count_version |= Q8_MBX_CMD_VERSION;
824
825         intrc->flags = Q8_MBX_INTRC_FLAGS_RCV;
826         intrc->cntxt_id = cntxt_id;
827
828         intrc->max_pkts = 256;
829         intrc->max_mswait = 3;
830
831         if (tenable) {
832                 intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC;
833                 intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC;
834
835                 for (i = 0; i < ha->hw.num_sds_rings; i++) {
836                         intrc->sds_ring_mask |= (1 << i);
837                 }
838                 intrc->ms_timeout = 1000;
839         }
840
841         if (qla_mbx_cmd(ha, (uint32_t *)intrc,
842                 (sizeof (q80_config_intr_coalesc_t) >> 2),
843                 ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) {
844                 device_printf(dev, "%s: failed0\n", __func__);
845                 return (-1);
846         }
847         intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox;
848
849         err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status);
850
851         if (err) {
852                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
853                 return (-1);
854         }
855         
856         return 0;
857 }
858
859
860 /*
861  * Name: qla_config_mac_addr
862  * Function: binds a MAC address to the context/interface.
863  *      Can be unicast, multicast or broadcast.
864  */
865 static int
866 qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac)
867 {
868         q80_config_mac_addr_t           *cmac;
869         q80_config_mac_addr_rsp_t       *cmac_rsp;
870         uint32_t                        err;
871         device_t                        dev = ha->pci_dev;
872
873         cmac = (q80_config_mac_addr_t *)ha->hw.mbox;
874         bzero(cmac, (sizeof (q80_config_mac_addr_t)));
875
876         cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR;
877         cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2;
878         cmac->count_version |= Q8_MBX_CMD_VERSION;
879
880         if (add_mac) 
881                 cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR;
882         else
883                 cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR;
884                 
885         cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS;
886
887         cmac->nmac_entries = 1;
888         cmac->cntxt_id = ha->hw.rcv_cntxt_id;
889         bcopy(mac_addr, cmac->mac_addr[0].addr, 6); 
890
891         if (qla_mbx_cmd(ha, (uint32_t *)cmac,
892                 (sizeof (q80_config_mac_addr_t) >> 2),
893                 ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) {
894                 device_printf(dev, "%s: %s failed0\n", __func__,
895                         (add_mac ? "Add" : "Del"));
896                 return (-1);
897         }
898         cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox;
899
900         err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status);
901
902         if (err) {
903                 device_printf(dev, "%s: %s "
904                         "%02x:%02x:%02x:%02x:%02x:%02x failed1 [0x%08x]\n",
905                         __func__, (add_mac ? "Add" : "Del"),
906                         mac_addr[0], mac_addr[1], mac_addr[2],
907                         mac_addr[3], mac_addr[4], mac_addr[5], err);
908                 return (-1);
909         }
910         
911         return 0;
912 }
913
914
915 /*
916  * Name: qla_set_mac_rcv_mode
917  * Function: Enable/Disable AllMulticast and Promiscous Modes.
918  */
919 static int
920 qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode)
921 {
922         q80_config_mac_rcv_mode_t       *rcv_mode;
923         uint32_t                        err;
924         q80_config_mac_rcv_mode_rsp_t   *rcv_mode_rsp;
925         device_t                        dev = ha->pci_dev;
926
927         rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox;
928         bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t)));
929
930         rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE;
931         rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2;
932         rcv_mode->count_version |= Q8_MBX_CMD_VERSION;
933
934         rcv_mode->mode = mode;
935
936         rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id;
937
938         if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode,
939                 (sizeof (q80_config_mac_rcv_mode_t) >> 2),
940                 ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) {
941                 device_printf(dev, "%s: failed0\n", __func__);
942                 return (-1);
943         }
944         rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox;
945
946         err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status);
947
948         if (err) {
949                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
950                 return (-1);
951         }
952         
953         return 0;
954 }
955
956 int
957 ql_set_promisc(qla_host_t *ha)
958 {
959         int ret;
960
961         ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE;
962         ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
963         return (ret);
964 }
965
966 int
967 ql_set_allmulti(qla_host_t *ha)
968 {
969         int ret;
970
971         ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE;
972         ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
973         return (ret);
974 }
975
976
977 /*
978  * Name: ql_set_max_mtu
979  * Function:
980  *      Sets the maximum transfer unit size for the specified rcv context.
981  */
982 int
983 ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id)
984 {
985         device_t                dev;
986         q80_set_max_mtu_t       *max_mtu;
987         q80_set_max_mtu_rsp_t   *max_mtu_rsp;
988         uint32_t                err;
989
990         dev = ha->pci_dev;
991
992         max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox;
993         bzero(max_mtu, (sizeof (q80_set_max_mtu_t)));
994
995         max_mtu->opcode = Q8_MBX_SET_MAX_MTU;
996         max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2);
997         max_mtu->count_version |= Q8_MBX_CMD_VERSION;
998
999         max_mtu->cntxt_id = cntxt_id;
1000         max_mtu->mtu = mtu;
1001
1002         if (qla_mbx_cmd(ha, (uint32_t *)max_mtu,
1003                 (sizeof (q80_set_max_mtu_t) >> 2),
1004                 ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) {
1005                 device_printf(dev, "%s: failed\n", __func__);
1006                 return -1;
1007         }
1008
1009         max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox;
1010
1011         err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status);
1012
1013         if (err) {
1014                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1015         }
1016
1017         return 0;
1018 }
1019
1020 static int
1021 qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id)
1022 {
1023         device_t                dev;
1024         q80_link_event_t        *lnk;
1025         q80_link_event_rsp_t    *lnk_rsp;
1026         uint32_t                err;
1027
1028         dev = ha->pci_dev;
1029
1030         lnk = (q80_link_event_t *)ha->hw.mbox;
1031         bzero(lnk, (sizeof (q80_link_event_t)));
1032
1033         lnk->opcode = Q8_MBX_LINK_EVENT_REQ;
1034         lnk->count_version = (sizeof (q80_link_event_t) >> 2);
1035         lnk->count_version |= Q8_MBX_CMD_VERSION;
1036
1037         lnk->cntxt_id = cntxt_id;
1038         lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC;
1039
1040         if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2),
1041                 ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) {
1042                 device_printf(dev, "%s: failed\n", __func__);
1043                 return -1;
1044         }
1045
1046         lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox;
1047
1048         err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status);
1049
1050         if (err) {
1051                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1052         }
1053
1054         return 0;
1055 }
1056
1057 static int
1058 qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id)
1059 {
1060         device_t                dev;
1061         q80_config_fw_lro_t     *fw_lro;
1062         q80_config_fw_lro_rsp_t *fw_lro_rsp;
1063         uint32_t                err;
1064
1065         dev = ha->pci_dev;
1066
1067         fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox;
1068         bzero(fw_lro, sizeof(q80_config_fw_lro_t));
1069
1070         fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO;
1071         fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2);
1072         fw_lro->count_version |= Q8_MBX_CMD_VERSION;
1073
1074         fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK;
1075
1076         fw_lro->cntxt_id = cntxt_id;
1077
1078         if (ha->hw.min_lro_pkt_size) {
1079                 fw_lro->flags |= Q8_MBX_FW_LRO_LOW_THRESHOLD;
1080                 fw_lro->low_threshold = ha->hw.min_lro_pkt_size;
1081         }
1082
1083         if (qla_mbx_cmd(ha, (uint32_t *)fw_lro,
1084                 (sizeof (q80_config_fw_lro_t) >> 2),
1085                 ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) {
1086                 device_printf(dev, "%s: failed\n", __func__);
1087                 return -1;
1088         }
1089
1090         fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox;
1091
1092         err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status);
1093
1094         if (err) {
1095                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1096         }
1097
1098         return 0;
1099 }
1100
1101 static void
1102 qla_xmt_stats(qla_host_t *ha, q80_xmt_stats_t *xstat)
1103 {
1104         device_t dev = ha->pci_dev;
1105
1106         device_printf(dev, "%s: total_bytes\t\t%" PRIu64 "\n", __func__,
1107                 xstat->total_bytes);
1108         device_printf(dev, "%s: total_pkts\t\t%" PRIu64 "\n", __func__,
1109                 xstat->total_pkts);
1110         device_printf(dev, "%s: errors\t\t%" PRIu64 "\n", __func__,
1111                 xstat->errors);
1112         device_printf(dev, "%s: pkts_dropped\t%" PRIu64 "\n", __func__,
1113                 xstat->pkts_dropped);
1114         device_printf(dev, "%s: switch_pkts\t\t%" PRIu64 "\n", __func__,
1115                 xstat->switch_pkts);
1116         device_printf(dev, "%s: num_buffers\t\t%" PRIu64 "\n", __func__,
1117                 xstat->num_buffers);
1118 }
1119
1120 static void
1121 qla_rcv_stats(qla_host_t *ha, q80_rcv_stats_t *rstat)
1122 {
1123         device_t dev = ha->pci_dev;
1124
1125         device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n", __func__,
1126                 rstat->total_bytes);
1127         device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n", __func__,
1128                 rstat->total_pkts);
1129         device_printf(dev, "%s: lro_pkt_count\t\t%" PRIu64 "\n", __func__,
1130                 rstat->lro_pkt_count);
1131         device_printf(dev, "%s: sw_pkt_count\t\t%" PRIu64 "\n", __func__,
1132                 rstat->sw_pkt_count);
1133         device_printf(dev, "%s: ip_chksum_err\t\t%" PRIu64 "\n", __func__,
1134                 rstat->ip_chksum_err);
1135         device_printf(dev, "%s: pkts_wo_acntxts\t\t%" PRIu64 "\n", __func__,
1136                 rstat->pkts_wo_acntxts);
1137         device_printf(dev, "%s: pkts_dropped_no_sds_card\t%" PRIu64 "\n",
1138                 __func__, rstat->pkts_dropped_no_sds_card);
1139         device_printf(dev, "%s: pkts_dropped_no_sds_host\t%" PRIu64 "\n",
1140                 __func__, rstat->pkts_dropped_no_sds_host);
1141         device_printf(dev, "%s: oversized_pkts\t\t%" PRIu64 "\n", __func__,
1142                 rstat->oversized_pkts);
1143         device_printf(dev, "%s: pkts_dropped_no_rds\t\t%" PRIu64 "\n",
1144                 __func__, rstat->pkts_dropped_no_rds);
1145         device_printf(dev, "%s: unxpctd_mcast_pkts\t\t%" PRIu64 "\n",
1146                 __func__, rstat->unxpctd_mcast_pkts);
1147         device_printf(dev, "%s: re1_fbq_error\t\t%" PRIu64 "\n", __func__,
1148                 rstat->re1_fbq_error);
1149         device_printf(dev, "%s: invalid_mac_addr\t\t%" PRIu64 "\n", __func__,
1150                 rstat->invalid_mac_addr);
1151         device_printf(dev, "%s: rds_prime_trys\t\t%" PRIu64 "\n", __func__,
1152                 rstat->rds_prime_trys);
1153         device_printf(dev, "%s: rds_prime_success\t\t%" PRIu64 "\n", __func__,
1154                 rstat->rds_prime_success);
1155         device_printf(dev, "%s: lro_flows_added\t\t%" PRIu64 "\n", __func__,
1156                 rstat->lro_flows_added);
1157         device_printf(dev, "%s: lro_flows_deleted\t\t%" PRIu64 "\n", __func__,
1158                 rstat->lro_flows_deleted);
1159         device_printf(dev, "%s: lro_flows_active\t\t%" PRIu64 "\n", __func__,
1160                 rstat->lro_flows_active);
1161         device_printf(dev, "%s: pkts_droped_unknown\t\t%" PRIu64 "\n",
1162                 __func__, rstat->pkts_droped_unknown);
1163 }
1164
1165 static void
1166 qla_mac_stats(qla_host_t *ha, q80_mac_stats_t *mstat)
1167 {
1168         device_t dev = ha->pci_dev;
1169
1170         device_printf(dev, "%s: xmt_frames\t\t\t%" PRIu64 "\n", __func__,
1171                 mstat->xmt_frames);
1172         device_printf(dev, "%s: xmt_bytes\t\t\t%" PRIu64 "\n", __func__,
1173                 mstat->xmt_bytes);
1174         device_printf(dev, "%s: xmt_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1175                 mstat->xmt_mcast_pkts);
1176         device_printf(dev, "%s: xmt_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1177                 mstat->xmt_bcast_pkts);
1178         device_printf(dev, "%s: xmt_pause_frames\t\t%" PRIu64 "\n", __func__,
1179                 mstat->xmt_pause_frames);
1180         device_printf(dev, "%s: xmt_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1181                 mstat->xmt_cntrl_pkts);
1182         device_printf(dev, "%s: xmt_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1183                 __func__, mstat->xmt_pkt_lt_64bytes);
1184         device_printf(dev, "%s: xmt_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1185                 __func__, mstat->xmt_pkt_lt_127bytes);
1186         device_printf(dev, "%s: xmt_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1187                 __func__, mstat->xmt_pkt_lt_255bytes);
1188         device_printf(dev, "%s: xmt_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1189                 __func__, mstat->xmt_pkt_lt_511bytes);
1190         device_printf(dev, "%s: xmt_pkt_lt_1023bytes\t%" PRIu64 "\n",
1191                 __func__, mstat->xmt_pkt_lt_1023bytes);
1192         device_printf(dev, "%s: xmt_pkt_lt_1518bytes\t%" PRIu64 "\n",
1193                 __func__, mstat->xmt_pkt_lt_1518bytes);
1194         device_printf(dev, "%s: xmt_pkt_gt_1518bytes\t%" PRIu64 "\n",
1195                 __func__, mstat->xmt_pkt_gt_1518bytes);
1196
1197         device_printf(dev, "%s: rcv_frames\t\t\t%" PRIu64 "\n", __func__,
1198                 mstat->rcv_frames);
1199         device_printf(dev, "%s: rcv_bytes\t\t\t%" PRIu64 "\n", __func__,
1200                 mstat->rcv_bytes);
1201         device_printf(dev, "%s: rcv_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1202                 mstat->rcv_mcast_pkts);
1203         device_printf(dev, "%s: rcv_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1204                 mstat->rcv_bcast_pkts);
1205         device_printf(dev, "%s: rcv_pause_frames\t\t%" PRIu64 "\n", __func__,
1206                 mstat->rcv_pause_frames);
1207         device_printf(dev, "%s: rcv_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1208                 mstat->rcv_cntrl_pkts);
1209         device_printf(dev, "%s: rcv_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1210                 __func__, mstat->rcv_pkt_lt_64bytes);
1211         device_printf(dev, "%s: rcv_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1212                 __func__, mstat->rcv_pkt_lt_127bytes);
1213         device_printf(dev, "%s: rcv_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1214                 __func__, mstat->rcv_pkt_lt_255bytes);
1215         device_printf(dev, "%s: rcv_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1216                 __func__, mstat->rcv_pkt_lt_511bytes);
1217         device_printf(dev, "%s: rcv_pkt_lt_1023bytes\t%" PRIu64 "\n",
1218                 __func__, mstat->rcv_pkt_lt_1023bytes);
1219         device_printf(dev, "%s: rcv_pkt_lt_1518bytes\t%" PRIu64 "\n",
1220                 __func__, mstat->rcv_pkt_lt_1518bytes);
1221         device_printf(dev, "%s: rcv_pkt_gt_1518bytes\t%" PRIu64 "\n",
1222                 __func__, mstat->rcv_pkt_gt_1518bytes);
1223
1224         device_printf(dev, "%s: rcv_len_error\t\t%" PRIu64 "\n", __func__,
1225                 mstat->rcv_len_error);
1226         device_printf(dev, "%s: rcv_len_small\t\t%" PRIu64 "\n", __func__,
1227                 mstat->rcv_len_small);
1228         device_printf(dev, "%s: rcv_len_large\t\t%" PRIu64 "\n", __func__,
1229                 mstat->rcv_len_large);
1230         device_printf(dev, "%s: rcv_jabber\t\t\t%" PRIu64 "\n", __func__,
1231                 mstat->rcv_jabber);
1232         device_printf(dev, "%s: rcv_dropped\t\t\t%" PRIu64 "\n", __func__,
1233                 mstat->rcv_dropped);
1234         device_printf(dev, "%s: fcs_error\t\t\t%" PRIu64 "\n", __func__,
1235                 mstat->fcs_error);
1236         device_printf(dev, "%s: align_error\t\t\t%" PRIu64 "\n", __func__,
1237                 mstat->align_error);
1238 }
1239
1240
1241 static int
1242 qla_get_hw_stats(qla_host_t *ha, uint32_t cmd)
1243 {
1244         device_t                dev;
1245         q80_get_stats_t         *stat;
1246         q80_get_stats_rsp_t     *stat_rsp;
1247         uint32_t                err;
1248
1249         dev = ha->pci_dev;
1250
1251         stat = (q80_get_stats_t *)ha->hw.mbox;
1252         bzero(stat, (sizeof (q80_get_stats_t)));
1253
1254         stat->opcode = Q8_MBX_GET_STATS;
1255         stat->count_version = 2;
1256         stat->count_version |= Q8_MBX_CMD_VERSION;
1257
1258         stat->cmd = cmd;
1259
1260         if (qla_mbx_cmd(ha, (uint32_t *)stat, 2,
1261                 ha->hw.mbox, (sizeof (q80_get_stats_rsp_t) >> 2), 0)) {
1262                 device_printf(dev, "%s: failed\n", __func__);
1263                 return -1;
1264         }
1265
1266         stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1267
1268         err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status);
1269
1270         if (err) {
1271                 return -1;
1272         }
1273
1274         return 0;
1275 }
1276
1277 void
1278 ql_get_stats(qla_host_t *ha)
1279 {
1280         q80_get_stats_rsp_t     *stat_rsp;
1281         q80_mac_stats_t         *mstat;
1282         q80_xmt_stats_t         *xstat;
1283         q80_rcv_stats_t         *rstat;
1284         uint32_t                cmd;
1285
1286         stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1287         /*
1288          * Get MAC Statistics
1289          */
1290         cmd = Q8_GET_STATS_CMD_TYPE_MAC;
1291
1292         cmd |= ((ha->pci_func & 0x1) << 16);
1293
1294         if (qla_get_hw_stats(ha, cmd) == 0) {
1295                 mstat = (q80_mac_stats_t *)&stat_rsp->u.mac;
1296                 qla_mac_stats(ha, mstat);
1297         } else {
1298                 device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n",
1299                         __func__, ha->hw.mbox[0]);
1300         }
1301         /*
1302          * Get RCV Statistics
1303          */
1304         cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT;
1305         cmd |= (ha->hw.rcv_cntxt_id << 16);
1306
1307         if (qla_get_hw_stats(ha, cmd) == 0) {
1308                 rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv;
1309                 qla_rcv_stats(ha, rstat);
1310         } else {
1311                 device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n",
1312                         __func__, ha->hw.mbox[0]);
1313         }
1314         /*
1315          * Get XMT Statistics
1316          */
1317         cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT;
1318         cmd |= (ha->hw.tx_cntxt[ha->txr_idx].tx_cntxt_id << 16);
1319
1320
1321         if (qla_get_hw_stats(ha, cmd) == 0) {
1322                 xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt;
1323                 qla_xmt_stats(ha, xstat);
1324         } else {
1325                 device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n",
1326                         __func__, ha->hw.mbox[0]);
1327         }
1328 }
1329
1330 /*
1331  * Name: qla_tx_tso
1332  * Function: Checks if the packet to be transmitted is a candidate for
1333  *      Large TCP Segment Offload. If yes, the appropriate fields in the Tx
1334  *      Ring Structure are plugged in.
1335  */
1336 static int
1337 qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
1338 {
1339         struct ether_vlan_header *eh;
1340         struct ip *ip = NULL;
1341         struct ip6_hdr *ip6 = NULL;
1342         struct tcphdr *th = NULL;
1343         uint32_t ehdrlen,  hdrlen, ip_hlen, tcp_hlen, tcp_opt_off;
1344         uint16_t etype, opcode, offload = 1;
1345         device_t dev;
1346
1347         dev = ha->pci_dev;
1348
1349
1350         eh = mtod(mp, struct ether_vlan_header *);
1351
1352         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1353                 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1354                 etype = ntohs(eh->evl_proto);
1355         } else {
1356                 ehdrlen = ETHER_HDR_LEN;
1357                 etype = ntohs(eh->evl_encap_proto);
1358         }
1359
1360         hdrlen = 0;
1361
1362         switch (etype) {
1363                 case ETHERTYPE_IP:
1364
1365                         tcp_opt_off = ehdrlen + sizeof(struct ip) +
1366                                         sizeof(struct tcphdr);
1367
1368                         if (mp->m_len < tcp_opt_off) {
1369                                 m_copydata(mp, 0, tcp_opt_off, hdr);
1370                                 ip = (struct ip *)(hdr + ehdrlen);
1371                         } else {
1372                                 ip = (struct ip *)(mp->m_data + ehdrlen);
1373                         }
1374
1375                         ip_hlen = ip->ip_hl << 2;
1376                         opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
1377
1378                                 
1379                         if ((ip->ip_p != IPPROTO_TCP) ||
1380                                 (ip_hlen != sizeof (struct ip))){
1381                                 /* IP Options are not supported */
1382
1383                                 offload = 0;
1384                         } else
1385                                 th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
1386
1387                 break;
1388
1389                 case ETHERTYPE_IPV6:
1390
1391                         tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) +
1392                                         sizeof (struct tcphdr);
1393
1394                         if (mp->m_len < tcp_opt_off) {
1395                                 m_copydata(mp, 0, tcp_opt_off, hdr);
1396                                 ip6 = (struct ip6_hdr *)(hdr + ehdrlen);
1397                         } else {
1398                                 ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1399                         }
1400
1401                         ip_hlen = sizeof(struct ip6_hdr);
1402                         opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6;
1403
1404                         if (ip6->ip6_nxt != IPPROTO_TCP) {
1405                                 //device_printf(dev, "%s: ipv6\n", __func__);
1406                                 offload = 0;
1407                         } else
1408                                 th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
1409                 break;
1410
1411                 default:
1412                         QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__));
1413                         offload = 0;
1414                 break;
1415         }
1416
1417         if (!offload)
1418                 return (-1);
1419
1420         tcp_hlen = th->th_off << 2;
1421         hdrlen = ehdrlen + ip_hlen + tcp_hlen;
1422
1423         if (mp->m_len < hdrlen) {
1424                 if (mp->m_len < tcp_opt_off) {
1425                         if (tcp_hlen > sizeof(struct tcphdr)) {
1426                                 m_copydata(mp, tcp_opt_off,
1427                                         (tcp_hlen - sizeof(struct tcphdr)),
1428                                         &hdr[tcp_opt_off]);
1429                         }
1430                 } else {
1431                         m_copydata(mp, 0, hdrlen, hdr);
1432                 }
1433         }
1434
1435         tx_cmd->mss = mp->m_pkthdr.tso_segsz;
1436
1437         tx_cmd->flags_opcode = opcode ;
1438         tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen;
1439         tx_cmd->total_hdr_len = hdrlen;
1440
1441         /* Check for Multicast least significant bit of MSB == 1 */
1442         if (eh->evl_dhost[0] & 0x01) {
1443                 tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST;
1444         }
1445
1446         if (mp->m_len < hdrlen) {
1447                 printf("%d\n", hdrlen);
1448                 return (1);
1449         }
1450
1451         return (0);
1452 }
1453
1454 /*
1455  * Name: qla_tx_chksum
1456  * Function: Checks if the packet to be transmitted is a candidate for
1457  *      TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx
1458  *      Ring Structure are plugged in.
1459  */
1460 static int
1461 qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code,
1462         uint32_t *tcp_hdr_off)
1463 {
1464         struct ether_vlan_header *eh;
1465         struct ip *ip;
1466         struct ip6_hdr *ip6;
1467         uint32_t ehdrlen, ip_hlen;
1468         uint16_t etype, opcode, offload = 1;
1469         device_t dev;
1470         uint8_t buf[sizeof(struct ip6_hdr)];
1471
1472         dev = ha->pci_dev;
1473
1474         *op_code = 0;
1475
1476         if ((mp->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) == 0)
1477                 return (-1);
1478
1479         eh = mtod(mp, struct ether_vlan_header *);
1480
1481         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1482                 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1483                 etype = ntohs(eh->evl_proto);
1484         } else {
1485                 ehdrlen = ETHER_HDR_LEN;
1486                 etype = ntohs(eh->evl_encap_proto);
1487         }
1488
1489                 
1490         switch (etype) {
1491                 case ETHERTYPE_IP:
1492                         ip = (struct ip *)(mp->m_data + ehdrlen);
1493
1494                         ip_hlen = sizeof (struct ip);
1495
1496                         if (mp->m_len < (ehdrlen + ip_hlen)) {
1497                                 m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
1498                                 ip = (struct ip *)buf;
1499                         }
1500
1501                         if (ip->ip_p == IPPROTO_TCP)
1502                                 opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM;
1503                         else if (ip->ip_p == IPPROTO_UDP)
1504                                 opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM;
1505                         else {
1506                                 //device_printf(dev, "%s: ipv4\n", __func__);
1507                                 offload = 0;
1508                         }
1509                 break;
1510
1511                 case ETHERTYPE_IPV6:
1512                         ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1513
1514                         ip_hlen = sizeof(struct ip6_hdr);
1515
1516                         if (mp->m_len < (ehdrlen + ip_hlen)) {
1517                                 m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
1518                                         buf);
1519                                 ip6 = (struct ip6_hdr *)buf;
1520                         }
1521
1522                         if (ip6->ip6_nxt == IPPROTO_TCP)
1523                                 opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6;
1524                         else if (ip6->ip6_nxt == IPPROTO_UDP)
1525                                 opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6;
1526                         else {
1527                                 //device_printf(dev, "%s: ipv6\n", __func__);
1528                                 offload = 0;
1529                         }
1530                 break;
1531
1532                 default:
1533                         offload = 0;
1534                 break;
1535         }
1536         if (!offload)
1537                 return (-1);
1538
1539         *op_code = opcode;
1540         *tcp_hdr_off = (ip_hlen + ehdrlen);
1541
1542         return (0);
1543 }
1544
1545 #define QLA_TX_MIN_FREE 2
1546 /*
1547  * Name: ql_hw_send
1548  * Function: Transmits a packet. It first checks if the packet is a
1549  *      candidate for Large TCP Segment Offload and then for UDP/TCP checksum
1550  *      offload. If either of these creteria are not met, it is transmitted
1551  *      as a regular ethernet frame.
1552  */
1553 int
1554 ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
1555         uint32_t tx_idx,  struct mbuf *mp, uint32_t txr_idx)
1556 {
1557         struct ether_vlan_header *eh;
1558         qla_hw_t *hw = &ha->hw;
1559         q80_tx_cmd_t *tx_cmd, tso_cmd;
1560         bus_dma_segment_t *c_seg;
1561         uint32_t num_tx_cmds, hdr_len = 0;
1562         uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next;
1563         device_t dev;
1564         int i, ret;
1565         uint8_t *src = NULL, *dst = NULL;
1566         uint8_t frame_hdr[QL_FRAME_HDR_SIZE];
1567         uint32_t op_code = 0;
1568         uint32_t tcp_hdr_off = 0;
1569
1570         dev = ha->pci_dev;
1571
1572         /*
1573          * Always make sure there is atleast one empty slot in the tx_ring
1574          * tx_ring is considered full when there only one entry available
1575          */
1576         num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2;
1577
1578         total_length = mp->m_pkthdr.len;
1579         if (total_length > QLA_MAX_TSO_FRAME_SIZE) {
1580                 device_printf(dev, "%s: total length exceeds maxlen(%d)\n",
1581                         __func__, total_length);
1582                 return (-1);
1583         }
1584         eh = mtod(mp, struct ether_vlan_header *);
1585
1586         if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
1587
1588                 bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
1589
1590                 src = frame_hdr;
1591                 ret = qla_tx_tso(ha, mp, &tso_cmd, src);
1592
1593                 if (!(ret & ~1)) {
1594                         /* find the additional tx_cmd descriptors required */
1595
1596                         if (mp->m_flags & M_VLANTAG)
1597                                 tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN;
1598
1599                         hdr_len = tso_cmd.total_hdr_len;
1600
1601                         bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
1602                         bytes = QL_MIN(bytes, hdr_len);
1603
1604                         num_tx_cmds++;
1605                         hdr_len -= bytes;
1606
1607                         while (hdr_len) {
1608                                 bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
1609                                 hdr_len -= bytes;
1610                                 num_tx_cmds++;
1611                         }
1612                         hdr_len = tso_cmd.total_hdr_len;
1613
1614                         if (ret == 0)
1615                                 src = (uint8_t *)eh;
1616                 } else 
1617                         return (EINVAL);
1618         } else {
1619                 (void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off);
1620         }
1621
1622         if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
1623                 qla_hw_tx_done_locked(ha, txr_idx);
1624                 if (hw->tx_cntxt[txr_idx].txr_free <=
1625                                 (num_tx_cmds + QLA_TX_MIN_FREE)) {
1626                         QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= "
1627                                 "(num_tx_cmds + QLA_TX_MIN_FREE))\n",
1628                                 __func__));
1629                         return (-1);
1630                 }
1631         }
1632
1633         tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx];
1634
1635         if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) {
1636
1637                 if (nsegs > ha->hw.max_tx_segs)
1638                         ha->hw.max_tx_segs = nsegs;
1639
1640                 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
1641
1642                 if (op_code) {
1643                         tx_cmd->flags_opcode = op_code;
1644                         tx_cmd->tcp_hdr_off = tcp_hdr_off;
1645
1646                 } else {
1647                         tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER;
1648                 }
1649         } else {
1650                 bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
1651                 ha->tx_tso_frames++;
1652         }
1653
1654         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1655                 tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
1656         } else if (mp->m_flags & M_VLANTAG) {
1657
1658                 if (hdr_len) { /* TSO */
1659                         tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED |
1660                                                 Q8_TX_CMD_FLAGS_HW_VLAN_ID);
1661                         tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN;
1662                 } else
1663                         tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID;
1664
1665                 ha->hw_vlan_tx_frames++;
1666                 tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag;
1667         }
1668
1669
1670         tx_cmd->n_bufs = (uint8_t)nsegs;
1671         tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF);
1672         tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8)));
1673         tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func);
1674
1675         c_seg = segs;
1676
1677         while (1) {
1678                 for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) {
1679
1680                         switch (i) {
1681                         case 0:
1682                                 tx_cmd->buf1_addr = c_seg->ds_addr;
1683                                 tx_cmd->buf1_len = c_seg->ds_len;
1684                                 break;
1685
1686                         case 1:
1687                                 tx_cmd->buf2_addr = c_seg->ds_addr;
1688                                 tx_cmd->buf2_len = c_seg->ds_len;
1689                                 break;
1690
1691                         case 2:
1692                                 tx_cmd->buf3_addr = c_seg->ds_addr;
1693                                 tx_cmd->buf3_len = c_seg->ds_len;
1694                                 break;
1695
1696                         case 3:
1697                                 tx_cmd->buf4_addr = c_seg->ds_addr;
1698                                 tx_cmd->buf4_len = c_seg->ds_len;
1699                                 break;
1700                         }
1701
1702                         c_seg++;
1703                         nsegs--;
1704                 }
1705
1706                 txr_next = hw->tx_cntxt[txr_idx].txr_next =
1707                         (hw->tx_cntxt[txr_idx].txr_next + 1) &
1708                                 (NUM_TX_DESCRIPTORS - 1);
1709                 tx_cmd_count++;
1710
1711                 if (!nsegs)
1712                         break;
1713                 
1714                 tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
1715                 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
1716         }
1717
1718         if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
1719
1720                 /* TSO : Copy the header in the following tx cmd descriptors */
1721
1722                 txr_next = hw->tx_cntxt[txr_idx].txr_next;
1723
1724                 tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
1725                 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
1726
1727                 bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
1728                 bytes = QL_MIN(bytes, hdr_len);
1729
1730                 dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN;
1731
1732                 if (mp->m_flags & M_VLANTAG) {
1733                         /* first copy the src/dst MAC addresses */
1734                         bcopy(src, dst, (ETHER_ADDR_LEN * 2));
1735                         dst += (ETHER_ADDR_LEN * 2);
1736                         src += (ETHER_ADDR_LEN * 2);
1737                         
1738                         *((uint16_t *)dst) = htons(ETHERTYPE_VLAN);
1739                         dst += 2;
1740                         *((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag);
1741                         dst += 2;
1742
1743                         /* bytes left in src header */
1744                         hdr_len -= ((ETHER_ADDR_LEN * 2) +
1745                                         ETHER_VLAN_ENCAP_LEN);
1746
1747                         /* bytes left in TxCmd Entry */
1748                         bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN);
1749
1750
1751                         bcopy(src, dst, bytes);
1752                         src += bytes;
1753                         hdr_len -= bytes;
1754                 } else {
1755                         bcopy(src, dst, bytes);
1756                         src += bytes;
1757                         hdr_len -= bytes;
1758                 }
1759
1760                 txr_next = hw->tx_cntxt[txr_idx].txr_next =
1761                                 (hw->tx_cntxt[txr_idx].txr_next + 1) &
1762                                         (NUM_TX_DESCRIPTORS - 1);
1763                 tx_cmd_count++;
1764                 
1765                 while (hdr_len) {
1766                         tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
1767                         bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
1768
1769                         bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
1770
1771                         bcopy(src, tx_cmd, bytes);
1772                         src += bytes;
1773                         hdr_len -= bytes;
1774
1775                         txr_next = hw->tx_cntxt[txr_idx].txr_next =
1776                                 (hw->tx_cntxt[txr_idx].txr_next + 1) &
1777                                         (NUM_TX_DESCRIPTORS - 1);
1778                         tx_cmd_count++;
1779                 }
1780         }
1781
1782         hw->tx_cntxt[txr_idx].txr_free =
1783                 hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count;
1784
1785         QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\
1786                 txr_idx);
1787         QL_DPRINT8(ha, (dev, "%s: return\n", __func__));
1788
1789         return (0);
1790 }
1791
1792
1793 static int
1794 qla_config_rss_ind_table(qla_host_t *ha)
1795 {
1796         uint32_t i, count;
1797         uint8_t rss_ind_tbl[16];
1798
1799         bzero(rss_ind_default_table, sizeof(rss_ind_default_table));
1800
1801
1802         for (i = 0; i < 16; i++) {
1803                 rss_ind_tbl[i] = i % ha->hw.num_sds_rings;
1804         }
1805
1806         for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ; i = i + 16) {
1807
1808                 if ((i + 16) > Q8_RSS_IND_TBL_MAX_IDX) {
1809                         count = Q8_RSS_IND_TBL_MAX_IDX - i + 1;
1810                 } else {
1811                         count = 16;
1812                 }
1813
1814                 if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id,
1815                         rss_ind_tbl))
1816                         return (-1);
1817         }
1818
1819         return (0);
1820 }
1821
1822 /*
1823  * Name: ql_del_hw_if
1824  * Function: Destroys the hardware specific entities corresponding to an
1825  *      Ethernet Interface
1826  */
1827 void
1828 ql_del_hw_if(qla_host_t *ha)
1829 {
1830
1831         qla_del_rcv_cntxt(ha);
1832         qla_del_xmt_cntxt(ha);
1833
1834         if (ha->hw.flags.init_intr_cnxt) {
1835                 qla_config_intr_cntxt(ha, ha->hw.num_sds_rings, 0);
1836                 ha->hw.flags.init_intr_cnxt = 0;
1837         }
1838 }
1839
1840 /*
1841  * Name: ql_init_hw_if
1842  * Function: Creates the hardware specific entities corresponding to an
1843  *      Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address
1844  *      corresponding to the interface. Enables LRO if allowed.
1845  */
1846 int
1847 ql_init_hw_if(qla_host_t *ha)
1848 {
1849         device_t        dev;
1850         uint32_t        i;
1851         uint8_t         bcast_mac[6];
1852         qla_rdesc_t     *rdesc;
1853
1854         dev = ha->pci_dev;
1855
1856         for (i = 0; i < ha->hw.num_sds_rings; i++) {
1857                 bzero(ha->hw.dma_buf.sds_ring[i].dma_b,
1858                         ha->hw.dma_buf.sds_ring[i].size);
1859         }
1860         ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX);
1861
1862         /* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */
1863         WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2);
1864         WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
1865
1866         qla_get_nic_partition(ha);
1867
1868         if (qla_config_intr_cntxt(ha, ha->hw.num_sds_rings, 1) == 0) {
1869                 ha->hw.flags.init_intr_cnxt = 1;
1870         } else 
1871                 return (-1);
1872
1873         if (ha->hw.mdump_init == 0) {
1874                 qla_minidump_init(ha);
1875         }
1876
1877         /*
1878          * Create Receive Context
1879          */
1880         if (qla_init_rcv_cntxt(ha)) {
1881                 return (-1);
1882         }
1883
1884         for (i = 0; i < ha->hw.num_rds_rings; i++) {
1885                 rdesc = &ha->hw.rds[i];
1886                 rdesc->rx_next = NUM_RX_DESCRIPTORS - 2;
1887                 rdesc->rx_in = 0;
1888                 /* Update the RDS Producer Indices */
1889                 QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\
1890                         rdesc->rx_next);
1891         }
1892
1893
1894         /*
1895          * Create Transmit Context
1896          */
1897         if (qla_init_xmt_cntxt(ha)) {
1898                 qla_del_rcv_cntxt(ha);
1899                 return (-1);
1900         }
1901         ha->hw.max_tx_segs = 0;
1902
1903         if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1))
1904                 return(-1);
1905
1906         ha->hw.flags.unicast_mac = 1;
1907
1908         bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
1909         bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
1910
1911         if (qla_config_mac_addr(ha, bcast_mac, 1))
1912                 return (-1);
1913
1914         ha->hw.flags.bcast_mac = 1;
1915
1916         /*
1917          * program any cached multicast addresses
1918          */
1919         if (qla_hw_add_all_mcast(ha))
1920                 return (-1);
1921
1922         if (qla_config_rss(ha, ha->hw.rcv_cntxt_id))
1923                 return (-1);
1924
1925         if (qla_config_rss_ind_table(ha))
1926                 return (-1);
1927
1928         if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0))
1929                 return (-1);
1930
1931         if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
1932                 return (-1);
1933
1934         if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
1935                 return (-1);
1936
1937         for (i = 0; i < ha->hw.num_sds_rings; i++)
1938                 QL_ENABLE_INTERRUPTS(ha, i);
1939
1940         return (0);
1941 }
1942
1943 static int
1944 qla_map_sds_to_rds(qla_host_t *ha)
1945 {
1946         device_t                dev = ha->pci_dev;
1947         q80_rq_map_sds_to_rds_t *map_rings;
1948         q80_rsp_add_rcv_rings_t *map_rings_rsp;
1949         uint32_t                i, err;
1950         qla_hw_t                *hw = &ha->hw;
1951
1952         map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox;
1953         bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t));
1954
1955         map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS;
1956         map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2);
1957         map_rings->count_version |= Q8_MBX_CMD_VERSION;
1958
1959         map_rings->cntxt_id = hw->rcv_cntxt_id;
1960         map_rings->num_rings = hw->num_sds_rings;
1961
1962         for (i = 0; i < hw->num_sds_rings; i++) {
1963                 map_rings->sds_rds[i].sds_ring = i;
1964                 map_rings->sds_rds[i].rds_ring = i;
1965         }
1966
1967         if (qla_mbx_cmd(ha, (uint32_t *)map_rings,
1968                 (sizeof (q80_rq_map_sds_to_rds_t) >> 2),
1969                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
1970                 device_printf(dev, "%s: failed0\n", __func__);
1971                 return (-1);
1972         }
1973
1974         map_rings_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
1975
1976         err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status);
1977
1978         if (err) {
1979                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1980                 return (-1);
1981         }
1982
1983         return (0);
1984 }
1985
1986 /*
1987  * Name: qla_init_rcv_cntxt
1988  * Function: Creates the Receive Context.
1989  */
1990 static int
1991 qla_init_rcv_cntxt(qla_host_t *ha)
1992 {
1993         q80_rq_rcv_cntxt_t      *rcntxt;
1994         q80_rsp_rcv_cntxt_t     *rcntxt_rsp;
1995         q80_stat_desc_t         *sdesc;
1996         int                     i, j;
1997         qla_hw_t                *hw = &ha->hw;
1998         device_t                dev;
1999         uint32_t                err;
2000         uint32_t                rcntxt_sds_rings;
2001         uint32_t                rcntxt_rds_rings;
2002
2003         dev = ha->pci_dev;
2004
2005         /*
2006          * Create Receive Context
2007          */
2008
2009         for (i = 0; i < hw->num_sds_rings; i++) {
2010                 sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0];
2011
2012                 for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) {
2013                         sdesc->data[0] = 1ULL;
2014                         sdesc->data[1] = 1ULL;
2015                 }
2016         }
2017
2018         rcntxt_sds_rings = hw->num_sds_rings;
2019         if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS)
2020                 rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS;
2021
2022         rcntxt_rds_rings = hw->num_rds_rings;
2023
2024         if (hw->num_rds_rings > MAX_RDS_RING_SETS)
2025                 rcntxt_rds_rings = MAX_RDS_RING_SETS;
2026
2027         rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox;
2028         bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t)));
2029
2030         rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT;
2031         rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2);
2032         rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2033
2034         rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW |
2035                         Q8_RCV_CNTXT_CAP0_LRO |
2036                         Q8_RCV_CNTXT_CAP0_HW_LRO |
2037                         Q8_RCV_CNTXT_CAP0_RSS |
2038                         Q8_RCV_CNTXT_CAP0_SGL_JUMBO |
2039                         Q8_RCV_CNTXT_CAP0_SGL_LRO;
2040
2041         if (ha->hw.num_rds_rings > 1) {
2042                 rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5);
2043                 rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS;
2044         } else
2045                 rcntxt->nrds_sets_rings = 0x1 | (1 << 5);
2046
2047         rcntxt->nsds_rings = rcntxt_sds_rings;
2048
2049         rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE;
2050
2051         rcntxt->rcv_vpid = 0;
2052
2053         for (i = 0; i <  rcntxt_sds_rings; i++) {
2054                 rcntxt->sds[i].paddr =
2055                         qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr);
2056                 rcntxt->sds[i].size =
2057                         qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2058                 if (ha->msix_count == 2) {
2059                         rcntxt->sds[i].intr_id =
2060                                 qla_host_to_le16(hw->intr_id[0]);
2061                         rcntxt->sds[i].intr_src_bit = qla_host_to_le16((i));
2062                 } else {
2063                         rcntxt->sds[i].intr_id =
2064                                 qla_host_to_le16(hw->intr_id[i]);
2065                         rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0);
2066                 }
2067         }
2068
2069         for (i = 0; i <  rcntxt_rds_rings; i++) {
2070                 rcntxt->rds[i].paddr_std =
2071                         qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr);
2072                 rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
2073                 rcntxt->rds[i].std_nentries =
2074                         qla_host_to_le32(NUM_RX_DESCRIPTORS);
2075         }
2076
2077         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2078                 (sizeof (q80_rq_rcv_cntxt_t) >> 2),
2079                 ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) {
2080                 device_printf(dev, "%s: failed0\n", __func__);
2081                 return (-1);
2082         }
2083
2084         rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox;
2085
2086         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2087
2088         if (err) {
2089                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2090                 return (-1);
2091         }
2092
2093         for (i = 0; i <  rcntxt_sds_rings; i++) {
2094                 hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i];
2095         }
2096
2097         for (i = 0; i <  rcntxt_rds_rings; i++) {
2098                 hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std;
2099         }
2100
2101         hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id;
2102
2103         ha->hw.flags.init_rx_cnxt = 1;
2104
2105         if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) {
2106                 err = qla_add_rcv_rings(ha, MAX_RCNTXT_SDS_RINGS);
2107                 if (err)
2108                         return -1;
2109         }
2110
2111         if (hw->num_rds_rings > 1) {
2112                 err = qla_map_sds_to_rds(ha);
2113                 if (err)
2114                         return -1;
2115         }
2116
2117         return (0);
2118 }
2119
2120 static int
2121 qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx)
2122 {
2123         device_t                dev = ha->pci_dev;
2124         q80_rq_add_rcv_rings_t  *add_rcv;
2125         q80_rsp_add_rcv_rings_t *add_rcv_rsp;
2126         uint32_t                i,j, err;
2127         uint8_t                 nsds;
2128         qla_hw_t                *hw = &ha->hw;
2129
2130         nsds = hw->num_sds_rings - MAX_RCNTXT_SDS_RINGS;
2131
2132         add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox;
2133         bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t));
2134
2135         add_rcv->opcode = Q8_MBX_ADD_RX_RINGS;
2136         add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2);
2137         add_rcv->count_version |= Q8_MBX_CMD_VERSION;
2138
2139         if (hw->num_rds_rings > 1)
2140                 add_rcv->nrds_sets_rings = nsds | (1 << 5);
2141         else
2142                 add_rcv->nrds_sets_rings = 0;
2143
2144         add_rcv->nsds_rings = nsds;
2145         add_rcv->cntxt_id = hw->rcv_cntxt_id;
2146
2147         for (i = 0; i <  nsds; i++) {
2148
2149                 j = i + sds_idx;
2150
2151                 add_rcv->sds[i].paddr =
2152                         qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr);
2153
2154                 add_rcv->sds[i].size =
2155                         qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2156
2157                 if (ha->msix_count == 2) {
2158                         add_rcv->sds[i].intr_id =
2159                                 qla_host_to_le16(hw->intr_id[0]);
2160                         add_rcv->sds[i].intr_src_bit = qla_host_to_le16(j);
2161                 } else {
2162                         add_rcv->sds[i].intr_id =
2163                                 qla_host_to_le16(hw->intr_id[j]);
2164                         add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0);
2165                 }
2166
2167         }
2168         for (i = 0; ((i <  nsds) && (hw->num_rds_rings > 1)); i++) {
2169                 j = i + sds_idx;
2170                 add_rcv->rds[i].paddr_std =
2171                         qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr);
2172                 add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
2173                 add_rcv->rds[i].std_nentries =
2174                         qla_host_to_le32(NUM_RX_DESCRIPTORS);
2175         }
2176
2177
2178         if (qla_mbx_cmd(ha, (uint32_t *)add_rcv,
2179                 (sizeof (q80_rq_add_rcv_rings_t) >> 2),
2180                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2181                 device_printf(dev, "%s: failed0\n", __func__);
2182                 return (-1);
2183         }
2184
2185         add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
2186
2187         err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status);
2188
2189         if (err) {
2190                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2191                 return (-1);
2192         }
2193
2194         for (i = sds_idx; i < hw->num_sds_rings; i++) {
2195                 hw->sds[i].sds_consumer = add_rcv_rsp->sds_cons[(i - sds_idx)];
2196         }
2197         for (i = sds_idx; i < hw->num_rds_rings; i++) {
2198                 hw->rds[i].prod_std = add_rcv_rsp->rds[(i - sds_idx)].prod_std;
2199         }
2200         return (0);
2201 }
2202
2203 /*
2204  * Name: qla_del_rcv_cntxt
2205  * Function: Destroys the Receive Context.
2206  */
2207 static void
2208 qla_del_rcv_cntxt(qla_host_t *ha)
2209 {
2210         device_t                        dev = ha->pci_dev;
2211         q80_rcv_cntxt_destroy_t         *rcntxt;
2212         q80_rcv_cntxt_destroy_rsp_t     *rcntxt_rsp;
2213         uint32_t                        err;
2214         uint8_t                         bcast_mac[6];
2215
2216         if (!ha->hw.flags.init_rx_cnxt)
2217                 return;
2218
2219         if (qla_hw_del_all_mcast(ha))
2220                 return;
2221
2222         if (ha->hw.flags.bcast_mac) {
2223
2224                 bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2225                 bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2226
2227                 if (qla_config_mac_addr(ha, bcast_mac, 0))
2228                         return;
2229                 ha->hw.flags.bcast_mac = 0;
2230
2231         }
2232
2233         if (ha->hw.flags.unicast_mac) {
2234                 if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0))
2235                         return;
2236                 ha->hw.flags.unicast_mac = 0;
2237         }
2238
2239         rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox;
2240         bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t)));
2241
2242         rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT;
2243         rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2);
2244         rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2245
2246         rcntxt->cntxt_id = ha->hw.rcv_cntxt_id;
2247
2248         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2249                 (sizeof (q80_rcv_cntxt_destroy_t) >> 2),
2250                 ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) {
2251                 device_printf(dev, "%s: failed0\n", __func__);
2252                 return;
2253         }
2254         rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox;
2255
2256         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2257
2258         if (err) {
2259                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2260         }
2261
2262         ha->hw.flags.init_rx_cnxt = 0;
2263         return;
2264 }
2265
2266 /*
2267  * Name: qla_init_xmt_cntxt
2268  * Function: Creates the Transmit Context.
2269  */
2270 static int
2271 qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2272 {
2273         device_t                dev;
2274         qla_hw_t                *hw = &ha->hw;
2275         q80_rq_tx_cntxt_t       *tcntxt;
2276         q80_rsp_tx_cntxt_t      *tcntxt_rsp;
2277         uint32_t                err;
2278         qla_hw_tx_cntxt_t       *hw_tx_cntxt;
2279
2280         hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
2281
2282         dev = ha->pci_dev;
2283
2284         /*
2285          * Create Transmit Context
2286          */
2287         tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox;
2288         bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t)));
2289
2290         tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT;
2291         tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2);
2292         tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2293
2294         tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO;
2295
2296         tcntxt->ntx_rings = 1;
2297
2298         tcntxt->tx_ring[0].paddr =
2299                 qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr);
2300         tcntxt->tx_ring[0].tx_consumer =
2301                 qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr);
2302         tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS);
2303
2304         tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[0]);
2305         tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0);
2306
2307
2308         hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS;
2309         hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0;
2310
2311         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2312                 (sizeof (q80_rq_tx_cntxt_t) >> 2),
2313                 ha->hw.mbox,
2314                 (sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) {
2315                 device_printf(dev, "%s: failed0\n", __func__);
2316                 return (-1);
2317         }
2318         tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox;
2319
2320         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2321
2322         if (err) {
2323                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2324                 return -1;
2325         }
2326
2327         hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index;
2328         hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id;
2329
2330         return (0);
2331 }
2332
2333
2334 /*
2335  * Name: qla_del_xmt_cntxt
2336  * Function: Destroys the Transmit Context.
2337  */
2338 static int
2339 qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2340 {
2341         device_t                        dev = ha->pci_dev;
2342         q80_tx_cntxt_destroy_t          *tcntxt;
2343         q80_tx_cntxt_destroy_rsp_t      *tcntxt_rsp;
2344         uint32_t                        err;
2345
2346         tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox;
2347         bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t)));
2348
2349         tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT;
2350         tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2);
2351         tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2352
2353         tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id;
2354
2355         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2356                 (sizeof (q80_tx_cntxt_destroy_t) >> 2),
2357                 ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) {
2358                 device_printf(dev, "%s: failed0\n", __func__);
2359                 return (-1);
2360         }
2361         tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox;
2362
2363         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2364
2365         if (err) {
2366                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2367                 return (-1);
2368         }
2369
2370         return (0);
2371 }
2372 static void
2373 qla_del_xmt_cntxt(qla_host_t *ha)
2374 {
2375         uint32_t i;
2376
2377         if (!ha->hw.flags.init_tx_cnxt)
2378                 return;
2379
2380         for (i = 0; i < ha->hw.num_tx_rings; i++) {
2381                 if (qla_del_xmt_cntxt_i(ha, i))
2382                         break;
2383         }
2384         ha->hw.flags.init_tx_cnxt = 0;
2385 }
2386
2387 static int
2388 qla_init_xmt_cntxt(qla_host_t *ha)
2389 {
2390         uint32_t i, j;
2391
2392         for (i = 0; i < ha->hw.num_tx_rings; i++) {
2393                 if (qla_init_xmt_cntxt_i(ha, i) != 0) {
2394                         for (j = 0; j < i; j++)
2395                                 qla_del_xmt_cntxt_i(ha, j);
2396                         return (-1);
2397                 }
2398         }
2399         ha->hw.flags.init_tx_cnxt = 1;
2400         return (0);
2401 }
2402
2403 static int
2404 qla_hw_add_all_mcast(qla_host_t *ha)
2405 {
2406         int i, nmcast;
2407
2408         nmcast = ha->hw.nmcast;
2409
2410         for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
2411                 if ((ha->hw.mcast[i].addr[0] != 0) || 
2412                         (ha->hw.mcast[i].addr[1] != 0) ||
2413                         (ha->hw.mcast[i].addr[2] != 0) ||
2414                         (ha->hw.mcast[i].addr[3] != 0) ||
2415                         (ha->hw.mcast[i].addr[4] != 0) ||
2416                         (ha->hw.mcast[i].addr[5] != 0)) {
2417
2418                         if (qla_config_mac_addr(ha, ha->hw.mcast[i].addr, 1)) {
2419                                 device_printf(ha->pci_dev, "%s: failed\n",
2420                                         __func__);
2421                                 return (-1);
2422                         }
2423
2424                         nmcast--;
2425                 }
2426         }
2427         return 0;
2428 }
2429
2430 static int
2431 qla_hw_del_all_mcast(qla_host_t *ha)
2432 {
2433         int i, nmcast;
2434
2435         nmcast = ha->hw.nmcast;
2436
2437         for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
2438                 if ((ha->hw.mcast[i].addr[0] != 0) || 
2439                         (ha->hw.mcast[i].addr[1] != 0) ||
2440                         (ha->hw.mcast[i].addr[2] != 0) ||
2441                         (ha->hw.mcast[i].addr[3] != 0) ||
2442                         (ha->hw.mcast[i].addr[4] != 0) ||
2443                         (ha->hw.mcast[i].addr[5] != 0)) {
2444
2445                         if (qla_config_mac_addr(ha, ha->hw.mcast[i].addr, 0))
2446                                 return (-1);
2447
2448                         nmcast--;
2449                 }
2450         }
2451         return 0;
2452 }
2453
2454 static int
2455 qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta)
2456 {
2457         int i;
2458
2459         for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
2460
2461                 if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0)
2462                         return 0; /* its been already added */
2463         }
2464
2465         for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
2466
2467                 if ((ha->hw.mcast[i].addr[0] == 0) && 
2468                         (ha->hw.mcast[i].addr[1] == 0) &&
2469                         (ha->hw.mcast[i].addr[2] == 0) &&
2470                         (ha->hw.mcast[i].addr[3] == 0) &&
2471                         (ha->hw.mcast[i].addr[4] == 0) &&
2472                         (ha->hw.mcast[i].addr[5] == 0)) {
2473
2474                         if (qla_config_mac_addr(ha, mta, 1))
2475                                 return (-1);
2476
2477                         bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN);
2478                         ha->hw.nmcast++;        
2479
2480                         return 0;
2481                 }
2482         }
2483         return 0;
2484 }
2485
2486 static int
2487 qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta)
2488 {
2489         int i;
2490
2491         for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
2492                 if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) {
2493
2494                         if (qla_config_mac_addr(ha, mta, 0))
2495                                 return (-1);
2496
2497                         ha->hw.mcast[i].addr[0] = 0;
2498                         ha->hw.mcast[i].addr[1] = 0;
2499                         ha->hw.mcast[i].addr[2] = 0;
2500                         ha->hw.mcast[i].addr[3] = 0;
2501                         ha->hw.mcast[i].addr[4] = 0;
2502                         ha->hw.mcast[i].addr[5] = 0;
2503
2504                         ha->hw.nmcast--;        
2505
2506                         return 0;
2507                 }
2508         }
2509         return 0;
2510 }
2511
2512 /*
2513  * Name: ql_hw_set_multi
2514  * Function: Sets the Multicast Addresses provided the host O.S into the
2515  *      hardware (for the given interface)
2516  */
2517 int
2518 ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast, uint32_t mcnt,
2519         uint32_t add_mac)
2520 {
2521         int i;
2522         uint8_t *mta = mcast;
2523         int ret = 0;
2524
2525         for (i = 0; i < mcnt; i++) {
2526                 if (add_mac) {
2527                         ret = qla_hw_add_mcast(ha, mta);
2528                         if (ret)
2529                                 break;
2530                 } else {
2531                         ret = qla_hw_del_mcast(ha, mta);
2532                         if (ret)
2533                                 break;
2534                 }
2535                         
2536                 mta += Q8_MAC_ADDR_LEN;
2537         }
2538         return (ret);
2539 }
2540
2541 /*
2542  * Name: qla_hw_tx_done_locked
2543  * Function: Handle Transmit Completions
2544  */
2545 static void
2546 qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx)
2547 {
2548         qla_tx_buf_t *txb;
2549         qla_hw_t *hw = &ha->hw;
2550         uint32_t comp_idx, comp_count = 0;
2551         qla_hw_tx_cntxt_t *hw_tx_cntxt;
2552
2553         hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
2554
2555         /* retrieve index of last entry in tx ring completed */
2556         comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons));
2557
2558         while (comp_idx != hw_tx_cntxt->txr_comp) {
2559
2560                 txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp];
2561
2562                 hw_tx_cntxt->txr_comp++;
2563                 if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS)
2564                         hw_tx_cntxt->txr_comp = 0;
2565
2566                 comp_count++;
2567
2568                 if (txb->m_head) {
2569                         ha->ifp->if_opackets++;
2570
2571                         bus_dmamap_sync(ha->tx_tag, txb->map,
2572                                 BUS_DMASYNC_POSTWRITE);
2573                         bus_dmamap_unload(ha->tx_tag, txb->map);
2574                         m_freem(txb->m_head);
2575
2576                         txb->m_head = NULL;
2577                 }
2578         }
2579
2580         hw_tx_cntxt->txr_free += comp_count;
2581         return;
2582 }
2583
2584 /*
2585  * Name: ql_hw_tx_done
2586  * Function: Handle Transmit Completions
2587  */
2588 void
2589 ql_hw_tx_done(qla_host_t *ha)
2590 {
2591         int i;
2592         uint32_t flag = 0;
2593
2594         if (!mtx_trylock(&ha->tx_lock)) {
2595                 QL_DPRINT8(ha, (ha->pci_dev,
2596                         "%s: !mtx_trylock(&ha->tx_lock)\n", __func__));
2597                 return;
2598         }
2599         for (i = 0; i < ha->hw.num_tx_rings; i++) {
2600                 qla_hw_tx_done_locked(ha, i);
2601                 if (ha->hw.tx_cntxt[i].txr_free <= (NUM_TX_DESCRIPTORS >> 1))
2602                         flag = 1;
2603         }
2604
2605         if (!flag)
2606                 ha->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2607
2608         QLA_TX_UNLOCK(ha);
2609         return;
2610 }
2611
2612 void
2613 ql_update_link_state(qla_host_t *ha)
2614 {
2615         uint32_t link_state;
2616         uint32_t prev_link_state;
2617
2618         if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
2619                 ha->hw.link_up = 0;
2620                 return;
2621         }
2622         link_state = READ_REG32(ha, Q8_LINK_STATE);
2623
2624         prev_link_state =  ha->hw.link_up;
2625
2626         if (ha->pci_func == 0) 
2627                 ha->hw.link_up = (((link_state & 0xF) == 1)? 1 : 0);
2628         else
2629                 ha->hw.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
2630
2631         if (prev_link_state !=  ha->hw.link_up) {
2632                 if (ha->hw.link_up) {
2633                         if_link_state_change(ha->ifp, LINK_STATE_UP);
2634                 } else {
2635                         if_link_state_change(ha->ifp, LINK_STATE_DOWN);
2636                 }
2637         }
2638         return;
2639 }
2640
2641 void
2642 ql_hw_stop_rcv(qla_host_t *ha)
2643 {
2644         int i, done, count = 100;
2645
2646         while (count--) {
2647                 done = 1;
2648                 for (i = 0; i < ha->hw.num_sds_rings; i++) {
2649                         if (ha->hw.sds[i].rcv_active)
2650                                 done = 0;
2651                 }
2652                 if (done)
2653                         break;
2654                 else 
2655                         qla_mdelay(__func__, 10);
2656         }
2657         if (!count)
2658                 device_printf(ha->pci_dev, "%s: Counter expired.\n", __func__);
2659
2660         return;
2661 }
2662
2663 int
2664 ql_hw_check_health(qla_host_t *ha)
2665 {
2666         uint32_t val;
2667
2668         ha->hw.health_count++;
2669
2670         if (ha->hw.health_count < 1000)
2671                 return 0;
2672
2673         ha->hw.health_count = 0;
2674
2675         val = READ_REG32(ha, Q8_ASIC_TEMPERATURE);
2676
2677         if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) ||
2678                 (QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) {
2679                 device_printf(ha->pci_dev, "%s: Temperature Alert [0x%08x]\n",
2680                         __func__, val);
2681                 return -1;
2682         }
2683
2684         val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT);
2685
2686         if ((val != ha->hw.hbeat_value) &&
2687                 (!(QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE)))) {
2688                 ha->hw.hbeat_value = val;
2689                 return 0;
2690         }
2691         device_printf(ha->pci_dev, "%s: Heartbeat Failue [0x%08x]\n",
2692                 __func__, val);
2693
2694         return -1;
2695 }
2696
2697 static int
2698 qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size)
2699 {
2700         uint32_t                        err;
2701         device_t                        dev = ha->pci_dev;
2702         q80_config_md_templ_size_t      *md_size;
2703         q80_config_md_templ_size_rsp_t  *md_size_rsp;
2704
2705         md_size = (q80_config_md_templ_size_t *) ha->hw.mbox;
2706         bzero(md_size, sizeof(q80_config_md_templ_size_t));
2707
2708         md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE;
2709         md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2);
2710         md_size->count_version |= Q8_MBX_CMD_VERSION;
2711
2712         if (qla_mbx_cmd(ha, (uint32_t *) md_size,
2713                 (sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox,
2714                 (sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) {
2715
2716                 device_printf(dev, "%s: failed\n", __func__);
2717
2718                 return (-1);
2719         }
2720
2721         md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox;
2722
2723         err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status);
2724
2725         if (err) {
2726                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
2727                 return(-1);
2728         }
2729
2730         *size = md_size_rsp->templ_size;
2731
2732         return (0);
2733 }
2734
2735 static int
2736 qla_get_minidump_template(qla_host_t *ha)
2737 {
2738         uint32_t                        err;
2739         device_t                        dev = ha->pci_dev;
2740         q80_config_md_templ_cmd_t       *md_templ;
2741         q80_config_md_templ_cmd_rsp_t   *md_templ_rsp;
2742
2743         md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox;
2744         bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t)));
2745
2746         md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT;
2747         md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2);
2748         md_templ->count_version |= Q8_MBX_CMD_VERSION;
2749
2750         md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr;
2751         md_templ->buff_size = ha->hw.dma_buf.minidump.size;
2752
2753         if (qla_mbx_cmd(ha, (uint32_t *) md_templ,
2754                 (sizeof(q80_config_md_templ_cmd_t) >> 2),
2755                  ha->hw.mbox,
2756                 (sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) {
2757
2758                 device_printf(dev, "%s: failed\n", __func__);
2759
2760                 return (-1);
2761         }
2762
2763         md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox;
2764
2765         err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status);
2766
2767         if (err) {
2768                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
2769                 return (-1);
2770         }
2771
2772         return (0);
2773
2774 }
2775
2776 static int
2777 qla_minidump_init(qla_host_t *ha)
2778 {
2779         int             ret;
2780         uint32_t        template_size = 0;
2781         device_t        dev = ha->pci_dev;
2782
2783         /*
2784          * Get Minidump Template Size
2785          */
2786         ret = qla_get_minidump_tmplt_size(ha, &template_size);
2787
2788         if (ret || (template_size == 0)) {
2789                 device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret,
2790                         template_size);
2791                 return (-1);
2792         }
2793
2794         /*
2795          * Allocate Memory for Minidump Template
2796          */
2797
2798         ha->hw.dma_buf.minidump.alignment = 8;
2799         ha->hw.dma_buf.minidump.size = template_size;
2800
2801         if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) {
2802
2803                 device_printf(dev, "%s: minidump dma alloc failed\n", __func__);
2804
2805                 return (-1);
2806         }
2807         ha->hw.dma_buf.flags.minidump = 1;
2808
2809         /*
2810          * Retrieve Minidump Template
2811          */
2812         ret = qla_get_minidump_template(ha);
2813
2814         if (ret) {
2815                 qla_minidump_free(ha);
2816         } else {
2817                 ha->hw.mdump_init = 1;
2818         }
2819
2820         return (ret);
2821 }
2822
2823
2824 static void
2825 qla_minidump_free(qla_host_t *ha)
2826 {
2827         ha->hw.mdump_init = 0;
2828         if (ha->hw.dma_buf.flags.minidump) {
2829                 ha->hw.dma_buf.flags.minidump = 0;
2830                 ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump);
2831         }
2832         return;
2833 }
2834
2835 void
2836 ql_minidump(qla_host_t *ha)
2837 {
2838         uint32_t delay = 6000;
2839
2840         if (!ha->hw.mdump_init)
2841                 return;
2842
2843         if (!ha->hw.mdump_active)
2844                 return;
2845
2846         if (ha->hw.mdump_active == 1) {
2847                 ha->hw.mdump_start_seq_index = ql_stop_sequence(ha);
2848                 ha->hw.mdump_start = 1;
2849         }
2850
2851         while (delay-- && ha->hw.mdump_active) {
2852                 qla_mdelay(__func__, 100);
2853         }
2854         ha->hw.mdump_start = 0;
2855         ql_start_sequence(ha, ha->hw.mdump_start_seq_index);
2856
2857         return;
2858 }