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