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