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