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