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