FreeBSD/Linux Kernel Cross Reference
sys/dev/qlxge/qls_hw.c
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2013-2014 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: qls_hw.c
32 * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
33 * Content: Contains Hardware dependent functions
34 */
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include "qls_os.h"
39 #include "qls_hw.h"
40 #include "qls_def.h"
41 #include "qls_inline.h"
42 #include "qls_ver.h"
43 #include "qls_glbl.h"
44 #include "qls_dbg.h"
45
46 /*
47 * Static Functions
48 */
49 static int qls_wait_for_mac_proto_idx_ready(qla_host_t *ha, uint32_t op);
50 static int qls_config_unicast_mac_addr(qla_host_t *ha, uint32_t add_mac);
51 static int qls_config_mcast_mac_addr(qla_host_t *ha, uint8_t *mac_addr,
52 uint32_t add_mac, uint32_t index);
53
54 static int qls_init_rss(qla_host_t *ha);
55 static int qls_init_comp_queue(qla_host_t *ha, int cid);
56 static int qls_init_work_queue(qla_host_t *ha, int wid);
57 static int qls_init_fw_routing_table(qla_host_t *ha);
58 static int qls_hw_add_all_mcast(qla_host_t *ha);
59 static int qls_hw_add_mcast(qla_host_t *ha, uint8_t *mta);
60 static int qls_hw_del_mcast(qla_host_t *ha, uint8_t *mta);
61 static int qls_wait_for_flash_ready(qla_host_t *ha);
62
63 static int qls_sem_lock(qla_host_t *ha, uint32_t mask, uint32_t value);
64 static void qls_sem_unlock(qla_host_t *ha, uint32_t mask);
65
66 static void qls_free_tx_dma(qla_host_t *ha);
67 static int qls_alloc_tx_dma(qla_host_t *ha);
68 static void qls_free_rx_dma(qla_host_t *ha);
69 static int qls_alloc_rx_dma(qla_host_t *ha);
70 static void qls_free_mpi_dma(qla_host_t *ha);
71 static int qls_alloc_mpi_dma(qla_host_t *ha);
72 static void qls_free_rss_dma(qla_host_t *ha);
73 static int qls_alloc_rss_dma(qla_host_t *ha);
74
75 static int qls_flash_validate(qla_host_t *ha, const char *signature);
76
77 static int qls_wait_for_proc_addr_ready(qla_host_t *ha);
78 static int qls_proc_addr_rd_reg(qla_host_t *ha, uint32_t addr_module,
79 uint32_t reg, uint32_t *data);
80 static int qls_proc_addr_wr_reg(qla_host_t *ha, uint32_t addr_module,
81 uint32_t reg, uint32_t data);
82
83 static int qls_hw_reset(qla_host_t *ha);
84
85 /*
86 * MPI Related Functions
87 */
88 static int qls_mbx_cmd(qla_host_t *ha, uint32_t *in_mbx, uint32_t i_count,
89 uint32_t *out_mbx, uint32_t o_count);
90 static int qls_mbx_set_mgmt_ctrl(qla_host_t *ha, uint32_t t_ctrl);
91 static int qls_mbx_get_mgmt_ctrl(qla_host_t *ha, uint32_t *t_status);
92 static void qls_mbx_get_link_status(qla_host_t *ha);
93 static void qls_mbx_about_fw(qla_host_t *ha);
94
95 int
96 qls_get_msix_count(qla_host_t *ha)
97 {
98 return (ha->num_rx_rings);
99 }
100
101 static int
102 qls_syctl_mpi_dump(SYSCTL_HANDLER_ARGS)
103 {
104 int err = 0, ret;
105 qla_host_t *ha;
106
107 err = sysctl_handle_int(oidp, &ret, 0, req);
108
109 if (err || !req->newptr)
110 return (err);
111
112 if (ret == 1) {
113 ha = (qla_host_t *)arg1;
114 qls_mpi_core_dump(ha);
115 }
116 return (err);
117 }
118
119 static int
120 qls_syctl_link_status(SYSCTL_HANDLER_ARGS)
121 {
122 int err = 0, ret;
123 qla_host_t *ha;
124
125 err = sysctl_handle_int(oidp, &ret, 0, req);
126
127 if (err || !req->newptr)
128 return (err);
129
130 if (ret == 1) {
131 ha = (qla_host_t *)arg1;
132 qls_mbx_get_link_status(ha);
133 qls_mbx_about_fw(ha);
134 }
135 return (err);
136 }
137
138 void
139 qls_hw_add_sysctls(qla_host_t *ha)
140 {
141 device_t dev;
142
143 dev = ha->pci_dev;
144
145 ha->num_rx_rings = MAX_RX_RINGS; ha->num_tx_rings = MAX_TX_RINGS;
146
147 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
148 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
149 OID_AUTO, "num_rx_rings", CTLFLAG_RD, &ha->num_rx_rings,
150 ha->num_rx_rings, "Number of Completion Queues");
151
152 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
153 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
154 OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->num_tx_rings,
155 ha->num_tx_rings, "Number of Transmit Rings");
156
157 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
158 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
159 OID_AUTO, "mpi_dump",
160 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, (void *)ha, 0,
161 qls_syctl_mpi_dump, "I", "MPI Dump");
162
163 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
164 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
165 OID_AUTO, "link_status",
166 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, (void *)ha, 0,
167 qls_syctl_link_status, "I", "Link Status");
168 }
169
170 /*
171 * Name: qls_free_dma
172 * Function: Frees the DMA'able memory allocated in qls_alloc_dma()
173 */
174 void
175 qls_free_dma(qla_host_t *ha)
176 {
177 qls_free_rss_dma(ha);
178 qls_free_mpi_dma(ha);
179 qls_free_tx_dma(ha);
180 qls_free_rx_dma(ha);
181 return;
182 }
183
184 /*
185 * Name: qls_alloc_dma
186 * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts.
187 */
188 int
189 qls_alloc_dma(qla_host_t *ha)
190 {
191 if (qls_alloc_rx_dma(ha))
192 return (-1);
193
194 if (qls_alloc_tx_dma(ha)) {
195 qls_free_rx_dma(ha);
196 return (-1);
197 }
198
199 if (qls_alloc_mpi_dma(ha)) {
200 qls_free_tx_dma(ha);
201 qls_free_rx_dma(ha);
202 return (-1);
203 }
204
205 if (qls_alloc_rss_dma(ha)) {
206 qls_free_mpi_dma(ha);
207 qls_free_tx_dma(ha);
208 qls_free_rx_dma(ha);
209 return (-1);
210 }
211
212 return (0);
213 }
214
215 static int
216 qls_wait_for_mac_proto_idx_ready(qla_host_t *ha, uint32_t op)
217 {
218 uint32_t data32;
219 uint32_t count = 3;
220
221 while (count--) {
222 data32 = READ_REG32(ha, Q81_CTL_MAC_PROTO_ADDR_INDEX);
223
224 if (data32 & op)
225 return (0);
226
227 QLA_USEC_DELAY(100);
228 }
229 ha->qla_initiate_recovery = 1;
230 return (-1);
231 }
232
233 /*
234 * Name: qls_config_unicast_mac_addr
235 * Function: binds/unbinds a unicast MAC address to the interface.
236 */
237 static int
238 qls_config_unicast_mac_addr(qla_host_t *ha, uint32_t add_mac)
239 {
240 int ret = 0;
241 uint32_t mac_upper = 0;
242 uint32_t mac_lower = 0;
243 uint32_t value = 0, index;
244
245 if (qls_sem_lock(ha, Q81_CTL_SEM_MASK_MAC_SERDES,
246 Q81_CTL_SEM_SET_MAC_SERDES)) {
247 QL_DPRINT1((ha->pci_dev, "%s: semlock failed\n", __func__));
248 return(-1);
249 }
250
251 if (add_mac) {
252 mac_upper = (ha->mac_addr[0] << 8) | ha->mac_addr[1];
253 mac_lower = (ha->mac_addr[2] << 24) | (ha->mac_addr[3] << 16) |
254 (ha->mac_addr[4] << 8) | ha->mac_addr[5];
255 }
256 ret = qls_wait_for_mac_proto_idx_ready(ha, Q81_CTL_MAC_PROTO_AI_MW);
257 if (ret)
258 goto qls_config_unicast_mac_addr_exit;
259
260 index = 128 * (ha->pci_func & 0x1); /* index */
261
262 value = (index << Q81_CTL_MAC_PROTO_AI_IDX_SHIFT) |
263 Q81_CTL_MAC_PROTO_AI_TYPE_CAM_MAC;
264
265 WRITE_REG32(ha, Q81_CTL_MAC_PROTO_ADDR_INDEX, value);
266 WRITE_REG32(ha, Q81_CTL_MAC_PROTO_ADDR_DATA, mac_lower);
267
268 ret = qls_wait_for_mac_proto_idx_ready(ha, Q81_CTL_MAC_PROTO_AI_MW);
269 if (ret)
270 goto qls_config_unicast_mac_addr_exit;
271
272 value = (index << Q81_CTL_MAC_PROTO_AI_IDX_SHIFT) |
273 Q81_CTL_MAC_PROTO_AI_TYPE_CAM_MAC | 0x1;
274
275 WRITE_REG32(ha, Q81_CTL_MAC_PROTO_ADDR_INDEX, value);
276 WRITE_REG32(ha, Q81_CTL_MAC_PROTO_ADDR_DATA, mac_upper);
277
278 ret = qls_wait_for_mac_proto_idx_ready(ha, Q81_CTL_MAC_PROTO_AI_MW);
279 if (ret)
280 goto qls_config_unicast_mac_addr_exit;
281
282 value = (index << Q81_CTL_MAC_PROTO_AI_IDX_SHIFT) |
283 Q81_CTL_MAC_PROTO_AI_TYPE_CAM_MAC | 0x2;
284
285 WRITE_REG32(ha, Q81_CTL_MAC_PROTO_ADDR_INDEX, value);
286
287 value = Q81_CAM_MAC_OFF2_ROUTE_NIC |
288 ((ha->pci_func & 0x1) << Q81_CAM_MAC_OFF2_FUNC_SHIFT) |
289 (0 << Q81_CAM_MAC_OFF2_CQID_SHIFT);
290
291 WRITE_REG32(ha, Q81_CTL_MAC_PROTO_ADDR_DATA, value);
292
293 qls_config_unicast_mac_addr_exit:
294 qls_sem_unlock(ha, Q81_CTL_SEM_MASK_MAC_SERDES);
295 return (ret);
296 }
297
298 /*
299 * Name: qls_config_mcast_mac_addr
300 * Function: binds/unbinds a multicast MAC address to the interface.
301 */
302 static int
303 qls_config_mcast_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac,
304 uint32_t index)
305 {
306 int ret = 0;
307 uint32_t mac_upper = 0;
308 uint32_t mac_lower = 0;
309 uint32_t value = 0;
310
311 if (qls_sem_lock(ha, Q81_CTL_SEM_MASK_MAC_SERDES,
312 Q81_CTL_SEM_SET_MAC_SERDES)) {
313 QL_DPRINT1((ha->pci_dev, "%s: semlock failed\n", __func__));
314 return(-1);
315 }
316
317 if (add_mac) {
318 mac_upper = (mac_addr[0] << 8) | mac_addr[1];
319 mac_lower = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
320 (mac_addr[4] << 8) | mac_addr[5];
321 }
322 ret = qls_wait_for_mac_proto_idx_ready(ha, Q81_CTL_MAC_PROTO_AI_MW);
323 if (ret)
324 goto qls_config_mcast_mac_addr_exit;
325
326 value = Q81_CTL_MAC_PROTO_AI_E |
327 (index << Q81_CTL_MAC_PROTO_AI_IDX_SHIFT) |
328 Q81_CTL_MAC_PROTO_AI_TYPE_MCAST ;
329
330 WRITE_REG32(ha, Q81_CTL_MAC_PROTO_ADDR_INDEX, value);
331 WRITE_REG32(ha, Q81_CTL_MAC_PROTO_ADDR_DATA, mac_lower);
332
333 ret = qls_wait_for_mac_proto_idx_ready(ha, Q81_CTL_MAC_PROTO_AI_MW);
334 if (ret)
335 goto qls_config_mcast_mac_addr_exit;
336
337 value = Q81_CTL_MAC_PROTO_AI_E |
338 (index << Q81_CTL_MAC_PROTO_AI_IDX_SHIFT) |
339 Q81_CTL_MAC_PROTO_AI_TYPE_MCAST | 0x1;
340
341 WRITE_REG32(ha, Q81_CTL_MAC_PROTO_ADDR_INDEX, value);
342 WRITE_REG32(ha, Q81_CTL_MAC_PROTO_ADDR_DATA, mac_upper);
343
344 qls_config_mcast_mac_addr_exit:
345 qls_sem_unlock(ha, Q81_CTL_SEM_MASK_MAC_SERDES);
346
347 return (ret);
348 }
349
350 /*
351 * Name: qls_set_mac_rcv_mode
352 * Function: Enable/Disable AllMulticast and Promiscuous Modes.
353 */
354 static int
355 qls_wait_for_route_idx_ready(qla_host_t *ha, uint32_t op)
356 {
357 uint32_t data32;
358 uint32_t count = 3;
359
360 while (count--) {
361 data32 = READ_REG32(ha, Q81_CTL_ROUTING_INDEX);
362
363 if (data32 & op)
364 return (0);
365
366 QLA_USEC_DELAY(100);
367 }
368 ha->qla_initiate_recovery = 1;
369 return (-1);
370 }
371
372 static int
373 qls_load_route_idx_reg(qla_host_t *ha, uint32_t index, uint32_t data)
374 {
375 int ret = 0;
376
377 ret = qls_wait_for_route_idx_ready(ha, Q81_CTL_RI_MW);
378
379 if (ret) {
380 device_printf(ha->pci_dev, "%s: [0x%08x, 0x%08x] failed\n",
381 __func__, index, data);
382 goto qls_load_route_idx_reg_exit;
383 }
384
385 WRITE_REG32(ha, Q81_CTL_ROUTING_INDEX, index);
386 WRITE_REG32(ha, Q81_CTL_ROUTING_DATA, data);
387
388 qls_load_route_idx_reg_exit:
389 return (ret);
390 }
391
392 static int
393 qls_load_route_idx_reg_locked(qla_host_t *ha, uint32_t index, uint32_t data)
394 {
395 int ret = 0;
396
397 if (qls_sem_lock(ha, Q81_CTL_SEM_MASK_RIDX_DATAREG,
398 Q81_CTL_SEM_SET_RIDX_DATAREG)) {
399 QL_DPRINT1((ha->pci_dev, "%s: semlock failed\n", __func__));
400 return(-1);
401 }
402
403 ret = qls_load_route_idx_reg(ha, index, data);
404
405 qls_sem_unlock(ha, Q81_CTL_SEM_MASK_RIDX_DATAREG);
406
407 return (ret);
408 }
409
410 static int
411 qls_clear_routing_table(qla_host_t *ha)
412 {
413 int i, ret = 0;
414
415 if (qls_sem_lock(ha, Q81_CTL_SEM_MASK_RIDX_DATAREG,
416 Q81_CTL_SEM_SET_RIDX_DATAREG)) {
417 QL_DPRINT1((ha->pci_dev, "%s: semlock failed\n", __func__));
418 return(-1);
419 }
420
421 for (i = 0; i < 16; i++) {
422 ret = qls_load_route_idx_reg(ha, (Q81_CTL_RI_TYPE_NICQMASK|
423 (i << 8) | Q81_CTL_RI_DST_DFLTQ), 0);
424 if (ret)
425 break;
426 }
427
428 qls_sem_unlock(ha, Q81_CTL_SEM_MASK_RIDX_DATAREG);
429
430 return (ret);
431 }
432
433 int
434 qls_set_promisc(qla_host_t *ha)
435 {
436 int ret;
437
438 ret = qls_load_route_idx_reg_locked(ha,
439 (Q81_CTL_RI_E | Q81_CTL_RI_TYPE_NICQMASK |
440 Q81_CTL_RI_IDX_PROMISCUOUS | Q81_CTL_RI_DST_DFLTQ),
441 Q81_CTL_RD_VALID_PKT);
442 return (ret);
443 }
444
445 void
446 qls_reset_promisc(qla_host_t *ha)
447 {
448 int ret;
449
450 ret = qls_load_route_idx_reg_locked(ha, (Q81_CTL_RI_TYPE_NICQMASK |
451 Q81_CTL_RI_IDX_PROMISCUOUS | Q81_CTL_RI_DST_DFLTQ), 0);
452 return;
453 }
454
455 int
456 qls_set_allmulti(qla_host_t *ha)
457 {
458 int ret;
459
460 ret = qls_load_route_idx_reg_locked(ha,
461 (Q81_CTL_RI_E | Q81_CTL_RI_TYPE_NICQMASK |
462 Q81_CTL_RI_IDX_ALLMULTI | Q81_CTL_RI_DST_DFLTQ),
463 Q81_CTL_RD_MCAST);
464 return (ret);
465 }
466
467 void
468 qls_reset_allmulti(qla_host_t *ha)
469 {
470 int ret;
471
472 ret = qls_load_route_idx_reg_locked(ha, (Q81_CTL_RI_TYPE_NICQMASK |
473 Q81_CTL_RI_IDX_ALLMULTI | Q81_CTL_RI_DST_DFLTQ), 0);
474 return;
475 }
476
477 static int
478 qls_init_fw_routing_table(qla_host_t *ha)
479 {
480 int ret = 0;
481
482 ret = qls_clear_routing_table(ha);
483 if (ret)
484 return (-1);
485
486 if (qls_sem_lock(ha, Q81_CTL_SEM_MASK_RIDX_DATAREG,
487 Q81_CTL_SEM_SET_RIDX_DATAREG)) {
488 QL_DPRINT1((ha->pci_dev, "%s: semlock failed\n", __func__));
489 return(-1);
490 }
491
492 ret = qls_load_route_idx_reg(ha, (Q81_CTL_RI_E | Q81_CTL_RI_DST_DROP |
493 Q81_CTL_RI_TYPE_NICQMASK | Q81_CTL_RI_IDX_ALL_ERROR),
494 Q81_CTL_RD_ERROR_PKT);
495 if (ret)
496 goto qls_init_fw_routing_table_exit;
497
498 ret = qls_load_route_idx_reg(ha, (Q81_CTL_RI_E | Q81_CTL_RI_DST_DFLTQ |
499 Q81_CTL_RI_TYPE_NICQMASK | Q81_CTL_RI_IDX_BCAST),
500 Q81_CTL_RD_BCAST);
501 if (ret)
502 goto qls_init_fw_routing_table_exit;
503
504 if (ha->num_rx_rings > 1 ) {
505 ret = qls_load_route_idx_reg(ha,
506 (Q81_CTL_RI_E | Q81_CTL_RI_DST_RSS |
507 Q81_CTL_RI_TYPE_NICQMASK |
508 Q81_CTL_RI_IDX_RSS_MATCH),
509 Q81_CTL_RD_RSS_MATCH);
510 if (ret)
511 goto qls_init_fw_routing_table_exit;
512 }
513
514 ret = qls_load_route_idx_reg(ha, (Q81_CTL_RI_E | Q81_CTL_RI_DST_DFLTQ |
515 Q81_CTL_RI_TYPE_NICQMASK | Q81_CTL_RI_IDX_MCAST_MATCH),
516 Q81_CTL_RD_MCAST_REG_MATCH);
517 if (ret)
518 goto qls_init_fw_routing_table_exit;
519
520 ret = qls_load_route_idx_reg(ha, (Q81_CTL_RI_E | Q81_CTL_RI_DST_DFLTQ |
521 Q81_CTL_RI_TYPE_NICQMASK | Q81_CTL_RI_IDX_CAM_HIT),
522 Q81_CTL_RD_CAM_HIT);
523 if (ret)
524 goto qls_init_fw_routing_table_exit;
525
526 qls_init_fw_routing_table_exit:
527 qls_sem_unlock(ha, Q81_CTL_SEM_MASK_RIDX_DATAREG);
528 return (ret);
529 }
530
531 static int
532 qls_tx_tso_chksum(qla_host_t *ha, struct mbuf *mp, q81_tx_tso_t *tx_mac)
533 {
534 struct ether_vlan_header *eh;
535 struct ip *ip;
536 struct ip6_hdr *ip6;
537 struct tcphdr *th;
538 uint32_t ehdrlen, ip_hlen;
539 int ret = 0;
540 uint16_t etype;
541 device_t dev;
542 uint8_t buf[sizeof(struct ip6_hdr)];
543
544 dev = ha->pci_dev;
545
546 eh = mtod(mp, struct ether_vlan_header *);
547
548 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
549 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
550 etype = ntohs(eh->evl_proto);
551 } else {
552 ehdrlen = ETHER_HDR_LEN;
553 etype = ntohs(eh->evl_encap_proto);
554 }
555
556 switch (etype) {
557 case ETHERTYPE_IP:
558 ip = (struct ip *)(mp->m_data + ehdrlen);
559
560 ip_hlen = sizeof (struct ip);
561
562 if (mp->m_len < (ehdrlen + ip_hlen)) {
563 m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
564 ip = (struct ip *)buf;
565 }
566 tx_mac->opcode = Q81_IOCB_TX_TSO;
567 tx_mac->flags |= Q81_TX_TSO_FLAGS_IPV4 ;
568
569 tx_mac->phdr_offsets = ehdrlen;
570
571 tx_mac->phdr_offsets |= ((ehdrlen + ip_hlen) <<
572 Q81_TX_TSO_PHDR_SHIFT);
573
574 ip->ip_sum = 0;
575
576 if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
577 tx_mac->flags |= Q81_TX_TSO_FLAGS_LSO;
578
579 th = (struct tcphdr *)(ip + 1);
580
581 th->th_sum = in_pseudo(ip->ip_src.s_addr,
582 ip->ip_dst.s_addr,
583 htons(IPPROTO_TCP));
584 tx_mac->mss = mp->m_pkthdr.tso_segsz;
585 tx_mac->phdr_length = ip_hlen + ehdrlen +
586 (th->th_off << 2);
587 break;
588 }
589 tx_mac->vlan_off |= Q81_TX_TSO_VLAN_OFF_IC ;
590
591 if (ip->ip_p == IPPROTO_TCP) {
592 tx_mac->flags |= Q81_TX_TSO_FLAGS_TC;
593 } else if (ip->ip_p == IPPROTO_UDP) {
594 tx_mac->flags |= Q81_TX_TSO_FLAGS_UC;
595 }
596 break;
597
598 case ETHERTYPE_IPV6:
599 ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
600
601 ip_hlen = sizeof(struct ip6_hdr);
602
603 if (mp->m_len < (ehdrlen + ip_hlen)) {
604 m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
605 buf);
606 ip6 = (struct ip6_hdr *)buf;
607 }
608
609 tx_mac->opcode = Q81_IOCB_TX_TSO;
610 tx_mac->flags |= Q81_TX_TSO_FLAGS_IPV6 ;
611 tx_mac->vlan_off |= Q81_TX_TSO_VLAN_OFF_IC ;
612
613 tx_mac->phdr_offsets = ehdrlen;
614 tx_mac->phdr_offsets |= ((ehdrlen + ip_hlen) <<
615 Q81_TX_TSO_PHDR_SHIFT);
616
617 if (ip6->ip6_nxt == IPPROTO_TCP) {
618 tx_mac->flags |= Q81_TX_TSO_FLAGS_TC;
619 } else if (ip6->ip6_nxt == IPPROTO_UDP) {
620 tx_mac->flags |= Q81_TX_TSO_FLAGS_UC;
621 }
622 break;
623
624 default:
625 ret = -1;
626 break;
627 }
628
629 return (ret);
630 }
631
632 #define QLA_TX_MIN_FREE 2
633 int
634 qls_hw_tx_done(qla_host_t *ha, uint32_t txr_idx)
635 {
636 uint32_t txr_done, txr_next;
637
638 txr_done = ha->tx_ring[txr_idx].txr_done;
639 txr_next = ha->tx_ring[txr_idx].txr_next;
640
641 if (txr_done == txr_next) {
642 ha->tx_ring[txr_idx].txr_free = NUM_TX_DESCRIPTORS;
643 } else if (txr_done > txr_next) {
644 ha->tx_ring[txr_idx].txr_free = txr_done - txr_next;
645 } else {
646 ha->tx_ring[txr_idx].txr_free = NUM_TX_DESCRIPTORS +
647 txr_done - txr_next;
648 }
649
650 if (ha->tx_ring[txr_idx].txr_free <= QLA_TX_MIN_FREE)
651 return (-1);
652
653 return (0);
654 }
655
656 /*
657 * Name: qls_hw_send
658 * Function: Transmits a packet. It first checks if the packet is a
659 * candidate for Large TCP Segment Offload and then for UDP/TCP checksum
660 * offload. If either of these creteria are not met, it is transmitted
661 * as a regular ethernet frame.
662 */
663 int
664 qls_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
665 uint32_t txr_next, struct mbuf *mp, uint32_t txr_idx)
666 {
667 q81_tx_mac_t *tx_mac;
668 q81_txb_desc_t *tx_desc;
669 uint32_t total_length = 0;
670 uint32_t i;
671 device_t dev;
672 int ret = 0;
673
674 dev = ha->pci_dev;
675
676 total_length = mp->m_pkthdr.len;
677
678 if (total_length > QLA_MAX_TSO_FRAME_SIZE) {
679 device_printf(dev, "%s: total length exceeds maxlen(%d)\n",
680 __func__, total_length);
681 return (-1);
682 }
683
684 if (ha->tx_ring[txr_idx].txr_free <= (NUM_TX_DESCRIPTORS >> 2)) {
685 if (qls_hw_tx_done(ha, txr_idx)) {
686 device_printf(dev, "%s: tx_free[%d] = %d\n",
687 __func__, txr_idx,
688 ha->tx_ring[txr_idx].txr_free);
689 return (-1);
690 }
691 }
692
693 tx_mac = (q81_tx_mac_t *)&ha->tx_ring[txr_idx].wq_vaddr[txr_next];
694
695 bzero(tx_mac, sizeof(q81_tx_mac_t));
696
697 if ((mp->m_pkthdr.csum_flags &
698 (CSUM_TCP | CSUM_UDP | CSUM_IP | CSUM_TSO)) != 0) {
699 ret = qls_tx_tso_chksum(ha, mp, (q81_tx_tso_t *)tx_mac);
700 if (ret)
701 return (EINVAL);
702
703 if (mp->m_pkthdr.csum_flags & CSUM_TSO)
704 ha->tx_ring[txr_idx].tx_tso_frames++;
705 else
706 ha->tx_ring[txr_idx].tx_frames++;
707
708 } else {
709 tx_mac->opcode = Q81_IOCB_TX_MAC;
710 }
711
712 if (mp->m_flags & M_VLANTAG) {
713 tx_mac->vlan_tci = mp->m_pkthdr.ether_vtag;
714 tx_mac->vlan_off |= Q81_TX_MAC_VLAN_OFF_V;
715
716 ha->tx_ring[txr_idx].tx_vlan_frames++;
717 }
718
719 tx_mac->frame_length = total_length;
720
721 tx_mac->tid_lo = txr_next;
722
723 if (nsegs <= MAX_TX_MAC_DESC) {
724 QL_DPRINT2((dev, "%s: 1 [%d, %d]\n", __func__, total_length,
725 tx_mac->tid_lo));
726
727 for (i = 0; i < nsegs; i++) {
728 tx_mac->txd[i].baddr = segs->ds_addr;
729 tx_mac->txd[i].length = segs->ds_len;
730 segs++;
731 }
732 tx_mac->txd[(nsegs - 1)].flags = Q81_RXB_DESC_FLAGS_E;
733
734 } else {
735 QL_DPRINT2((dev, "%s: 2 [%d, %d]\n", __func__, total_length,
736 tx_mac->tid_lo));
737
738 tx_mac->txd[0].baddr =
739 ha->tx_ring[txr_idx].tx_buf[txr_next].oal_paddr;
740 tx_mac->txd[0].length =
741 nsegs * (sizeof(q81_txb_desc_t));
742 tx_mac->txd[0].flags = Q81_RXB_DESC_FLAGS_C;
743
744 tx_desc = ha->tx_ring[txr_idx].tx_buf[txr_next].oal_vaddr;
745
746 for (i = 0; i < nsegs; i++) {
747 tx_desc->baddr = segs->ds_addr;
748 tx_desc->length = segs->ds_len;
749
750 if (i == (nsegs -1))
751 tx_desc->flags = Q81_RXB_DESC_FLAGS_E;
752 else
753 tx_desc->flags = 0;
754
755 segs++;
756 tx_desc++;
757 }
758 }
759 txr_next = (txr_next + 1) & (NUM_TX_DESCRIPTORS - 1);
760 ha->tx_ring[txr_idx].txr_next = txr_next;
761
762 ha->tx_ring[txr_idx].txr_free--;
763
764 Q81_WR_WQ_PROD_IDX(txr_idx, txr_next);
765
766 return (0);
767 }
768
769 /*
770 * Name: qls_del_hw_if
771 * Function: Destroys the hardware specific entities corresponding to an
772 * Ethernet Interface
773 */
774 void
775 qls_del_hw_if(qla_host_t *ha)
776 {
777 uint32_t value;
778 int i;
779 //int count;
780
781 if (ha->hw_init == 0) {
782 qls_hw_reset(ha);
783 return;
784 }
785
786 for (i = 0; i < ha->num_tx_rings; i++) {
787 Q81_SET_WQ_INVALID(i);
788 }
789 for (i = 0; i < ha->num_rx_rings; i++) {
790 Q81_SET_CQ_INVALID(i);
791 }
792
793 for (i = 0; i < ha->num_rx_rings; i++) {
794 Q81_DISABLE_INTR(ha, i); /* MSI-x i */
795 }
796
797 value = (Q81_CTL_INTRE_IHD << Q81_CTL_INTRE_MASK_SHIFT);
798 WRITE_REG32(ha, Q81_CTL_INTR_ENABLE, value);
799
800 value = (Q81_CTL_INTRE_EI << Q81_CTL_INTRE_MASK_SHIFT);
801 WRITE_REG32(ha, Q81_CTL_INTR_ENABLE, value);
802 ha->flags.intr_enable = 0;
803
804 qls_hw_reset(ha);
805
806 return;
807 }
808
809 /*
810 * Name: qls_init_hw_if
811 * Function: Creates the hardware specific entities corresponding to an
812 * Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address
813 * corresponding to the interface. Enables LRO if allowed.
814 */
815 int
816 qls_init_hw_if(qla_host_t *ha)
817 {
818 device_t dev;
819 uint32_t value;
820 int ret = 0;
821 int i;
822
823 QL_DPRINT2((ha->pci_dev, "%s:enter\n", __func__));
824
825 dev = ha->pci_dev;
826
827 ret = qls_hw_reset(ha);
828 if (ret)
829 goto qls_init_hw_if_exit;
830
831 ha->vm_pgsize = 4096;
832
833 /* Enable FAE and EFE bits in System Register */
834 value = Q81_CTL_SYSTEM_ENABLE_FAE | Q81_CTL_SYSTEM_ENABLE_EFE;
835 value = (value << Q81_CTL_SYSTEM_MASK_SHIFT) | value;
836
837 WRITE_REG32(ha, Q81_CTL_SYSTEM, value);
838
839 /* Set Default Completion Queue_ID in NIC Rcv Configuration Register */
840 value = (Q81_CTL_NIC_RCVC_DCQ_MASK << Q81_CTL_NIC_RCVC_MASK_SHIFT);
841 WRITE_REG32(ha, Q81_CTL_NIC_RCV_CONFIG, value);
842
843 /* Function Specific Control Register - Set Page Size and Enable NIC */
844 value = Q81_CTL_FUNC_SPECIFIC_FE |
845 Q81_CTL_FUNC_SPECIFIC_VM_PGSIZE_MASK |
846 Q81_CTL_FUNC_SPECIFIC_EPC_O |
847 Q81_CTL_FUNC_SPECIFIC_EPC_I |
848 Q81_CTL_FUNC_SPECIFIC_EC;
849 value = (value << Q81_CTL_FUNC_SPECIFIC_MASK_SHIFT) |
850 Q81_CTL_FUNC_SPECIFIC_FE |
851 Q81_CTL_FUNC_SPECIFIC_VM_PGSIZE_4K |
852 Q81_CTL_FUNC_SPECIFIC_EPC_O |
853 Q81_CTL_FUNC_SPECIFIC_EPC_I |
854 Q81_CTL_FUNC_SPECIFIC_EC;
855
856 WRITE_REG32(ha, Q81_CTL_FUNC_SPECIFIC, value);
857
858 /* Interrupt Mask Register */
859 value = Q81_CTL_INTRM_PI;
860 value = (value << Q81_CTL_INTRM_MASK_SHIFT) | value;
861
862 WRITE_REG32(ha, Q81_CTL_INTR_MASK, value);
863
864 /* Initialiatize Completion Queue */
865 for (i = 0; i < ha->num_rx_rings; i++) {
866 ret = qls_init_comp_queue(ha, i);
867 if (ret)
868 goto qls_init_hw_if_exit;
869 }
870
871 if (ha->num_rx_rings > 1 ) {
872 ret = qls_init_rss(ha);
873 if (ret)
874 goto qls_init_hw_if_exit;
875 }
876
877 /* Initialize Work Queue */
878
879 for (i = 0; i < ha->num_tx_rings; i++) {
880 ret = qls_init_work_queue(ha, i);
881 if (ret)
882 goto qls_init_hw_if_exit;
883 }
884
885 if (ret)
886 goto qls_init_hw_if_exit;
887
888 /* Set up CAM RAM with MAC Address */
889 ret = qls_config_unicast_mac_addr(ha, 1);
890 if (ret)
891 goto qls_init_hw_if_exit;
892
893 ret = qls_hw_add_all_mcast(ha);
894 if (ret)
895 goto qls_init_hw_if_exit;
896
897 /* Initialize Firmware Routing Table */
898 ret = qls_init_fw_routing_table(ha);
899 if (ret)
900 goto qls_init_hw_if_exit;
901
902 /* Get Chip Revision ID */
903 ha->rev_id = READ_REG32(ha, Q81_CTL_REV_ID);
904
905 /* Enable Global Interrupt */
906 value = Q81_CTL_INTRE_EI;
907 value = (value << Q81_CTL_INTRE_MASK_SHIFT) | value;
908
909 WRITE_REG32(ha, Q81_CTL_INTR_ENABLE, value);
910
911 /* Enable Interrupt Handshake Disable */
912 value = Q81_CTL_INTRE_IHD;
913 value = (value << Q81_CTL_INTRE_MASK_SHIFT) | value;
914
915 WRITE_REG32(ha, Q81_CTL_INTR_ENABLE, value);
916
917 /* Enable Completion Interrupt */
918
919 ha->flags.intr_enable = 1;
920
921 for (i = 0; i < ha->num_rx_rings; i++) {
922 Q81_ENABLE_INTR(ha, i); /* MSI-x i */
923 }
924
925 ha->hw_init = 1;
926
927 qls_mbx_get_link_status(ha);
928
929 QL_DPRINT2((ha->pci_dev, "%s:rxr [0x%08x]\n", __func__,
930 ha->rx_ring[0].cq_db_offset));
931 QL_DPRINT2((ha->pci_dev, "%s:txr [0x%08x]\n", __func__,
932 ha->tx_ring[0].wq_db_offset));
933
934 for (i = 0; i < ha->num_rx_rings; i++) {
935 Q81_WR_CQ_CONS_IDX(i, 0);
936 Q81_WR_LBQ_PROD_IDX(i, ha->rx_ring[i].lbq_in);
937 Q81_WR_SBQ_PROD_IDX(i, ha->rx_ring[i].sbq_in);
938
939 QL_DPRINT2((dev, "%s: [wq_idx, cq_idx, lbq_idx, sbq_idx]"
940 "[0x%08x, 0x%08x, 0x%08x, 0x%08x]\n", __func__,
941 Q81_RD_WQ_IDX(i), Q81_RD_CQ_IDX(i), Q81_RD_LBQ_IDX(i),
942 Q81_RD_SBQ_IDX(i)));
943 }
944
945 for (i = 0; i < ha->num_rx_rings; i++) {
946 Q81_SET_CQ_VALID(i);
947 }
948
949 qls_init_hw_if_exit:
950 QL_DPRINT2((ha->pci_dev, "%s:exit\n", __func__));
951 return (ret);
952 }
953
954 static int
955 qls_wait_for_config_reg_bits(qla_host_t *ha, uint32_t bits, uint32_t value)
956 {
957 uint32_t data32;
958 uint32_t count = 3;
959
960 while (count--) {
961 data32 = READ_REG32(ha, Q81_CTL_CONFIG);
962
963 if ((data32 & bits) == value)
964 return (0);
965
966 QLA_USEC_DELAY(100);
967 }
968 ha->qla_initiate_recovery = 1;
969 device_printf(ha->pci_dev, "%s: failed\n", __func__);
970 return (-1);
971 }
972
973 static uint8_t q81_hash_key[] = {
974 0xda, 0x56, 0x5a, 0x6d,
975 0xc2, 0x0e, 0x5b, 0x25,
976 0x3d, 0x25, 0x67, 0x41,
977 0xb0, 0x8f, 0xa3, 0x43,
978 0xcb, 0x2b, 0xca, 0xd0,
979 0xb4, 0x30, 0x7b, 0xae,
980 0xa3, 0x2d, 0xcb, 0x77,
981 0x0c, 0xf2, 0x30, 0x80,
982 0x3b, 0xb7, 0x42, 0x6a,
983 0xfa, 0x01, 0xac, 0xbe };
984
985 static int
986 qls_init_rss(qla_host_t *ha)
987 {
988 q81_rss_icb_t *rss_icb;
989 int ret = 0;
990 int i;
991 uint32_t value;
992
993 rss_icb = ha->rss_dma.dma_b;
994
995 bzero(rss_icb, sizeof (q81_rss_icb_t));
996
997 rss_icb->flags_base_cq_num = Q81_RSS_ICB_FLAGS_L4K |
998 Q81_RSS_ICB_FLAGS_L6K | Q81_RSS_ICB_FLAGS_LI |
999 Q81_RSS_ICB_FLAGS_LB | Q81_RSS_ICB_FLAGS_LM |
1000 Q81_RSS_ICB_FLAGS_RT4 | Q81_RSS_ICB_FLAGS_RT6;
1001
1002 rss_icb->mask = 0x3FF;
1003
1004 for (i = 0; i < Q81_RSS_ICB_NUM_INDTBL_ENTRIES; i++) {
1005 rss_icb->cq_id[i] = (i & (ha->num_rx_rings - 1));
1006 }
1007
1008 memcpy(rss_icb->ipv6_rss_hash_key, q81_hash_key, 40);
1009 memcpy(rss_icb->ipv4_rss_hash_key, q81_hash_key, 16);
1010
1011 ret = qls_wait_for_config_reg_bits(ha, Q81_CTL_CONFIG_LR, 0);
1012
1013 if (ret)
1014 goto qls_init_rss_exit;
1015
1016 ret = qls_sem_lock(ha, Q81_CTL_SEM_MASK_ICB, Q81_CTL_SEM_SET_ICB);
1017
1018 if (ret) {
1019 QL_DPRINT1((ha->pci_dev, "%s: semlock failed\n", __func__));
1020 goto qls_init_rss_exit;
1021 }
1022
1023 value = (uint32_t)ha->rss_dma.dma_addr;
1024 WRITE_REG32(ha, Q81_CTL_ICB_ACCESS_ADDR_LO, value);
1025
1026 value = (uint32_t)(ha->rss_dma.dma_addr >> 32);
1027 WRITE_REG32(ha, Q81_CTL_ICB_ACCESS_ADDR_HI, value);
1028
1029 qls_sem_unlock(ha, Q81_CTL_SEM_MASK_ICB);
1030
1031 value = (Q81_CTL_CONFIG_LR << Q81_CTL_CONFIG_MASK_SHIFT) |
1032 Q81_CTL_CONFIG_LR;
1033
1034 WRITE_REG32(ha, Q81_CTL_CONFIG, value);
1035
1036 ret = qls_wait_for_config_reg_bits(ha, Q81_CTL_CONFIG_LR, 0);
1037
1038 qls_init_rss_exit:
1039 return (ret);
1040 }
1041
1042 static int
1043 qls_init_comp_queue(qla_host_t *ha, int cid)
1044 {
1045 q81_cq_icb_t *cq_icb;
1046 qla_rx_ring_t *rxr;
1047 int ret = 0;
1048 uint32_t value;
1049
1050 rxr = &ha->rx_ring[cid];
1051
1052 rxr->cq_db_offset = ha->vm_pgsize * (128 + cid);
1053
1054 cq_icb = rxr->cq_icb_vaddr;
1055
1056 bzero(cq_icb, sizeof (q81_cq_icb_t));
1057
1058 cq_icb->msix_vector = cid;
1059 cq_icb->flags = Q81_CQ_ICB_FLAGS_LC |
1060 Q81_CQ_ICB_FLAGS_LI |
1061 Q81_CQ_ICB_FLAGS_LL |
1062 Q81_CQ_ICB_FLAGS_LS |
1063 Q81_CQ_ICB_FLAGS_LV;
1064
1065 cq_icb->length_v = NUM_CQ_ENTRIES;
1066
1067 cq_icb->cq_baddr_lo = (rxr->cq_base_paddr & 0xFFFFFFFF);
1068 cq_icb->cq_baddr_hi = (rxr->cq_base_paddr >> 32) & 0xFFFFFFFF;
1069
1070 cq_icb->cqi_addr_lo = (rxr->cqi_paddr & 0xFFFFFFFF);
1071 cq_icb->cqi_addr_hi = (rxr->cqi_paddr >> 32) & 0xFFFFFFFF;
1072
1073 cq_icb->pkt_idelay = 10;
1074 cq_icb->idelay = 100;
1075
1076 cq_icb->lbq_baddr_lo = (rxr->lbq_addr_tbl_paddr & 0xFFFFFFFF);
1077 cq_icb->lbq_baddr_hi = (rxr->lbq_addr_tbl_paddr >> 32) & 0xFFFFFFFF;
1078
1079 cq_icb->lbq_bsize = QLA_LGB_SIZE;
1080 cq_icb->lbq_length = QLA_NUM_LGB_ENTRIES;
1081
1082 cq_icb->sbq_baddr_lo = (rxr->sbq_addr_tbl_paddr & 0xFFFFFFFF);
1083 cq_icb->sbq_baddr_hi = (rxr->sbq_addr_tbl_paddr >> 32) & 0xFFFFFFFF;
1084
1085 cq_icb->sbq_bsize = (uint16_t)ha->msize;
1086 cq_icb->sbq_length = QLA_NUM_SMB_ENTRIES;
1087
1088 QL_DUMP_CQ(ha);
1089
1090 ret = qls_wait_for_config_reg_bits(ha, Q81_CTL_CONFIG_LCQ, 0);
1091
1092 if (ret)
1093 goto qls_init_comp_queue_exit;
1094
1095 ret = qls_sem_lock(ha, Q81_CTL_SEM_MASK_ICB, Q81_CTL_SEM_SET_ICB);
1096
1097 if (ret) {
1098 QL_DPRINT1((ha->pci_dev, "%s: semlock failed\n", __func__));
1099 goto qls_init_comp_queue_exit;
1100 }
1101
1102 value = (uint32_t)rxr->cq_icb_paddr;
1103 WRITE_REG32(ha, Q81_CTL_ICB_ACCESS_ADDR_LO, value);
1104
1105 value = (uint32_t)(rxr->cq_icb_paddr >> 32);
1106 WRITE_REG32(ha, Q81_CTL_ICB_ACCESS_ADDR_HI, value);
1107
1108 qls_sem_unlock(ha, Q81_CTL_SEM_MASK_ICB);
1109
1110 value = Q81_CTL_CONFIG_LCQ | Q81_CTL_CONFIG_Q_NUM_MASK;
1111 value = (value << Q81_CTL_CONFIG_MASK_SHIFT) | Q81_CTL_CONFIG_LCQ;
1112 value |= (cid << Q81_CTL_CONFIG_Q_NUM_SHIFT);
1113 WRITE_REG32(ha, Q81_CTL_CONFIG, value);
1114
1115 ret = qls_wait_for_config_reg_bits(ha, Q81_CTL_CONFIG_LCQ, 0);
1116
1117 rxr->cq_next = 0;
1118 rxr->lbq_next = rxr->lbq_free = 0;
1119 rxr->sbq_next = rxr->sbq_free = 0;
1120 rxr->rx_free = rxr->rx_next = 0;
1121 rxr->lbq_in = (QLA_NUM_LGB_ENTRIES - 1) & ~0xF;
1122 rxr->sbq_in = (QLA_NUM_SMB_ENTRIES - 1) & ~0xF;
1123
1124 qls_init_comp_queue_exit:
1125 return (ret);
1126 }
1127
1128 static int
1129 qls_init_work_queue(qla_host_t *ha, int wid)
1130 {
1131 q81_wq_icb_t *wq_icb;
1132 qla_tx_ring_t *txr;
1133 int ret = 0;
1134 uint32_t value;
1135
1136 txr = &ha->tx_ring[wid];
1137
1138 txr->wq_db_addr = (struct resource *)((uint8_t *)ha->pci_reg1
1139 + (ha->vm_pgsize * wid));
1140
1141 txr->wq_db_offset = (ha->vm_pgsize * wid);
1142
1143 wq_icb = txr->wq_icb_vaddr;
1144 bzero(wq_icb, sizeof (q81_wq_icb_t));
1145
1146 wq_icb->length_v = NUM_TX_DESCRIPTORS |
1147 Q81_WQ_ICB_VALID;
1148
1149 wq_icb->flags = Q81_WQ_ICB_FLAGS_LO | Q81_WQ_ICB_FLAGS_LI |
1150 Q81_WQ_ICB_FLAGS_LB | Q81_WQ_ICB_FLAGS_LC;
1151
1152 wq_icb->wqcqid_rss = wid;
1153
1154 wq_icb->baddr_lo = txr->wq_paddr & 0xFFFFFFFF;
1155 wq_icb->baddr_hi = (txr->wq_paddr >> 32)& 0xFFFFFFFF;
1156
1157 wq_icb->ci_addr_lo = txr->txr_cons_paddr & 0xFFFFFFFF;
1158 wq_icb->ci_addr_hi = (txr->txr_cons_paddr >> 32)& 0xFFFFFFFF;
1159
1160 ret = qls_wait_for_config_reg_bits(ha, Q81_CTL_CONFIG_LRQ, 0);
1161
1162 if (ret)
1163 goto qls_init_wq_exit;
1164
1165 ret = qls_sem_lock(ha, Q81_CTL_SEM_MASK_ICB, Q81_CTL_SEM_SET_ICB);
1166
1167 if (ret) {
1168 QL_DPRINT1((ha->pci_dev, "%s: semlock failed\n", __func__));
1169 goto qls_init_wq_exit;
1170 }
1171
1172 value = (uint32_t)txr->wq_icb_paddr;
1173 WRITE_REG32(ha, Q81_CTL_ICB_ACCESS_ADDR_LO, value);
1174
1175 value = (uint32_t)(txr->wq_icb_paddr >> 32);
1176 WRITE_REG32(ha, Q81_CTL_ICB_ACCESS_ADDR_HI, value);
1177
1178 qls_sem_unlock(ha, Q81_CTL_SEM_MASK_ICB);
1179
1180 value = Q81_CTL_CONFIG_LRQ | Q81_CTL_CONFIG_Q_NUM_MASK;
1181 value = (value << Q81_CTL_CONFIG_MASK_SHIFT) | Q81_CTL_CONFIG_LRQ;
1182 value |= (wid << Q81_CTL_CONFIG_Q_NUM_SHIFT);
1183 WRITE_REG32(ha, Q81_CTL_CONFIG, value);
1184
1185 ret = qls_wait_for_config_reg_bits(ha, Q81_CTL_CONFIG_LRQ, 0);
1186
1187 txr->txr_free = NUM_TX_DESCRIPTORS;
1188 txr->txr_next = 0;
1189 txr->txr_done = 0;
1190
1191 qls_init_wq_exit:
1192 return (ret);
1193 }
1194
1195 static int
1196 qls_hw_add_all_mcast(qla_host_t *ha)
1197 {
1198 int i, nmcast;
1199
1200 nmcast = ha->nmcast;
1201
1202 for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
1203 if ((ha->mcast[i].addr[0] != 0) ||
1204 (ha->mcast[i].addr[1] != 0) ||
1205 (ha->mcast[i].addr[2] != 0) ||
1206 (ha->mcast[i].addr[3] != 0) ||
1207 (ha->mcast[i].addr[4] != 0) ||
1208 (ha->mcast[i].addr[5] != 0)) {
1209 if (qls_config_mcast_mac_addr(ha, ha->mcast[i].addr,
1210 1, i)) {
1211 device_printf(ha->pci_dev, "%s: failed\n",
1212 __func__);
1213 return (-1);
1214 }
1215
1216 nmcast--;
1217 }
1218 }
1219 return 0;
1220 }
1221
1222 static int
1223 qls_hw_add_mcast(qla_host_t *ha, uint8_t *mta)
1224 {
1225 int i;
1226
1227 for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
1228 if (QL_MAC_CMP(ha->mcast[i].addr, mta) == 0)
1229 return 0; /* its been already added */
1230 }
1231
1232 for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
1233 if ((ha->mcast[i].addr[0] == 0) &&
1234 (ha->mcast[i].addr[1] == 0) &&
1235 (ha->mcast[i].addr[2] == 0) &&
1236 (ha->mcast[i].addr[3] == 0) &&
1237 (ha->mcast[i].addr[4] == 0) &&
1238 (ha->mcast[i].addr[5] == 0)) {
1239 if (qls_config_mcast_mac_addr(ha, mta, 1, i))
1240 return (-1);
1241
1242 bcopy(mta, ha->mcast[i].addr, Q8_MAC_ADDR_LEN);
1243 ha->nmcast++;
1244
1245 return 0;
1246 }
1247 }
1248 return 0;
1249 }
1250
1251 static int
1252 qls_hw_del_mcast(qla_host_t *ha, uint8_t *mta)
1253 {
1254 int i;
1255
1256 for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
1257 if (QL_MAC_CMP(ha->mcast[i].addr, mta) == 0) {
1258 if (qls_config_mcast_mac_addr(ha, mta, 0, i))
1259 return (-1);
1260
1261 ha->mcast[i].addr[0] = 0;
1262 ha->mcast[i].addr[1] = 0;
1263 ha->mcast[i].addr[2] = 0;
1264 ha->mcast[i].addr[3] = 0;
1265 ha->mcast[i].addr[4] = 0;
1266 ha->mcast[i].addr[5] = 0;
1267
1268 ha->nmcast--;
1269
1270 return 0;
1271 }
1272 }
1273 return 0;
1274 }
1275
1276 /*
1277 * Name: qls_hw_set_multi
1278 * Function: Sets the Multicast Addresses provided the host O.S into the
1279 * hardware (for the given interface)
1280 */
1281 void
1282 qls_hw_set_multi(qla_host_t *ha, uint8_t *mta, uint32_t mcnt,
1283 uint32_t add_mac)
1284 {
1285 int i;
1286
1287 for (i = 0; i < mcnt; i++) {
1288 if (add_mac) {
1289 if (qls_hw_add_mcast(ha, mta))
1290 break;
1291 } else {
1292 if (qls_hw_del_mcast(ha, mta))
1293 break;
1294 }
1295
1296 mta += Q8_MAC_ADDR_LEN;
1297 }
1298 return;
1299 }
1300
1301 void
1302 qls_update_link_state(qla_host_t *ha)
1303 {
1304 uint32_t link_state;
1305 uint32_t prev_link_state;
1306
1307 if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1308 ha->link_up = 0;
1309 return;
1310 }
1311 link_state = READ_REG32(ha, Q81_CTL_STATUS);
1312
1313 prev_link_state = ha->link_up;
1314
1315 if ((ha->pci_func & 0x1) == 0)
1316 ha->link_up = ((link_state & Q81_CTL_STATUS_PL0)? 1 : 0);
1317 else
1318 ha->link_up = ((link_state & Q81_CTL_STATUS_PL1)? 1 : 0);
1319
1320 if (prev_link_state != ha->link_up) {
1321 if (ha->link_up) {
1322 if_link_state_change(ha->ifp, LINK_STATE_UP);
1323 } else {
1324 if_link_state_change(ha->ifp, LINK_STATE_DOWN);
1325 }
1326 }
1327 return;
1328 }
1329
1330 static void
1331 qls_free_tx_ring_dma(qla_host_t *ha, int r_idx)
1332 {
1333 if (ha->tx_ring[r_idx].flags.wq_dma) {
1334 qls_free_dmabuf(ha, &ha->tx_ring[r_idx].wq_dma);
1335 ha->tx_ring[r_idx].flags.wq_dma = 0;
1336 }
1337
1338 if (ha->tx_ring[r_idx].flags.privb_dma) {
1339 qls_free_dmabuf(ha, &ha->tx_ring[r_idx].privb_dma);
1340 ha->tx_ring[r_idx].flags.privb_dma = 0;
1341 }
1342 return;
1343 }
1344
1345 static void
1346 qls_free_tx_dma(qla_host_t *ha)
1347 {
1348 int i, j;
1349 qla_tx_buf_t *txb;
1350
1351 for (i = 0; i < ha->num_tx_rings; i++) {
1352 qls_free_tx_ring_dma(ha, i);
1353
1354 for (j = 0; j < NUM_TX_DESCRIPTORS; j++) {
1355 txb = &ha->tx_ring[i].tx_buf[j];
1356
1357 if (txb->map) {
1358 bus_dmamap_destroy(ha->tx_tag, txb->map);
1359 }
1360 }
1361 }
1362
1363 if (ha->tx_tag != NULL) {
1364 bus_dma_tag_destroy(ha->tx_tag);
1365 ha->tx_tag = NULL;
1366 }
1367
1368 return;
1369 }
1370
1371 static int
1372 qls_alloc_tx_ring_dma(qla_host_t *ha, int ridx)
1373 {
1374 int ret = 0, i;
1375 uint8_t *v_addr;
1376 bus_addr_t p_addr;
1377 qla_tx_buf_t *txb;
1378 device_t dev = ha->pci_dev;
1379
1380 ha->tx_ring[ridx].wq_dma.alignment = 8;
1381 ha->tx_ring[ridx].wq_dma.size =
1382 NUM_TX_DESCRIPTORS * (sizeof (q81_tx_cmd_t));
1383
1384 ret = qls_alloc_dmabuf(ha, &ha->tx_ring[ridx].wq_dma);
1385
1386 if (ret) {
1387 device_printf(dev, "%s: [%d] txr failed\n", __func__, ridx);
1388 goto qls_alloc_tx_ring_dma_exit;
1389 }
1390 ha->tx_ring[ridx].flags.wq_dma = 1;
1391
1392 ha->tx_ring[ridx].privb_dma.alignment = 8;
1393 ha->tx_ring[ridx].privb_dma.size = QLA_TX_PRIVATE_BSIZE;
1394
1395 ret = qls_alloc_dmabuf(ha, &ha->tx_ring[ridx].privb_dma);
1396
1397 if (ret) {
1398 device_printf(dev, "%s: [%d] oalb failed\n", __func__, ridx);
1399 goto qls_alloc_tx_ring_dma_exit;
1400 }
1401
1402 ha->tx_ring[ridx].flags.privb_dma = 1;
1403
1404 ha->tx_ring[ridx].wq_vaddr = ha->tx_ring[ridx].wq_dma.dma_b;
1405 ha->tx_ring[ridx].wq_paddr = ha->tx_ring[ridx].wq_dma.dma_addr;
1406
1407 v_addr = ha->tx_ring[ridx].privb_dma.dma_b;
1408 p_addr = ha->tx_ring[ridx].privb_dma.dma_addr;
1409
1410 ha->tx_ring[ridx].wq_icb_vaddr = v_addr;
1411 ha->tx_ring[ridx].wq_icb_paddr = p_addr;
1412
1413 ha->tx_ring[ridx].txr_cons_vaddr =
1414 (uint32_t *)(v_addr + (PAGE_SIZE >> 1));
1415 ha->tx_ring[ridx].txr_cons_paddr = p_addr + (PAGE_SIZE >> 1);
1416
1417 v_addr = v_addr + (PAGE_SIZE >> 1);
1418 p_addr = p_addr + (PAGE_SIZE >> 1);
1419
1420 txb = ha->tx_ring[ridx].tx_buf;
1421
1422 for (i = 0; i < NUM_TX_DESCRIPTORS; i++) {
1423 txb[i].oal_vaddr = v_addr;
1424 txb[i].oal_paddr = p_addr;
1425
1426 v_addr = v_addr + QLA_OAL_BLK_SIZE;
1427 p_addr = p_addr + QLA_OAL_BLK_SIZE;
1428 }
1429
1430 qls_alloc_tx_ring_dma_exit:
1431 return (ret);
1432 }
1433
1434 static int
1435 qls_alloc_tx_dma(qla_host_t *ha)
1436 {
1437 int i, j;
1438 int ret = 0;
1439 qla_tx_buf_t *txb;
1440
1441 if (bus_dma_tag_create(NULL, /* parent */
1442 1, 0, /* alignment, bounds */
1443 BUS_SPACE_MAXADDR, /* lowaddr */
1444 BUS_SPACE_MAXADDR, /* highaddr */
1445 NULL, NULL, /* filter, filterarg */
1446 QLA_MAX_TSO_FRAME_SIZE, /* maxsize */
1447 QLA_MAX_SEGMENTS, /* nsegments */
1448 PAGE_SIZE, /* maxsegsize */
1449 BUS_DMA_ALLOCNOW, /* flags */
1450 NULL, /* lockfunc */
1451 NULL, /* lockfuncarg */
1452 &ha->tx_tag)) {
1453 device_printf(ha->pci_dev, "%s: tx_tag alloc failed\n",
1454 __func__);
1455 return (ENOMEM);
1456 }
1457
1458 for (i = 0; i < ha->num_tx_rings; i++) {
1459 ret = qls_alloc_tx_ring_dma(ha, i);
1460
1461 if (ret) {
1462 qls_free_tx_dma(ha);
1463 break;
1464 }
1465
1466 for (j = 0; j < NUM_TX_DESCRIPTORS; j++) {
1467 txb = &ha->tx_ring[i].tx_buf[j];
1468
1469 ret = bus_dmamap_create(ha->tx_tag,
1470 BUS_DMA_NOWAIT, &txb->map);
1471 if (ret) {
1472 ha->err_tx_dmamap_create++;
1473 device_printf(ha->pci_dev,
1474 "%s: bus_dmamap_create failed[%d, %d, %d]\n",
1475 __func__, ret, i, j);
1476
1477 qls_free_tx_dma(ha);
1478
1479 return (ret);
1480 }
1481 }
1482 }
1483
1484 return (ret);
1485 }
1486
1487 static void
1488 qls_free_rss_dma(qla_host_t *ha)
1489 {
1490 qls_free_dmabuf(ha, &ha->rss_dma);
1491 ha->flags.rss_dma = 0;
1492 }
1493
1494 static int
1495 qls_alloc_rss_dma(qla_host_t *ha)
1496 {
1497 int ret = 0;
1498
1499 ha->rss_dma.alignment = 4;
1500 ha->rss_dma.size = PAGE_SIZE;
1501
1502 ret = qls_alloc_dmabuf(ha, &ha->rss_dma);
1503
1504 if (ret)
1505 device_printf(ha->pci_dev, "%s: failed\n", __func__);
1506 else
1507 ha->flags.rss_dma = 1;
1508
1509 return (ret);
1510 }
1511
1512 static void
1513 qls_free_mpi_dma(qla_host_t *ha)
1514 {
1515 qls_free_dmabuf(ha, &ha->mpi_dma);
1516 ha->flags.mpi_dma = 0;
1517 }
1518
1519 static int
1520 qls_alloc_mpi_dma(qla_host_t *ha)
1521 {
1522 int ret = 0;
1523
1524 ha->mpi_dma.alignment = 4;
1525 ha->mpi_dma.size = (0x4000 * 4);
1526
1527 ret = qls_alloc_dmabuf(ha, &ha->mpi_dma);
1528 if (ret)
1529 device_printf(ha->pci_dev, "%s: failed\n", __func__);
1530 else
1531 ha->flags.mpi_dma = 1;
1532
1533 return (ret);
1534 }
1535
1536 static void
1537 qls_free_rx_ring_dma(qla_host_t *ha, int ridx)
1538 {
1539 if (ha->rx_ring[ridx].flags.cq_dma) {
1540 qls_free_dmabuf(ha, &ha->rx_ring[ridx].cq_dma);
1541 ha->rx_ring[ridx].flags.cq_dma = 0;
1542 }
1543
1544 if (ha->rx_ring[ridx].flags.lbq_dma) {
1545 qls_free_dmabuf(ha, &ha->rx_ring[ridx].lbq_dma);
1546 ha->rx_ring[ridx].flags.lbq_dma = 0;
1547 }
1548
1549 if (ha->rx_ring[ridx].flags.sbq_dma) {
1550 qls_free_dmabuf(ha, &ha->rx_ring[ridx].sbq_dma);
1551 ha->rx_ring[ridx].flags.sbq_dma = 0;
1552 }
1553
1554 if (ha->rx_ring[ridx].flags.lb_dma) {
1555 qls_free_dmabuf(ha, &ha->rx_ring[ridx].lb_dma);
1556 ha->rx_ring[ridx].flags.lb_dma = 0;
1557 }
1558 return;
1559 }
1560
1561 static void
1562 qls_free_rx_dma(qla_host_t *ha)
1563 {
1564 int i;
1565
1566 for (i = 0; i < ha->num_rx_rings; i++) {
1567 qls_free_rx_ring_dma(ha, i);
1568 }
1569
1570 if (ha->rx_tag != NULL) {
1571 bus_dma_tag_destroy(ha->rx_tag);
1572 ha->rx_tag = NULL;
1573 }
1574
1575 return;
1576 }
1577
1578 static int
1579 qls_alloc_rx_ring_dma(qla_host_t *ha, int ridx)
1580 {
1581 int i, ret = 0;
1582 uint8_t *v_addr;
1583 bus_addr_t p_addr;
1584 volatile q81_bq_addr_e_t *bq_e;
1585 device_t dev = ha->pci_dev;
1586
1587 ha->rx_ring[ridx].cq_dma.alignment = 128;
1588 ha->rx_ring[ridx].cq_dma.size =
1589 (NUM_CQ_ENTRIES * (sizeof (q81_cq_e_t))) + PAGE_SIZE;
1590
1591 ret = qls_alloc_dmabuf(ha, &ha->rx_ring[ridx].cq_dma);
1592
1593 if (ret) {
1594 device_printf(dev, "%s: [%d] cq failed\n", __func__, ridx);
1595 goto qls_alloc_rx_ring_dma_exit;
1596 }
1597 ha->rx_ring[ridx].flags.cq_dma = 1;
1598
1599 ha->rx_ring[ridx].lbq_dma.alignment = 8;
1600 ha->rx_ring[ridx].lbq_dma.size = QLA_LGBQ_AND_TABLE_SIZE;
1601
1602 ret = qls_alloc_dmabuf(ha, &ha->rx_ring[ridx].lbq_dma);
1603
1604 if (ret) {
1605 device_printf(dev, "%s: [%d] lbq failed\n", __func__, ridx);
1606 goto qls_alloc_rx_ring_dma_exit;
1607 }
1608 ha->rx_ring[ridx].flags.lbq_dma = 1;
1609
1610 ha->rx_ring[ridx].sbq_dma.alignment = 8;
1611 ha->rx_ring[ridx].sbq_dma.size = QLA_SMBQ_AND_TABLE_SIZE;
1612
1613 ret = qls_alloc_dmabuf(ha, &ha->rx_ring[ridx].sbq_dma);
1614
1615 if (ret) {
1616 device_printf(dev, "%s: [%d] sbq failed\n", __func__, ridx);
1617 goto qls_alloc_rx_ring_dma_exit;
1618 }
1619 ha->rx_ring[ridx].flags.sbq_dma = 1;
1620
1621 ha->rx_ring[ridx].lb_dma.alignment = 8;
1622 ha->rx_ring[ridx].lb_dma.size = (QLA_LGB_SIZE * QLA_NUM_LGB_ENTRIES);
1623
1624 ret = qls_alloc_dmabuf(ha, &ha->rx_ring[ridx].lb_dma);
1625 if (ret) {
1626 device_printf(dev, "%s: [%d] lb failed\n", __func__, ridx);
1627 goto qls_alloc_rx_ring_dma_exit;
1628 }
1629 ha->rx_ring[ridx].flags.lb_dma = 1;
1630
1631 bzero(ha->rx_ring[ridx].cq_dma.dma_b, ha->rx_ring[ridx].cq_dma.size);
1632 bzero(ha->rx_ring[ridx].lbq_dma.dma_b, ha->rx_ring[ridx].lbq_dma.size);
1633 bzero(ha->rx_ring[ridx].sbq_dma.dma_b, ha->rx_ring[ridx].sbq_dma.size);
1634 bzero(ha->rx_ring[ridx].lb_dma.dma_b, ha->rx_ring[ridx].lb_dma.size);
1635
1636 /* completion queue */
1637 ha->rx_ring[ridx].cq_base_vaddr = ha->rx_ring[ridx].cq_dma.dma_b;
1638 ha->rx_ring[ridx].cq_base_paddr = ha->rx_ring[ridx].cq_dma.dma_addr;
1639
1640 v_addr = ha->rx_ring[ridx].cq_dma.dma_b;
1641 p_addr = ha->rx_ring[ridx].cq_dma.dma_addr;
1642
1643 v_addr = v_addr + (NUM_CQ_ENTRIES * (sizeof (q81_cq_e_t)));
1644 p_addr = p_addr + (NUM_CQ_ENTRIES * (sizeof (q81_cq_e_t)));
1645
1646 /* completion queue icb */
1647 ha->rx_ring[ridx].cq_icb_vaddr = v_addr;
1648 ha->rx_ring[ridx].cq_icb_paddr = p_addr;
1649
1650 v_addr = v_addr + (PAGE_SIZE >> 2);
1651 p_addr = p_addr + (PAGE_SIZE >> 2);
1652
1653 /* completion queue index register */
1654 ha->rx_ring[ridx].cqi_vaddr = (uint32_t *)v_addr;
1655 ha->rx_ring[ridx].cqi_paddr = p_addr;
1656
1657 v_addr = ha->rx_ring[ridx].lbq_dma.dma_b;
1658 p_addr = ha->rx_ring[ridx].lbq_dma.dma_addr;
1659
1660 /* large buffer queue address table */
1661 ha->rx_ring[ridx].lbq_addr_tbl_vaddr = v_addr;
1662 ha->rx_ring[ridx].lbq_addr_tbl_paddr = p_addr;
1663
1664 /* large buffer queue */
1665 ha->rx_ring[ridx].lbq_vaddr = v_addr + PAGE_SIZE;
1666 ha->rx_ring[ridx].lbq_paddr = p_addr + PAGE_SIZE;
1667
1668 v_addr = ha->rx_ring[ridx].sbq_dma.dma_b;
1669 p_addr = ha->rx_ring[ridx].sbq_dma.dma_addr;
1670
1671 /* small buffer queue address table */
1672 ha->rx_ring[ridx].sbq_addr_tbl_vaddr = v_addr;
1673 ha->rx_ring[ridx].sbq_addr_tbl_paddr = p_addr;
1674
1675 /* small buffer queue */
1676 ha->rx_ring[ridx].sbq_vaddr = v_addr + PAGE_SIZE;
1677 ha->rx_ring[ridx].sbq_paddr = p_addr + PAGE_SIZE;
1678
1679 ha->rx_ring[ridx].lb_vaddr = ha->rx_ring[ridx].lb_dma.dma_b;
1680 ha->rx_ring[ridx].lb_paddr = ha->rx_ring[ridx].lb_dma.dma_addr;
1681
1682 /* Initialize Large Buffer Queue Table */
1683
1684 p_addr = ha->rx_ring[ridx].lbq_paddr;
1685 bq_e = ha->rx_ring[ridx].lbq_addr_tbl_vaddr;
1686
1687 bq_e->addr_lo = p_addr & 0xFFFFFFFF;
1688 bq_e->addr_hi = (p_addr >> 32) & 0xFFFFFFFF;
1689
1690 p_addr = ha->rx_ring[ridx].lb_paddr;
1691 bq_e = ha->rx_ring[ridx].lbq_vaddr;
1692
1693 for (i = 0; i < QLA_NUM_LGB_ENTRIES; i++) {
1694 bq_e->addr_lo = p_addr & 0xFFFFFFFF;
1695 bq_e->addr_hi = (p_addr >> 32) & 0xFFFFFFFF;
1696
1697 p_addr = p_addr + QLA_LGB_SIZE;
1698 bq_e++;
1699 }
1700
1701 /* Initialize Small Buffer Queue Table */
1702
1703 p_addr = ha->rx_ring[ridx].sbq_paddr;
1704 bq_e = ha->rx_ring[ridx].sbq_addr_tbl_vaddr;
1705
1706 for (i =0; i < (QLA_SBQ_SIZE/QLA_PAGE_SIZE); i++) {
1707 bq_e->addr_lo = p_addr & 0xFFFFFFFF;
1708 bq_e->addr_hi = (p_addr >> 32) & 0xFFFFFFFF;
1709
1710 p_addr = p_addr + QLA_PAGE_SIZE;
1711 bq_e++;
1712 }
1713
1714 qls_alloc_rx_ring_dma_exit:
1715 return (ret);
1716 }
1717
1718 static int
1719 qls_alloc_rx_dma(qla_host_t *ha)
1720 {
1721 int i;
1722 int ret = 0;
1723
1724 if (bus_dma_tag_create(NULL, /* parent */
1725 1, 0, /* alignment, bounds */
1726 BUS_SPACE_MAXADDR, /* lowaddr */
1727 BUS_SPACE_MAXADDR, /* highaddr */
1728 NULL, NULL, /* filter, filterarg */
1729 MJUM9BYTES, /* maxsize */
1730 1, /* nsegments */
1731 MJUM9BYTES, /* maxsegsize */
1732 BUS_DMA_ALLOCNOW, /* flags */
1733 NULL, /* lockfunc */
1734 NULL, /* lockfuncarg */
1735 &ha->rx_tag)) {
1736 device_printf(ha->pci_dev, "%s: rx_tag alloc failed\n",
1737 __func__);
1738
1739 return (ENOMEM);
1740 }
1741
1742 for (i = 0; i < ha->num_rx_rings; i++) {
1743 ret = qls_alloc_rx_ring_dma(ha, i);
1744
1745 if (ret) {
1746 qls_free_rx_dma(ha);
1747 break;
1748 }
1749 }
1750
1751 return (ret);
1752 }
1753
1754 static int
1755 qls_wait_for_flash_ready(qla_host_t *ha)
1756 {
1757 uint32_t data32;
1758 uint32_t count = 3;
1759
1760 while (count--) {
1761 data32 = READ_REG32(ha, Q81_CTL_FLASH_ADDR);
1762
1763 if (data32 & Q81_CTL_FLASH_ADDR_ERR)
1764 goto qls_wait_for_flash_ready_exit;
1765
1766 if (data32 & Q81_CTL_FLASH_ADDR_RDY)
1767 return (0);
1768
1769 QLA_USEC_DELAY(100);
1770 }
1771
1772 qls_wait_for_flash_ready_exit:
1773 QL_DPRINT1((ha->pci_dev, "%s: failed\n", __func__));
1774
1775 return (-1);
1776 }
1777
1778 /*
1779 * Name: qls_rd_flash32
1780 * Function: Read Flash Memory
1781 */
1782 int
1783 qls_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data)
1784 {
1785 int ret;
1786
1787 ret = qls_wait_for_flash_ready(ha);
1788
1789 if (ret)
1790 return (ret);
1791
1792 WRITE_REG32(ha, Q81_CTL_FLASH_ADDR, (addr | Q81_CTL_FLASH_ADDR_R));
1793
1794 ret = qls_wait_for_flash_ready(ha);
1795
1796 if (ret)
1797 return (ret);
1798
1799 *data = READ_REG32(ha, Q81_CTL_FLASH_DATA);
1800
1801 return 0;
1802 }
1803
1804 static int
1805 qls_flash_validate(qla_host_t *ha, const char *signature)
1806 {
1807 uint16_t csum16 = 0;
1808 uint16_t *data16;
1809 int i;
1810
1811 if (bcmp(ha->flash.id, signature, 4)) {
1812 QL_DPRINT1((ha->pci_dev, "%s: invalid signature "
1813 "%x:%x:%x:%x %s\n", __func__, ha->flash.id[0],
1814 ha->flash.id[1], ha->flash.id[2], ha->flash.id[3],
1815 signature));
1816 return(-1);
1817 }
1818
1819 data16 = (uint16_t *)&ha->flash;
1820
1821 for (i = 0; i < (sizeof (q81_flash_t) >> 1); i++) {
1822 csum16 += *data16++;
1823 }
1824
1825 if (csum16) {
1826 QL_DPRINT1((ha->pci_dev, "%s: invalid checksum\n", __func__));
1827 return(-1);
1828 }
1829 return(0);
1830 }
1831
1832 int
1833 qls_rd_nic_params(qla_host_t *ha)
1834 {
1835 int i, ret = 0;
1836 uint32_t faddr;
1837 uint32_t *qflash;
1838
1839 if (qls_sem_lock(ha, Q81_CTL_SEM_MASK_FLASH, Q81_CTL_SEM_SET_FLASH)) {
1840 QL_DPRINT1((ha->pci_dev, "%s: semlock failed\n", __func__));
1841 return(-1);
1842 }
1843
1844 if ((ha->pci_func & 0x1) == 0)
1845 faddr = Q81_F0_FLASH_OFFSET >> 2;
1846 else
1847 faddr = Q81_F1_FLASH_OFFSET >> 2;
1848
1849 qflash = (uint32_t *)&ha->flash;
1850
1851 for (i = 0; i < (sizeof(q81_flash_t) >> 2) ; i++) {
1852 ret = qls_rd_flash32(ha, faddr, qflash);
1853
1854 if (ret)
1855 goto qls_rd_flash_data_exit;
1856
1857 faddr++;
1858 qflash++;
1859 }
1860
1861 QL_DUMP_BUFFER8(ha, __func__, (&ha->flash), (sizeof (q81_flash_t)));
1862
1863 ret = qls_flash_validate(ha, Q81_FLASH_ID);
1864
1865 if (ret)
1866 goto qls_rd_flash_data_exit;
1867
1868 bcopy(ha->flash.mac_addr0, ha->mac_addr, ETHER_ADDR_LEN);
1869
1870 QL_DPRINT1((ha->pci_dev, "%s: mac %02x:%02x:%02x:%02x:%02x:%02x\n",
1871 __func__, ha->mac_addr[0], ha->mac_addr[1], ha->mac_addr[2],
1872 ha->mac_addr[3], ha->mac_addr[4], ha->mac_addr[5]));
1873
1874 qls_rd_flash_data_exit:
1875
1876 qls_sem_unlock(ha, Q81_CTL_SEM_MASK_FLASH);
1877
1878 return(ret);
1879 }
1880
1881 static int
1882 qls_sem_lock(qla_host_t *ha, uint32_t mask, uint32_t value)
1883 {
1884 uint32_t count = 30;
1885 uint32_t data;
1886
1887 while (count--) {
1888 WRITE_REG32(ha, Q81_CTL_SEMAPHORE, (mask|value));
1889
1890 data = READ_REG32(ha, Q81_CTL_SEMAPHORE);
1891
1892 if (data & value) {
1893 return (0);
1894 } else {
1895 QLA_USEC_DELAY(100);
1896 }
1897 }
1898 ha->qla_initiate_recovery = 1;
1899 return (-1);
1900 }
1901
1902 static void
1903 qls_sem_unlock(qla_host_t *ha, uint32_t mask)
1904 {
1905 WRITE_REG32(ha, Q81_CTL_SEMAPHORE, mask);
1906 }
1907
1908 static int
1909 qls_wait_for_proc_addr_ready(qla_host_t *ha)
1910 {
1911 uint32_t data32;
1912 uint32_t count = 3;
1913
1914 while (count--) {
1915 data32 = READ_REG32(ha, Q81_CTL_PROC_ADDR);
1916
1917 if (data32 & Q81_CTL_PROC_ADDR_ERR)
1918 goto qls_wait_for_proc_addr_ready_exit;
1919
1920 if (data32 & Q81_CTL_PROC_ADDR_RDY)
1921 return (0);
1922
1923 QLA_USEC_DELAY(100);
1924 }
1925
1926 qls_wait_for_proc_addr_ready_exit:
1927 QL_DPRINT1((ha->pci_dev, "%s: failed\n", __func__));
1928
1929 ha->qla_initiate_recovery = 1;
1930 return (-1);
1931 }
1932
1933 static int
1934 qls_proc_addr_rd_reg(qla_host_t *ha, uint32_t addr_module, uint32_t reg,
1935 uint32_t *data)
1936 {
1937 int ret;
1938 uint32_t value;
1939
1940 ret = qls_wait_for_proc_addr_ready(ha);
1941
1942 if (ret)
1943 goto qls_proc_addr_rd_reg_exit;
1944
1945 value = addr_module | reg | Q81_CTL_PROC_ADDR_READ;
1946
1947 WRITE_REG32(ha, Q81_CTL_PROC_ADDR, value);
1948
1949 ret = qls_wait_for_proc_addr_ready(ha);
1950
1951 if (ret)
1952 goto qls_proc_addr_rd_reg_exit;
1953
1954 *data = READ_REG32(ha, Q81_CTL_PROC_DATA);
1955
1956 qls_proc_addr_rd_reg_exit:
1957 return (ret);
1958 }
1959
1960 static int
1961 qls_proc_addr_wr_reg(qla_host_t *ha, uint32_t addr_module, uint32_t reg,
1962 uint32_t data)
1963 {
1964 int ret;
1965 uint32_t value;
1966
1967 ret = qls_wait_for_proc_addr_ready(ha);
1968
1969 if (ret)
1970 goto qls_proc_addr_wr_reg_exit;
1971
1972 WRITE_REG32(ha, Q81_CTL_PROC_DATA, data);
1973
1974 value = addr_module | reg;
1975
1976 WRITE_REG32(ha, Q81_CTL_PROC_ADDR, value);
1977
1978 ret = qls_wait_for_proc_addr_ready(ha);
1979
1980 qls_proc_addr_wr_reg_exit:
1981 return (ret);
1982 }
1983
1984 static int
1985 qls_hw_nic_reset(qla_host_t *ha)
1986 {
1987 int count;
1988 uint32_t data;
1989 device_t dev = ha->pci_dev;
1990
1991 ha->hw_init = 0;
1992
1993 data = (Q81_CTL_RESET_FUNC << Q81_CTL_RESET_MASK_SHIFT) |
1994 Q81_CTL_RESET_FUNC;
1995 WRITE_REG32(ha, Q81_CTL_RESET, data);
1996
1997 count = 10;
1998 while (count--) {
1999 data = READ_REG32(ha, Q81_CTL_RESET);
2000 if ((data & Q81_CTL_RESET_FUNC) == 0)
2001 break;
2002 QLA_USEC_DELAY(10);
2003 }
2004 if (count == 0) {
2005 device_printf(dev, "%s: Bit 15 not cleared after Reset\n",
2006 __func__);
2007 return (-1);
2008 }
2009 return (0);
2010 }
2011
2012 static int
2013 qls_hw_reset(qla_host_t *ha)
2014 {
2015 device_t dev = ha->pci_dev;
2016 int ret;
2017 int count;
2018 uint32_t data;
2019
2020 QL_DPRINT2((ha->pci_dev, "%s:enter[%d]\n", __func__, ha->hw_init));
2021
2022 if (ha->hw_init == 0) {
2023 ret = qls_hw_nic_reset(ha);
2024 goto qls_hw_reset_exit;
2025 }
2026
2027 ret = qls_clear_routing_table(ha);
2028 if (ret)
2029 goto qls_hw_reset_exit;
2030
2031 ret = qls_mbx_set_mgmt_ctrl(ha, Q81_MBX_SET_MGMT_CTL_STOP);
2032 if (ret)
2033 goto qls_hw_reset_exit;
2034
2035 /*
2036 * Wait for FIFO to empty
2037 */
2038 count = 5;
2039 while (count--) {
2040 data = READ_REG32(ha, Q81_CTL_STATUS);
2041 if (data & Q81_CTL_STATUS_NFE)
2042 break;
2043 qls_mdelay(__func__, 100);
2044 }
2045 if (count == 0) {
2046 device_printf(dev, "%s: NFE bit not set\n", __func__);
2047 goto qls_hw_reset_exit;
2048 }
2049
2050 count = 5;
2051 while (count--) {
2052 (void)qls_mbx_get_mgmt_ctrl(ha, &data);
2053
2054 if ((data & Q81_MBX_GET_MGMT_CTL_FIFO_EMPTY) &&
2055 (data & Q81_MBX_GET_MGMT_CTL_SET_MGMT))
2056 break;
2057 qls_mdelay(__func__, 100);
2058 }
2059 if (count == 0)
2060 goto qls_hw_reset_exit;
2061
2062 /*
2063 * Reset the NIC function
2064 */
2065 ret = qls_hw_nic_reset(ha);
2066 if (ret)
2067 goto qls_hw_reset_exit;
2068
2069 ret = qls_mbx_set_mgmt_ctrl(ha, Q81_MBX_SET_MGMT_CTL_RESUME);
2070
2071 qls_hw_reset_exit:
2072 if (ret)
2073 device_printf(dev, "%s: failed\n", __func__);
2074
2075 return (ret);
2076 }
2077
2078 /*
2079 * MPI Related Functions
2080 */
2081 int
2082 qls_mpi_risc_rd_reg(qla_host_t *ha, uint32_t reg, uint32_t *data)
2083 {
2084 int ret;
2085
2086 ret = qls_proc_addr_rd_reg(ha, Q81_CTL_PROC_ADDR_MPI_RISC,
2087 reg, data);
2088 return (ret);
2089 }
2090
2091 int
2092 qls_mpi_risc_wr_reg(qla_host_t *ha, uint32_t reg, uint32_t data)
2093 {
2094 int ret;
2095
2096 ret = qls_proc_addr_wr_reg(ha, Q81_CTL_PROC_ADDR_MPI_RISC,
2097 reg, data);
2098 return (ret);
2099 }
2100
2101 int
2102 qls_mbx_rd_reg(qla_host_t *ha, uint32_t reg, uint32_t *data)
2103 {
2104 int ret;
2105
2106 if ((ha->pci_func & 0x1) == 0)
2107 reg += Q81_FUNC0_MBX_OUT_REG0;
2108 else
2109 reg += Q81_FUNC1_MBX_OUT_REG0;
2110
2111 ret = qls_mpi_risc_rd_reg(ha, reg, data);
2112
2113 return (ret);
2114 }
2115
2116 int
2117 qls_mbx_wr_reg(qla_host_t *ha, uint32_t reg, uint32_t data)
2118 {
2119 int ret;
2120
2121 if ((ha->pci_func & 0x1) == 0)
2122 reg += Q81_FUNC0_MBX_IN_REG0;
2123 else
2124 reg += Q81_FUNC1_MBX_IN_REG0;
2125
2126 ret = qls_mpi_risc_wr_reg(ha, reg, data);
2127
2128 return (ret);
2129 }
2130
2131 static int
2132 qls_mbx_cmd(qla_host_t *ha, uint32_t *in_mbx, uint32_t i_count,
2133 uint32_t *out_mbx, uint32_t o_count)
2134 {
2135 int i, ret = -1;
2136 uint32_t data32, mbx_cmd = 0;
2137 uint32_t count = 50;
2138
2139 QL_DPRINT2((ha->pci_dev, "%s: enter[0x%08x 0x%08x 0x%08x]\n",
2140 __func__, *in_mbx, *(in_mbx + 1), *(in_mbx + 2)));
2141
2142 data32 = READ_REG32(ha, Q81_CTL_HOST_CMD_STATUS);
2143
2144 if (data32 & Q81_CTL_HCS_HTR_INTR) {
2145 device_printf(ha->pci_dev, "%s: cmd_status[0x%08x]\n",
2146 __func__, data32);
2147 goto qls_mbx_cmd_exit;
2148 }
2149
2150 if (qls_sem_lock(ha, Q81_CTL_SEM_MASK_PROC_ADDR_NIC_RCV,
2151 Q81_CTL_SEM_SET_PROC_ADDR_NIC_RCV)) {
2152 device_printf(ha->pci_dev, "%s: semlock failed\n", __func__);
2153 goto qls_mbx_cmd_exit;
2154 }
2155
2156 ha->mbx_done = 0;
2157
2158 mbx_cmd = *in_mbx;
2159
2160 for (i = 0; i < i_count; i++) {
2161 ret = qls_mbx_wr_reg(ha, i, *in_mbx);
2162
2163 if (ret) {
2164 device_printf(ha->pci_dev,
2165 "%s: mbx_wr[%d, 0x%08x] failed\n", __func__,
2166 i, *in_mbx);
2167 qls_sem_unlock(ha, Q81_CTL_SEM_MASK_PROC_ADDR_NIC_RCV);
2168 goto qls_mbx_cmd_exit;
2169 }
2170
2171 in_mbx++;
2172 }
2173 WRITE_REG32(ha, Q81_CTL_HOST_CMD_STATUS, Q81_CTL_HCS_CMD_SET_HTR_INTR);
2174
2175 qls_sem_unlock(ha, Q81_CTL_SEM_MASK_PROC_ADDR_NIC_RCV);
2176
2177 ret = -1;
2178 ha->mbx_done = 0;
2179
2180 while (count--) {
2181 if (ha->flags.intr_enable == 0) {
2182 data32 = READ_REG32(ha, Q81_CTL_STATUS);
2183
2184 if (!(data32 & Q81_CTL_STATUS_PI)) {
2185 qls_mdelay(__func__, 100);
2186 continue;
2187 }
2188
2189 ret = qls_mbx_rd_reg(ha, 0, &data32);
2190
2191 if (ret == 0 ) {
2192 if ((data32 & 0xF000) == 0x4000) {
2193 out_mbx[0] = data32;
2194
2195 for (i = 1; i < o_count; i++) {
2196 ret = qls_mbx_rd_reg(ha, i,
2197 &data32);
2198 if (ret) {
2199 device_printf(
2200 ha->pci_dev,
2201 "%s: mbx_rd[%d]"
2202 " failed\n",
2203 __func__, i);
2204 break;
2205 }
2206 out_mbx[i] = data32;
2207 }
2208 break;
2209 } else if ((data32 & 0xF000) == 0x8000) {
2210 count = 50;
2211 WRITE_REG32(ha,\
2212 Q81_CTL_HOST_CMD_STATUS,\
2213 Q81_CTL_HCS_CMD_CLR_RTH_INTR);
2214 }
2215 }
2216 } else {
2217 if (ha->mbx_done) {
2218 for (i = 1; i < o_count; i++) {
2219 out_mbx[i] = ha->mbox[i];
2220 }
2221 ret = 0;
2222 break;
2223 }
2224 }
2225 qls_mdelay(__func__, 1000);
2226 }
2227
2228 qls_mbx_cmd_exit:
2229
2230 if (ha->flags.intr_enable == 0) {
2231 WRITE_REG32(ha, Q81_CTL_HOST_CMD_STATUS,\
2232 Q81_CTL_HCS_CMD_CLR_RTH_INTR);
2233 }
2234
2235 if (ret) {
2236 ha->qla_initiate_recovery = 1;
2237 }
2238
2239 QL_DPRINT2((ha->pci_dev, "%s: exit[%d]\n", __func__, ret));
2240 return (ret);
2241 }
2242
2243 static int
2244 qls_mbx_set_mgmt_ctrl(qla_host_t *ha, uint32_t t_ctrl)
2245 {
2246 uint32_t *mbox;
2247 device_t dev = ha->pci_dev;
2248
2249 mbox = ha->mbox;
2250 bzero(mbox, (sizeof (uint32_t) * Q81_NUM_MBX_REGISTERS));
2251
2252 mbox[0] = Q81_MBX_SET_MGMT_CTL;
2253 mbox[1] = t_ctrl;
2254
2255 if (qls_mbx_cmd(ha, mbox, 2, mbox, 1)) {
2256 device_printf(dev, "%s failed\n", __func__);
2257 return (-1);
2258 }
2259
2260 if ((mbox[0] == Q81_MBX_CMD_COMPLETE) ||
2261 ((t_ctrl == Q81_MBX_SET_MGMT_CTL_STOP) &&
2262 (mbox[0] == Q81_MBX_CMD_ERROR))){
2263 return (0);
2264 }
2265 device_printf(dev, "%s failed [0x%08x]\n", __func__, mbox[0]);
2266 return (-1);
2267
2268 }
2269
2270 static int
2271 qls_mbx_get_mgmt_ctrl(qla_host_t *ha, uint32_t *t_status)
2272 {
2273 uint32_t *mbox;
2274 device_t dev = ha->pci_dev;
2275
2276 *t_status = 0;
2277
2278 mbox = ha->mbox;
2279 bzero(mbox, (sizeof (uint32_t) * Q81_NUM_MBX_REGISTERS));
2280
2281 mbox[0] = Q81_MBX_GET_MGMT_CTL;
2282
2283 if (qls_mbx_cmd(ha, mbox, 1, mbox, 2)) {
2284 device_printf(dev, "%s failed\n", __func__);
2285 return (-1);
2286 }
2287
2288 *t_status = mbox[1];
2289
2290 return (0);
2291 }
2292
2293 static void
2294 qls_mbx_get_link_status(qla_host_t *ha)
2295 {
2296 uint32_t *mbox;
2297 device_t dev = ha->pci_dev;
2298
2299 mbox = ha->mbox;
2300 bzero(mbox, (sizeof (uint32_t) * Q81_NUM_MBX_REGISTERS));
2301
2302 mbox[0] = Q81_MBX_GET_LNK_STATUS;
2303
2304 if (qls_mbx_cmd(ha, mbox, 1, mbox, 6)) {
2305 device_printf(dev, "%s failed\n", __func__);
2306 return;
2307 }
2308
2309 ha->link_status = mbox[1];
2310 ha->link_down_info = mbox[2];
2311 ha->link_hw_info = mbox[3];
2312 ha->link_dcbx_counters = mbox[4];
2313 ha->link_change_counters = mbox[5];
2314
2315 device_printf(dev, "%s 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
2316 __func__, mbox[0],mbox[1],mbox[2],mbox[3],mbox[4],mbox[5]);
2317
2318 return;
2319 }
2320
2321 static void
2322 qls_mbx_about_fw(qla_host_t *ha)
2323 {
2324 uint32_t *mbox;
2325 device_t dev = ha->pci_dev;
2326
2327 mbox = ha->mbox;
2328 bzero(mbox, (sizeof (uint32_t) * Q81_NUM_MBX_REGISTERS));
2329
2330 mbox[0] = Q81_MBX_ABOUT_FW;
2331
2332 if (qls_mbx_cmd(ha, mbox, 1, mbox, 6)) {
2333 device_printf(dev, "%s failed\n", __func__);
2334 return;
2335 }
2336
2337 device_printf(dev, "%s 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
2338 __func__, mbox[0],mbox[1],mbox[2],mbox[3],mbox[4],mbox[5]);
2339 }
2340
2341 int
2342 qls_mbx_dump_risc_ram(qla_host_t *ha, void *buf, uint32_t r_addr,
2343 uint32_t r_size)
2344 {
2345 bus_addr_t b_paddr;
2346 uint32_t *mbox;
2347 device_t dev = ha->pci_dev;
2348
2349 mbox = ha->mbox;
2350 bzero(mbox, (sizeof (uint32_t) * Q81_NUM_MBX_REGISTERS));
2351
2352 bzero(ha->mpi_dma.dma_b,(r_size << 2));
2353 b_paddr = ha->mpi_dma.dma_addr;
2354
2355 mbox[0] = Q81_MBX_DUMP_RISC_RAM;
2356 mbox[1] = r_addr & 0xFFFF;
2357 mbox[2] = ((uint32_t)(b_paddr >> 16)) & 0xFFFF;
2358 mbox[3] = ((uint32_t)b_paddr) & 0xFFFF;
2359 mbox[4] = (r_size >> 16) & 0xFFFF;
2360 mbox[5] = r_size & 0xFFFF;
2361 mbox[6] = ((uint32_t)(b_paddr >> 48)) & 0xFFFF;
2362 mbox[7] = ((uint32_t)(b_paddr >> 32)) & 0xFFFF;
2363 mbox[8] = (r_addr >> 16) & 0xFFFF;
2364
2365 bus_dmamap_sync(ha->mpi_dma.dma_tag, ha->mpi_dma.dma_map,
2366 BUS_DMASYNC_PREREAD);
2367
2368 if (qls_mbx_cmd(ha, mbox, 9, mbox, 1)) {
2369 device_printf(dev, "%s failed\n", __func__);
2370 return (-1);
2371 }
2372 if (mbox[0] != 0x4000) {
2373 device_printf(ha->pci_dev, "%s: failed!\n", __func__);
2374 return (-1);
2375 } else {
2376 bus_dmamap_sync(ha->mpi_dma.dma_tag, ha->mpi_dma.dma_map,
2377 BUS_DMASYNC_POSTREAD);
2378 bcopy(ha->mpi_dma.dma_b, buf, (r_size << 2));
2379 }
2380
2381 return (0);
2382 }
2383
2384 int
2385 qls_mpi_reset(qla_host_t *ha)
2386 {
2387 int count;
2388 uint32_t data;
2389 device_t dev = ha->pci_dev;
2390
2391 WRITE_REG32(ha, Q81_CTL_HOST_CMD_STATUS,\
2392 Q81_CTL_HCS_CMD_SET_RISC_RESET);
2393
2394 count = 10;
2395 while (count--) {
2396 data = READ_REG32(ha, Q81_CTL_HOST_CMD_STATUS);
2397 if (data & Q81_CTL_HCS_RISC_RESET) {
2398 WRITE_REG32(ha, Q81_CTL_HOST_CMD_STATUS,\
2399 Q81_CTL_HCS_CMD_CLR_RISC_RESET);
2400 break;
2401 }
2402 qls_mdelay(__func__, 10);
2403 }
2404 if (count == 0) {
2405 device_printf(dev, "%s: failed\n", __func__);
2406 return (-1);
2407 }
2408 return (0);
2409 }
Cache object: 7b3a476b30f557f6929c5423f6fe5a47
|