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