ql_hw.c revision 322975
1/*
2 * Copyright (c) 2013-2016 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: stable/10/sys/dev/qlxgbe/ql_hw.c 322975 2017-08-28 19:17:28Z davidcs $");
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#include "ql_minidump.h"
45
46/*
47 * Static Functions
48 */
49
50static void qla_del_rcv_cntxt(qla_host_t *ha);
51static int qla_init_rcv_cntxt(qla_host_t *ha);
52static void qla_del_xmt_cntxt(qla_host_t *ha);
53static int qla_init_xmt_cntxt(qla_host_t *ha);
54static 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);
56static int qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx,
57	uint32_t num_intrs, uint32_t create);
58static int qla_config_rss(qla_host_t *ha, uint16_t cntxt_id);
59static int qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id,
60	int tenable, int rcv);
61static int qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode);
62static int qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id);
63
64static int qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd,
65		uint8_t *hdr);
66static int qla_hw_add_all_mcast(qla_host_t *ha);
67static int qla_hw_del_all_mcast(qla_host_t *ha);
68static int qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds);
69
70static int qla_init_nic_func(qla_host_t *ha);
71static int qla_stop_nic_func(qla_host_t *ha);
72static int qla_query_fw_dcbx_caps(qla_host_t *ha);
73static int qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits);
74static int qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits);
75static int qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode);
76static int qla_get_cam_search_mode(qla_host_t *ha);
77
78static void ql_minidump_free(qla_host_t *ha);
79
80#ifdef QL_DBG
81
82static void
83qla_stop_pegs(qla_host_t *ha)
84{
85        uint32_t val = 1;
86
87        ql_rdwr_indreg32(ha, Q8_CRB_PEG_0, &val, 0);
88        ql_rdwr_indreg32(ha, Q8_CRB_PEG_1, &val, 0);
89        ql_rdwr_indreg32(ha, Q8_CRB_PEG_2, &val, 0);
90        ql_rdwr_indreg32(ha, Q8_CRB_PEG_3, &val, 0);
91        ql_rdwr_indreg32(ha, Q8_CRB_PEG_4, &val, 0);
92        device_printf(ha->pci_dev, "%s PEGS HALTED!!!!!\n", __func__);
93}
94
95static int
96qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS)
97{
98	int err, ret = 0;
99	qla_host_t *ha;
100
101	err = sysctl_handle_int(oidp, &ret, 0, req);
102
103
104	if (err || !req->newptr)
105		return (err);
106
107	if (ret == 1) {
108		ha = (qla_host_t *)arg1;
109		if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
110			qla_stop_pegs(ha);
111			QLA_UNLOCK(ha, __func__);
112		}
113	}
114
115	return err;
116}
117#endif /* #ifdef QL_DBG */
118
119static int
120qla_validate_set_port_cfg_bit(uint32_t bits)
121{
122        if ((bits & 0xF) > 1)
123                return (-1);
124
125        if (((bits >> 4) & 0xF) > 2)
126                return (-1);
127
128        if (((bits >> 8) & 0xF) > 2)
129                return (-1);
130
131        return (0);
132}
133
134static int
135qla_sysctl_port_cfg(SYSCTL_HANDLER_ARGS)
136{
137        int err, ret = 0;
138        qla_host_t *ha;
139        uint32_t cfg_bits;
140
141        err = sysctl_handle_int(oidp, &ret, 0, req);
142
143        if (err || !req->newptr)
144                return (err);
145
146	ha = (qla_host_t *)arg1;
147
148        if ((qla_validate_set_port_cfg_bit((uint32_t)ret) == 0)) {
149
150                err = qla_get_port_config(ha, &cfg_bits);
151
152                if (err)
153                        goto qla_sysctl_set_port_cfg_exit;
154
155                if (ret & 0x1) {
156                        cfg_bits |= Q8_PORT_CFG_BITS_DCBX_ENABLE;
157                } else {
158                        cfg_bits &= ~Q8_PORT_CFG_BITS_DCBX_ENABLE;
159                }
160
161                ret = ret >> 4;
162                cfg_bits &= ~Q8_PORT_CFG_BITS_PAUSE_CFG_MASK;
163
164                if ((ret & 0xF) == 0) {
165                        cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_DISABLED;
166                } else if ((ret & 0xF) == 1){
167                        cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_STD;
168                } else {
169                        cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_PPM;
170                }
171
172                ret = ret >> 4;
173                cfg_bits &= ~Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK;
174
175                if (ret == 0) {
176                        cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT_RCV;
177                } else if (ret == 1){
178                        cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT;
179                } else {
180                        cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_RCV;
181                }
182
183		if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
184                	err = qla_set_port_config(ha, cfg_bits);
185			QLA_UNLOCK(ha, __func__);
186		} else {
187			device_printf(ha->pci_dev, "%s: failed\n", __func__);
188		}
189        } else {
190		if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
191                	err = qla_get_port_config(ha, &cfg_bits);
192			QLA_UNLOCK(ha, __func__);
193		} else {
194			device_printf(ha->pci_dev, "%s: failed\n", __func__);
195		}
196        }
197
198qla_sysctl_set_port_cfg_exit:
199        return err;
200}
201
202static int
203qla_sysctl_set_cam_search_mode(SYSCTL_HANDLER_ARGS)
204{
205	int err, ret = 0;
206	qla_host_t *ha;
207
208	err = sysctl_handle_int(oidp, &ret, 0, req);
209
210	if (err || !req->newptr)
211		return (err);
212
213	ha = (qla_host_t *)arg1;
214
215	if ((ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_INTERNAL) ||
216		(ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_AUTO)) {
217
218		if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
219			err = qla_set_cam_search_mode(ha, (uint32_t)ret);
220			QLA_UNLOCK(ha, __func__);
221		} else {
222			device_printf(ha->pci_dev, "%s: failed\n", __func__);
223		}
224
225	} else {
226		device_printf(ha->pci_dev, "%s: ret = %d\n", __func__, ret);
227	}
228
229	return (err);
230}
231
232static int
233qla_sysctl_get_cam_search_mode(SYSCTL_HANDLER_ARGS)
234{
235	int err, ret = 0;
236	qla_host_t *ha;
237
238	err = sysctl_handle_int(oidp, &ret, 0, req);
239
240	if (err || !req->newptr)
241		return (err);
242
243	ha = (qla_host_t *)arg1;
244	if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
245		err = qla_get_cam_search_mode(ha);
246		QLA_UNLOCK(ha, __func__);
247	} else {
248		device_printf(ha->pci_dev, "%s: failed\n", __func__);
249	}
250
251	return (err);
252}
253
254static void
255qlnx_add_hw_mac_stats_sysctls(qla_host_t *ha)
256{
257        struct sysctl_ctx_list  *ctx;
258        struct sysctl_oid_list  *children;
259        struct sysctl_oid       *ctx_oid;
260
261        ctx = device_get_sysctl_ctx(ha->pci_dev);
262        children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
263
264        ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_hw_mac",
265                        CTLFLAG_RD, NULL, "stats_hw_mac");
266        children = SYSCTL_CHILDREN(ctx_oid);
267
268        SYSCTL_ADD_QUAD(ctx, children,
269                OID_AUTO, "xmt_frames",
270                CTLFLAG_RD, &ha->hw.mac.xmt_frames,
271                "xmt_frames");
272
273        SYSCTL_ADD_QUAD(ctx, children,
274                OID_AUTO, "xmt_bytes",
275                CTLFLAG_RD, &ha->hw.mac.xmt_bytes,
276                "xmt_frames");
277
278        SYSCTL_ADD_QUAD(ctx, children,
279                OID_AUTO, "xmt_mcast_pkts",
280                CTLFLAG_RD, &ha->hw.mac.xmt_mcast_pkts,
281                "xmt_mcast_pkts");
282
283        SYSCTL_ADD_QUAD(ctx, children,
284                OID_AUTO, "xmt_bcast_pkts",
285                CTLFLAG_RD, &ha->hw.mac.xmt_bcast_pkts,
286                "xmt_bcast_pkts");
287
288        SYSCTL_ADD_QUAD(ctx, children,
289                OID_AUTO, "xmt_pause_frames",
290                CTLFLAG_RD, &ha->hw.mac.xmt_pause_frames,
291                "xmt_pause_frames");
292
293        SYSCTL_ADD_QUAD(ctx, children,
294                OID_AUTO, "xmt_cntrl_pkts",
295                CTLFLAG_RD, &ha->hw.mac.xmt_cntrl_pkts,
296                "xmt_cntrl_pkts");
297
298        SYSCTL_ADD_QUAD(ctx, children,
299                OID_AUTO, "xmt_pkt_lt_64bytes",
300                CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_64bytes,
301                "xmt_pkt_lt_64bytes");
302
303        SYSCTL_ADD_QUAD(ctx, children,
304                OID_AUTO, "xmt_pkt_lt_127bytes",
305                CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_127bytes,
306                "xmt_pkt_lt_127bytes");
307
308        SYSCTL_ADD_QUAD(ctx, children,
309                OID_AUTO, "xmt_pkt_lt_255bytes",
310                CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_255bytes,
311                "xmt_pkt_lt_255bytes");
312
313        SYSCTL_ADD_QUAD(ctx, children,
314                OID_AUTO, "xmt_pkt_lt_511bytes",
315                CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_511bytes,
316                "xmt_pkt_lt_511bytes");
317
318        SYSCTL_ADD_QUAD(ctx, children,
319                OID_AUTO, "xmt_pkt_lt_1023bytes",
320                CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_1023bytes,
321                "xmt_pkt_lt_1023bytes");
322
323        SYSCTL_ADD_QUAD(ctx, children,
324                OID_AUTO, "xmt_pkt_lt_1518bytes",
325                CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_1518bytes,
326                "xmt_pkt_lt_1518bytes");
327
328        SYSCTL_ADD_QUAD(ctx, children,
329                OID_AUTO, "xmt_pkt_gt_1518bytes",
330                CTLFLAG_RD, &ha->hw.mac.xmt_pkt_gt_1518bytes,
331                "xmt_pkt_gt_1518bytes");
332
333        SYSCTL_ADD_QUAD(ctx, children,
334                OID_AUTO, "rcv_frames",
335                CTLFLAG_RD, &ha->hw.mac.rcv_frames,
336                "rcv_frames");
337
338        SYSCTL_ADD_QUAD(ctx, children,
339                OID_AUTO, "rcv_bytes",
340                CTLFLAG_RD, &ha->hw.mac.rcv_bytes,
341                "rcv_bytes");
342
343        SYSCTL_ADD_QUAD(ctx, children,
344                OID_AUTO, "rcv_mcast_pkts",
345                CTLFLAG_RD, &ha->hw.mac.rcv_mcast_pkts,
346                "rcv_mcast_pkts");
347
348        SYSCTL_ADD_QUAD(ctx, children,
349                OID_AUTO, "rcv_bcast_pkts",
350                CTLFLAG_RD, &ha->hw.mac.rcv_bcast_pkts,
351                "rcv_bcast_pkts");
352
353        SYSCTL_ADD_QUAD(ctx, children,
354                OID_AUTO, "rcv_pause_frames",
355                CTLFLAG_RD, &ha->hw.mac.rcv_pause_frames,
356                "rcv_pause_frames");
357
358        SYSCTL_ADD_QUAD(ctx, children,
359                OID_AUTO, "rcv_cntrl_pkts",
360                CTLFLAG_RD, &ha->hw.mac.rcv_cntrl_pkts,
361                "rcv_cntrl_pkts");
362
363        SYSCTL_ADD_QUAD(ctx, children,
364                OID_AUTO, "rcv_pkt_lt_64bytes",
365                CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_64bytes,
366                "rcv_pkt_lt_64bytes");
367
368        SYSCTL_ADD_QUAD(ctx, children,
369                OID_AUTO, "rcv_pkt_lt_127bytes",
370                CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_127bytes,
371                "rcv_pkt_lt_127bytes");
372
373        SYSCTL_ADD_QUAD(ctx, children,
374                OID_AUTO, "rcv_pkt_lt_255bytes",
375                CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_255bytes,
376                "rcv_pkt_lt_255bytes");
377
378        SYSCTL_ADD_QUAD(ctx, children,
379                OID_AUTO, "rcv_pkt_lt_511bytes",
380                CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_511bytes,
381                "rcv_pkt_lt_511bytes");
382
383        SYSCTL_ADD_QUAD(ctx, children,
384                OID_AUTO, "rcv_pkt_lt_1023bytes",
385                CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_1023bytes,
386                "rcv_pkt_lt_1023bytes");
387
388        SYSCTL_ADD_QUAD(ctx, children,
389                OID_AUTO, "rcv_pkt_lt_1518bytes",
390                CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_1518bytes,
391                "rcv_pkt_lt_1518bytes");
392
393        SYSCTL_ADD_QUAD(ctx, children,
394                OID_AUTO, "rcv_pkt_gt_1518bytes",
395                CTLFLAG_RD, &ha->hw.mac.rcv_pkt_gt_1518bytes,
396                "rcv_pkt_gt_1518bytes");
397
398        SYSCTL_ADD_QUAD(ctx, children,
399                OID_AUTO, "rcv_len_error",
400                CTLFLAG_RD, &ha->hw.mac.rcv_len_error,
401                "rcv_len_error");
402
403        SYSCTL_ADD_QUAD(ctx, children,
404                OID_AUTO, "rcv_len_small",
405                CTLFLAG_RD, &ha->hw.mac.rcv_len_small,
406                "rcv_len_small");
407
408        SYSCTL_ADD_QUAD(ctx, children,
409                OID_AUTO, "rcv_len_large",
410                CTLFLAG_RD, &ha->hw.mac.rcv_len_large,
411                "rcv_len_large");
412
413        SYSCTL_ADD_QUAD(ctx, children,
414                OID_AUTO, "rcv_jabber",
415                CTLFLAG_RD, &ha->hw.mac.rcv_jabber,
416                "rcv_jabber");
417
418        SYSCTL_ADD_QUAD(ctx, children,
419                OID_AUTO, "rcv_dropped",
420                CTLFLAG_RD, &ha->hw.mac.rcv_dropped,
421                "rcv_dropped");
422
423        SYSCTL_ADD_QUAD(ctx, children,
424                OID_AUTO, "fcs_error",
425                CTLFLAG_RD, &ha->hw.mac.fcs_error,
426                "fcs_error");
427
428        SYSCTL_ADD_QUAD(ctx, children,
429                OID_AUTO, "align_error",
430                CTLFLAG_RD, &ha->hw.mac.align_error,
431                "align_error");
432
433        SYSCTL_ADD_QUAD(ctx, children,
434                OID_AUTO, "eswitched_frames",
435                CTLFLAG_RD, &ha->hw.mac.eswitched_frames,
436                "eswitched_frames");
437
438        SYSCTL_ADD_QUAD(ctx, children,
439                OID_AUTO, "eswitched_bytes",
440                CTLFLAG_RD, &ha->hw.mac.eswitched_bytes,
441                "eswitched_bytes");
442
443        SYSCTL_ADD_QUAD(ctx, children,
444                OID_AUTO, "eswitched_mcast_frames",
445                CTLFLAG_RD, &ha->hw.mac.eswitched_mcast_frames,
446                "eswitched_mcast_frames");
447
448        SYSCTL_ADD_QUAD(ctx, children,
449                OID_AUTO, "eswitched_bcast_frames",
450                CTLFLAG_RD, &ha->hw.mac.eswitched_bcast_frames,
451                "eswitched_bcast_frames");
452
453        SYSCTL_ADD_QUAD(ctx, children,
454                OID_AUTO, "eswitched_ucast_frames",
455                CTLFLAG_RD, &ha->hw.mac.eswitched_ucast_frames,
456                "eswitched_ucast_frames");
457
458        SYSCTL_ADD_QUAD(ctx, children,
459                OID_AUTO, "eswitched_err_free_frames",
460                CTLFLAG_RD, &ha->hw.mac.eswitched_err_free_frames,
461                "eswitched_err_free_frames");
462
463        SYSCTL_ADD_QUAD(ctx, children,
464                OID_AUTO, "eswitched_err_free_bytes",
465                CTLFLAG_RD, &ha->hw.mac.eswitched_err_free_bytes,
466                "eswitched_err_free_bytes");
467
468	return;
469}
470
471static void
472qlnx_add_hw_rcv_stats_sysctls(qla_host_t *ha)
473{
474        struct sysctl_ctx_list  *ctx;
475        struct sysctl_oid_list  *children;
476        struct sysctl_oid       *ctx_oid;
477
478        ctx = device_get_sysctl_ctx(ha->pci_dev);
479        children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
480
481        ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_hw_rcv",
482                        CTLFLAG_RD, NULL, "stats_hw_rcv");
483        children = SYSCTL_CHILDREN(ctx_oid);
484
485        SYSCTL_ADD_QUAD(ctx, children,
486                OID_AUTO, "total_bytes",
487                CTLFLAG_RD, &ha->hw.rcv.total_bytes,
488                "total_bytes");
489
490        SYSCTL_ADD_QUAD(ctx, children,
491                OID_AUTO, "total_pkts",
492                CTLFLAG_RD, &ha->hw.rcv.total_pkts,
493                "total_pkts");
494
495        SYSCTL_ADD_QUAD(ctx, children,
496                OID_AUTO, "lro_pkt_count",
497                CTLFLAG_RD, &ha->hw.rcv.lro_pkt_count,
498                "lro_pkt_count");
499
500        SYSCTL_ADD_QUAD(ctx, children,
501                OID_AUTO, "sw_pkt_count",
502                CTLFLAG_RD, &ha->hw.rcv.sw_pkt_count,
503                "sw_pkt_count");
504
505        SYSCTL_ADD_QUAD(ctx, children,
506                OID_AUTO, "ip_chksum_err",
507                CTLFLAG_RD, &ha->hw.rcv.ip_chksum_err,
508                "ip_chksum_err");
509
510        SYSCTL_ADD_QUAD(ctx, children,
511                OID_AUTO, "pkts_wo_acntxts",
512                CTLFLAG_RD, &ha->hw.rcv.pkts_wo_acntxts,
513                "pkts_wo_acntxts");
514
515        SYSCTL_ADD_QUAD(ctx, children,
516                OID_AUTO, "pkts_dropped_no_sds_card",
517                CTLFLAG_RD, &ha->hw.rcv.pkts_dropped_no_sds_card,
518                "pkts_dropped_no_sds_card");
519
520        SYSCTL_ADD_QUAD(ctx, children,
521                OID_AUTO, "pkts_dropped_no_sds_host",
522                CTLFLAG_RD, &ha->hw.rcv.pkts_dropped_no_sds_host,
523                "pkts_dropped_no_sds_host");
524
525        SYSCTL_ADD_QUAD(ctx, children,
526                OID_AUTO, "oversized_pkts",
527                CTLFLAG_RD, &ha->hw.rcv.oversized_pkts,
528                "oversized_pkts");
529
530        SYSCTL_ADD_QUAD(ctx, children,
531                OID_AUTO, "pkts_dropped_no_rds",
532                CTLFLAG_RD, &ha->hw.rcv.pkts_dropped_no_rds,
533                "pkts_dropped_no_rds");
534
535        SYSCTL_ADD_QUAD(ctx, children,
536                OID_AUTO, "unxpctd_mcast_pkts",
537                CTLFLAG_RD, &ha->hw.rcv.unxpctd_mcast_pkts,
538                "unxpctd_mcast_pkts");
539
540        SYSCTL_ADD_QUAD(ctx, children,
541                OID_AUTO, "re1_fbq_error",
542                CTLFLAG_RD, &ha->hw.rcv.re1_fbq_error,
543                "re1_fbq_error");
544
545        SYSCTL_ADD_QUAD(ctx, children,
546                OID_AUTO, "invalid_mac_addr",
547                CTLFLAG_RD, &ha->hw.rcv.invalid_mac_addr,
548                "invalid_mac_addr");
549
550        SYSCTL_ADD_QUAD(ctx, children,
551                OID_AUTO, "rds_prime_trys",
552                CTLFLAG_RD, &ha->hw.rcv.rds_prime_trys,
553                "rds_prime_trys");
554
555        SYSCTL_ADD_QUAD(ctx, children,
556                OID_AUTO, "rds_prime_success",
557                CTLFLAG_RD, &ha->hw.rcv.rds_prime_success,
558                "rds_prime_success");
559
560        SYSCTL_ADD_QUAD(ctx, children,
561                OID_AUTO, "lro_flows_added",
562                CTLFLAG_RD, &ha->hw.rcv.lro_flows_added,
563                "lro_flows_added");
564
565        SYSCTL_ADD_QUAD(ctx, children,
566                OID_AUTO, "lro_flows_deleted",
567                CTLFLAG_RD, &ha->hw.rcv.lro_flows_deleted,
568                "lro_flows_deleted");
569
570        SYSCTL_ADD_QUAD(ctx, children,
571                OID_AUTO, "lro_flows_active",
572                CTLFLAG_RD, &ha->hw.rcv.lro_flows_active,
573                "lro_flows_active");
574
575        SYSCTL_ADD_QUAD(ctx, children,
576                OID_AUTO, "pkts_droped_unknown",
577                CTLFLAG_RD, &ha->hw.rcv.pkts_droped_unknown,
578                "pkts_droped_unknown");
579
580        SYSCTL_ADD_QUAD(ctx, children,
581                OID_AUTO, "pkts_cnt_oversized",
582                CTLFLAG_RD, &ha->hw.rcv.pkts_cnt_oversized,
583                "pkts_cnt_oversized");
584
585	return;
586}
587
588static void
589qlnx_add_hw_xmt_stats_sysctls(qla_host_t *ha)
590{
591        struct sysctl_ctx_list  *ctx;
592        struct sysctl_oid_list  *children;
593        struct sysctl_oid_list  *node_children;
594        struct sysctl_oid       *ctx_oid;
595        int                     i;
596        uint8_t                 name_str[16];
597
598        ctx = device_get_sysctl_ctx(ha->pci_dev);
599        children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
600
601        ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_hw_xmt",
602                        CTLFLAG_RD, NULL, "stats_hw_xmt");
603        children = SYSCTL_CHILDREN(ctx_oid);
604
605        for (i = 0; i < ha->hw.num_tx_rings; i++) {
606
607                bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
608                snprintf(name_str, sizeof(name_str), "%d", i);
609
610                ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
611                        CTLFLAG_RD, NULL, name_str);
612                node_children = SYSCTL_CHILDREN(ctx_oid);
613
614                /* Tx Related */
615
616                SYSCTL_ADD_QUAD(ctx, node_children,
617			OID_AUTO, "total_bytes",
618                        CTLFLAG_RD, &ha->hw.xmt[i].total_bytes,
619                        "total_bytes");
620
621                SYSCTL_ADD_QUAD(ctx, node_children,
622			OID_AUTO, "total_pkts",
623                        CTLFLAG_RD, &ha->hw.xmt[i].total_pkts,
624                        "total_pkts");
625
626                SYSCTL_ADD_QUAD(ctx, node_children,
627			OID_AUTO, "errors",
628                        CTLFLAG_RD, &ha->hw.xmt[i].errors,
629                        "errors");
630
631                SYSCTL_ADD_QUAD(ctx, node_children,
632			OID_AUTO, "pkts_dropped",
633                        CTLFLAG_RD, &ha->hw.xmt[i].pkts_dropped,
634                        "pkts_dropped");
635
636                SYSCTL_ADD_QUAD(ctx, node_children,
637			OID_AUTO, "switch_pkts",
638                        CTLFLAG_RD, &ha->hw.xmt[i].switch_pkts,
639                        "switch_pkts");
640
641                SYSCTL_ADD_QUAD(ctx, node_children,
642			OID_AUTO, "num_buffers",
643                        CTLFLAG_RD, &ha->hw.xmt[i].num_buffers,
644                        "num_buffers");
645	}
646
647	return;
648}
649
650static void
651qlnx_add_hw_stats_sysctls(qla_host_t *ha)
652{
653	qlnx_add_hw_mac_stats_sysctls(ha);
654	qlnx_add_hw_rcv_stats_sysctls(ha);
655	qlnx_add_hw_xmt_stats_sysctls(ha);
656
657	return;
658}
659
660static void
661qlnx_add_drvr_sds_stats(qla_host_t *ha)
662{
663        struct sysctl_ctx_list  *ctx;
664        struct sysctl_oid_list  *children;
665        struct sysctl_oid_list  *node_children;
666        struct sysctl_oid       *ctx_oid;
667        int                     i;
668        uint8_t                 name_str[16];
669
670        ctx = device_get_sysctl_ctx(ha->pci_dev);
671        children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
672
673        ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_sds",
674                        CTLFLAG_RD, NULL, "stats_drvr_sds");
675        children = SYSCTL_CHILDREN(ctx_oid);
676
677        for (i = 0; i < ha->hw.num_sds_rings; i++) {
678
679                bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
680                snprintf(name_str, sizeof(name_str), "%d", i);
681
682                ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
683                        CTLFLAG_RD, NULL, name_str);
684                node_children = SYSCTL_CHILDREN(ctx_oid);
685
686                SYSCTL_ADD_QUAD(ctx, node_children,
687			OID_AUTO, "intr_count",
688                        CTLFLAG_RD, &ha->hw.sds[i].intr_count,
689                        "intr_count");
690
691                SYSCTL_ADD_UINT(ctx, node_children,
692			OID_AUTO, "rx_free",
693                        CTLFLAG_RD, &ha->hw.sds[i].rx_free,
694			ha->hw.sds[i].rx_free, "rx_free");
695	}
696
697	return;
698}
699static void
700qlnx_add_drvr_rds_stats(qla_host_t *ha)
701{
702        struct sysctl_ctx_list  *ctx;
703        struct sysctl_oid_list  *children;
704        struct sysctl_oid_list  *node_children;
705        struct sysctl_oid       *ctx_oid;
706        int                     i;
707        uint8_t                 name_str[16];
708
709        ctx = device_get_sysctl_ctx(ha->pci_dev);
710        children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
711
712        ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_rds",
713                        CTLFLAG_RD, NULL, "stats_drvr_rds");
714        children = SYSCTL_CHILDREN(ctx_oid);
715
716        for (i = 0; i < ha->hw.num_rds_rings; i++) {
717
718                bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
719                snprintf(name_str, sizeof(name_str), "%d", i);
720
721                ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
722                        CTLFLAG_RD, NULL, name_str);
723                node_children = SYSCTL_CHILDREN(ctx_oid);
724
725                SYSCTL_ADD_QUAD(ctx, node_children,
726			OID_AUTO, "count",
727                        CTLFLAG_RD, &ha->hw.rds[i].count,
728                        "count");
729
730                SYSCTL_ADD_QUAD(ctx, node_children,
731			OID_AUTO, "lro_pkt_count",
732                        CTLFLAG_RD, &ha->hw.rds[i].lro_pkt_count,
733                        "lro_pkt_count");
734
735                SYSCTL_ADD_QUAD(ctx, node_children,
736			OID_AUTO, "lro_bytes",
737                        CTLFLAG_RD, &ha->hw.rds[i].lro_bytes,
738                        "lro_bytes");
739	}
740
741	return;
742}
743
744static void
745qlnx_add_drvr_tx_stats(qla_host_t *ha)
746{
747        struct sysctl_ctx_list  *ctx;
748        struct sysctl_oid_list  *children;
749        struct sysctl_oid_list  *node_children;
750        struct sysctl_oid       *ctx_oid;
751        int                     i;
752        uint8_t                 name_str[16];
753
754        ctx = device_get_sysctl_ctx(ha->pci_dev);
755        children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
756
757        ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_xmt",
758                        CTLFLAG_RD, NULL, "stats_drvr_xmt");
759        children = SYSCTL_CHILDREN(ctx_oid);
760
761        for (i = 0; i < ha->hw.num_tx_rings; i++) {
762
763                bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
764                snprintf(name_str, sizeof(name_str), "%d", i);
765
766                ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
767                        CTLFLAG_RD, NULL, name_str);
768                node_children = SYSCTL_CHILDREN(ctx_oid);
769
770                SYSCTL_ADD_QUAD(ctx, node_children,
771			OID_AUTO, "count",
772                        CTLFLAG_RD, &ha->tx_ring[i].count,
773                        "count");
774
775#ifdef QL_ENABLE_ISCSI_TLV
776                SYSCTL_ADD_QUAD(ctx, node_children,
777			OID_AUTO, "iscsi_pkt_count",
778                        CTLFLAG_RD, &ha->tx_ring[i].iscsi_pkt_count,
779                        "iscsi_pkt_count");
780#endif /* #ifdef QL_ENABLE_ISCSI_TLV */
781	}
782
783	return;
784}
785
786static void
787qlnx_add_drvr_stats_sysctls(qla_host_t *ha)
788{
789	qlnx_add_drvr_sds_stats(ha);
790	qlnx_add_drvr_rds_stats(ha);
791	qlnx_add_drvr_tx_stats(ha);
792	return;
793}
794
795/*
796 * Name: ql_hw_add_sysctls
797 * Function: Add P3Plus specific sysctls
798 */
799void
800ql_hw_add_sysctls(qla_host_t *ha)
801{
802        device_t	dev;
803
804        dev = ha->pci_dev;
805
806	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
807		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
808		OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings,
809		ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings");
810
811        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
812                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
813                OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings,
814		ha->hw.num_sds_rings, "Number of Status Descriptor Rings");
815
816        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
817                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
818                OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings,
819		ha->hw.num_tx_rings, "Number of Transmit Rings");
820
821        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
822                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
823                OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx,
824		ha->txr_idx, "Tx Ring Used");
825
826        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
827                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
828                OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs,
829		ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt");
830
831	ha->hw.sds_cidx_thres = 32;
832        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
833                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
834                OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres,
835		ha->hw.sds_cidx_thres,
836		"Number of SDS entries to process before updating"
837		" SDS Ring Consumer Index");
838
839	ha->hw.rds_pidx_thres = 32;
840        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
841                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
842                OID_AUTO, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres,
843		ha->hw.rds_pidx_thres,
844		"Number of Rcv Rings Entries to post before updating"
845		" RDS Ring Producer Index");
846
847        ha->hw.rcv_intr_coalesce = (3 << 16) | 256;
848        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
849                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
850                OID_AUTO, "rcv_intr_coalesce", CTLFLAG_RW,
851                &ha->hw.rcv_intr_coalesce,
852                ha->hw.rcv_intr_coalesce,
853                "Rcv Intr Coalescing Parameters\n"
854                "\tbits 15:0 max packets\n"
855                "\tbits 31:16 max micro-seconds to wait\n"
856                "\tplease run\n"
857                "\tifconfig <if> down && ifconfig <if> up\n"
858                "\tto take effect \n");
859
860        ha->hw.xmt_intr_coalesce = (64 << 16) | 64;
861        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
862                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
863                OID_AUTO, "xmt_intr_coalesce", CTLFLAG_RW,
864                &ha->hw.xmt_intr_coalesce,
865                ha->hw.xmt_intr_coalesce,
866                "Xmt Intr Coalescing Parameters\n"
867                "\tbits 15:0 max packets\n"
868                "\tbits 31:16 max micro-seconds to wait\n"
869                "\tplease run\n"
870                "\tifconfig <if> down && ifconfig <if> up\n"
871                "\tto take effect \n");
872
873        SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
874                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
875                OID_AUTO, "port_cfg", CTLTYPE_INT | CTLFLAG_RW,
876                (void *)ha, 0,
877                qla_sysctl_port_cfg, "I",
878                        "Set Port Configuration if values below "
879                        "otherwise Get Port Configuration\n"
880                        "\tBits 0-3 ; 1 = DCBX Enable; 0 = DCBX Disable\n"
881                        "\tBits 4-7 : 0 = no pause; 1 = std ; 2 = ppm \n"
882                        "\tBits 8-11: std pause cfg; 0 = xmt and rcv;"
883                        " 1 = xmt only; 2 = rcv only;\n"
884                );
885
886	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
887		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
888		OID_AUTO, "set_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW,
889		(void *)ha, 0,
890		qla_sysctl_set_cam_search_mode, "I",
891			"Set CAM Search Mode"
892			"\t 1 = search mode internal\n"
893			"\t 2 = search mode auto\n");
894
895	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
896		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
897		OID_AUTO, "get_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW,
898		(void *)ha, 0,
899		qla_sysctl_get_cam_search_mode, "I",
900			"Get CAM Search Mode"
901			"\t 1 = search mode internal\n"
902			"\t 2 = search mode auto\n");
903
904        ha->hw.enable_9kb = 1;
905
906        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
907                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
908                OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb,
909                ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000");
910
911        ha->hw.enable_hw_lro = 1;
912
913        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
914                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
915                OID_AUTO, "enable_hw_lro", CTLFLAG_RW, &ha->hw.enable_hw_lro,
916                ha->hw.enable_hw_lro, "Enable Hardware LRO; Default is true \n"
917		"\t 1 : Hardware LRO if LRO is enabled\n"
918		"\t 0 : Software LRO if LRO is enabled\n"
919		"\t Any change requires ifconfig down/up to take effect\n"
920		"\t Note that LRO may be turned off/on via ifconfig\n");
921
922	ha->hw.mdump_active = 0;
923        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
924                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
925                OID_AUTO, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active,
926		ha->hw.mdump_active,
927		"Minidump retrieval is Active");
928
929	ha->hw.mdump_done = 0;
930        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
931                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
932                OID_AUTO, "mdump_done", CTLFLAG_RW,
933		&ha->hw.mdump_done, ha->hw.mdump_done,
934		"Minidump has been done and available for retrieval");
935
936	ha->hw.mdump_capture_mask = 0xF;
937        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
938                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
939                OID_AUTO, "minidump_capture_mask", CTLFLAG_RW,
940		&ha->hw.mdump_capture_mask, ha->hw.mdump_capture_mask,
941		"Minidump capture mask");
942#ifdef QL_DBG
943
944	ha->err_inject = 0;
945        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
946                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
947                OID_AUTO, "err_inject",
948                CTLFLAG_RW, &ha->err_inject, ha->err_inject,
949                "Error to be injected\n"
950                "\t\t\t 0: No Errors\n"
951                "\t\t\t 1: rcv: rxb struct invalid\n"
952                "\t\t\t 2: rcv: mp == NULL\n"
953                "\t\t\t 3: lro: rxb struct invalid\n"
954                "\t\t\t 4: lro: mp == NULL\n"
955                "\t\t\t 5: rcv: num handles invalid\n"
956                "\t\t\t 6: reg: indirect reg rd_wr failure\n"
957                "\t\t\t 7: ocm: offchip memory rd_wr failure\n"
958                "\t\t\t 8: mbx: mailbox command failure\n"
959                "\t\t\t 9: heartbeat failure\n"
960                "\t\t\t A: temperature failure\n"
961		"\t\t\t 11: m_getcl or m_getjcl failure\n" );
962
963	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
964                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
965                OID_AUTO, "peg_stop", CTLTYPE_INT | CTLFLAG_RW,
966                (void *)ha, 0,
967                qla_sysctl_stop_pegs, "I", "Peg Stop");
968
969#endif /* #ifdef QL_DBG */
970
971        ha->hw.user_pri_nic = 0;
972        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
973                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
974                OID_AUTO, "user_pri_nic", CTLFLAG_RW, &ha->hw.user_pri_nic,
975                ha->hw.user_pri_nic,
976                "VLAN Tag User Priority for Normal Ethernet Packets");
977
978        ha->hw.user_pri_iscsi = 4;
979        SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
980                SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
981                OID_AUTO, "user_pri_iscsi", CTLFLAG_RW, &ha->hw.user_pri_iscsi,
982                ha->hw.user_pri_iscsi,
983                "VLAN Tag User Priority for iSCSI Packets");
984
985	qlnx_add_hw_stats_sysctls(ha);
986	qlnx_add_drvr_stats_sysctls(ha);
987
988	return;
989}
990
991void
992ql_hw_link_status(qla_host_t *ha)
993{
994	device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui);
995
996	if (ha->hw.link_up) {
997		device_printf(ha->pci_dev, "link Up\n");
998	} else {
999		device_printf(ha->pci_dev, "link Down\n");
1000	}
1001
1002	if (ha->hw.flags.fduplex) {
1003		device_printf(ha->pci_dev, "Full Duplex\n");
1004	} else {
1005		device_printf(ha->pci_dev, "Half Duplex\n");
1006	}
1007
1008	if (ha->hw.flags.autoneg) {
1009		device_printf(ha->pci_dev, "Auto Negotiation Enabled\n");
1010	} else {
1011		device_printf(ha->pci_dev, "Auto Negotiation Disabled\n");
1012	}
1013
1014	switch (ha->hw.link_speed) {
1015	case 0x710:
1016		device_printf(ha->pci_dev, "link speed\t\t 10Gps\n");
1017		break;
1018
1019	case 0x3E8:
1020		device_printf(ha->pci_dev, "link speed\t\t 1Gps\n");
1021		break;
1022
1023	case 0x64:
1024		device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n");
1025		break;
1026
1027	default:
1028		device_printf(ha->pci_dev, "link speed\t\t Unknown\n");
1029		break;
1030	}
1031
1032	switch (ha->hw.module_type) {
1033
1034	case 0x01:
1035		device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n");
1036		break;
1037
1038	case 0x02:
1039		device_printf(ha->pci_dev, "Module Type 10GBase-LR\n");
1040		break;
1041
1042	case 0x03:
1043		device_printf(ha->pci_dev, "Module Type 10GBase-SR\n");
1044		break;
1045
1046	case 0x04:
1047		device_printf(ha->pci_dev,
1048			"Module Type 10GE Passive Copper(Compliant)[%d m]\n",
1049			ha->hw.cable_length);
1050		break;
1051
1052	case 0x05:
1053		device_printf(ha->pci_dev, "Module Type 10GE Active"
1054			" Limiting Copper(Compliant)[%d m]\n",
1055			ha->hw.cable_length);
1056		break;
1057
1058	case 0x06:
1059		device_printf(ha->pci_dev,
1060			"Module Type 10GE Passive Copper"
1061			" (Legacy, Best Effort)[%d m]\n",
1062			ha->hw.cable_length);
1063		break;
1064
1065	case 0x07:
1066		device_printf(ha->pci_dev, "Module Type 1000Base-SX\n");
1067		break;
1068
1069	case 0x08:
1070		device_printf(ha->pci_dev, "Module Type 1000Base-LX\n");
1071		break;
1072
1073	case 0x09:
1074		device_printf(ha->pci_dev, "Module Type 1000Base-CX\n");
1075		break;
1076
1077	case 0x0A:
1078		device_printf(ha->pci_dev, "Module Type 1000Base-T\n");
1079		break;
1080
1081	case 0x0B:
1082		device_printf(ha->pci_dev, "Module Type 1GE Passive Copper"
1083			"(Legacy, Best Effort)\n");
1084		break;
1085
1086	default:
1087		device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n",
1088			ha->hw.module_type);
1089		break;
1090	}
1091
1092	if (ha->hw.link_faults == 1)
1093		device_printf(ha->pci_dev, "SFP Power Fault\n");
1094}
1095
1096/*
1097 * Name: ql_free_dma
1098 * Function: Frees the DMA'able memory allocated in ql_alloc_dma()
1099 */
1100void
1101ql_free_dma(qla_host_t *ha)
1102{
1103	uint32_t i;
1104
1105        if (ha->hw.dma_buf.flags.sds_ring) {
1106		for (i = 0; i < ha->hw.num_sds_rings; i++) {
1107			ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]);
1108		}
1109        	ha->hw.dma_buf.flags.sds_ring = 0;
1110	}
1111
1112        if (ha->hw.dma_buf.flags.rds_ring) {
1113		for (i = 0; i < ha->hw.num_rds_rings; i++) {
1114			ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]);
1115		}
1116        	ha->hw.dma_buf.flags.rds_ring = 0;
1117	}
1118
1119        if (ha->hw.dma_buf.flags.tx_ring) {
1120		ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring);
1121        	ha->hw.dma_buf.flags.tx_ring = 0;
1122	}
1123	ql_minidump_free(ha);
1124}
1125
1126/*
1127 * Name: ql_alloc_dma
1128 * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts.
1129 */
1130int
1131ql_alloc_dma(qla_host_t *ha)
1132{
1133        device_t                dev;
1134	uint32_t		i, j, size, tx_ring_size;
1135	qla_hw_t		*hw;
1136	qla_hw_tx_cntxt_t	*tx_cntxt;
1137	uint8_t			*vaddr;
1138	bus_addr_t		paddr;
1139
1140        dev = ha->pci_dev;
1141
1142        QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
1143
1144	hw = &ha->hw;
1145	/*
1146	 * Allocate Transmit Ring
1147	 */
1148	tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS);
1149	size = (tx_ring_size * ha->hw.num_tx_rings);
1150
1151	hw->dma_buf.tx_ring.alignment = 8;
1152	hw->dma_buf.tx_ring.size = size + PAGE_SIZE;
1153
1154        if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) {
1155                device_printf(dev, "%s: tx ring alloc failed\n", __func__);
1156                goto ql_alloc_dma_exit;
1157        }
1158
1159	vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b;
1160	paddr = hw->dma_buf.tx_ring.dma_addr;
1161
1162	for (i = 0; i < ha->hw.num_tx_rings; i++) {
1163		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
1164
1165		tx_cntxt->tx_ring_base = (q80_tx_cmd_t *)vaddr;
1166		tx_cntxt->tx_ring_paddr = paddr;
1167
1168		vaddr += tx_ring_size;
1169		paddr += tx_ring_size;
1170	}
1171
1172	for (i = 0; i < ha->hw.num_tx_rings; i++) {
1173		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
1174
1175		tx_cntxt->tx_cons = (uint32_t *)vaddr;
1176		tx_cntxt->tx_cons_paddr = paddr;
1177
1178		vaddr += sizeof (uint32_t);
1179		paddr += sizeof (uint32_t);
1180	}
1181
1182        ha->hw.dma_buf.flags.tx_ring = 1;
1183
1184	QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n",
1185		__func__, (void *)(hw->dma_buf.tx_ring.dma_addr),
1186		hw->dma_buf.tx_ring.dma_b));
1187	/*
1188	 * Allocate Receive Descriptor Rings
1189	 */
1190
1191	for (i = 0; i < hw->num_rds_rings; i++) {
1192
1193		hw->dma_buf.rds_ring[i].alignment = 8;
1194		hw->dma_buf.rds_ring[i].size =
1195			(sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS;
1196
1197		if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) {
1198			device_printf(dev, "%s: rds ring[%d] alloc failed\n",
1199				__func__, i);
1200
1201			for (j = 0; j < i; j++)
1202				ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]);
1203
1204			goto ql_alloc_dma_exit;
1205		}
1206		QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n",
1207			__func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr),
1208			hw->dma_buf.rds_ring[i].dma_b));
1209	}
1210
1211	hw->dma_buf.flags.rds_ring = 1;
1212
1213	/*
1214	 * Allocate Status Descriptor Rings
1215	 */
1216
1217	for (i = 0; i < hw->num_sds_rings; i++) {
1218		hw->dma_buf.sds_ring[i].alignment = 8;
1219		hw->dma_buf.sds_ring[i].size =
1220			(sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS;
1221
1222		if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) {
1223			device_printf(dev, "%s: sds ring alloc failed\n",
1224				__func__);
1225
1226			for (j = 0; j < i; j++)
1227				ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]);
1228
1229			goto ql_alloc_dma_exit;
1230		}
1231		QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n",
1232			__func__, i,
1233			(void *)(hw->dma_buf.sds_ring[i].dma_addr),
1234			hw->dma_buf.sds_ring[i].dma_b));
1235	}
1236	for (i = 0; i < hw->num_sds_rings; i++) {
1237		hw->sds[i].sds_ring_base =
1238			(q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b;
1239	}
1240
1241	hw->dma_buf.flags.sds_ring = 1;
1242
1243	return 0;
1244
1245ql_alloc_dma_exit:
1246	ql_free_dma(ha);
1247	return -1;
1248}
1249
1250#define Q8_MBX_MSEC_DELAY	5000
1251
1252static int
1253qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
1254	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause)
1255{
1256	uint32_t i;
1257	uint32_t data;
1258	int ret = 0;
1259
1260	if (QL_ERR_INJECT(ha, INJCT_MBX_CMD_FAILURE)) {
1261		ret = -3;
1262		ha->qla_initiate_recovery = 1;
1263		goto exit_qla_mbx_cmd;
1264	}
1265
1266	if (no_pause)
1267		i = 1000;
1268	else
1269		i = Q8_MBX_MSEC_DELAY;
1270
1271	while (i) {
1272		data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL);
1273		if (data == 0)
1274			break;
1275		if (no_pause) {
1276			DELAY(1000);
1277		} else {
1278			qla_mdelay(__func__, 1);
1279		}
1280		i--;
1281	}
1282
1283	if (i == 0) {
1284		device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n",
1285			__func__, data);
1286		ret = -1;
1287		ha->qla_initiate_recovery = 1;
1288		goto exit_qla_mbx_cmd;
1289	}
1290
1291	for (i = 0; i < n_hmbox; i++) {
1292		WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox);
1293		h_mbox++;
1294	}
1295
1296	WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1);
1297
1298
1299	i = Q8_MBX_MSEC_DELAY;
1300	while (i) {
1301		data = READ_REG32(ha, Q8_FW_MBOX_CNTRL);
1302
1303		if ((data & 0x3) == 1) {
1304			data = READ_REG32(ha, Q8_FW_MBOX0);
1305			if ((data & 0xF000) != 0x8000)
1306				break;
1307		}
1308		if (no_pause) {
1309			DELAY(1000);
1310		} else {
1311			qla_mdelay(__func__, 1);
1312		}
1313		i--;
1314	}
1315	if (i == 0) {
1316		device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n",
1317			__func__, data);
1318		ret = -2;
1319		ha->qla_initiate_recovery = 1;
1320		goto exit_qla_mbx_cmd;
1321	}
1322
1323	for (i = 0; i < n_fwmbox; i++) {
1324		*fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2)));
1325	}
1326
1327	WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0);
1328	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
1329
1330exit_qla_mbx_cmd:
1331	return (ret);
1332}
1333
1334int
1335qla_get_nic_partition(qla_host_t *ha, uint32_t *supports_9kb,
1336	uint32_t *num_rcvq)
1337{
1338	uint32_t *mbox, err;
1339	device_t dev = ha->pci_dev;
1340
1341	bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX));
1342
1343	mbox = ha->hw.mbox;
1344
1345	mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29);
1346
1347	if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) {
1348		device_printf(dev, "%s: failed0\n", __func__);
1349		return (-1);
1350	}
1351	err = mbox[0] >> 25;
1352
1353	if (supports_9kb != NULL) {
1354		if (mbox[16] & 0x80) /* bit 7 of mbox 16 */
1355			*supports_9kb = 1;
1356		else
1357			*supports_9kb = 0;
1358	}
1359
1360	if (num_rcvq != NULL)
1361		*num_rcvq =  ((mbox[6] >> 16) & 0xFFFF);
1362
1363	if ((err != 1) && (err != 0)) {
1364		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1365		return (-1);
1366	}
1367	return 0;
1368}
1369
1370static int
1371qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx, uint32_t num_intrs,
1372	uint32_t create)
1373{
1374	uint32_t i, err;
1375	device_t dev = ha->pci_dev;
1376	q80_config_intr_t *c_intr;
1377	q80_config_intr_rsp_t *c_intr_rsp;
1378
1379	c_intr = (q80_config_intr_t *)ha->hw.mbox;
1380	bzero(c_intr, (sizeof (q80_config_intr_t)));
1381
1382	c_intr->opcode = Q8_MBX_CONFIG_INTR;
1383
1384	c_intr->count_version = (sizeof (q80_config_intr_t) >> 2);
1385	c_intr->count_version |= Q8_MBX_CMD_VERSION;
1386
1387	c_intr->nentries = num_intrs;
1388
1389	for (i = 0; i < num_intrs; i++) {
1390		if (create) {
1391			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE;
1392			c_intr->intr[i].msix_index = start_idx + 1 + i;
1393		} else {
1394			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE;
1395			c_intr->intr[i].msix_index =
1396				ha->hw.intr_id[(start_idx + i)];
1397		}
1398
1399		c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X;
1400	}
1401
1402	if (qla_mbx_cmd(ha, (uint32_t *)c_intr,
1403		(sizeof (q80_config_intr_t) >> 2),
1404		ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) {
1405		device_printf(dev, "%s: failed0\n", __func__);
1406		return (-1);
1407	}
1408
1409	c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox;
1410
1411	err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status);
1412
1413	if (err) {
1414		device_printf(dev, "%s: failed1 [0x%08x, %d]\n", __func__, err,
1415			c_intr_rsp->nentries);
1416
1417		for (i = 0; i < c_intr_rsp->nentries; i++) {
1418			device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n",
1419				__func__, i,
1420				c_intr_rsp->intr[i].status,
1421				c_intr_rsp->intr[i].intr_id,
1422				c_intr_rsp->intr[i].intr_src);
1423		}
1424
1425		return (-1);
1426	}
1427
1428	for (i = 0; ((i < num_intrs) && create); i++) {
1429		if (!c_intr_rsp->intr[i].status) {
1430			ha->hw.intr_id[(start_idx + i)] =
1431				c_intr_rsp->intr[i].intr_id;
1432			ha->hw.intr_src[(start_idx + i)] =
1433				c_intr_rsp->intr[i].intr_src;
1434		}
1435	}
1436
1437	return (0);
1438}
1439
1440/*
1441 * Name: qla_config_rss
1442 * Function: Configure RSS for the context/interface.
1443 */
1444static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL,
1445			0x8030f20c77cb2da3ULL,
1446			0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
1447			0x255b0ec26d5a56daULL };
1448
1449static int
1450qla_config_rss(qla_host_t *ha, uint16_t cntxt_id)
1451{
1452	q80_config_rss_t	*c_rss;
1453	q80_config_rss_rsp_t	*c_rss_rsp;
1454	uint32_t		err, i;
1455	device_t		dev = ha->pci_dev;
1456
1457	c_rss = (q80_config_rss_t *)ha->hw.mbox;
1458	bzero(c_rss, (sizeof (q80_config_rss_t)));
1459
1460	c_rss->opcode = Q8_MBX_CONFIG_RSS;
1461
1462	c_rss->count_version = (sizeof (q80_config_rss_t) >> 2);
1463	c_rss->count_version |= Q8_MBX_CMD_VERSION;
1464
1465	c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP |
1466				Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP);
1467	//c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP |
1468	//			Q8_MBX_RSS_HASH_TYPE_IPV6_TCP);
1469
1470	c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS;
1471	c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE;
1472
1473	c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK;
1474
1475	c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID;
1476	c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS;
1477
1478	c_rss->cntxt_id = cntxt_id;
1479
1480	for (i = 0; i < 5; i++) {
1481		c_rss->rss_key[i] = rss_key[i];
1482	}
1483
1484	if (qla_mbx_cmd(ha, (uint32_t *)c_rss,
1485		(sizeof (q80_config_rss_t) >> 2),
1486		ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) {
1487		device_printf(dev, "%s: failed0\n", __func__);
1488		return (-1);
1489	}
1490	c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox;
1491
1492	err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status);
1493
1494	if (err) {
1495		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1496		return (-1);
1497	}
1498	return 0;
1499}
1500
1501static int
1502qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count,
1503        uint16_t cntxt_id, uint8_t *ind_table)
1504{
1505        q80_config_rss_ind_table_t      *c_rss_ind;
1506        q80_config_rss_ind_table_rsp_t  *c_rss_ind_rsp;
1507        uint32_t                        err;
1508        device_t                        dev = ha->pci_dev;
1509
1510	if ((count > Q8_RSS_IND_TBL_SIZE) ||
1511		((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) {
1512		device_printf(dev, "%s: illegal count [%d, %d]\n", __func__,
1513			start_idx, count);
1514		return (-1);
1515	}
1516
1517        c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox;
1518        bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t));
1519
1520        c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE;
1521        c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2);
1522        c_rss_ind->count_version |= Q8_MBX_CMD_VERSION;
1523
1524	c_rss_ind->start_idx = start_idx;
1525	c_rss_ind->end_idx = start_idx + count - 1;
1526	c_rss_ind->cntxt_id = cntxt_id;
1527	bcopy(ind_table, c_rss_ind->ind_table, count);
1528
1529	if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind,
1530		(sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox,
1531		(sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) {
1532		device_printf(dev, "%s: failed0\n", __func__);
1533		return (-1);
1534	}
1535
1536	c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox;
1537	err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status);
1538
1539	if (err) {
1540		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1541		return (-1);
1542	}
1543	return 0;
1544}
1545
1546/*
1547 * Name: qla_config_intr_coalesce
1548 * Function: Configure Interrupt Coalescing.
1549 */
1550static int
1551qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable,
1552	int rcv)
1553{
1554	q80_config_intr_coalesc_t	*intrc;
1555	q80_config_intr_coalesc_rsp_t	*intrc_rsp;
1556	uint32_t			err, i;
1557	device_t			dev = ha->pci_dev;
1558
1559	intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox;
1560	bzero(intrc, (sizeof (q80_config_intr_coalesc_t)));
1561
1562	intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE;
1563	intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2);
1564	intrc->count_version |= Q8_MBX_CMD_VERSION;
1565
1566	if (rcv) {
1567		intrc->flags = Q8_MBX_INTRC_FLAGS_RCV;
1568		intrc->max_pkts = ha->hw.rcv_intr_coalesce & 0xFFFF;
1569		intrc->max_mswait = (ha->hw.rcv_intr_coalesce >> 16) & 0xFFFF;
1570	} else {
1571		intrc->flags = Q8_MBX_INTRC_FLAGS_XMT;
1572		intrc->max_pkts = ha->hw.xmt_intr_coalesce & 0xFFFF;
1573		intrc->max_mswait = (ha->hw.xmt_intr_coalesce >> 16) & 0xFFFF;
1574	}
1575
1576	intrc->cntxt_id = cntxt_id;
1577
1578	if (tenable) {
1579		intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC;
1580		intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC;
1581
1582		for (i = 0; i < ha->hw.num_sds_rings; i++) {
1583			intrc->sds_ring_mask |= (1 << i);
1584		}
1585		intrc->ms_timeout = 1000;
1586	}
1587
1588	if (qla_mbx_cmd(ha, (uint32_t *)intrc,
1589		(sizeof (q80_config_intr_coalesc_t) >> 2),
1590		ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) {
1591		device_printf(dev, "%s: failed0\n", __func__);
1592		return (-1);
1593	}
1594	intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox;
1595
1596	err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status);
1597
1598	if (err) {
1599		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1600		return (-1);
1601	}
1602
1603	return 0;
1604}
1605
1606
1607/*
1608 * Name: qla_config_mac_addr
1609 * Function: binds a MAC address to the context/interface.
1610 *	Can be unicast, multicast or broadcast.
1611 */
1612static int
1613qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac,
1614	uint32_t num_mac)
1615{
1616	q80_config_mac_addr_t		*cmac;
1617	q80_config_mac_addr_rsp_t	*cmac_rsp;
1618	uint32_t			err;
1619	device_t			dev = ha->pci_dev;
1620	int				i;
1621	uint8_t				*mac_cpy = mac_addr;
1622
1623	if (num_mac > Q8_MAX_MAC_ADDRS) {
1624		device_printf(dev, "%s: %s num_mac [0x%x] > Q8_MAX_MAC_ADDRS\n",
1625			__func__, (add_mac ? "Add" : "Del"), num_mac);
1626		return (-1);
1627	}
1628
1629	cmac = (q80_config_mac_addr_t *)ha->hw.mbox;
1630	bzero(cmac, (sizeof (q80_config_mac_addr_t)));
1631
1632	cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR;
1633	cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2;
1634	cmac->count_version |= Q8_MBX_CMD_VERSION;
1635
1636	if (add_mac)
1637		cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR;
1638	else
1639		cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR;
1640
1641	cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS;
1642
1643	cmac->nmac_entries = num_mac;
1644	cmac->cntxt_id = ha->hw.rcv_cntxt_id;
1645
1646	for (i = 0; i < num_mac; i++) {
1647		bcopy(mac_addr, cmac->mac_addr[i].addr, Q8_ETHER_ADDR_LEN);
1648		mac_addr = mac_addr + ETHER_ADDR_LEN;
1649	}
1650
1651	if (qla_mbx_cmd(ha, (uint32_t *)cmac,
1652		(sizeof (q80_config_mac_addr_t) >> 2),
1653		ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) {
1654		device_printf(dev, "%s: %s failed0\n", __func__,
1655			(add_mac ? "Add" : "Del"));
1656		return (-1);
1657	}
1658	cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox;
1659
1660	err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status);
1661
1662	if (err) {
1663		device_printf(dev, "%s: %s failed1 [0x%08x]\n", __func__,
1664			(add_mac ? "Add" : "Del"), err);
1665		for (i = 0; i < num_mac; i++) {
1666			device_printf(dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
1667				__func__, mac_cpy[0], mac_cpy[1], mac_cpy[2],
1668				mac_cpy[3], mac_cpy[4], mac_cpy[5]);
1669			mac_cpy += ETHER_ADDR_LEN;
1670		}
1671		return (-1);
1672	}
1673
1674	return 0;
1675}
1676
1677
1678/*
1679 * Name: qla_set_mac_rcv_mode
1680 * Function: Enable/Disable AllMulticast and Promiscous Modes.
1681 */
1682static int
1683qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode)
1684{
1685	q80_config_mac_rcv_mode_t	*rcv_mode;
1686	uint32_t			err;
1687	q80_config_mac_rcv_mode_rsp_t	*rcv_mode_rsp;
1688	device_t			dev = ha->pci_dev;
1689
1690	rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox;
1691	bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t)));
1692
1693	rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE;
1694	rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2;
1695	rcv_mode->count_version |= Q8_MBX_CMD_VERSION;
1696
1697	rcv_mode->mode = mode;
1698
1699	rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id;
1700
1701	if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode,
1702		(sizeof (q80_config_mac_rcv_mode_t) >> 2),
1703		ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) {
1704		device_printf(dev, "%s: failed0\n", __func__);
1705		return (-1);
1706	}
1707	rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox;
1708
1709	err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status);
1710
1711	if (err) {
1712		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1713		return (-1);
1714	}
1715
1716	return 0;
1717}
1718
1719int
1720ql_set_promisc(qla_host_t *ha)
1721{
1722	int ret;
1723
1724	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE;
1725	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1726	return (ret);
1727}
1728
1729void
1730qla_reset_promisc(qla_host_t *ha)
1731{
1732	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_RCV_PROMISC_ENABLE;
1733	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1734}
1735
1736int
1737ql_set_allmulti(qla_host_t *ha)
1738{
1739	int ret;
1740
1741	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE;
1742	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1743	return (ret);
1744}
1745
1746void
1747qla_reset_allmulti(qla_host_t *ha)
1748{
1749	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_ALL_MULTI_ENABLE;
1750	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1751}
1752
1753/*
1754 * Name: ql_set_max_mtu
1755 * Function:
1756 *	Sets the maximum transfer unit size for the specified rcv context.
1757 */
1758int
1759ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id)
1760{
1761	device_t		dev;
1762	q80_set_max_mtu_t	*max_mtu;
1763	q80_set_max_mtu_rsp_t	*max_mtu_rsp;
1764	uint32_t		err;
1765
1766	dev = ha->pci_dev;
1767
1768	max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox;
1769	bzero(max_mtu, (sizeof (q80_set_max_mtu_t)));
1770
1771	max_mtu->opcode = Q8_MBX_SET_MAX_MTU;
1772	max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2);
1773	max_mtu->count_version |= Q8_MBX_CMD_VERSION;
1774
1775	max_mtu->cntxt_id = cntxt_id;
1776	max_mtu->mtu = mtu;
1777
1778        if (qla_mbx_cmd(ha, (uint32_t *)max_mtu,
1779		(sizeof (q80_set_max_mtu_t) >> 2),
1780                ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) {
1781                device_printf(dev, "%s: failed\n", __func__);
1782                return -1;
1783        }
1784
1785	max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox;
1786
1787        err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status);
1788
1789        if (err) {
1790                device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1791        }
1792
1793	return 0;
1794}
1795
1796static int
1797qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id)
1798{
1799	device_t		dev;
1800	q80_link_event_t	*lnk;
1801	q80_link_event_rsp_t	*lnk_rsp;
1802	uint32_t		err;
1803
1804	dev = ha->pci_dev;
1805
1806	lnk = (q80_link_event_t *)ha->hw.mbox;
1807	bzero(lnk, (sizeof (q80_link_event_t)));
1808
1809	lnk->opcode = Q8_MBX_LINK_EVENT_REQ;
1810	lnk->count_version = (sizeof (q80_link_event_t) >> 2);
1811	lnk->count_version |= Q8_MBX_CMD_VERSION;
1812
1813	lnk->cntxt_id = cntxt_id;
1814	lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC;
1815
1816        if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2),
1817                ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) {
1818                device_printf(dev, "%s: failed\n", __func__);
1819                return -1;
1820        }
1821
1822	lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox;
1823
1824        err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status);
1825
1826        if (err) {
1827                device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1828        }
1829
1830	return 0;
1831}
1832
1833static int
1834qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id)
1835{
1836	device_t		dev;
1837	q80_config_fw_lro_t	*fw_lro;
1838	q80_config_fw_lro_rsp_t	*fw_lro_rsp;
1839	uint32_t		err;
1840
1841	dev = ha->pci_dev;
1842
1843	fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox;
1844	bzero(fw_lro, sizeof(q80_config_fw_lro_t));
1845
1846	fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO;
1847	fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2);
1848	fw_lro->count_version |= Q8_MBX_CMD_VERSION;
1849
1850	fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK;
1851	fw_lro->flags |= Q8_MBX_FW_LRO_IPV6 | Q8_MBX_FW_LRO_IPV6_WO_DST_IP_CHK;
1852
1853	fw_lro->cntxt_id = cntxt_id;
1854
1855	if (qla_mbx_cmd(ha, (uint32_t *)fw_lro,
1856		(sizeof (q80_config_fw_lro_t) >> 2),
1857		ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) {
1858		device_printf(dev, "%s: failed\n", __func__);
1859		return -1;
1860	}
1861
1862	fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox;
1863
1864	err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status);
1865
1866	if (err) {
1867		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1868	}
1869
1870	return 0;
1871}
1872
1873static int
1874qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode)
1875{
1876	device_t                dev;
1877	q80_hw_config_t         *hw_config;
1878	q80_hw_config_rsp_t     *hw_config_rsp;
1879	uint32_t                err;
1880
1881	dev = ha->pci_dev;
1882
1883	hw_config = (q80_hw_config_t *)ha->hw.mbox;
1884	bzero(hw_config, sizeof (q80_hw_config_t));
1885
1886	hw_config->opcode = Q8_MBX_HW_CONFIG;
1887	hw_config->count_version = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE_COUNT;
1888	hw_config->count_version |= Q8_MBX_CMD_VERSION;
1889
1890	hw_config->cmd = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE;
1891
1892	hw_config->u.set_cam_search_mode.mode = search_mode;
1893
1894	if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
1895		(sizeof (q80_hw_config_t) >> 2),
1896		ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
1897		device_printf(dev, "%s: failed\n", __func__);
1898		return -1;
1899	}
1900	hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
1901
1902	err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
1903
1904	if (err) {
1905		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1906	}
1907
1908	return 0;
1909}
1910
1911static int
1912qla_get_cam_search_mode(qla_host_t *ha)
1913{
1914	device_t                dev;
1915	q80_hw_config_t         *hw_config;
1916	q80_hw_config_rsp_t     *hw_config_rsp;
1917	uint32_t                err;
1918
1919	dev = ha->pci_dev;
1920
1921	hw_config = (q80_hw_config_t *)ha->hw.mbox;
1922	bzero(hw_config, sizeof (q80_hw_config_t));
1923
1924	hw_config->opcode = Q8_MBX_HW_CONFIG;
1925	hw_config->count_version = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE_COUNT;
1926	hw_config->count_version |= Q8_MBX_CMD_VERSION;
1927
1928	hw_config->cmd = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE;
1929
1930	if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
1931		(sizeof (q80_hw_config_t) >> 2),
1932		ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
1933		device_printf(dev, "%s: failed\n", __func__);
1934		return -1;
1935	}
1936	hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
1937
1938	err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
1939
1940	if (err) {
1941		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1942	} else {
1943		device_printf(dev, "%s: cam search mode [0x%08x]\n", __func__,
1944			hw_config_rsp->u.get_cam_search_mode.mode);
1945	}
1946
1947	return 0;
1948}
1949
1950static int
1951qla_get_hw_stats(qla_host_t *ha, uint32_t cmd, uint32_t rsp_size)
1952{
1953	device_t		dev;
1954	q80_get_stats_t		*stat;
1955	q80_get_stats_rsp_t	*stat_rsp;
1956	uint32_t		err;
1957
1958	dev = ha->pci_dev;
1959
1960	stat = (q80_get_stats_t *)ha->hw.mbox;
1961	bzero(stat, (sizeof (q80_get_stats_t)));
1962
1963	stat->opcode = Q8_MBX_GET_STATS;
1964	stat->count_version = 2;
1965	stat->count_version |= Q8_MBX_CMD_VERSION;
1966
1967	stat->cmd = cmd;
1968
1969        if (qla_mbx_cmd(ha, (uint32_t *)stat, 2,
1970                ha->hw.mbox, (rsp_size >> 2), 0)) {
1971                device_printf(dev, "%s: failed\n", __func__);
1972                return -1;
1973        }
1974
1975	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1976
1977        err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status);
1978
1979        if (err) {
1980                return -1;
1981        }
1982
1983	return 0;
1984}
1985
1986void
1987ql_get_stats(qla_host_t *ha)
1988{
1989	q80_get_stats_rsp_t	*stat_rsp;
1990	q80_mac_stats_t		*mstat;
1991	q80_xmt_stats_t		*xstat;
1992	q80_rcv_stats_t		*rstat;
1993	uint32_t		cmd;
1994	int			i;
1995	struct ifnet *ifp = ha->ifp;
1996
1997	if (ifp == NULL)
1998		return;
1999
2000	if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) != 0) {
2001		device_printf(ha->pci_dev, "%s: failed\n", __func__);
2002		return;
2003	}
2004
2005	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
2006		QLA_UNLOCK(ha, __func__);
2007		return;
2008	}
2009
2010	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
2011	/*
2012	 * Get MAC Statistics
2013	 */
2014	cmd = Q8_GET_STATS_CMD_TYPE_MAC;
2015//	cmd |= Q8_GET_STATS_CMD_CLEAR;
2016
2017	cmd |= ((ha->pci_func & 0x1) << 16);
2018
2019	if (ha->qla_watchdog_pause)
2020		goto ql_get_stats_exit;
2021
2022	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
2023		mstat = (q80_mac_stats_t *)&stat_rsp->u.mac;
2024		bcopy(mstat, &ha->hw.mac, sizeof(q80_mac_stats_t));
2025	} else {
2026                device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n",
2027			__func__, ha->hw.mbox[0]);
2028	}
2029	/*
2030	 * Get RCV Statistics
2031	 */
2032	cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT;
2033//	cmd |= Q8_GET_STATS_CMD_CLEAR;
2034	cmd |= (ha->hw.rcv_cntxt_id << 16);
2035
2036	if (ha->qla_watchdog_pause)
2037		goto ql_get_stats_exit;
2038
2039	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
2040		rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv;
2041		bcopy(rstat, &ha->hw.rcv, sizeof(q80_rcv_stats_t));
2042	} else {
2043                device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n",
2044			__func__, ha->hw.mbox[0]);
2045	}
2046
2047	if (ha->qla_watchdog_pause)
2048		goto ql_get_stats_exit;
2049	/*
2050	 * Get XMT Statistics
2051	 */
2052	for (i = 0 ; ((i < ha->hw.num_tx_rings) && (!ha->qla_watchdog_pause));
2053		i++) {
2054		cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT;
2055//		cmd |= Q8_GET_STATS_CMD_CLEAR;
2056		cmd |= (ha->hw.tx_cntxt[i].tx_cntxt_id << 16);
2057
2058		if (qla_get_hw_stats(ha, cmd, sizeof(q80_get_stats_rsp_t))
2059			== 0) {
2060			xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt;
2061			bcopy(xstat, &ha->hw.xmt[i], sizeof(q80_xmt_stats_t));
2062		} else {
2063			device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n",
2064				__func__, ha->hw.mbox[0]);
2065		}
2066	}
2067
2068ql_get_stats_exit:
2069	QLA_UNLOCK(ha, __func__);
2070
2071	return;
2072}
2073
2074/*
2075 * Name: qla_tx_tso
2076 * Function: Checks if the packet to be transmitted is a candidate for
2077 *	Large TCP Segment Offload. If yes, the appropriate fields in the Tx
2078 *	Ring Structure are plugged in.
2079 */
2080static int
2081qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
2082{
2083	struct ether_vlan_header *eh;
2084	struct ip *ip = NULL;
2085	struct ip6_hdr *ip6 = NULL;
2086	struct tcphdr *th = NULL;
2087	uint32_t ehdrlen,  hdrlen, ip_hlen, tcp_hlen, tcp_opt_off;
2088	uint16_t etype, opcode, offload = 1;
2089	device_t dev;
2090
2091	dev = ha->pci_dev;
2092
2093
2094	eh = mtod(mp, struct ether_vlan_header *);
2095
2096	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2097		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
2098		etype = ntohs(eh->evl_proto);
2099	} else {
2100		ehdrlen = ETHER_HDR_LEN;
2101		etype = ntohs(eh->evl_encap_proto);
2102	}
2103
2104	hdrlen = 0;
2105
2106	switch (etype) {
2107		case ETHERTYPE_IP:
2108
2109			tcp_opt_off = ehdrlen + sizeof(struct ip) +
2110					sizeof(struct tcphdr);
2111
2112			if (mp->m_len < tcp_opt_off) {
2113				m_copydata(mp, 0, tcp_opt_off, hdr);
2114				ip = (struct ip *)(hdr + ehdrlen);
2115			} else {
2116				ip = (struct ip *)(mp->m_data + ehdrlen);
2117			}
2118
2119			ip_hlen = ip->ip_hl << 2;
2120			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
2121
2122
2123			if ((ip->ip_p != IPPROTO_TCP) ||
2124				(ip_hlen != sizeof (struct ip))){
2125				/* IP Options are not supported */
2126
2127				offload = 0;
2128			} else
2129				th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
2130
2131		break;
2132
2133		case ETHERTYPE_IPV6:
2134
2135			tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) +
2136					sizeof (struct tcphdr);
2137
2138			if (mp->m_len < tcp_opt_off) {
2139				m_copydata(mp, 0, tcp_opt_off, hdr);
2140				ip6 = (struct ip6_hdr *)(hdr + ehdrlen);
2141			} else {
2142				ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
2143			}
2144
2145			ip_hlen = sizeof(struct ip6_hdr);
2146			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6;
2147
2148			if (ip6->ip6_nxt != IPPROTO_TCP) {
2149				//device_printf(dev, "%s: ipv6\n", __func__);
2150				offload = 0;
2151			} else
2152				th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
2153		break;
2154
2155		default:
2156			QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__));
2157			offload = 0;
2158		break;
2159	}
2160
2161	if (!offload)
2162		return (-1);
2163
2164	tcp_hlen = th->th_off << 2;
2165	hdrlen = ehdrlen + ip_hlen + tcp_hlen;
2166
2167        if (mp->m_len < hdrlen) {
2168                if (mp->m_len < tcp_opt_off) {
2169                        if (tcp_hlen > sizeof(struct tcphdr)) {
2170                                m_copydata(mp, tcp_opt_off,
2171                                        (tcp_hlen - sizeof(struct tcphdr)),
2172                                        &hdr[tcp_opt_off]);
2173                        }
2174                } else {
2175                        m_copydata(mp, 0, hdrlen, hdr);
2176                }
2177        }
2178
2179	tx_cmd->mss = mp->m_pkthdr.tso_segsz;
2180
2181	tx_cmd->flags_opcode = opcode ;
2182	tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen;
2183	tx_cmd->total_hdr_len = hdrlen;
2184
2185	/* Check for Multicast least significant bit of MSB == 1 */
2186	if (eh->evl_dhost[0] & 0x01) {
2187		tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST;
2188	}
2189
2190	if (mp->m_len < hdrlen) {
2191		printf("%d\n", hdrlen);
2192		return (1);
2193	}
2194
2195	return (0);
2196}
2197
2198/*
2199 * Name: qla_tx_chksum
2200 * Function: Checks if the packet to be transmitted is a candidate for
2201 *	TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx
2202 *	Ring Structure are plugged in.
2203 */
2204static int
2205qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code,
2206	uint32_t *tcp_hdr_off)
2207{
2208	struct ether_vlan_header *eh;
2209	struct ip *ip;
2210	struct ip6_hdr *ip6;
2211	uint32_t ehdrlen, ip_hlen;
2212	uint16_t etype, opcode, offload = 1;
2213	device_t dev;
2214	uint8_t buf[sizeof(struct ip6_hdr)];
2215
2216	dev = ha->pci_dev;
2217
2218	*op_code = 0;
2219
2220	if ((mp->m_pkthdr.csum_flags &
2221		(CSUM_TCP|CSUM_UDP|CSUM_TCP_IPV6 | CSUM_UDP_IPV6)) == 0)
2222		return (-1);
2223
2224	eh = mtod(mp, struct ether_vlan_header *);
2225
2226	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2227		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
2228		etype = ntohs(eh->evl_proto);
2229	} else {
2230		ehdrlen = ETHER_HDR_LEN;
2231		etype = ntohs(eh->evl_encap_proto);
2232	}
2233
2234
2235	switch (etype) {
2236		case ETHERTYPE_IP:
2237			ip = (struct ip *)(mp->m_data + ehdrlen);
2238
2239			ip_hlen = sizeof (struct ip);
2240
2241			if (mp->m_len < (ehdrlen + ip_hlen)) {
2242				m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
2243				ip = (struct ip *)buf;
2244			}
2245
2246			if (ip->ip_p == IPPROTO_TCP)
2247				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM;
2248			else if (ip->ip_p == IPPROTO_UDP)
2249				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM;
2250			else {
2251				//device_printf(dev, "%s: ipv4\n", __func__);
2252				offload = 0;
2253			}
2254		break;
2255
2256		case ETHERTYPE_IPV6:
2257			ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
2258
2259			ip_hlen = sizeof(struct ip6_hdr);
2260
2261			if (mp->m_len < (ehdrlen + ip_hlen)) {
2262				m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
2263					buf);
2264				ip6 = (struct ip6_hdr *)buf;
2265			}
2266
2267			if (ip6->ip6_nxt == IPPROTO_TCP)
2268				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6;
2269			else if (ip6->ip6_nxt == IPPROTO_UDP)
2270				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6;
2271			else {
2272				//device_printf(dev, "%s: ipv6\n", __func__);
2273				offload = 0;
2274			}
2275		break;
2276
2277		default:
2278			offload = 0;
2279		break;
2280	}
2281	if (!offload)
2282		return (-1);
2283
2284	*op_code = opcode;
2285	*tcp_hdr_off = (ip_hlen + ehdrlen);
2286
2287	return (0);
2288}
2289
2290#define QLA_TX_MIN_FREE 2
2291/*
2292 * Name: ql_hw_send
2293 * Function: Transmits a packet. It first checks if the packet is a
2294 *	candidate for Large TCP Segment Offload and then for UDP/TCP checksum
2295 *	offload. If either of these creteria are not met, it is transmitted
2296 *	as a regular ethernet frame.
2297 */
2298int
2299ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
2300	uint32_t tx_idx, struct mbuf *mp, uint32_t txr_idx, uint32_t iscsi_pdu)
2301{
2302	struct ether_vlan_header *eh;
2303	qla_hw_t *hw = &ha->hw;
2304	q80_tx_cmd_t *tx_cmd, tso_cmd;
2305	bus_dma_segment_t *c_seg;
2306	uint32_t num_tx_cmds, hdr_len = 0;
2307	uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next;
2308	device_t dev;
2309	int i, ret;
2310	uint8_t *src = NULL, *dst = NULL;
2311	uint8_t frame_hdr[QL_FRAME_HDR_SIZE];
2312	uint32_t op_code = 0;
2313	uint32_t tcp_hdr_off = 0;
2314
2315	dev = ha->pci_dev;
2316
2317	/*
2318	 * Always make sure there is atleast one empty slot in the tx_ring
2319	 * tx_ring is considered full when there only one entry available
2320	 */
2321        num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2;
2322
2323	total_length = mp->m_pkthdr.len;
2324	if (total_length > QLA_MAX_TSO_FRAME_SIZE) {
2325		device_printf(dev, "%s: total length exceeds maxlen(%d)\n",
2326			__func__, total_length);
2327		return (-1);
2328	}
2329	eh = mtod(mp, struct ether_vlan_header *);
2330
2331	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2332
2333		bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
2334
2335		src = frame_hdr;
2336		ret = qla_tx_tso(ha, mp, &tso_cmd, src);
2337
2338		if (!(ret & ~1)) {
2339			/* find the additional tx_cmd descriptors required */
2340
2341			if (mp->m_flags & M_VLANTAG)
2342				tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN;
2343
2344			hdr_len = tso_cmd.total_hdr_len;
2345
2346			bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2347			bytes = QL_MIN(bytes, hdr_len);
2348
2349			num_tx_cmds++;
2350			hdr_len -= bytes;
2351
2352			while (hdr_len) {
2353				bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2354				hdr_len -= bytes;
2355				num_tx_cmds++;
2356			}
2357			hdr_len = tso_cmd.total_hdr_len;
2358
2359			if (ret == 0)
2360				src = (uint8_t *)eh;
2361		} else
2362			return (EINVAL);
2363	} else {
2364		(void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off);
2365	}
2366
2367	if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
2368		ql_hw_tx_done_locked(ha, txr_idx);
2369		if (hw->tx_cntxt[txr_idx].txr_free <=
2370				(num_tx_cmds + QLA_TX_MIN_FREE)) {
2371        		QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= "
2372				"(num_tx_cmds + QLA_TX_MIN_FREE))\n",
2373				__func__));
2374			return (-1);
2375		}
2376	}
2377
2378	tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx];
2379
2380        if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) {
2381
2382                if (nsegs > ha->hw.max_tx_segs)
2383                        ha->hw.max_tx_segs = nsegs;
2384
2385                bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2386
2387                if (op_code) {
2388                        tx_cmd->flags_opcode = op_code;
2389                        tx_cmd->tcp_hdr_off = tcp_hdr_off;
2390
2391                } else {
2392                        tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER;
2393                }
2394	} else {
2395		bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
2396		ha->tx_tso_frames++;
2397	}
2398
2399	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2400        	tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
2401
2402		if (iscsi_pdu)
2403			eh->evl_tag |= ha->hw.user_pri_iscsi << 13;
2404
2405	} else if (mp->m_flags & M_VLANTAG) {
2406
2407		if (hdr_len) { /* TSO */
2408			tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED |
2409						Q8_TX_CMD_FLAGS_HW_VLAN_ID);
2410			tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN;
2411		} else
2412			tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID;
2413
2414		ha->hw_vlan_tx_frames++;
2415		tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag;
2416
2417		if (iscsi_pdu) {
2418			tx_cmd->vlan_tci |= ha->hw.user_pri_iscsi << 13;
2419			mp->m_pkthdr.ether_vtag = tx_cmd->vlan_tci;
2420		}
2421	}
2422
2423
2424        tx_cmd->n_bufs = (uint8_t)nsegs;
2425        tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF);
2426        tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8)));
2427	tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func);
2428
2429	c_seg = segs;
2430
2431	while (1) {
2432		for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) {
2433
2434			switch (i) {
2435			case 0:
2436				tx_cmd->buf1_addr = c_seg->ds_addr;
2437				tx_cmd->buf1_len = c_seg->ds_len;
2438				break;
2439
2440			case 1:
2441				tx_cmd->buf2_addr = c_seg->ds_addr;
2442				tx_cmd->buf2_len = c_seg->ds_len;
2443				break;
2444
2445			case 2:
2446				tx_cmd->buf3_addr = c_seg->ds_addr;
2447				tx_cmd->buf3_len = c_seg->ds_len;
2448				break;
2449
2450			case 3:
2451				tx_cmd->buf4_addr = c_seg->ds_addr;
2452				tx_cmd->buf4_len = c_seg->ds_len;
2453				break;
2454			}
2455
2456			c_seg++;
2457			nsegs--;
2458		}
2459
2460		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2461			(hw->tx_cntxt[txr_idx].txr_next + 1) &
2462				(NUM_TX_DESCRIPTORS - 1);
2463		tx_cmd_count++;
2464
2465		if (!nsegs)
2466			break;
2467
2468		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2469		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2470	}
2471
2472	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2473
2474		/* TSO : Copy the header in the following tx cmd descriptors */
2475
2476		txr_next = hw->tx_cntxt[txr_idx].txr_next;
2477
2478		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2479		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2480
2481		bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2482		bytes = QL_MIN(bytes, hdr_len);
2483
2484		dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN;
2485
2486		if (mp->m_flags & M_VLANTAG) {
2487			/* first copy the src/dst MAC addresses */
2488			bcopy(src, dst, (ETHER_ADDR_LEN * 2));
2489			dst += (ETHER_ADDR_LEN * 2);
2490			src += (ETHER_ADDR_LEN * 2);
2491
2492			*((uint16_t *)dst) = htons(ETHERTYPE_VLAN);
2493			dst += 2;
2494			*((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag);
2495			dst += 2;
2496
2497			/* bytes left in src header */
2498			hdr_len -= ((ETHER_ADDR_LEN * 2) +
2499					ETHER_VLAN_ENCAP_LEN);
2500
2501			/* bytes left in TxCmd Entry */
2502			bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN);
2503
2504
2505			bcopy(src, dst, bytes);
2506			src += bytes;
2507			hdr_len -= bytes;
2508		} else {
2509			bcopy(src, dst, bytes);
2510			src += bytes;
2511			hdr_len -= bytes;
2512		}
2513
2514		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2515				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2516					(NUM_TX_DESCRIPTORS - 1);
2517		tx_cmd_count++;
2518
2519		while (hdr_len) {
2520			tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2521			bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2522
2523			bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2524
2525			bcopy(src, tx_cmd, bytes);
2526			src += bytes;
2527			hdr_len -= bytes;
2528
2529			txr_next = hw->tx_cntxt[txr_idx].txr_next =
2530				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2531					(NUM_TX_DESCRIPTORS - 1);
2532			tx_cmd_count++;
2533		}
2534	}
2535
2536	hw->tx_cntxt[txr_idx].txr_free =
2537		hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count;
2538
2539	QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\
2540		txr_idx);
2541       	QL_DPRINT8(ha, (dev, "%s: return\n", __func__));
2542
2543	return (0);
2544}
2545
2546
2547
2548#define Q8_CONFIG_IND_TBL_SIZE	32 /* < Q8_RSS_IND_TBL_SIZE and power of 2 */
2549static int
2550qla_config_rss_ind_table(qla_host_t *ha)
2551{
2552	uint32_t i, count;
2553	uint8_t rss_ind_tbl[Q8_CONFIG_IND_TBL_SIZE];
2554
2555
2556	for (i = 0; i < Q8_CONFIG_IND_TBL_SIZE; i++) {
2557		rss_ind_tbl[i] = i % ha->hw.num_sds_rings;
2558	}
2559
2560	for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ;
2561		i = i + Q8_CONFIG_IND_TBL_SIZE) {
2562
2563		if ((i + Q8_CONFIG_IND_TBL_SIZE) > Q8_RSS_IND_TBL_MAX_IDX) {
2564			count = Q8_RSS_IND_TBL_MAX_IDX - i + 1;
2565		} else {
2566			count = Q8_CONFIG_IND_TBL_SIZE;
2567		}
2568
2569		if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id,
2570			rss_ind_tbl))
2571			return (-1);
2572	}
2573
2574	return (0);
2575}
2576
2577static int
2578qla_config_soft_lro(qla_host_t *ha)
2579{
2580        int i;
2581        qla_hw_t *hw = &ha->hw;
2582        struct lro_ctrl *lro;
2583
2584        for (i = 0; i < hw->num_sds_rings; i++) {
2585                lro = &hw->sds[i].lro;
2586
2587		bzero(lro, sizeof(struct lro_ctrl));
2588
2589#if (__FreeBSD_version >= 1100101)
2590                if (tcp_lro_init_args(lro, ha->ifp, 0, NUM_RX_DESCRIPTORS)) {
2591                        device_printf(ha->pci_dev,
2592				"%s: tcp_lro_init_args [%d] failed\n",
2593                                __func__, i);
2594                        return (-1);
2595                }
2596#else
2597                if (tcp_lro_init(lro)) {
2598                        device_printf(ha->pci_dev,
2599				"%s: tcp_lro_init [%d] failed\n",
2600                                __func__, i);
2601                        return (-1);
2602                }
2603#endif /* #if (__FreeBSD_version >= 1100101) */
2604
2605                lro->ifp = ha->ifp;
2606        }
2607
2608        QL_DPRINT2(ha, (ha->pci_dev, "%s: LRO initialized\n", __func__));
2609        return (0);
2610}
2611
2612static void
2613qla_drain_soft_lro(qla_host_t *ha)
2614{
2615        int i;
2616        qla_hw_t *hw = &ha->hw;
2617        struct lro_ctrl *lro;
2618
2619       	for (i = 0; i < hw->num_sds_rings; i++) {
2620               	lro = &hw->sds[i].lro;
2621
2622#if (__FreeBSD_version >= 1100101)
2623		tcp_lro_flush_all(lro);
2624#else
2625                struct lro_entry *queued;
2626
2627		while ((!SLIST_EMPTY(&lro->lro_active))) {
2628			queued = SLIST_FIRST(&lro->lro_active);
2629			SLIST_REMOVE_HEAD(&lro->lro_active, next);
2630			tcp_lro_flush(lro, queued);
2631		}
2632#endif /* #if (__FreeBSD_version >= 1100101) */
2633	}
2634
2635	return;
2636}
2637
2638static void
2639qla_free_soft_lro(qla_host_t *ha)
2640{
2641        int i;
2642        qla_hw_t *hw = &ha->hw;
2643        struct lro_ctrl *lro;
2644
2645        for (i = 0; i < hw->num_sds_rings; i++) {
2646               	lro = &hw->sds[i].lro;
2647		tcp_lro_free(lro);
2648	}
2649
2650	return;
2651}
2652
2653
2654/*
2655 * Name: ql_del_hw_if
2656 * Function: Destroys the hardware specific entities corresponding to an
2657 *	Ethernet Interface
2658 */
2659void
2660ql_del_hw_if(qla_host_t *ha)
2661{
2662	uint32_t i;
2663	uint32_t num_msix;
2664
2665	(void)qla_stop_nic_func(ha);
2666
2667	qla_del_rcv_cntxt(ha);
2668
2669	qla_del_xmt_cntxt(ha);
2670
2671	if (ha->hw.flags.init_intr_cnxt) {
2672		for (i = 0; i < ha->hw.num_sds_rings; ) {
2673
2674			if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
2675				num_msix = Q8_MAX_INTR_VECTORS;
2676			else
2677				num_msix = ha->hw.num_sds_rings - i;
2678			qla_config_intr_cntxt(ha, i, num_msix, 0);
2679
2680			i += num_msix;
2681		}
2682
2683		ha->hw.flags.init_intr_cnxt = 0;
2684	}
2685
2686	if (ha->hw.enable_soft_lro) {
2687		qla_drain_soft_lro(ha);
2688		qla_free_soft_lro(ha);
2689	}
2690
2691	return;
2692}
2693
2694void
2695qla_confirm_9kb_enable(qla_host_t *ha)
2696{
2697	uint32_t supports_9kb = 0;
2698
2699	ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX);
2700
2701	/* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */
2702	WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2);
2703	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
2704
2705	qla_get_nic_partition(ha, &supports_9kb, NULL);
2706
2707	if (!supports_9kb)
2708		ha->hw.enable_9kb = 0;
2709
2710	return;
2711}
2712
2713/*
2714 * Name: ql_init_hw_if
2715 * Function: Creates the hardware specific entities corresponding to an
2716 *	Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address
2717 *	corresponding to the interface. Enables LRO if allowed.
2718 */
2719int
2720ql_init_hw_if(qla_host_t *ha)
2721{
2722	device_t	dev;
2723	uint32_t	i;
2724	uint8_t		bcast_mac[6];
2725	qla_rdesc_t	*rdesc;
2726	uint32_t	num_msix;
2727
2728	dev = ha->pci_dev;
2729
2730	for (i = 0; i < ha->hw.num_sds_rings; i++) {
2731		bzero(ha->hw.dma_buf.sds_ring[i].dma_b,
2732			ha->hw.dma_buf.sds_ring[i].size);
2733	}
2734
2735	for (i = 0; i < ha->hw.num_sds_rings; ) {
2736
2737		if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
2738			num_msix = Q8_MAX_INTR_VECTORS;
2739		else
2740			num_msix = ha->hw.num_sds_rings - i;
2741
2742		if (qla_config_intr_cntxt(ha, i, num_msix, 1)) {
2743
2744			if (i > 0) {
2745
2746				num_msix = i;
2747
2748				for (i = 0; i < num_msix; ) {
2749					qla_config_intr_cntxt(ha, i,
2750						Q8_MAX_INTR_VECTORS, 0);
2751					i += Q8_MAX_INTR_VECTORS;
2752				}
2753			}
2754			return (-1);
2755		}
2756
2757		i = i + num_msix;
2758	}
2759
2760        ha->hw.flags.init_intr_cnxt = 1;
2761
2762	/*
2763	 * Create Receive Context
2764	 */
2765	if (qla_init_rcv_cntxt(ha)) {
2766		return (-1);
2767	}
2768
2769	for (i = 0; i < ha->hw.num_rds_rings; i++) {
2770		rdesc = &ha->hw.rds[i];
2771		rdesc->rx_next = NUM_RX_DESCRIPTORS - 2;
2772		rdesc->rx_in = 0;
2773		/* Update the RDS Producer Indices */
2774		QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\
2775			rdesc->rx_next);
2776	}
2777
2778	/*
2779	 * Create Transmit Context
2780	 */
2781	if (qla_init_xmt_cntxt(ha)) {
2782		qla_del_rcv_cntxt(ha);
2783		return (-1);
2784	}
2785	ha->hw.max_tx_segs = 0;
2786
2787	if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1, 1))
2788		return(-1);
2789
2790	ha->hw.flags.unicast_mac = 1;
2791
2792	bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2793	bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2794
2795	if (qla_config_mac_addr(ha, bcast_mac, 1, 1))
2796		return (-1);
2797
2798	ha->hw.flags.bcast_mac = 1;
2799
2800	/*
2801	 * program any cached multicast addresses
2802	 */
2803	if (qla_hw_add_all_mcast(ha))
2804		return (-1);
2805
2806	if (ql_set_max_mtu(ha, ha->max_frame_size, ha->hw.rcv_cntxt_id))
2807		return (-1);
2808
2809	if (qla_config_rss(ha, ha->hw.rcv_cntxt_id))
2810		return (-1);
2811
2812	if (qla_config_rss_ind_table(ha))
2813		return (-1);
2814
2815	if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0, 1))
2816		return (-1);
2817
2818	if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
2819		return (-1);
2820
2821	if (ha->ifp->if_capenable & IFCAP_LRO) {
2822		if (ha->hw.enable_hw_lro) {
2823			ha->hw.enable_soft_lro = 0;
2824
2825			if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
2826				return (-1);
2827		} else {
2828			ha->hw.enable_soft_lro = 1;
2829
2830			if (qla_config_soft_lro(ha))
2831				return (-1);
2832		}
2833	}
2834
2835        if (qla_init_nic_func(ha))
2836                return (-1);
2837
2838        if (qla_query_fw_dcbx_caps(ha))
2839                return (-1);
2840
2841	for (i = 0; i < ha->hw.num_sds_rings; i++)
2842		QL_ENABLE_INTERRUPTS(ha, i);
2843
2844	return (0);
2845}
2846
2847static int
2848qla_map_sds_to_rds(qla_host_t *ha, uint32_t start_idx, uint32_t num_idx)
2849{
2850        device_t                dev = ha->pci_dev;
2851        q80_rq_map_sds_to_rds_t *map_rings;
2852	q80_rsp_map_sds_to_rds_t *map_rings_rsp;
2853        uint32_t                i, err;
2854        qla_hw_t                *hw = &ha->hw;
2855
2856        map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox;
2857        bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t));
2858
2859        map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS;
2860        map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2);
2861        map_rings->count_version |= Q8_MBX_CMD_VERSION;
2862
2863        map_rings->cntxt_id = hw->rcv_cntxt_id;
2864        map_rings->num_rings = num_idx;
2865
2866	for (i = 0; i < num_idx; i++) {
2867		map_rings->sds_rds[i].sds_ring = i + start_idx;
2868		map_rings->sds_rds[i].rds_ring = i + start_idx;
2869	}
2870
2871        if (qla_mbx_cmd(ha, (uint32_t *)map_rings,
2872                (sizeof (q80_rq_map_sds_to_rds_t) >> 2),
2873                ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2874                device_printf(dev, "%s: failed0\n", __func__);
2875                return (-1);
2876        }
2877
2878        map_rings_rsp = (q80_rsp_map_sds_to_rds_t *)ha->hw.mbox;
2879
2880        err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status);
2881
2882        if (err) {
2883                device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2884                return (-1);
2885        }
2886
2887        return (0);
2888}
2889
2890/*
2891 * Name: qla_init_rcv_cntxt
2892 * Function: Creates the Receive Context.
2893 */
2894static int
2895qla_init_rcv_cntxt(qla_host_t *ha)
2896{
2897	q80_rq_rcv_cntxt_t	*rcntxt;
2898	q80_rsp_rcv_cntxt_t	*rcntxt_rsp;
2899	q80_stat_desc_t		*sdesc;
2900	int			i, j;
2901        qla_hw_t		*hw = &ha->hw;
2902	device_t		dev;
2903	uint32_t		err;
2904	uint32_t		rcntxt_sds_rings;
2905	uint32_t		rcntxt_rds_rings;
2906	uint32_t		max_idx;
2907
2908	dev = ha->pci_dev;
2909
2910	/*
2911	 * Create Receive Context
2912	 */
2913
2914	for (i = 0; i < hw->num_sds_rings; i++) {
2915		sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0];
2916
2917		for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) {
2918			sdesc->data[0] = 1ULL;
2919			sdesc->data[1] = 1ULL;
2920		}
2921	}
2922
2923	rcntxt_sds_rings = hw->num_sds_rings;
2924	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS)
2925		rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS;
2926
2927	rcntxt_rds_rings = hw->num_rds_rings;
2928
2929	if (hw->num_rds_rings > MAX_RDS_RING_SETS)
2930		rcntxt_rds_rings = MAX_RDS_RING_SETS;
2931
2932	rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox;
2933	bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t)));
2934
2935	rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT;
2936	rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2);
2937	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2938
2939	rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW |
2940			Q8_RCV_CNTXT_CAP0_LRO |
2941			Q8_RCV_CNTXT_CAP0_HW_LRO |
2942			Q8_RCV_CNTXT_CAP0_RSS |
2943			Q8_RCV_CNTXT_CAP0_SGL_LRO;
2944
2945	if (ha->hw.enable_9kb)
2946		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SINGLE_JUMBO;
2947	else
2948		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SGL_JUMBO;
2949
2950	if (ha->hw.num_rds_rings > 1) {
2951		rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5);
2952		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS;
2953	} else
2954		rcntxt->nrds_sets_rings = 0x1 | (1 << 5);
2955
2956	rcntxt->nsds_rings = rcntxt_sds_rings;
2957
2958	rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE;
2959
2960	rcntxt->rcv_vpid = 0;
2961
2962	for (i = 0; i <  rcntxt_sds_rings; i++) {
2963		rcntxt->sds[i].paddr =
2964			qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr);
2965		rcntxt->sds[i].size =
2966			qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2967		rcntxt->sds[i].intr_id = qla_host_to_le16(hw->intr_id[i]);
2968		rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0);
2969	}
2970
2971	for (i = 0; i <  rcntxt_rds_rings; i++) {
2972		rcntxt->rds[i].paddr_std =
2973			qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr);
2974
2975		if (ha->hw.enable_9kb)
2976			rcntxt->rds[i].std_bsize =
2977				qla_host_to_le64(MJUM9BYTES);
2978		else
2979			rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
2980
2981		rcntxt->rds[i].std_nentries =
2982			qla_host_to_le32(NUM_RX_DESCRIPTORS);
2983	}
2984
2985        if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2986		(sizeof (q80_rq_rcv_cntxt_t) >> 2),
2987                ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) {
2988                device_printf(dev, "%s: failed0\n", __func__);
2989                return (-1);
2990        }
2991
2992        rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox;
2993
2994        err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2995
2996        if (err) {
2997                device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2998                return (-1);
2999        }
3000
3001	for (i = 0; i <  rcntxt_sds_rings; i++) {
3002		hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i];
3003	}
3004
3005	for (i = 0; i <  rcntxt_rds_rings; i++) {
3006		hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std;
3007	}
3008
3009	hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id;
3010
3011	ha->hw.flags.init_rx_cnxt = 1;
3012
3013	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) {
3014
3015		for (i = MAX_RCNTXT_SDS_RINGS; i < hw->num_sds_rings;) {
3016
3017			if ((i + MAX_RCNTXT_SDS_RINGS) < hw->num_sds_rings)
3018				max_idx = MAX_RCNTXT_SDS_RINGS;
3019			else
3020				max_idx = hw->num_sds_rings - i;
3021
3022			err = qla_add_rcv_rings(ha, i, max_idx);
3023			if (err)
3024				return -1;
3025
3026			i += max_idx;
3027		}
3028	}
3029
3030	if (hw->num_rds_rings > 1) {
3031
3032		for (i = 0; i < hw->num_rds_rings; ) {
3033
3034			if ((i + MAX_SDS_TO_RDS_MAP) < hw->num_rds_rings)
3035				max_idx = MAX_SDS_TO_RDS_MAP;
3036			else
3037				max_idx = hw->num_rds_rings - i;
3038
3039			err = qla_map_sds_to_rds(ha, i, max_idx);
3040			if (err)
3041				return -1;
3042
3043			i += max_idx;
3044		}
3045	}
3046
3047	return (0);
3048}
3049
3050static int
3051qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds)
3052{
3053	device_t		dev = ha->pci_dev;
3054	q80_rq_add_rcv_rings_t	*add_rcv;
3055	q80_rsp_add_rcv_rings_t	*add_rcv_rsp;
3056	uint32_t		i,j, err;
3057        qla_hw_t		*hw = &ha->hw;
3058
3059	add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox;
3060	bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t));
3061
3062	add_rcv->opcode = Q8_MBX_ADD_RX_RINGS;
3063	add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2);
3064	add_rcv->count_version |= Q8_MBX_CMD_VERSION;
3065
3066	add_rcv->nrds_sets_rings = nsds | (1 << 5);
3067	add_rcv->nsds_rings = nsds;
3068	add_rcv->cntxt_id = hw->rcv_cntxt_id;
3069
3070        for (i = 0; i <  nsds; i++) {
3071
3072		j = i + sds_idx;
3073
3074                add_rcv->sds[i].paddr =
3075                        qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr);
3076
3077                add_rcv->sds[i].size =
3078                        qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
3079
3080                add_rcv->sds[i].intr_id = qla_host_to_le16(hw->intr_id[j]);
3081                add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0);
3082
3083        }
3084
3085        for (i = 0; (i <  nsds); i++) {
3086                j = i + sds_idx;
3087
3088                add_rcv->rds[i].paddr_std =
3089                        qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr);
3090
3091		if (ha->hw.enable_9kb)
3092			add_rcv->rds[i].std_bsize =
3093				qla_host_to_le64(MJUM9BYTES);
3094		else
3095                	add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
3096
3097                add_rcv->rds[i].std_nentries =
3098                        qla_host_to_le32(NUM_RX_DESCRIPTORS);
3099        }
3100
3101
3102        if (qla_mbx_cmd(ha, (uint32_t *)add_rcv,
3103		(sizeof (q80_rq_add_rcv_rings_t) >> 2),
3104                ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
3105                device_printf(dev, "%s: failed0\n", __func__);
3106                return (-1);
3107        }
3108
3109        add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
3110
3111        err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status);
3112
3113        if (err) {
3114                device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3115                return (-1);
3116        }
3117
3118	for (i = 0; i < nsds; i++) {
3119		hw->sds[(i + sds_idx)].sds_consumer = add_rcv_rsp->sds_cons[i];
3120	}
3121
3122	for (i = 0; i < nsds; i++) {
3123		hw->rds[(i + sds_idx)].prod_std = add_rcv_rsp->rds[i].prod_std;
3124	}
3125
3126	return (0);
3127}
3128
3129/*
3130 * Name: qla_del_rcv_cntxt
3131 * Function: Destroys the Receive Context.
3132 */
3133static void
3134qla_del_rcv_cntxt(qla_host_t *ha)
3135{
3136	device_t			dev = ha->pci_dev;
3137	q80_rcv_cntxt_destroy_t		*rcntxt;
3138	q80_rcv_cntxt_destroy_rsp_t	*rcntxt_rsp;
3139	uint32_t			err;
3140	uint8_t				bcast_mac[6];
3141
3142	if (!ha->hw.flags.init_rx_cnxt)
3143		return;
3144
3145	if (qla_hw_del_all_mcast(ha))
3146		return;
3147
3148	if (ha->hw.flags.bcast_mac) {
3149
3150		bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
3151		bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
3152
3153		if (qla_config_mac_addr(ha, bcast_mac, 0, 1))
3154			return;
3155		ha->hw.flags.bcast_mac = 0;
3156
3157	}
3158
3159	if (ha->hw.flags.unicast_mac) {
3160		if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0, 1))
3161			return;
3162		ha->hw.flags.unicast_mac = 0;
3163	}
3164
3165	rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox;
3166	bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t)));
3167
3168	rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT;
3169	rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2);
3170	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
3171
3172	rcntxt->cntxt_id = ha->hw.rcv_cntxt_id;
3173
3174        if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
3175		(sizeof (q80_rcv_cntxt_destroy_t) >> 2),
3176                ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) {
3177                device_printf(dev, "%s: failed0\n", __func__);
3178                return;
3179        }
3180        rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox;
3181
3182        err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
3183
3184        if (err) {
3185                device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3186        }
3187
3188	ha->hw.flags.init_rx_cnxt = 0;
3189	return;
3190}
3191
3192/*
3193 * Name: qla_init_xmt_cntxt
3194 * Function: Creates the Transmit Context.
3195 */
3196static int
3197qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
3198{
3199	device_t		dev;
3200        qla_hw_t		*hw = &ha->hw;
3201	q80_rq_tx_cntxt_t	*tcntxt;
3202	q80_rsp_tx_cntxt_t	*tcntxt_rsp;
3203	uint32_t		err;
3204	qla_hw_tx_cntxt_t       *hw_tx_cntxt;
3205	uint32_t		intr_idx;
3206
3207	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
3208
3209	dev = ha->pci_dev;
3210
3211	/*
3212	 * Create Transmit Context
3213	 */
3214	tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox;
3215	bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t)));
3216
3217	tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT;
3218	tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2);
3219	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
3220
3221	intr_idx = txr_idx;
3222
3223#ifdef QL_ENABLE_ISCSI_TLV
3224
3225	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO |
3226				Q8_TX_CNTXT_CAP0_TC;
3227
3228	if (txr_idx >= (ha->hw.num_tx_rings >> 1)) {
3229		tcntxt->traffic_class = 1;
3230	}
3231
3232	intr_idx = txr_idx % (ha->hw.num_tx_rings >> 1);
3233
3234#else
3235	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO;
3236
3237#endif /* #ifdef QL_ENABLE_ISCSI_TLV */
3238
3239	tcntxt->ntx_rings = 1;
3240
3241	tcntxt->tx_ring[0].paddr =
3242		qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr);
3243	tcntxt->tx_ring[0].tx_consumer =
3244		qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr);
3245	tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS);
3246
3247	tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[intr_idx]);
3248	tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0);
3249
3250	hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS;
3251	hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0;
3252
3253        if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
3254		(sizeof (q80_rq_tx_cntxt_t) >> 2),
3255                ha->hw.mbox,
3256		(sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) {
3257                device_printf(dev, "%s: failed0\n", __func__);
3258                return (-1);
3259        }
3260        tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox;
3261
3262        err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
3263
3264        if (err) {
3265                device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3266		return -1;
3267        }
3268
3269	hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index;
3270	hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id;
3271
3272	if (qla_config_intr_coalesce(ha, hw_tx_cntxt->tx_cntxt_id, 0, 0))
3273		return (-1);
3274
3275	return (0);
3276}
3277
3278
3279/*
3280 * Name: qla_del_xmt_cntxt
3281 * Function: Destroys the Transmit Context.
3282 */
3283static int
3284qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
3285{
3286	device_t			dev = ha->pci_dev;
3287	q80_tx_cntxt_destroy_t		*tcntxt;
3288	q80_tx_cntxt_destroy_rsp_t	*tcntxt_rsp;
3289	uint32_t			err;
3290
3291	tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox;
3292	bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t)));
3293
3294	tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT;
3295	tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2);
3296	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
3297
3298	tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id;
3299
3300        if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
3301		(sizeof (q80_tx_cntxt_destroy_t) >> 2),
3302                ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) {
3303                device_printf(dev, "%s: failed0\n", __func__);
3304                return (-1);
3305        }
3306        tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox;
3307
3308        err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
3309
3310        if (err) {
3311                device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3312		return (-1);
3313        }
3314
3315	return (0);
3316}
3317static void
3318qla_del_xmt_cntxt(qla_host_t *ha)
3319{
3320	uint32_t i;
3321
3322	if (!ha->hw.flags.init_tx_cnxt)
3323		return;
3324
3325	for (i = 0; i < ha->hw.num_tx_rings; i++) {
3326		if (qla_del_xmt_cntxt_i(ha, i))
3327			break;
3328	}
3329	ha->hw.flags.init_tx_cnxt = 0;
3330}
3331
3332static int
3333qla_init_xmt_cntxt(qla_host_t *ha)
3334{
3335	uint32_t i, j;
3336
3337	for (i = 0; i < ha->hw.num_tx_rings; i++) {
3338		if (qla_init_xmt_cntxt_i(ha, i) != 0) {
3339			for (j = 0; j < i; j++)
3340				qla_del_xmt_cntxt_i(ha, j);
3341			return (-1);
3342		}
3343	}
3344	ha->hw.flags.init_tx_cnxt = 1;
3345	return (0);
3346}
3347
3348static int
3349qla_hw_all_mcast(qla_host_t *ha, uint32_t add_mcast)
3350{
3351	int i, nmcast;
3352	uint32_t count = 0;
3353	uint8_t *mcast;
3354
3355	nmcast = ha->hw.nmcast;
3356
3357	QL_DPRINT2(ha, (ha->pci_dev,
3358		"%s:[0x%x] enter nmcast = %d \n", __func__, add_mcast, nmcast));
3359
3360	mcast = ha->hw.mac_addr_arr;
3361	memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3362
3363	for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
3364		if ((ha->hw.mcast[i].addr[0] != 0) ||
3365			(ha->hw.mcast[i].addr[1] != 0) ||
3366			(ha->hw.mcast[i].addr[2] != 0) ||
3367			(ha->hw.mcast[i].addr[3] != 0) ||
3368			(ha->hw.mcast[i].addr[4] != 0) ||
3369			(ha->hw.mcast[i].addr[5] != 0)) {
3370
3371			bcopy(ha->hw.mcast[i].addr, mcast, ETHER_ADDR_LEN);
3372			mcast = mcast + ETHER_ADDR_LEN;
3373			count++;
3374
3375			if (count == Q8_MAX_MAC_ADDRS) {
3376				if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
3377					add_mcast, count)) {
3378                			device_printf(ha->pci_dev,
3379						"%s: failed\n", __func__);
3380					return (-1);
3381				}
3382
3383				count = 0;
3384				mcast = ha->hw.mac_addr_arr;
3385				memset(mcast, 0,
3386					(Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3387			}
3388
3389			nmcast--;
3390		}
3391	}
3392
3393	if (count) {
3394		if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mcast,
3395			count)) {
3396                	device_printf(ha->pci_dev, "%s: failed\n", __func__);
3397			return (-1);
3398		}
3399	}
3400	QL_DPRINT2(ha, (ha->pci_dev,
3401		"%s:[0x%x] exit nmcast = %d \n", __func__, add_mcast, nmcast));
3402
3403	return 0;
3404}
3405
3406static int
3407qla_hw_add_all_mcast(qla_host_t *ha)
3408{
3409	int ret;
3410
3411	ret = qla_hw_all_mcast(ha, 1);
3412
3413	return (ret);
3414}
3415
3416static int
3417qla_hw_del_all_mcast(qla_host_t *ha)
3418{
3419	int ret;
3420
3421	ret = qla_hw_all_mcast(ha, 0);
3422
3423	bzero(ha->hw.mcast, (sizeof (qla_mcast_t) * Q8_MAX_NUM_MULTICAST_ADDRS));
3424	ha->hw.nmcast = 0;
3425
3426	return (ret);
3427}
3428
3429static int
3430qla_hw_mac_addr_present(qla_host_t *ha, uint8_t *mta)
3431{
3432	int i;
3433
3434	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3435		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0)
3436			return (0); /* its been already added */
3437	}
3438	return (-1);
3439}
3440
3441static int
3442qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3443{
3444	int i;
3445
3446	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3447
3448		if ((ha->hw.mcast[i].addr[0] == 0) &&
3449			(ha->hw.mcast[i].addr[1] == 0) &&
3450			(ha->hw.mcast[i].addr[2] == 0) &&
3451			(ha->hw.mcast[i].addr[3] == 0) &&
3452			(ha->hw.mcast[i].addr[4] == 0) &&
3453			(ha->hw.mcast[i].addr[5] == 0)) {
3454
3455			bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN);
3456			ha->hw.nmcast++;
3457
3458			mta = mta + ETHER_ADDR_LEN;
3459			nmcast--;
3460
3461			if (nmcast == 0)
3462				break;
3463		}
3464
3465	}
3466	return 0;
3467}
3468
3469static int
3470qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3471{
3472	int i;
3473
3474	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3475		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) {
3476
3477			ha->hw.mcast[i].addr[0] = 0;
3478			ha->hw.mcast[i].addr[1] = 0;
3479			ha->hw.mcast[i].addr[2] = 0;
3480			ha->hw.mcast[i].addr[3] = 0;
3481			ha->hw.mcast[i].addr[4] = 0;
3482			ha->hw.mcast[i].addr[5] = 0;
3483
3484			ha->hw.nmcast--;
3485
3486			mta = mta + ETHER_ADDR_LEN;
3487			nmcast--;
3488
3489			if (nmcast == 0)
3490				break;
3491		}
3492	}
3493	return 0;
3494}
3495
3496/*
3497 * Name: ql_hw_set_multi
3498 * Function: Sets the Multicast Addresses provided by the host O.S into the
3499 *	hardware (for the given interface)
3500 */
3501int
3502ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast_addr, uint32_t mcnt,
3503	uint32_t add_mac)
3504{
3505	uint8_t *mta = mcast_addr;
3506	int i;
3507	int ret = 0;
3508	uint32_t count = 0;
3509	uint8_t *mcast;
3510
3511	mcast = ha->hw.mac_addr_arr;
3512	memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3513
3514	for (i = 0; i < mcnt; i++) {
3515		if (mta[0] || mta[1] || mta[2] || mta[3] || mta[4] || mta[5]) {
3516			if (add_mac) {
3517				if (qla_hw_mac_addr_present(ha, mta) != 0) {
3518					bcopy(mta, mcast, ETHER_ADDR_LEN);
3519					mcast = mcast + ETHER_ADDR_LEN;
3520					count++;
3521				}
3522			} else {
3523				if (qla_hw_mac_addr_present(ha, mta) == 0) {
3524					bcopy(mta, mcast, ETHER_ADDR_LEN);
3525					mcast = mcast + ETHER_ADDR_LEN;
3526					count++;
3527				}
3528			}
3529		}
3530		if (count == Q8_MAX_MAC_ADDRS) {
3531			if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
3532				add_mac, count)) {
3533                		device_printf(ha->pci_dev, "%s: failed\n",
3534					__func__);
3535				return (-1);
3536			}
3537
3538			if (add_mac) {
3539				qla_hw_add_mcast(ha, ha->hw.mac_addr_arr,
3540					count);
3541			} else {
3542				qla_hw_del_mcast(ha, ha->hw.mac_addr_arr,
3543					count);
3544			}
3545
3546			count = 0;
3547			mcast = ha->hw.mac_addr_arr;
3548			memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3549		}
3550
3551		mta += Q8_MAC_ADDR_LEN;
3552	}
3553
3554	if (count) {
3555		if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mac,
3556			count)) {
3557                	device_printf(ha->pci_dev, "%s: failed\n", __func__);
3558			return (-1);
3559		}
3560		if (add_mac) {
3561			qla_hw_add_mcast(ha, ha->hw.mac_addr_arr, count);
3562		} else {
3563			qla_hw_del_mcast(ha, ha->hw.mac_addr_arr, count);
3564		}
3565	}
3566
3567	return (ret);
3568}
3569
3570/*
3571 * Name: ql_hw_tx_done_locked
3572 * Function: Handle Transmit Completions
3573 */
3574void
3575ql_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx)
3576{
3577	qla_tx_buf_t *txb;
3578        qla_hw_t *hw = &ha->hw;
3579	uint32_t comp_idx, comp_count = 0;
3580	qla_hw_tx_cntxt_t *hw_tx_cntxt;
3581
3582	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
3583
3584	/* retrieve index of last entry in tx ring completed */
3585	comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons));
3586
3587	while (comp_idx != hw_tx_cntxt->txr_comp) {
3588
3589		txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp];
3590
3591		hw_tx_cntxt->txr_comp++;
3592		if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS)
3593			hw_tx_cntxt->txr_comp = 0;
3594
3595		comp_count++;
3596
3597		if (txb->m_head) {
3598			ha->ifp->if_opackets++;
3599
3600			bus_dmamap_sync(ha->tx_tag, txb->map,
3601				BUS_DMASYNC_POSTWRITE);
3602			bus_dmamap_unload(ha->tx_tag, txb->map);
3603			m_freem(txb->m_head);
3604
3605			txb->m_head = NULL;
3606		}
3607	}
3608
3609	hw_tx_cntxt->txr_free += comp_count;
3610	return;
3611}
3612
3613void
3614ql_update_link_state(qla_host_t *ha)
3615{
3616	uint32_t link_state;
3617	uint32_t prev_link_state;
3618
3619	if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
3620		ha->hw.link_up = 0;
3621		return;
3622	}
3623	link_state = READ_REG32(ha, Q8_LINK_STATE);
3624
3625	prev_link_state =  ha->hw.link_up;
3626
3627	if (ha->pci_func == 0)
3628		ha->hw.link_up = (((link_state & 0xF) == 1)? 1 : 0);
3629	else
3630		ha->hw.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
3631
3632	if (prev_link_state !=  ha->hw.link_up) {
3633		if (ha->hw.link_up) {
3634			if_link_state_change(ha->ifp, LINK_STATE_UP);
3635		} else {
3636			if_link_state_change(ha->ifp, LINK_STATE_DOWN);
3637		}
3638	}
3639	return;
3640}
3641
3642int
3643ql_hw_check_health(qla_host_t *ha)
3644{
3645	uint32_t val;
3646
3647	ha->hw.health_count++;
3648
3649	if (ha->hw.health_count < 500)
3650		return 0;
3651
3652	ha->hw.health_count = 0;
3653
3654	val = READ_REG32(ha, Q8_ASIC_TEMPERATURE);
3655
3656	if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) ||
3657		(QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) {
3658		device_printf(ha->pci_dev, "%s: Temperature Alert [0x%08x]\n",
3659			__func__, val);
3660		return -1;
3661	}
3662
3663	val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT);
3664
3665	if ((val != ha->hw.hbeat_value) &&
3666		(!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) {
3667		ha->hw.hbeat_value = val;
3668		ha->hw.hbeat_failure = 0;
3669		return 0;
3670	}
3671
3672	ha->hw.hbeat_failure++;
3673
3674
3675	if ((ha->dbg_level & 0x8000) && (ha->hw.hbeat_failure == 1))
3676		device_printf(ha->pci_dev, "%s: Heartbeat Failue 1[0x%08x]\n",
3677			__func__, val);
3678	if (ha->hw.hbeat_failure < 2) /* we ignore the first failure */
3679		return 0;
3680	else
3681		device_printf(ha->pci_dev, "%s: Heartbeat Failue [0x%08x]\n",
3682			__func__, val);
3683
3684	return -1;
3685}
3686
3687static int
3688qla_init_nic_func(qla_host_t *ha)
3689{
3690        device_t                dev;
3691        q80_init_nic_func_t     *init_nic;
3692        q80_init_nic_func_rsp_t *init_nic_rsp;
3693        uint32_t                err;
3694
3695        dev = ha->pci_dev;
3696
3697        init_nic = (q80_init_nic_func_t *)ha->hw.mbox;
3698        bzero(init_nic, sizeof(q80_init_nic_func_t));
3699
3700        init_nic->opcode = Q8_MBX_INIT_NIC_FUNC;
3701        init_nic->count_version = (sizeof (q80_init_nic_func_t) >> 2);
3702        init_nic->count_version |= Q8_MBX_CMD_VERSION;
3703
3704        init_nic->options = Q8_INIT_NIC_REG_DCBX_CHNG_AEN;
3705        init_nic->options |= Q8_INIT_NIC_REG_SFP_CHNG_AEN;
3706        init_nic->options |= Q8_INIT_NIC_REG_IDC_AEN;
3707
3708//qla_dump_buf8(ha, __func__, init_nic, sizeof (q80_init_nic_func_t));
3709        if (qla_mbx_cmd(ha, (uint32_t *)init_nic,
3710                (sizeof (q80_init_nic_func_t) >> 2),
3711                ha->hw.mbox, (sizeof (q80_init_nic_func_rsp_t) >> 2), 0)) {
3712                device_printf(dev, "%s: failed\n", __func__);
3713                return -1;
3714        }
3715
3716        init_nic_rsp = (q80_init_nic_func_rsp_t *)ha->hw.mbox;
3717// qla_dump_buf8(ha, __func__, init_nic_rsp, sizeof (q80_init_nic_func_rsp_t));
3718
3719        err = Q8_MBX_RSP_STATUS(init_nic_rsp->regcnt_status);
3720
3721        if (err) {
3722                device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3723        }
3724
3725        return 0;
3726}
3727
3728static int
3729qla_stop_nic_func(qla_host_t *ha)
3730{
3731        device_t                dev;
3732        q80_stop_nic_func_t     *stop_nic;
3733        q80_stop_nic_func_rsp_t *stop_nic_rsp;
3734        uint32_t                err;
3735
3736        dev = ha->pci_dev;
3737
3738        stop_nic = (q80_stop_nic_func_t *)ha->hw.mbox;
3739        bzero(stop_nic, sizeof(q80_stop_nic_func_t));
3740
3741        stop_nic->opcode = Q8_MBX_STOP_NIC_FUNC;
3742        stop_nic->count_version = (sizeof (q80_stop_nic_func_t) >> 2);
3743        stop_nic->count_version |= Q8_MBX_CMD_VERSION;
3744
3745        stop_nic->options = Q8_STOP_NIC_DEREG_DCBX_CHNG_AEN;
3746        stop_nic->options |= Q8_STOP_NIC_DEREG_SFP_CHNG_AEN;
3747
3748//qla_dump_buf8(ha, __func__, stop_nic, sizeof (q80_stop_nic_func_t));
3749        if (qla_mbx_cmd(ha, (uint32_t *)stop_nic,
3750                (sizeof (q80_stop_nic_func_t) >> 2),
3751                ha->hw.mbox, (sizeof (q80_stop_nic_func_rsp_t) >> 2), 0)) {
3752                device_printf(dev, "%s: failed\n", __func__);
3753                return -1;
3754        }
3755
3756        stop_nic_rsp = (q80_stop_nic_func_rsp_t *)ha->hw.mbox;
3757//qla_dump_buf8(ha, __func__, stop_nic_rsp, sizeof (q80_stop_nic_func_rsp_ t));
3758
3759        err = Q8_MBX_RSP_STATUS(stop_nic_rsp->regcnt_status);
3760
3761        if (err) {
3762                device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3763        }
3764
3765        return 0;
3766}
3767
3768static int
3769qla_query_fw_dcbx_caps(qla_host_t *ha)
3770{
3771        device_t                        dev;
3772        q80_query_fw_dcbx_caps_t        *fw_dcbx;
3773        q80_query_fw_dcbx_caps_rsp_t    *fw_dcbx_rsp;
3774        uint32_t                        err;
3775
3776        dev = ha->pci_dev;
3777
3778        fw_dcbx = (q80_query_fw_dcbx_caps_t *)ha->hw.mbox;
3779        bzero(fw_dcbx, sizeof(q80_query_fw_dcbx_caps_t));
3780
3781        fw_dcbx->opcode = Q8_MBX_GET_FW_DCBX_CAPS;
3782        fw_dcbx->count_version = (sizeof (q80_query_fw_dcbx_caps_t) >> 2);
3783        fw_dcbx->count_version |= Q8_MBX_CMD_VERSION;
3784
3785        ql_dump_buf8(ha, __func__, fw_dcbx, sizeof (q80_query_fw_dcbx_caps_t));
3786        if (qla_mbx_cmd(ha, (uint32_t *)fw_dcbx,
3787                (sizeof (q80_query_fw_dcbx_caps_t) >> 2),
3788                ha->hw.mbox, (sizeof (q80_query_fw_dcbx_caps_rsp_t) >> 2), 0)) {
3789                device_printf(dev, "%s: failed\n", __func__);
3790                return -1;
3791        }
3792
3793        fw_dcbx_rsp = (q80_query_fw_dcbx_caps_rsp_t *)ha->hw.mbox;
3794        ql_dump_buf8(ha, __func__, fw_dcbx_rsp,
3795                sizeof (q80_query_fw_dcbx_caps_rsp_t));
3796
3797        err = Q8_MBX_RSP_STATUS(fw_dcbx_rsp->regcnt_status);
3798
3799        if (err) {
3800                device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3801        }
3802
3803        return 0;
3804}
3805
3806static int
3807qla_idc_ack(qla_host_t *ha, uint32_t aen_mb1, uint32_t aen_mb2,
3808        uint32_t aen_mb3, uint32_t aen_mb4)
3809{
3810        device_t                dev;
3811        q80_idc_ack_t           *idc_ack;
3812        q80_idc_ack_rsp_t       *idc_ack_rsp;
3813        uint32_t                err;
3814        int                     count = 300;
3815
3816        dev = ha->pci_dev;
3817
3818        idc_ack = (q80_idc_ack_t *)ha->hw.mbox;
3819        bzero(idc_ack, sizeof(q80_idc_ack_t));
3820
3821        idc_ack->opcode = Q8_MBX_IDC_ACK;
3822        idc_ack->count_version = (sizeof (q80_idc_ack_t) >> 2);
3823        idc_ack->count_version |= Q8_MBX_CMD_VERSION;
3824
3825        idc_ack->aen_mb1 = aen_mb1;
3826        idc_ack->aen_mb2 = aen_mb2;
3827        idc_ack->aen_mb3 = aen_mb3;
3828        idc_ack->aen_mb4 = aen_mb4;
3829
3830        ha->hw.imd_compl= 0;
3831
3832        if (qla_mbx_cmd(ha, (uint32_t *)idc_ack,
3833                (sizeof (q80_idc_ack_t) >> 2),
3834                ha->hw.mbox, (sizeof (q80_idc_ack_rsp_t) >> 2), 0)) {
3835                device_printf(dev, "%s: failed\n", __func__);
3836                return -1;
3837        }
3838
3839        idc_ack_rsp = (q80_idc_ack_rsp_t *)ha->hw.mbox;
3840
3841        err = Q8_MBX_RSP_STATUS(idc_ack_rsp->regcnt_status);
3842
3843        if (err) {
3844                device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3845                return(-1);
3846        }
3847
3848        while (count && !ha->hw.imd_compl) {
3849                qla_mdelay(__func__, 100);
3850                count--;
3851        }
3852
3853        if (!count)
3854                return -1;
3855        else
3856                device_printf(dev, "%s: count %d\n", __func__, count);
3857
3858        return (0);
3859}
3860
3861static int
3862qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits)
3863{
3864        device_t                dev;
3865        q80_set_port_cfg_t      *pcfg;
3866        q80_set_port_cfg_rsp_t  *pfg_rsp;
3867        uint32_t                err;
3868        int                     count = 300;
3869
3870        dev = ha->pci_dev;
3871
3872        pcfg = (q80_set_port_cfg_t *)ha->hw.mbox;
3873        bzero(pcfg, sizeof(q80_set_port_cfg_t));
3874
3875        pcfg->opcode = Q8_MBX_SET_PORT_CONFIG;
3876        pcfg->count_version = (sizeof (q80_set_port_cfg_t) >> 2);
3877        pcfg->count_version |= Q8_MBX_CMD_VERSION;
3878
3879        pcfg->cfg_bits = cfg_bits;
3880
3881        device_printf(dev, "%s: cfg_bits"
3882                " [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
3883                " [0x%x, 0x%x, 0x%x]\n", __func__,
3884                ((cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
3885                ((cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
3886                ((cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0));
3887
3888        ha->hw.imd_compl= 0;
3889
3890        if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
3891                (sizeof (q80_set_port_cfg_t) >> 2),
3892                ha->hw.mbox, (sizeof (q80_set_port_cfg_rsp_t) >> 2), 0)) {
3893                device_printf(dev, "%s: failed\n", __func__);
3894                return -1;
3895        }
3896
3897        pfg_rsp = (q80_set_port_cfg_rsp_t *)ha->hw.mbox;
3898
3899        err = Q8_MBX_RSP_STATUS(pfg_rsp->regcnt_status);
3900
3901        if (err == Q8_MBX_RSP_IDC_INTRMD_RSP) {
3902                while (count && !ha->hw.imd_compl) {
3903                        qla_mdelay(__func__, 100);
3904                        count--;
3905                }
3906                if (count) {
3907                        device_printf(dev, "%s: count %d\n", __func__, count);
3908
3909                        err = 0;
3910                }
3911        }
3912
3913        if (err) {
3914                device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3915                return(-1);
3916        }
3917
3918        return (0);
3919}
3920
3921
3922static int
3923qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size)
3924{
3925	uint32_t			err;
3926	device_t			dev = ha->pci_dev;
3927	q80_config_md_templ_size_t	*md_size;
3928	q80_config_md_templ_size_rsp_t	*md_size_rsp;
3929
3930#ifndef QL_LDFLASH_FW
3931
3932	ql_minidump_template_hdr_t *hdr;
3933
3934	hdr = (ql_minidump_template_hdr_t *)ql83xx_minidump;
3935	*size = hdr->size_of_template;
3936	return (0);
3937
3938#endif /* #ifdef QL_LDFLASH_FW */
3939
3940	md_size = (q80_config_md_templ_size_t *) ha->hw.mbox;
3941	bzero(md_size, sizeof(q80_config_md_templ_size_t));
3942
3943	md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE;
3944	md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2);
3945	md_size->count_version |= Q8_MBX_CMD_VERSION;
3946
3947	if (qla_mbx_cmd(ha, (uint32_t *) md_size,
3948		(sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox,
3949		(sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) {
3950
3951		device_printf(dev, "%s: failed\n", __func__);
3952
3953		return (-1);
3954	}
3955
3956	md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox;
3957
3958	err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status);
3959
3960        if (err) {
3961		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3962		return(-1);
3963        }
3964
3965	*size = md_size_rsp->templ_size;
3966
3967	return (0);
3968}
3969
3970static int
3971qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits)
3972{
3973        device_t                dev;
3974        q80_get_port_cfg_t      *pcfg;
3975        q80_get_port_cfg_rsp_t  *pcfg_rsp;
3976        uint32_t                err;
3977
3978        dev = ha->pci_dev;
3979
3980        pcfg = (q80_get_port_cfg_t *)ha->hw.mbox;
3981        bzero(pcfg, sizeof(q80_get_port_cfg_t));
3982
3983        pcfg->opcode = Q8_MBX_GET_PORT_CONFIG;
3984        pcfg->count_version = (sizeof (q80_get_port_cfg_t) >> 2);
3985        pcfg->count_version |= Q8_MBX_CMD_VERSION;
3986
3987        if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
3988                (sizeof (q80_get_port_cfg_t) >> 2),
3989                ha->hw.mbox, (sizeof (q80_get_port_cfg_rsp_t) >> 2), 0)) {
3990                device_printf(dev, "%s: failed\n", __func__);
3991                return -1;
3992        }
3993
3994        pcfg_rsp = (q80_get_port_cfg_rsp_t *)ha->hw.mbox;
3995
3996        err = Q8_MBX_RSP_STATUS(pcfg_rsp->regcnt_status);
3997
3998        if (err) {
3999                device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
4000                return(-1);
4001        }
4002
4003        device_printf(dev, "%s: [cfg_bits, port type]"
4004                " [0x%08x, 0x%02x] [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
4005                " [0x%x, 0x%x, 0x%x]\n", __func__,
4006                pcfg_rsp->cfg_bits, pcfg_rsp->phys_port_type,
4007                ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
4008                ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
4009                ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0)
4010                );
4011
4012        *cfg_bits = pcfg_rsp->cfg_bits;
4013
4014        return (0);
4015}
4016
4017int
4018ql_iscsi_pdu(qla_host_t *ha, struct mbuf *mp)
4019{
4020        struct ether_vlan_header        *eh;
4021        uint16_t                        etype;
4022        struct ip                       *ip = NULL;
4023        struct ip6_hdr                  *ip6 = NULL;
4024        struct tcphdr                   *th = NULL;
4025        uint32_t                        hdrlen;
4026        uint32_t                        offset;
4027        uint8_t                         buf[sizeof(struct ip6_hdr)];
4028
4029        eh = mtod(mp, struct ether_vlan_header *);
4030
4031        if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
4032                hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
4033                etype = ntohs(eh->evl_proto);
4034        } else {
4035                hdrlen = ETHER_HDR_LEN;
4036                etype = ntohs(eh->evl_encap_proto);
4037        }
4038
4039	if (etype == ETHERTYPE_IP) {
4040
4041		offset = (hdrlen + sizeof (struct ip));
4042
4043		if (mp->m_len >= offset) {
4044                        ip = (struct ip *)(mp->m_data + hdrlen);
4045		} else {
4046			m_copydata(mp, hdrlen, sizeof (struct ip), buf);
4047                        ip = (struct ip *)buf;
4048		}
4049
4050                if (ip->ip_p == IPPROTO_TCP) {
4051
4052			hdrlen += ip->ip_hl << 2;
4053			offset = hdrlen + 4;
4054
4055			if (mp->m_len >= offset) {
4056				th = (struct tcphdr *)(mp->m_data + hdrlen);;
4057			} else {
4058                                m_copydata(mp, hdrlen, 4, buf);
4059				th = (struct tcphdr *)buf;
4060			}
4061                }
4062
4063	} else if (etype == ETHERTYPE_IPV6) {
4064
4065		offset = (hdrlen + sizeof (struct ip6_hdr));
4066
4067		if (mp->m_len >= offset) {
4068                        ip6 = (struct ip6_hdr *)(mp->m_data + hdrlen);
4069		} else {
4070                        m_copydata(mp, hdrlen, sizeof (struct ip6_hdr), buf);
4071                        ip6 = (struct ip6_hdr *)buf;
4072		}
4073
4074                if (ip6->ip6_nxt == IPPROTO_TCP) {
4075
4076			hdrlen += sizeof(struct ip6_hdr);
4077			offset = hdrlen + 4;
4078
4079			if (mp->m_len >= offset) {
4080				th = (struct tcphdr *)(mp->m_data + hdrlen);;
4081			} else {
4082				m_copydata(mp, hdrlen, 4, buf);
4083				th = (struct tcphdr *)buf;
4084			}
4085                }
4086	}
4087
4088        if (th != NULL) {
4089                if ((th->th_sport == htons(3260)) ||
4090                        (th->th_dport == htons(3260)))
4091                        return 0;
4092        }
4093        return (-1);
4094}
4095
4096void
4097qla_hw_async_event(qla_host_t *ha)
4098{
4099        switch (ha->hw.aen_mb0) {
4100        case 0x8101:
4101                (void)qla_idc_ack(ha, ha->hw.aen_mb1, ha->hw.aen_mb2,
4102                        ha->hw.aen_mb3, ha->hw.aen_mb4);
4103
4104                break;
4105
4106        default:
4107                break;
4108        }
4109
4110        return;
4111}
4112
4113#ifdef QL_LDFLASH_FW
4114static int
4115ql_get_minidump_template(qla_host_t *ha)
4116{
4117	uint32_t			err;
4118	device_t			dev = ha->pci_dev;
4119	q80_config_md_templ_cmd_t	*md_templ;
4120	q80_config_md_templ_cmd_rsp_t	*md_templ_rsp;
4121
4122	md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox;
4123	bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t)));
4124
4125	md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT;
4126	md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2);
4127	md_templ->count_version |= Q8_MBX_CMD_VERSION;
4128
4129	md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr;
4130	md_templ->buff_size = ha->hw.dma_buf.minidump.size;
4131
4132	if (qla_mbx_cmd(ha, (uint32_t *) md_templ,
4133		(sizeof(q80_config_md_templ_cmd_t) >> 2),
4134		 ha->hw.mbox,
4135		(sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) {
4136
4137		device_printf(dev, "%s: failed\n", __func__);
4138
4139		return (-1);
4140	}
4141
4142	md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox;
4143
4144	err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status);
4145
4146	if (err) {
4147		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
4148		return (-1);
4149	}
4150
4151	return (0);
4152
4153}
4154#endif /* #ifdef QL_LDFLASH_FW */
4155
4156/*
4157 * Minidump related functionality
4158 */
4159
4160static int ql_parse_template(qla_host_t *ha);
4161
4162static uint32_t ql_rdcrb(qla_host_t *ha,
4163			ql_minidump_entry_rdcrb_t *crb_entry,
4164			uint32_t * data_buff);
4165
4166static uint32_t ql_pollrd(qla_host_t *ha,
4167			ql_minidump_entry_pollrd_t *entry,
4168			uint32_t * data_buff);
4169
4170static uint32_t ql_pollrd_modify_write(qla_host_t *ha,
4171			ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
4172			uint32_t *data_buff);
4173
4174static uint32_t ql_L2Cache(qla_host_t *ha,
4175			ql_minidump_entry_cache_t *cacheEntry,
4176			uint32_t * data_buff);
4177
4178static uint32_t ql_L1Cache(qla_host_t *ha,
4179			ql_minidump_entry_cache_t *cacheEntry,
4180			uint32_t *data_buff);
4181
4182static uint32_t ql_rdocm(qla_host_t *ha,
4183			ql_minidump_entry_rdocm_t *ocmEntry,
4184			uint32_t *data_buff);
4185
4186static uint32_t ql_rdmem(qla_host_t *ha,
4187			ql_minidump_entry_rdmem_t *mem_entry,
4188			uint32_t *data_buff);
4189
4190static uint32_t ql_rdrom(qla_host_t *ha,
4191			ql_minidump_entry_rdrom_t *romEntry,
4192			uint32_t *data_buff);
4193
4194static uint32_t ql_rdmux(qla_host_t *ha,
4195			ql_minidump_entry_mux_t *muxEntry,
4196			uint32_t *data_buff);
4197
4198static uint32_t ql_rdmux2(qla_host_t *ha,
4199			ql_minidump_entry_mux2_t *muxEntry,
4200			uint32_t *data_buff);
4201
4202static uint32_t ql_rdqueue(qla_host_t *ha,
4203			ql_minidump_entry_queue_t *queueEntry,
4204			uint32_t *data_buff);
4205
4206static uint32_t ql_cntrl(qla_host_t *ha,
4207			ql_minidump_template_hdr_t *template_hdr,
4208			ql_minidump_entry_cntrl_t *crbEntry);
4209
4210
4211static uint32_t
4212ql_minidump_size(qla_host_t *ha)
4213{
4214	uint32_t i, k;
4215	uint32_t size = 0;
4216	ql_minidump_template_hdr_t *hdr;
4217
4218	hdr = (ql_minidump_template_hdr_t *)ha->hw.dma_buf.minidump.dma_b;
4219
4220	i = 0x2;
4221
4222	for (k = 1; k < QL_DBG_CAP_SIZE_ARRAY_LEN; k++) {
4223		if (i & ha->hw.mdump_capture_mask)
4224			size += hdr->capture_size_array[k];
4225		i = i << 1;
4226	}
4227	return (size);
4228}
4229
4230static void
4231ql_free_minidump_buffer(qla_host_t *ha)
4232{
4233	if (ha->hw.mdump_buffer != NULL) {
4234		free(ha->hw.mdump_buffer, M_QLA83XXBUF);
4235		ha->hw.mdump_buffer = NULL;
4236		ha->hw.mdump_buffer_size = 0;
4237	}
4238	return;
4239}
4240
4241static int
4242ql_alloc_minidump_buffer(qla_host_t *ha)
4243{
4244	ha->hw.mdump_buffer_size = ql_minidump_size(ha);
4245
4246	if (!ha->hw.mdump_buffer_size)
4247		return (-1);
4248
4249	ha->hw.mdump_buffer = malloc(ha->hw.mdump_buffer_size, M_QLA83XXBUF,
4250					M_NOWAIT);
4251
4252	if (ha->hw.mdump_buffer == NULL)
4253		return (-1);
4254
4255	return (0);
4256}
4257
4258static void
4259ql_free_minidump_template_buffer(qla_host_t *ha)
4260{
4261	if (ha->hw.mdump_template != NULL) {
4262		free(ha->hw.mdump_template, M_QLA83XXBUF);
4263		ha->hw.mdump_template = NULL;
4264		ha->hw.mdump_template_size = 0;
4265	}
4266	return;
4267}
4268
4269static int
4270ql_alloc_minidump_template_buffer(qla_host_t *ha)
4271{
4272	ha->hw.mdump_template_size = ha->hw.dma_buf.minidump.size;
4273
4274	ha->hw.mdump_template = malloc(ha->hw.mdump_template_size,
4275					M_QLA83XXBUF, M_NOWAIT);
4276
4277	if (ha->hw.mdump_template == NULL)
4278		return (-1);
4279
4280	return (0);
4281}
4282
4283static int
4284ql_alloc_minidump_buffers(qla_host_t *ha)
4285{
4286	int ret;
4287
4288	ret = ql_alloc_minidump_template_buffer(ha);
4289
4290	if (ret)
4291		return (ret);
4292
4293	ret = ql_alloc_minidump_buffer(ha);
4294
4295	if (ret)
4296		ql_free_minidump_template_buffer(ha);
4297
4298	return (ret);
4299}
4300
4301
4302static uint32_t
4303ql_validate_minidump_checksum(qla_host_t *ha)
4304{
4305        uint64_t sum = 0;
4306	int count;
4307	uint32_t *template_buff;
4308
4309	count = ha->hw.dma_buf.minidump.size / sizeof (uint32_t);
4310	template_buff = ha->hw.dma_buf.minidump.dma_b;
4311
4312	while (count-- > 0) {
4313		sum += *template_buff++;
4314	}
4315
4316	while (sum >> 32) {
4317		sum = (sum & 0xFFFFFFFF) + (sum >> 32);
4318	}
4319
4320	return (~sum);
4321}
4322
4323int
4324ql_minidump_init(qla_host_t *ha)
4325{
4326	int		ret = 0;
4327	uint32_t	template_size = 0;
4328	device_t	dev = ha->pci_dev;
4329
4330	/*
4331	 * Get Minidump Template Size
4332 	 */
4333	ret = qla_get_minidump_tmplt_size(ha, &template_size);
4334
4335	if (ret || (template_size == 0)) {
4336		device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret,
4337			template_size);
4338		return (-1);
4339	}
4340
4341	/*
4342	 * Allocate Memory for Minidump Template
4343	 */
4344
4345	ha->hw.dma_buf.minidump.alignment = 8;
4346	ha->hw.dma_buf.minidump.size = template_size;
4347
4348#ifdef QL_LDFLASH_FW
4349	if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) {
4350
4351		device_printf(dev, "%s: minidump dma alloc failed\n", __func__);
4352
4353		return (-1);
4354	}
4355	ha->hw.dma_buf.flags.minidump = 1;
4356
4357	/*
4358	 * Retrieve Minidump Template
4359	 */
4360	ret = ql_get_minidump_template(ha);
4361#else
4362	ha->hw.dma_buf.minidump.dma_b = ql83xx_minidump;
4363
4364#endif /* #ifdef QL_LDFLASH_FW */
4365
4366	if (ret == 0) {
4367
4368		ret = ql_validate_minidump_checksum(ha);
4369
4370		if (ret == 0) {
4371
4372			ret = ql_alloc_minidump_buffers(ha);
4373
4374			if (ret == 0)
4375		ha->hw.mdump_init = 1;
4376			else
4377				device_printf(dev,
4378					"%s: ql_alloc_minidump_buffers"
4379					" failed\n", __func__);
4380		} else {
4381			device_printf(dev, "%s: ql_validate_minidump_checksum"
4382				" failed\n", __func__);
4383		}
4384	} else {
4385		device_printf(dev, "%s: ql_get_minidump_template failed\n",
4386			 __func__);
4387	}
4388
4389	if (ret)
4390		ql_minidump_free(ha);
4391
4392	return (ret);
4393}
4394
4395static void
4396ql_minidump_free(qla_host_t *ha)
4397{
4398	ha->hw.mdump_init = 0;
4399	if (ha->hw.dma_buf.flags.minidump) {
4400		ha->hw.dma_buf.flags.minidump = 0;
4401		ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump);
4402	}
4403
4404	ql_free_minidump_template_buffer(ha);
4405	ql_free_minidump_buffer(ha);
4406
4407	return;
4408}
4409
4410void
4411ql_minidump(qla_host_t *ha)
4412{
4413	if (!ha->hw.mdump_init)
4414		return;
4415
4416	if (ha->hw.mdump_done)
4417		return;
4418
4419		ha->hw.mdump_start_seq_index = ql_stop_sequence(ha);
4420
4421	bzero(ha->hw.mdump_buffer, ha->hw.mdump_buffer_size);
4422	bzero(ha->hw.mdump_template, ha->hw.mdump_template_size);
4423
4424	bcopy(ha->hw.dma_buf.minidump.dma_b, ha->hw.mdump_template,
4425		ha->hw.mdump_template_size);
4426
4427	ql_parse_template(ha);
4428
4429	ql_start_sequence(ha, ha->hw.mdump_start_seq_index);
4430
4431	ha->hw.mdump_done = 1;
4432
4433	return;
4434}
4435
4436
4437/*
4438 * helper routines
4439 */
4440static void
4441ql_entry_err_chk(ql_minidump_entry_t *entry, uint32_t esize)
4442{
4443	if (esize != entry->hdr.entry_capture_size) {
4444		entry->hdr.entry_capture_size = esize;
4445		entry->hdr.driver_flags |= QL_DBG_SIZE_ERR_FLAG;
4446	}
4447	return;
4448}
4449
4450
4451static int
4452ql_parse_template(qla_host_t *ha)
4453{
4454	uint32_t num_of_entries, buff_level, e_cnt, esize;
4455	uint32_t end_cnt, rv = 0;
4456	char *dump_buff, *dbuff;
4457	int sane_start = 0, sane_end = 0;
4458	ql_minidump_template_hdr_t *template_hdr;
4459	ql_minidump_entry_t *entry;
4460	uint32_t capture_mask;
4461	uint32_t dump_size;
4462
4463	/* Setup parameters */
4464	template_hdr = (ql_minidump_template_hdr_t *)ha->hw.mdump_template;
4465
4466	if (template_hdr->entry_type == TLHDR)
4467		sane_start = 1;
4468
4469	dump_buff = (char *) ha->hw.mdump_buffer;
4470
4471	num_of_entries = template_hdr->num_of_entries;
4472
4473	entry = (ql_minidump_entry_t *) ((char *)template_hdr
4474			+ template_hdr->first_entry_offset );
4475
4476	template_hdr->saved_state_array[QL_OCM0_ADDR_INDX] =
4477		template_hdr->ocm_window_array[ha->pci_func];
4478	template_hdr->saved_state_array[QL_PCIE_FUNC_INDX] = ha->pci_func;
4479
4480	capture_mask = ha->hw.mdump_capture_mask;
4481	dump_size = ha->hw.mdump_buffer_size;
4482
4483	template_hdr->driver_capture_mask = capture_mask;
4484
4485	QL_DPRINT80(ha, (ha->pci_dev,
4486		"%s: sane_start = %d num_of_entries = %d "
4487		"capture_mask = 0x%x dump_size = %d \n",
4488		__func__, sane_start, num_of_entries, capture_mask, dump_size));
4489
4490	for (buff_level = 0, e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
4491
4492		/*
4493		 * If the capture_mask of the entry does not match capture mask
4494		 * skip the entry after marking the driver_flags indicator.
4495		 */
4496
4497		if (!(entry->hdr.entry_capture_mask & capture_mask)) {
4498
4499			entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4500			entry = (ql_minidump_entry_t *) ((char *) entry
4501					+ entry->hdr.entry_size);
4502			continue;
4503		}
4504
4505		/*
4506		 * This is ONLY needed in implementations where
4507		 * the capture buffer allocated is too small to capture
4508		 * all of the required entries for a given capture mask.
4509		 * We need to empty the buffer contents to a file
4510		 * if possible, before processing the next entry
4511		 * If the buff_full_flag is set, no further capture will happen
4512		 * and all remaining non-control entries will be skipped.
4513		 */
4514		if (entry->hdr.entry_capture_size != 0) {
4515			if ((buff_level + entry->hdr.entry_capture_size) >
4516				dump_size) {
4517				/*  Try to recover by emptying buffer to file */
4518				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4519				entry = (ql_minidump_entry_t *) ((char *) entry
4520						+ entry->hdr.entry_size);
4521				continue;
4522			}
4523		}
4524
4525		/*
4526		 * Decode the entry type and process it accordingly
4527		 */
4528
4529		switch (entry->hdr.entry_type) {
4530		case RDNOP:
4531			break;
4532
4533		case RDEND:
4534			if (sane_end == 0) {
4535				end_cnt = e_cnt;
4536			}
4537			sane_end++;
4538			break;
4539
4540		case RDCRB:
4541			dbuff = dump_buff + buff_level;
4542			esize = ql_rdcrb(ha, (void *)entry, (void *)dbuff);
4543			ql_entry_err_chk(entry, esize);
4544			buff_level += esize;
4545			break;
4546
4547                case POLLRD:
4548                        dbuff = dump_buff + buff_level;
4549                        esize = ql_pollrd(ha, (void *)entry, (void *)dbuff);
4550                        ql_entry_err_chk(entry, esize);
4551                        buff_level += esize;
4552                        break;
4553
4554                case POLLRDMWR:
4555                        dbuff = dump_buff + buff_level;
4556                        esize = ql_pollrd_modify_write(ha, (void *)entry,
4557					(void *)dbuff);
4558                        ql_entry_err_chk(entry, esize);
4559                        buff_level += esize;
4560                        break;
4561
4562		case L2ITG:
4563		case L2DTG:
4564		case L2DAT:
4565		case L2INS:
4566			dbuff = dump_buff + buff_level;
4567			esize = ql_L2Cache(ha, (void *)entry, (void *)dbuff);
4568			if (esize == -1) {
4569				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4570			} else {
4571				ql_entry_err_chk(entry, esize);
4572				buff_level += esize;
4573			}
4574			break;
4575
4576		case L1DAT:
4577		case L1INS:
4578			dbuff = dump_buff + buff_level;
4579			esize = ql_L1Cache(ha, (void *)entry, (void *)dbuff);
4580			ql_entry_err_chk(entry, esize);
4581			buff_level += esize;
4582			break;
4583
4584		case RDOCM:
4585			dbuff = dump_buff + buff_level;
4586			esize = ql_rdocm(ha, (void *)entry, (void *)dbuff);
4587			ql_entry_err_chk(entry, esize);
4588			buff_level += esize;
4589			break;
4590
4591		case RDMEM:
4592			dbuff = dump_buff + buff_level;
4593			esize = ql_rdmem(ha, (void *)entry, (void *)dbuff);
4594			ql_entry_err_chk(entry, esize);
4595			buff_level += esize;
4596			break;
4597
4598		case BOARD:
4599		case RDROM:
4600			dbuff = dump_buff + buff_level;
4601			esize = ql_rdrom(ha, (void *)entry, (void *)dbuff);
4602			ql_entry_err_chk(entry, esize);
4603			buff_level += esize;
4604			break;
4605
4606		case RDMUX:
4607			dbuff = dump_buff + buff_level;
4608			esize = ql_rdmux(ha, (void *)entry, (void *)dbuff);
4609			ql_entry_err_chk(entry, esize);
4610			buff_level += esize;
4611			break;
4612
4613                case RDMUX2:
4614                        dbuff = dump_buff + buff_level;
4615                        esize = ql_rdmux2(ha, (void *)entry, (void *)dbuff);
4616                        ql_entry_err_chk(entry, esize);
4617                        buff_level += esize;
4618                        break;
4619
4620		case QUEUE:
4621			dbuff = dump_buff + buff_level;
4622			esize = ql_rdqueue(ha, (void *)entry, (void *)dbuff);
4623			ql_entry_err_chk(entry, esize);
4624			buff_level += esize;
4625			break;
4626
4627		case CNTRL:
4628			if ((rv = ql_cntrl(ha, template_hdr, (void *)entry))) {
4629				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4630			}
4631			break;
4632		default:
4633			entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4634			break;
4635		}
4636		/*  next entry in the template */
4637		entry = (ql_minidump_entry_t *) ((char *) entry
4638						+ entry->hdr.entry_size);
4639	}
4640
4641	if (!sane_start || (sane_end > 1)) {
4642		device_printf(ha->pci_dev,
4643			"\n%s: Template configuration error. Check Template\n",
4644			__func__);
4645	}
4646
4647	QL_DPRINT80(ha, (ha->pci_dev, "%s: Minidump num of entries = %d\n",
4648		__func__, template_hdr->num_of_entries));
4649
4650	return 0;
4651}
4652
4653/*
4654 * Read CRB operation.
4655 */
4656static uint32_t
4657ql_rdcrb(qla_host_t *ha, ql_minidump_entry_rdcrb_t * crb_entry,
4658	uint32_t * data_buff)
4659{
4660	int loop_cnt;
4661	int ret;
4662	uint32_t op_count, addr, stride, value = 0;
4663
4664	addr = crb_entry->addr;
4665	op_count = crb_entry->op_count;
4666	stride = crb_entry->addr_stride;
4667
4668	for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
4669
4670		ret = ql_rdwr_indreg32(ha, addr, &value, 1);
4671
4672		if (ret)
4673			return (0);
4674
4675		*data_buff++ = addr;
4676		*data_buff++ = value;
4677		addr = addr + stride;
4678	}
4679
4680	/*
4681	 * for testing purpose we return amount of data written
4682	 */
4683	return (op_count * (2 * sizeof(uint32_t)));
4684}
4685
4686/*
4687 * Handle L2 Cache.
4688 */
4689
4690static uint32_t
4691ql_L2Cache(qla_host_t *ha, ql_minidump_entry_cache_t *cacheEntry,
4692	uint32_t * data_buff)
4693{
4694	int i, k;
4695	int loop_cnt;
4696	int ret;
4697
4698	uint32_t read_value;
4699	uint32_t addr, read_addr, cntrl_addr, tag_reg_addr, cntl_value_w;
4700	uint32_t tag_value, read_cnt;
4701	volatile uint8_t cntl_value_r;
4702	long timeout;
4703	uint32_t data;
4704
4705	loop_cnt = cacheEntry->op_count;
4706
4707	read_addr = cacheEntry->read_addr;
4708	cntrl_addr = cacheEntry->control_addr;
4709	cntl_value_w = (uint32_t) cacheEntry->write_value;
4710
4711	tag_reg_addr = cacheEntry->tag_reg_addr;
4712
4713	tag_value = cacheEntry->init_tag_value;
4714	read_cnt = cacheEntry->read_addr_cnt;
4715
4716	for (i = 0; i < loop_cnt; i++) {
4717
4718		ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
4719		if (ret)
4720			return (0);
4721
4722		if (cacheEntry->write_value != 0) {
4723
4724			ret = ql_rdwr_indreg32(ha, cntrl_addr,
4725					&cntl_value_w, 0);
4726			if (ret)
4727				return (0);
4728		}
4729
4730		if (cacheEntry->poll_mask != 0) {
4731
4732			timeout = cacheEntry->poll_wait;
4733
4734			ret = ql_rdwr_indreg32(ha, cntrl_addr, &data, 1);
4735			if (ret)
4736				return (0);
4737
4738			cntl_value_r = (uint8_t)data;
4739
4740			while ((cntl_value_r & cacheEntry->poll_mask) != 0) {
4741
4742				if (timeout) {
4743					qla_mdelay(__func__, 1);
4744					timeout--;
4745				} else
4746					break;
4747
4748				ret = ql_rdwr_indreg32(ha, cntrl_addr,
4749						&data, 1);
4750				if (ret)
4751					return (0);
4752
4753				cntl_value_r = (uint8_t)data;
4754			}
4755			if (!timeout) {
4756				/* Report timeout error.
4757				 * core dump capture failed
4758				 * Skip remaining entries.
4759				 * Write buffer out to file
4760				 * Use driver specific fields in template header
4761				 * to report this error.
4762				 */
4763				return (-1);
4764			}
4765		}
4766
4767		addr = read_addr;
4768		for (k = 0; k < read_cnt; k++) {
4769
4770			ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
4771			if (ret)
4772				return (0);
4773
4774			*data_buff++ = read_value;
4775			addr += cacheEntry->read_addr_stride;
4776		}
4777
4778		tag_value += cacheEntry->tag_value_stride;
4779	}
4780
4781	return (read_cnt * loop_cnt * sizeof(uint32_t));
4782}
4783
4784/*
4785 * Handle L1 Cache.
4786 */
4787
4788static uint32_t
4789ql_L1Cache(qla_host_t *ha,
4790	ql_minidump_entry_cache_t *cacheEntry,
4791	uint32_t *data_buff)
4792{
4793	int ret;
4794	int i, k;
4795	int loop_cnt;
4796
4797	uint32_t read_value;
4798	uint32_t addr, read_addr, cntrl_addr, tag_reg_addr;
4799	uint32_t tag_value, read_cnt;
4800	uint32_t cntl_value_w;
4801
4802	loop_cnt = cacheEntry->op_count;
4803
4804	read_addr = cacheEntry->read_addr;
4805	cntrl_addr = cacheEntry->control_addr;
4806	cntl_value_w = (uint32_t) cacheEntry->write_value;
4807
4808	tag_reg_addr = cacheEntry->tag_reg_addr;
4809
4810	tag_value = cacheEntry->init_tag_value;
4811	read_cnt = cacheEntry->read_addr_cnt;
4812
4813	for (i = 0; i < loop_cnt; i++) {
4814
4815		ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
4816		if (ret)
4817			return (0);
4818
4819		ret = ql_rdwr_indreg32(ha, cntrl_addr, &cntl_value_w, 0);
4820		if (ret)
4821			return (0);
4822
4823		addr = read_addr;
4824		for (k = 0; k < read_cnt; k++) {
4825
4826			ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
4827			if (ret)
4828				return (0);
4829
4830			*data_buff++ = read_value;
4831			addr += cacheEntry->read_addr_stride;
4832		}
4833
4834		tag_value += cacheEntry->tag_value_stride;
4835	}
4836
4837	return (read_cnt * loop_cnt * sizeof(uint32_t));
4838}
4839
4840/*
4841 * Reading OCM memory
4842 */
4843
4844static uint32_t
4845ql_rdocm(qla_host_t *ha,
4846	ql_minidump_entry_rdocm_t *ocmEntry,
4847	uint32_t *data_buff)
4848{
4849	int i, loop_cnt;
4850	volatile uint32_t addr;
4851	volatile uint32_t value;
4852
4853	addr = ocmEntry->read_addr;
4854	loop_cnt = ocmEntry->op_count;
4855
4856	for (i = 0; i < loop_cnt; i++) {
4857		value = READ_REG32(ha, addr);
4858		*data_buff++ = value;
4859		addr += ocmEntry->read_addr_stride;
4860	}
4861	return (loop_cnt * sizeof(value));
4862}
4863
4864/*
4865 * Read memory
4866 */
4867
4868static uint32_t
4869ql_rdmem(qla_host_t *ha,
4870	ql_minidump_entry_rdmem_t *mem_entry,
4871	uint32_t *data_buff)
4872{
4873	int ret;
4874        int i, loop_cnt;
4875        volatile uint32_t addr;
4876	q80_offchip_mem_val_t val;
4877
4878        addr = mem_entry->read_addr;
4879
4880	/* size in bytes / 16 */
4881        loop_cnt = mem_entry->read_data_size / (sizeof(uint32_t) * 4);
4882
4883        for (i = 0; i < loop_cnt; i++) {
4884
4885		ret = ql_rdwr_offchip_mem(ha, (addr & 0x0ffffffff), &val, 1);
4886		if (ret)
4887			return (0);
4888
4889                *data_buff++ = val.data_lo;
4890                *data_buff++ = val.data_hi;
4891                *data_buff++ = val.data_ulo;
4892                *data_buff++ = val.data_uhi;
4893
4894                addr += (sizeof(uint32_t) * 4);
4895        }
4896
4897        return (loop_cnt * (sizeof(uint32_t) * 4));
4898}
4899
4900/*
4901 * Read Rom
4902 */
4903
4904static uint32_t
4905ql_rdrom(qla_host_t *ha,
4906	ql_minidump_entry_rdrom_t *romEntry,
4907	uint32_t *data_buff)
4908{
4909	int ret;
4910	int i, loop_cnt;
4911	uint32_t addr;
4912	uint32_t value;
4913
4914	addr = romEntry->read_addr;
4915	loop_cnt = romEntry->read_data_size; /* This is size in bytes */
4916	loop_cnt /= sizeof(value);
4917
4918	for (i = 0; i < loop_cnt; i++) {
4919
4920		ret = ql_rd_flash32(ha, addr, &value);
4921		if (ret)
4922			return (0);
4923
4924		*data_buff++ = value;
4925		addr += sizeof(value);
4926	}
4927
4928	return (loop_cnt * sizeof(value));
4929}
4930
4931/*
4932 * Read MUX data
4933 */
4934
4935static uint32_t
4936ql_rdmux(qla_host_t *ha,
4937	ql_minidump_entry_mux_t *muxEntry,
4938	uint32_t *data_buff)
4939{
4940	int ret;
4941	int loop_cnt;
4942	uint32_t read_value, sel_value;
4943	uint32_t read_addr, select_addr;
4944
4945	select_addr = muxEntry->select_addr;
4946	sel_value = muxEntry->select_value;
4947	read_addr = muxEntry->read_addr;
4948
4949	for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {
4950
4951		ret = ql_rdwr_indreg32(ha, select_addr, &sel_value, 0);
4952		if (ret)
4953			return (0);
4954
4955		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
4956		if (ret)
4957			return (0);
4958
4959		*data_buff++ = sel_value;
4960		*data_buff++ = read_value;
4961
4962		sel_value += muxEntry->select_value_stride;
4963	}
4964
4965	return (loop_cnt * (2 * sizeof(uint32_t)));
4966}
4967
4968static uint32_t
4969ql_rdmux2(qla_host_t *ha,
4970	ql_minidump_entry_mux2_t *muxEntry,
4971	uint32_t *data_buff)
4972{
4973	int ret;
4974        int loop_cnt;
4975
4976        uint32_t select_addr_1, select_addr_2;
4977        uint32_t select_value_1, select_value_2;
4978        uint32_t select_value_count, select_value_mask;
4979        uint32_t read_addr, read_value;
4980
4981        select_addr_1 = muxEntry->select_addr_1;
4982        select_addr_2 = muxEntry->select_addr_2;
4983        select_value_1 = muxEntry->select_value_1;
4984        select_value_2 = muxEntry->select_value_2;
4985        select_value_count = muxEntry->select_value_count;
4986        select_value_mask  = muxEntry->select_value_mask;
4987
4988        read_addr = muxEntry->read_addr;
4989
4990        for (loop_cnt = 0; loop_cnt < muxEntry->select_value_count;
4991		loop_cnt++) {
4992
4993                uint32_t temp_sel_val;
4994
4995		ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_1, 0);
4996		if (ret)
4997			return (0);
4998
4999                temp_sel_val = select_value_1 & select_value_mask;
5000
5001		ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
5002		if (ret)
5003			return (0);
5004
5005		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
5006		if (ret)
5007			return (0);
5008
5009                *data_buff++ = temp_sel_val;
5010                *data_buff++ = read_value;
5011
5012		ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_2, 0);
5013		if (ret)
5014			return (0);
5015
5016                temp_sel_val = select_value_2 & select_value_mask;
5017
5018		ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
5019		if (ret)
5020			return (0);
5021
5022		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
5023		if (ret)
5024			return (0);
5025
5026                *data_buff++ = temp_sel_val;
5027                *data_buff++ = read_value;
5028
5029                select_value_1 += muxEntry->select_value_stride;
5030                select_value_2 += muxEntry->select_value_stride;
5031        }
5032
5033        return (loop_cnt * (4 * sizeof(uint32_t)));
5034}
5035
5036/*
5037 * Handling Queue State Reads.
5038 */
5039
5040static uint32_t
5041ql_rdqueue(qla_host_t *ha,
5042	ql_minidump_entry_queue_t *queueEntry,
5043	uint32_t *data_buff)
5044{
5045	int ret;
5046	int loop_cnt, k;
5047	uint32_t read_value;
5048	uint32_t read_addr, read_stride, select_addr;
5049	uint32_t queue_id, read_cnt;
5050
5051	read_cnt = queueEntry->read_addr_cnt;
5052	read_stride = queueEntry->read_addr_stride;
5053	select_addr = queueEntry->select_addr;
5054
5055	for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;
5056		loop_cnt++) {
5057
5058		ret = ql_rdwr_indreg32(ha, select_addr, &queue_id, 0);
5059		if (ret)
5060			return (0);
5061
5062		read_addr = queueEntry->read_addr;
5063
5064		for (k = 0; k < read_cnt; k++) {
5065
5066			ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
5067			if (ret)
5068				return (0);
5069
5070			*data_buff++ = read_value;
5071			read_addr += read_stride;
5072		}
5073
5074		queue_id += queueEntry->queue_id_stride;
5075	}
5076
5077	return (loop_cnt * (read_cnt * sizeof(uint32_t)));
5078}
5079
5080/*
5081 * Handling control entries.
5082 */
5083
5084static uint32_t
5085ql_cntrl(qla_host_t *ha,
5086	ql_minidump_template_hdr_t *template_hdr,
5087	ql_minidump_entry_cntrl_t *crbEntry)
5088{
5089	int ret;
5090	int count;
5091	uint32_t opcode, read_value, addr, entry_addr;
5092	long timeout;
5093
5094	entry_addr = crbEntry->addr;
5095
5096	for (count = 0; count < crbEntry->op_count; count++) {
5097		opcode = crbEntry->opcode;
5098
5099		if (opcode & QL_DBG_OPCODE_WR) {
5100
5101                	ret = ql_rdwr_indreg32(ha, entry_addr,
5102					&crbEntry->value_1, 0);
5103			if (ret)
5104				return (0);
5105
5106			opcode &= ~QL_DBG_OPCODE_WR;
5107		}
5108
5109		if (opcode & QL_DBG_OPCODE_RW) {
5110
5111                	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
5112			if (ret)
5113				return (0);
5114
5115                	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
5116			if (ret)
5117				return (0);
5118
5119			opcode &= ~QL_DBG_OPCODE_RW;
5120		}
5121
5122		if (opcode & QL_DBG_OPCODE_AND) {
5123
5124                	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
5125			if (ret)
5126				return (0);
5127
5128			read_value &= crbEntry->value_2;
5129			opcode &= ~QL_DBG_OPCODE_AND;
5130
5131			if (opcode & QL_DBG_OPCODE_OR) {
5132				read_value |= crbEntry->value_3;
5133				opcode &= ~QL_DBG_OPCODE_OR;
5134			}
5135
5136                	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
5137			if (ret)
5138				return (0);
5139		}
5140
5141		if (opcode & QL_DBG_OPCODE_OR) {
5142
5143                	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
5144			if (ret)
5145				return (0);
5146
5147			read_value |= crbEntry->value_3;
5148
5149                	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
5150			if (ret)
5151				return (0);
5152
5153			opcode &= ~QL_DBG_OPCODE_OR;
5154		}
5155
5156		if (opcode & QL_DBG_OPCODE_POLL) {
5157
5158			opcode &= ~QL_DBG_OPCODE_POLL;
5159			timeout = crbEntry->poll_timeout;
5160			addr = entry_addr;
5161
5162                	ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
5163			if (ret)
5164				return (0);
5165
5166			while ((read_value & crbEntry->value_2)
5167				!= crbEntry->value_1) {
5168
5169				if (timeout) {
5170					qla_mdelay(__func__, 1);
5171					timeout--;
5172				} else
5173					break;
5174
5175                		ret = ql_rdwr_indreg32(ha, addr,
5176						&read_value, 1);
5177				if (ret)
5178					return (0);
5179			}
5180
5181			if (!timeout) {
5182				/*
5183				 * Report timeout error.
5184				 * core dump capture failed
5185				 * Skip remaining entries.
5186				 * Write buffer out to file
5187				 * Use driver specific fields in template header
5188				 * to report this error.
5189				 */
5190				return (-1);
5191			}
5192		}
5193
5194		if (opcode & QL_DBG_OPCODE_RDSTATE) {
5195			/*
5196			 * decide which address to use.
5197			 */
5198			if (crbEntry->state_index_a) {
5199				addr = template_hdr->saved_state_array[
5200						crbEntry-> state_index_a];
5201			} else {
5202				addr = entry_addr;
5203			}
5204
5205                	ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
5206			if (ret)
5207				return (0);
5208
5209			template_hdr->saved_state_array[crbEntry->state_index_v]
5210					= read_value;
5211			opcode &= ~QL_DBG_OPCODE_RDSTATE;
5212		}
5213
5214		if (opcode & QL_DBG_OPCODE_WRSTATE) {
5215			/*
5216			 * decide which value to use.
5217			 */
5218			if (crbEntry->state_index_v) {
5219				read_value = template_hdr->saved_state_array[
5220						crbEntry->state_index_v];
5221			} else {
5222				read_value = crbEntry->value_1;
5223			}
5224			/*
5225			 * decide which address to use.
5226			 */
5227			if (crbEntry->state_index_a) {
5228				addr = template_hdr->saved_state_array[
5229						crbEntry-> state_index_a];
5230			} else {
5231				addr = entry_addr;
5232			}
5233
5234                	ret = ql_rdwr_indreg32(ha, addr, &read_value, 0);
5235			if (ret)
5236				return (0);
5237
5238			opcode &= ~QL_DBG_OPCODE_WRSTATE;
5239		}
5240
5241		if (opcode & QL_DBG_OPCODE_MDSTATE) {
5242			/*  Read value from saved state using index */
5243			read_value = template_hdr->saved_state_array[
5244						crbEntry->state_index_v];
5245
5246			read_value <<= crbEntry->shl; /*Shift left operation */
5247			read_value >>= crbEntry->shr; /*Shift right operation */
5248
5249			if (crbEntry->value_2) {
5250				/* check if AND mask is provided */
5251				read_value &= crbEntry->value_2;
5252			}
5253
5254			read_value |= crbEntry->value_3; /* OR operation */
5255			read_value += crbEntry->value_1; /* increment op */
5256
5257			/* Write value back to state area. */
5258
5259			template_hdr->saved_state_array[crbEntry->state_index_v]
5260					= read_value;
5261			opcode &= ~QL_DBG_OPCODE_MDSTATE;
5262		}
5263
5264		entry_addr += crbEntry->addr_stride;
5265	}
5266
5267	return (0);
5268}
5269
5270/*
5271 * Handling rd poll entry.
5272 */
5273
5274static uint32_t
5275ql_pollrd(qla_host_t *ha, ql_minidump_entry_pollrd_t *entry,
5276	uint32_t *data_buff)
5277{
5278        int ret;
5279        int loop_cnt;
5280        uint32_t op_count, select_addr, select_value_stride, select_value;
5281        uint32_t read_addr, poll, mask, data_size, data;
5282        uint32_t wait_count = 0;
5283
5284        select_addr            = entry->select_addr;
5285        read_addr              = entry->read_addr;
5286        select_value           = entry->select_value;
5287        select_value_stride    = entry->select_value_stride;
5288        op_count               = entry->op_count;
5289        poll                   = entry->poll;
5290        mask                   = entry->mask;
5291        data_size              = entry->data_size;
5292
5293        for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
5294
5295                ret = ql_rdwr_indreg32(ha, select_addr, &select_value, 0);
5296		if (ret)
5297			return (0);
5298
5299                wait_count = 0;
5300
5301                while (wait_count < poll) {
5302
5303                        uint32_t temp;
5304
5305			ret = ql_rdwr_indreg32(ha, select_addr, &temp, 1);
5306			if (ret)
5307				return (0);
5308
5309                        if ( (temp & mask) != 0 ) {
5310                                break;
5311                        }
5312                        wait_count++;
5313                }
5314
5315                if (wait_count == poll) {
5316                        device_printf(ha->pci_dev,
5317				"%s: Error in processing entry\n", __func__);
5318                        device_printf(ha->pci_dev,
5319				"%s: wait_count <0x%x> poll <0x%x>\n",
5320				__func__, wait_count, poll);
5321                        return 0;
5322                }
5323
5324		ret = ql_rdwr_indreg32(ha, read_addr, &data, 1);
5325		if (ret)
5326			return (0);
5327
5328                *data_buff++ = select_value;
5329                *data_buff++ = data;
5330                select_value = select_value + select_value_stride;
5331        }
5332
5333        /*
5334         * for testing purpose we return amount of data written
5335         */
5336        return (loop_cnt * (2 * sizeof(uint32_t)));
5337}
5338
5339
5340/*
5341 * Handling rd modify write poll entry.
5342 */
5343
5344static uint32_t
5345ql_pollrd_modify_write(qla_host_t *ha,
5346	ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
5347	uint32_t *data_buff)
5348{
5349	int ret;
5350        uint32_t addr_1, addr_2, value_1, value_2, data;
5351        uint32_t poll, mask, data_size, modify_mask;
5352        uint32_t wait_count = 0;
5353
5354        addr_1		= entry->addr_1;
5355        addr_2		= entry->addr_2;
5356        value_1		= entry->value_1;
5357        value_2		= entry->value_2;
5358
5359        poll		= entry->poll;
5360        mask		= entry->mask;
5361        modify_mask	= entry->modify_mask;
5362        data_size	= entry->data_size;
5363
5364
5365	ret = ql_rdwr_indreg32(ha, addr_1, &value_1, 0);
5366	if (ret)
5367		return (0);
5368
5369        wait_count = 0;
5370        while (wait_count < poll) {
5371
5372		uint32_t temp;
5373
5374		ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
5375		if (ret)
5376			return (0);
5377
5378                if ( (temp & mask) != 0 ) {
5379                        break;
5380                }
5381                wait_count++;
5382        }
5383
5384        if (wait_count == poll) {
5385                device_printf(ha->pci_dev, "%s Error in processing entry\n",
5386			__func__);
5387        } else {
5388
5389		ret = ql_rdwr_indreg32(ha, addr_2, &data, 1);
5390		if (ret)
5391			return (0);
5392
5393                data = (data & modify_mask);
5394
5395		ret = ql_rdwr_indreg32(ha, addr_2, &data, 0);
5396		if (ret)
5397			return (0);
5398
5399		ret = ql_rdwr_indreg32(ha, addr_1, &value_2, 0);
5400		if (ret)
5401			return (0);
5402
5403                /* Poll again */
5404                wait_count = 0;
5405                while (wait_count < poll) {
5406
5407                        uint32_t temp;
5408
5409			ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
5410			if (ret)
5411				return (0);
5412
5413                        if ( (temp & mask) != 0 ) {
5414                                break;
5415                        }
5416                        wait_count++;
5417                }
5418                *data_buff++ = addr_2;
5419                *data_buff++ = data;
5420        }
5421
5422        /*
5423         * for testing purpose we return amount of data written
5424         */
5425        return (2 * sizeof(uint32_t));
5426}
5427
5428
5429