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