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 dependant 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 45 /* 46 * Static Functions 47 */ 48 49 static void qla_del_rcv_cntxt(qla_host_t *ha); 50 static int qla_init_rcv_cntxt(qla_host_t *ha); 51 static void qla_del_xmt_cntxt(qla_host_t *ha); 52 static int qla_init_xmt_cntxt(qla_host_t *ha); 53 static void qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx); 54 static int qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox, 55 uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause); 56 static int qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx, 57 uint32_t num_intrs, uint32_t create); 58 static int qla_config_rss(qla_host_t *ha, uint16_t cntxt_id); 59 static int qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, 60 int tenable, int rcv); 61 static int qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode); 62 static int qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id); 63 64 static int qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, 65 uint8_t *hdr); 66 static int qla_hw_add_all_mcast(qla_host_t *ha); 67 static int qla_hw_del_all_mcast(qla_host_t *ha); 68 static int qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds); 69 70 static int qla_init_nic_func(qla_host_t *ha); 71 static int qla_stop_nic_func(qla_host_t *ha); 72 static int qla_query_fw_dcbx_caps(qla_host_t *ha); 73 static int qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits); 74 static int qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits); 75 static void qla_get_quick_stats(qla_host_t *ha); 76 77 static int qla_minidump_init(qla_host_t *ha); 78 static void qla_minidump_free(qla_host_t *ha); 79 80 81 static int 82 qla_sysctl_get_drvr_stats(SYSCTL_HANDLER_ARGS) 83 { 84 int err = 0, ret; 85 qla_host_t *ha; 86 uint32_t i; 87 88 err = sysctl_handle_int(oidp, &ret, 0, req); 89 90 if (err || !req->newptr) 91 return (err); 92 93 if (ret == 1) { 94 95 ha = (qla_host_t *)arg1; 96 97 for (i = 0; i < ha->hw.num_sds_rings; i++) 98 device_printf(ha->pci_dev, 99 "%s: sds_ring[%d] = %p\n", __func__,i, 100 (void *)ha->hw.sds[i].intr_count); 101 102 for (i = 0; i < ha->hw.num_tx_rings; i++) 103 device_printf(ha->pci_dev, 104 "%s: tx[%d] = %p\n", __func__,i, 105 (void *)ha->tx_ring[i].count); 106 107 for (i = 0; i < ha->hw.num_rds_rings; i++) 108 device_printf(ha->pci_dev, 109 "%s: rds_ring[%d] = %p\n", __func__,i, 110 (void *)ha->hw.rds[i].count); 111 112 device_printf(ha->pci_dev, "%s: lro_pkt_count = %p\n", __func__, 113 (void *)ha->lro_pkt_count); 114 115 device_printf(ha->pci_dev, "%s: lro_bytes = %p\n", __func__, 116 (void *)ha->lro_bytes); 117 118 #ifdef QL_ENABLE_ISCSI_TLV 119 device_printf(ha->pci_dev, "%s: iscsi_pkts = %p\n", __func__, 120 (void *)ha->hw.iscsi_pkt_count); 121 #endif /* #ifdef QL_ENABLE_ISCSI_TLV */ 122 123 } 124 return (err); 125 } 126 127 static int 128 qla_sysctl_get_quick_stats(SYSCTL_HANDLER_ARGS) 129 { 130 int err, ret = 0; 131 qla_host_t *ha; 132 133 err = sysctl_handle_int(oidp, &ret, 0, req); 134 135 if (err || !req->newptr) 136 return (err); 137 138 if (ret == 1) { 139 ha = (qla_host_t *)arg1; 140 qla_get_quick_stats(ha); 141 } 142 return (err); 143 } 144 145 #ifdef QL_DBG 146 147 static void 148 qla_stop_pegs(qla_host_t *ha) 149 { 150 uint32_t val = 1; 151 152 ql_rdwr_indreg32(ha, Q8_CRB_PEG_0, &val, 0); 153 ql_rdwr_indreg32(ha, Q8_CRB_PEG_1, &val, 0); 154 ql_rdwr_indreg32(ha, Q8_CRB_PEG_2, &val, 0); 155 ql_rdwr_indreg32(ha, Q8_CRB_PEG_3, &val, 0); 156 ql_rdwr_indreg32(ha, Q8_CRB_PEG_4, &val, 0); 157 device_printf(ha->pci_dev, "%s PEGS HALTED!!!!!\n", __func__); 158 } 159 160 static int 161 qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS) 162 { 163 int err, ret = 0; 164 qla_host_t *ha; 165 166 err = sysctl_handle_int(oidp, &ret, 0, req); 167 168 169 if (err || !req->newptr) 170 return (err); 171 172 if (ret == 1) { 173 ha = (qla_host_t *)arg1; 174 (void)QLA_LOCK(ha, __func__, 0); 175 qla_stop_pegs(ha); 176 QLA_UNLOCK(ha, __func__); 177 } 178 179 return err; 180 } 181 #endif /* #ifdef QL_DBG */ 182 183 static int 184 qla_validate_set_port_cfg_bit(uint32_t bits) 185 { 186 if ((bits & 0xF) > 1) 187 return (-1); 188 189 if (((bits >> 4) & 0xF) > 2) 190 return (-1); 191 192 if (((bits >> 8) & 0xF) > 2) 193 return (-1); 194 195 return (0); 196 } 197 198 static int 199 qla_sysctl_port_cfg(SYSCTL_HANDLER_ARGS) 200 { 201 int err, ret = 0; 202 qla_host_t *ha; 203 uint32_t cfg_bits; 204 205 err = sysctl_handle_int(oidp, &ret, 0, req); 206 207 if (err || !req->newptr) 208 return (err); 209 210 if ((qla_validate_set_port_cfg_bit((uint32_t)ret) == 0)) { 211 212 ha = (qla_host_t *)arg1; 213 214 err = qla_get_port_config(ha, &cfg_bits); 215 216 if (err) 217 goto qla_sysctl_set_port_cfg_exit; 218 219 if (ret & 0x1) { 220 cfg_bits |= Q8_PORT_CFG_BITS_DCBX_ENABLE; 221 } else { 222 cfg_bits &= ~Q8_PORT_CFG_BITS_DCBX_ENABLE; 223 } 224 225 ret = ret >> 4; 226 cfg_bits &= ~Q8_PORT_CFG_BITS_PAUSE_CFG_MASK; 227 228 if ((ret & 0xF) == 0) { 229 cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_DISABLED; 230 } else if ((ret & 0xF) == 1){ 231 cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_STD; 232 } else { 233 cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_PPM; 234 } 235 236 ret = ret >> 4; 237 cfg_bits &= ~Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK; 238 239 if (ret == 0) { 240 cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT_RCV; 241 } else if (ret == 1){ 242 cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT; 243 } else { 244 cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_RCV; 245 } 246 247 err = qla_set_port_config(ha, cfg_bits); 248 } else { 249 ha = (qla_host_t *)arg1; 250 251 err = qla_get_port_config(ha, &cfg_bits); 252 } 253 254 qla_sysctl_set_port_cfg_exit: 255 return err; 256 } 257 258 /* 259 * Name: ql_hw_add_sysctls 260 * Function: Add P3Plus specific sysctls 261 */ 262 void 263 ql_hw_add_sysctls(qla_host_t *ha) 264 { 265 device_t dev; 266 267 dev = ha->pci_dev; 268 269 ha->hw.num_sds_rings = MAX_SDS_RINGS; 270 ha->hw.num_rds_rings = MAX_RDS_RINGS; 271 ha->hw.num_tx_rings = NUM_TX_RINGS; 272 273 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 274 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 275 OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings, 276 ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings"); 277 278 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 279 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 280 OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings, 281 ha->hw.num_sds_rings, "Number of Status Descriptor Rings"); 282 283 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 284 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 285 OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings, 286 ha->hw.num_tx_rings, "Number of Transmit Rings"); 287 288 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 289 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 290 OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx, 291 ha->txr_idx, "Tx Ring Used"); 292 293 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 294 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 295 OID_AUTO, "drvr_stats", CTLTYPE_INT | CTLFLAG_RW, 296 (void *)ha, 0, 297 qla_sysctl_get_drvr_stats, "I", "Driver Maintained Statistics"); 298 299 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 300 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 301 OID_AUTO, "quick_stats", CTLTYPE_INT | CTLFLAG_RW, 302 (void *)ha, 0, 303 qla_sysctl_get_quick_stats, "I", "Quick Statistics"); 304 305 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 306 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 307 OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs, 308 ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt"); 309 310 ha->hw.sds_cidx_thres = 32; 311 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 312 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 313 OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres, 314 ha->hw.sds_cidx_thres, 315 "Number of SDS entries to process before updating" 316 " SDS Ring Consumer Index"); 317 318 ha->hw.rds_pidx_thres = 32; 319 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 320 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 321 OID_AUTO, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres, 322 ha->hw.rds_pidx_thres, 323 "Number of Rcv Rings Entries to post before updating" 324 " RDS Ring Producer Index"); 325 326 ha->hw.rcv_intr_coalesce = (3 << 16) | 256; 327 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 328 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 329 OID_AUTO, "rcv_intr_coalesce", CTLFLAG_RW, 330 &ha->hw.rcv_intr_coalesce, 331 ha->hw.rcv_intr_coalesce, 332 "Rcv Intr Coalescing Parameters\n" 333 "\tbits 15:0 max packets\n" 334 "\tbits 31:16 max micro-seconds to wait\n" 335 "\tplease run\n" 336 "\tifconfig <if> down && ifconfig <if> up\n" 337 "\tto take effect \n"); 338 339 ha->hw.xmt_intr_coalesce = (64 << 16) | 64; 340 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 341 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 342 OID_AUTO, "xmt_intr_coalesce", CTLFLAG_RW, 343 &ha->hw.xmt_intr_coalesce, 344 ha->hw.xmt_intr_coalesce, 345 "Xmt Intr Coalescing Parameters\n" 346 "\tbits 15:0 max packets\n" 347 "\tbits 31:16 max micro-seconds to wait\n" 348 "\tplease run\n" 349 "\tifconfig <if> down && ifconfig <if> up\n" 350 "\tto take effect \n"); 351 352 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 353 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 354 OID_AUTO, "port_cfg", CTLTYPE_INT | CTLFLAG_RW, 355 (void *)ha, 0, 356 qla_sysctl_port_cfg, "I", 357 "Set Port Configuration if values below " 358 "otherwise Get Port Configuration\n" 359 "\tBits 0-3 ; 1 = DCBX Enable; 0 = DCBX Disable\n" 360 "\tBits 4-7 : 0 = no pause; 1 = std ; 2 = ppm \n" 361 "\tBits 8-11: std pause cfg; 0 = xmt and rcv;" 362 " 1 = xmt only; 2 = rcv only;\n" 363 ); 364 365 ha->hw.enable_9kb = 1; 366 367 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 368 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 369 OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb, 370 ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000"); 371 372 ha->hw.mdump_active = 0; 373 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 374 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 375 OID_AUTO, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active, 376 ha->hw.mdump_active, 377 "Minidump Utility is Active \n" 378 "\t 0 = Minidump Utility is not active\n" 379 "\t 1 = Minidump Utility is retrieved on this port\n" 380 "\t 2 = Minidump Utility is retrieved on the other port\n"); 381 382 ha->hw.mdump_start = 0; 383 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 384 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 385 OID_AUTO, "minidump_start", CTLFLAG_RW, 386 &ha->hw.mdump_start, ha->hw.mdump_start, 387 "Minidump Utility can start minidump process"); 388 #ifdef QL_DBG 389 390 ha->err_inject = 0; 391 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 392 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 393 OID_AUTO, "err_inject", 394 CTLFLAG_RW, &ha->err_inject, ha->err_inject, 395 "Error to be injected\n" 396 "\t\t\t 0: No Errors\n" 397 "\t\t\t 1: rcv: rxb struct invalid\n" 398 "\t\t\t 2: rcv: mp == NULL\n" 399 "\t\t\t 3: lro: rxb struct invalid\n" 400 "\t\t\t 4: lro: mp == NULL\n" 401 "\t\t\t 5: rcv: num handles invalid\n" 402 "\t\t\t 6: reg: indirect reg rd_wr failure\n" 403 "\t\t\t 7: ocm: offchip memory rd_wr failure\n" 404 "\t\t\t 8: mbx: mailbox command failure\n" 405 "\t\t\t 9: heartbeat failure\n" 406 "\t\t\t A: temperature failure\n" ); 407 408 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 409 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 410 OID_AUTO, "peg_stop", CTLTYPE_INT | CTLFLAG_RW, 411 (void *)ha, 0, 412 qla_sysctl_stop_pegs, "I", "Peg Stop"); 413 414 #endif /* #ifdef QL_DBG */ 415 416 ha->hw.user_pri_nic = 0; 417 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 418 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 419 OID_AUTO, "user_pri_nic", CTLFLAG_RW, &ha->hw.user_pri_nic, 420 ha->hw.user_pri_nic, 421 "VLAN Tag User Priority for Normal Ethernet Packets"); 422 423 ha->hw.user_pri_iscsi = 4; 424 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 425 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 426 OID_AUTO, "user_pri_iscsi", CTLFLAG_RW, &ha->hw.user_pri_iscsi, 427 ha->hw.user_pri_iscsi, 428 "VLAN Tag User Priority for iSCSI Packets"); 429 430 } 431 432 void 433 ql_hw_link_status(qla_host_t *ha) 434 { 435 device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui); 436 437 if (ha->hw.link_up) { 438 device_printf(ha->pci_dev, "link Up\n"); 439 } else { 440 device_printf(ha->pci_dev, "link Down\n"); 441 } 442 443 if (ha->hw.flags.fduplex) { 444 device_printf(ha->pci_dev, "Full Duplex\n"); 445 } else { 446 device_printf(ha->pci_dev, "Half Duplex\n"); 447 } 448 449 if (ha->hw.flags.autoneg) { 450 device_printf(ha->pci_dev, "Auto Negotiation Enabled\n"); 451 } else { 452 device_printf(ha->pci_dev, "Auto Negotiation Disabled\n"); 453 } 454 455 switch (ha->hw.link_speed) { 456 case 0x710: 457 device_printf(ha->pci_dev, "link speed\t\t 10Gps\n"); 458 break; 459 460 case 0x3E8: 461 device_printf(ha->pci_dev, "link speed\t\t 1Gps\n"); 462 break; 463 464 case 0x64: 465 device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n"); 466 break; 467 468 default: 469 device_printf(ha->pci_dev, "link speed\t\t Unknown\n"); 470 break; 471 } 472 473 switch (ha->hw.module_type) { 474 475 case 0x01: 476 device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n"); 477 break; 478 479 case 0x02: 480 device_printf(ha->pci_dev, "Module Type 10GBase-LR\n"); 481 break; 482 483 case 0x03: 484 device_printf(ha->pci_dev, "Module Type 10GBase-SR\n"); 485 break; 486 487 case 0x04: 488 device_printf(ha->pci_dev, 489 "Module Type 10GE Passive Copper(Compliant)[%d m]\n", 490 ha->hw.cable_length); 491 break; 492 493 case 0x05: 494 device_printf(ha->pci_dev, "Module Type 10GE Active" 495 " Limiting Copper(Compliant)[%d m]\n", 496 ha->hw.cable_length); 497 break; 498 499 case 0x06: 500 device_printf(ha->pci_dev, 501 "Module Type 10GE Passive Copper" 502 " (Legacy, Best Effort)[%d m]\n", 503 ha->hw.cable_length); 504 break; 505 506 case 0x07: 507 device_printf(ha->pci_dev, "Module Type 1000Base-SX\n"); 508 break; 509 510 case 0x08: 511 device_printf(ha->pci_dev, "Module Type 1000Base-LX\n"); 512 break; 513 514 case 0x09: 515 device_printf(ha->pci_dev, "Module Type 1000Base-CX\n"); 516 break; 517 518 case 0x0A: 519 device_printf(ha->pci_dev, "Module Type 1000Base-T\n"); 520 break; 521 522 case 0x0B: 523 device_printf(ha->pci_dev, "Module Type 1GE Passive Copper" 524 "(Legacy, Best Effort)\n"); 525 break; 526 527 default: 528 device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n", 529 ha->hw.module_type); 530 break; 531 } 532 533 if (ha->hw.link_faults == 1) 534 device_printf(ha->pci_dev, "SFP Power Fault\n"); 535 } 536 537 /* 538 * Name: ql_free_dma 539 * Function: Frees the DMA'able memory allocated in ql_alloc_dma() 540 */ 541 void 542 ql_free_dma(qla_host_t *ha) 543 { 544 uint32_t i; 545 546 if (ha->hw.dma_buf.flags.sds_ring) { 547 for (i = 0; i < ha->hw.num_sds_rings; i++) { 548 ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]); 549 } 550 ha->hw.dma_buf.flags.sds_ring = 0; 551 } 552 553 if (ha->hw.dma_buf.flags.rds_ring) { 554 for (i = 0; i < ha->hw.num_rds_rings; i++) { 555 ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]); 556 } 557 ha->hw.dma_buf.flags.rds_ring = 0; 558 } 559 560 if (ha->hw.dma_buf.flags.tx_ring) { 561 ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring); 562 ha->hw.dma_buf.flags.tx_ring = 0; 563 } 564 qla_minidump_free(ha); 565 } 566 567 /* 568 * Name: ql_alloc_dma 569 * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts. 570 */ 571 int 572 ql_alloc_dma(qla_host_t *ha) 573 { 574 device_t dev; 575 uint32_t i, j, size, tx_ring_size; 576 qla_hw_t *hw; 577 qla_hw_tx_cntxt_t *tx_cntxt; 578 uint8_t *vaddr; 579 bus_addr_t paddr; 580 581 dev = ha->pci_dev; 582 583 QL_DPRINT2(ha, (dev, "%s: enter\n", __func__)); 584 585 hw = &ha->hw; 586 /* 587 * Allocate Transmit Ring 588 */ 589 tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS); 590 size = (tx_ring_size * ha->hw.num_tx_rings); 591 592 hw->dma_buf.tx_ring.alignment = 8; 593 hw->dma_buf.tx_ring.size = size + PAGE_SIZE; 594 595 if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) { 596 device_printf(dev, "%s: tx ring alloc failed\n", __func__); 597 goto ql_alloc_dma_exit; 598 } 599 600 vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b; 601 paddr = hw->dma_buf.tx_ring.dma_addr; 602 603 for (i = 0; i < ha->hw.num_tx_rings; i++) { 604 tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i]; 605 606 tx_cntxt->tx_ring_base = (q80_tx_cmd_t *)vaddr; 607 tx_cntxt->tx_ring_paddr = paddr; 608 609 vaddr += tx_ring_size; 610 paddr += tx_ring_size; 611 } 612 613 for (i = 0; i < ha->hw.num_tx_rings; i++) { 614 tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i]; 615 616 tx_cntxt->tx_cons = (uint32_t *)vaddr; 617 tx_cntxt->tx_cons_paddr = paddr; 618 619 vaddr += sizeof (uint32_t); 620 paddr += sizeof (uint32_t); 621 } 622 623 ha->hw.dma_buf.flags.tx_ring = 1; 624 625 QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n", 626 __func__, (void *)(hw->dma_buf.tx_ring.dma_addr), 627 hw->dma_buf.tx_ring.dma_b)); 628 /* 629 * Allocate Receive Descriptor Rings 630 */ 631 632 for (i = 0; i < hw->num_rds_rings; i++) { 633 634 hw->dma_buf.rds_ring[i].alignment = 8; 635 hw->dma_buf.rds_ring[i].size = 636 (sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS; 637 638 if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) { 639 device_printf(dev, "%s: rds ring[%d] alloc failed\n", 640 __func__, i); 641 642 for (j = 0; j < i; j++) 643 ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]); 644 645 goto ql_alloc_dma_exit; 646 } 647 QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n", 648 __func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr), 649 hw->dma_buf.rds_ring[i].dma_b)); 650 } 651 652 hw->dma_buf.flags.rds_ring = 1; 653 654 /* 655 * Allocate Status Descriptor Rings 656 */ 657 658 for (i = 0; i < hw->num_sds_rings; i++) { 659 hw->dma_buf.sds_ring[i].alignment = 8; 660 hw->dma_buf.sds_ring[i].size = 661 (sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS; 662 663 if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) { 664 device_printf(dev, "%s: sds ring alloc failed\n", 665 __func__); 666 667 for (j = 0; j < i; j++) 668 ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]); 669 670 goto ql_alloc_dma_exit; 671 } 672 QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n", 673 __func__, i, 674 (void *)(hw->dma_buf.sds_ring[i].dma_addr), 675 hw->dma_buf.sds_ring[i].dma_b)); 676 } 677 for (i = 0; i < hw->num_sds_rings; i++) { 678 hw->sds[i].sds_ring_base = 679 (q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b; 680 } 681 682 hw->dma_buf.flags.sds_ring = 1; 683 684 return 0; 685 686 ql_alloc_dma_exit: 687 ql_free_dma(ha); 688 return -1; 689 } 690 691 #define Q8_MBX_MSEC_DELAY 5000 692 693 static int 694 qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox, 695 uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause) 696 { 697 uint32_t i; 698 uint32_t data; 699 int ret = 0; 700 701 if (QL_ERR_INJECT(ha, INJCT_MBX_CMD_FAILURE)) { 702 ret = -3; 703 ha->qla_initiate_recovery = 1; 704 goto exit_qla_mbx_cmd; 705 } 706 707 if (no_pause) 708 i = 1000; 709 else 710 i = Q8_MBX_MSEC_DELAY; 711 712 while (i) { 713 data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL); 714 if (data == 0) 715 break; 716 if (no_pause) { 717 DELAY(1000); 718 } else { 719 qla_mdelay(__func__, 1); 720 } 721 i--; 722 } 723 724 if (i == 0) { 725 device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n", 726 __func__, data); 727 ret = -1; 728 ha->qla_initiate_recovery = 1; 729 goto exit_qla_mbx_cmd; 730 } 731 732 for (i = 0; i < n_hmbox; i++) { 733 WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox); 734 h_mbox++; 735 } 736 737 WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1); 738 739 740 i = Q8_MBX_MSEC_DELAY; 741 while (i) { 742 data = READ_REG32(ha, Q8_FW_MBOX_CNTRL); 743 744 if ((data & 0x3) == 1) { 745 data = READ_REG32(ha, Q8_FW_MBOX0); 746 if ((data & 0xF000) != 0x8000) 747 break; 748 } 749 if (no_pause) { 750 DELAY(1000); 751 } else { 752 qla_mdelay(__func__, 1); 753 } 754 i--; 755 } 756 if (i == 0) { 757 device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n", 758 __func__, data); 759 ret = -2; 760 ha->qla_initiate_recovery = 1; 761 goto exit_qla_mbx_cmd; 762 } 763 764 for (i = 0; i < n_fwmbox; i++) { 765 *fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2))); 766 } 767 768 WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0); 769 WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0); 770 771 exit_qla_mbx_cmd: 772 return (ret); 773 } 774 775 int 776 qla_get_nic_partition(qla_host_t *ha, uint32_t *supports_9kb, 777 uint32_t *num_rcvq) 778 { 779 uint32_t *mbox, err; 780 device_t dev = ha->pci_dev; 781 782 bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX)); 783 784 mbox = ha->hw.mbox; 785 786 mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29); 787 788 if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) { 789 device_printf(dev, "%s: failed0\n", __func__); 790 return (-1); 791 } 792 err = mbox[0] >> 25; 793 794 if (supports_9kb != NULL) { 795 if (mbox[16] & 0x80) /* bit 7 of mbox 16 */ 796 *supports_9kb = 1; 797 else 798 *supports_9kb = 0; 799 } 800 801 if (num_rcvq != NULL) 802 *num_rcvq = ((mbox[6] >> 16) & 0xFFFF); 803 804 if ((err != 1) && (err != 0)) { 805 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 806 return (-1); 807 } 808 return 0; 809 } 810 811 static int 812 qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx, uint32_t num_intrs, 813 uint32_t create) 814 { 815 uint32_t i, err; 816 device_t dev = ha->pci_dev; 817 q80_config_intr_t *c_intr; 818 q80_config_intr_rsp_t *c_intr_rsp; 819 820 c_intr = (q80_config_intr_t *)ha->hw.mbox; 821 bzero(c_intr, (sizeof (q80_config_intr_t))); 822 823 c_intr->opcode = Q8_MBX_CONFIG_INTR; 824 825 c_intr->count_version = (sizeof (q80_config_intr_t) >> 2); 826 c_intr->count_version |= Q8_MBX_CMD_VERSION; 827 828 c_intr->nentries = num_intrs; 829 830 for (i = 0; i < num_intrs; i++) { 831 if (create) { 832 c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE; 833 c_intr->intr[i].msix_index = start_idx + 1 + i; 834 } else { 835 c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE; 836 c_intr->intr[i].msix_index = 837 ha->hw.intr_id[(start_idx + i)]; 838 } 839 840 c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X; 841 } 842 843 if (qla_mbx_cmd(ha, (uint32_t *)c_intr, 844 (sizeof (q80_config_intr_t) >> 2), 845 ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) { 846 device_printf(dev, "%s: failed0\n", __func__); 847 return (-1); 848 } 849 850 c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox; 851 852 err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status); 853 854 if (err) { 855 device_printf(dev, "%s: failed1 [0x%08x, %d]\n", __func__, err, 856 c_intr_rsp->nentries); 857 858 for (i = 0; i < c_intr_rsp->nentries; i++) { 859 device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n", 860 __func__, i, 861 c_intr_rsp->intr[i].status, 862 c_intr_rsp->intr[i].intr_id, 863 c_intr_rsp->intr[i].intr_src); 864 } 865 866 return (-1); 867 } 868 869 for (i = 0; ((i < num_intrs) && create); i++) { 870 if (!c_intr_rsp->intr[i].status) { 871 ha->hw.intr_id[(start_idx + i)] = 872 c_intr_rsp->intr[i].intr_id; 873 ha->hw.intr_src[(start_idx + i)] = 874 c_intr_rsp->intr[i].intr_src; 875 } 876 } 877 878 return (0); 879 } 880 881 /* 882 * Name: qla_config_rss 883 * Function: Configure RSS for the context/interface. 884 */ 885 static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL, 886 0x8030f20c77cb2da3ULL, 887 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL, 888 0x255b0ec26d5a56daULL }; 889 890 static int 891 qla_config_rss(qla_host_t *ha, uint16_t cntxt_id) 892 { 893 q80_config_rss_t *c_rss; 894 q80_config_rss_rsp_t *c_rss_rsp; 895 uint32_t err, i; 896 device_t dev = ha->pci_dev; 897 898 c_rss = (q80_config_rss_t *)ha->hw.mbox; 899 bzero(c_rss, (sizeof (q80_config_rss_t))); 900 901 c_rss->opcode = Q8_MBX_CONFIG_RSS; 902 903 c_rss->count_version = (sizeof (q80_config_rss_t) >> 2); 904 c_rss->count_version |= Q8_MBX_CMD_VERSION; 905 906 c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP | 907 Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP); 908 //c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP | 909 // Q8_MBX_RSS_HASH_TYPE_IPV6_TCP); 910 911 c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS; 912 c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE; 913 914 c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK; 915 916 c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID; 917 c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS; 918 919 c_rss->cntxt_id = cntxt_id; 920 921 for (i = 0; i < 5; i++) { 922 c_rss->rss_key[i] = rss_key[i]; 923 } 924 925 if (qla_mbx_cmd(ha, (uint32_t *)c_rss, 926 (sizeof (q80_config_rss_t) >> 2), 927 ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) { 928 device_printf(dev, "%s: failed0\n", __func__); 929 return (-1); 930 } 931 c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox; 932 933 err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status); 934 935 if (err) { 936 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 937 return (-1); 938 } 939 return 0; 940 } 941 942 static int 943 qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count, 944 uint16_t cntxt_id, uint8_t *ind_table) 945 { 946 q80_config_rss_ind_table_t *c_rss_ind; 947 q80_config_rss_ind_table_rsp_t *c_rss_ind_rsp; 948 uint32_t err; 949 device_t dev = ha->pci_dev; 950 951 if ((count > Q8_RSS_IND_TBL_SIZE) || 952 ((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) { 953 device_printf(dev, "%s: illegal count [%d, %d]\n", __func__, 954 start_idx, count); 955 return (-1); 956 } 957 958 c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox; 959 bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t)); 960 961 c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE; 962 c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2); 963 c_rss_ind->count_version |= Q8_MBX_CMD_VERSION; 964 965 c_rss_ind->start_idx = start_idx; 966 c_rss_ind->end_idx = start_idx + count - 1; 967 c_rss_ind->cntxt_id = cntxt_id; 968 bcopy(ind_table, c_rss_ind->ind_table, count); 969 970 if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind, 971 (sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox, 972 (sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) { 973 device_printf(dev, "%s: failed0\n", __func__); 974 return (-1); 975 } 976 977 c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox; 978 err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status); 979 980 if (err) { 981 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 982 return (-1); 983 } 984 return 0; 985 } 986 987 /* 988 * Name: qla_config_intr_coalesce 989 * Function: Configure Interrupt Coalescing. 990 */ 991 static int 992 qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable, 993 int rcv) 994 { 995 q80_config_intr_coalesc_t *intrc; 996 q80_config_intr_coalesc_rsp_t *intrc_rsp; 997 uint32_t err, i; 998 device_t dev = ha->pci_dev; 999 1000 intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox; 1001 bzero(intrc, (sizeof (q80_config_intr_coalesc_t))); 1002 1003 intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE; 1004 intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2); 1005 intrc->count_version |= Q8_MBX_CMD_VERSION; 1006 1007 if (rcv) { 1008 intrc->flags = Q8_MBX_INTRC_FLAGS_RCV; 1009 intrc->max_pkts = ha->hw.rcv_intr_coalesce & 0xFFFF; 1010 intrc->max_mswait = (ha->hw.rcv_intr_coalesce >> 16) & 0xFFFF; 1011 } else { 1012 intrc->flags = Q8_MBX_INTRC_FLAGS_XMT; 1013 intrc->max_pkts = ha->hw.xmt_intr_coalesce & 0xFFFF; 1014 intrc->max_mswait = (ha->hw.xmt_intr_coalesce >> 16) & 0xFFFF; 1015 } 1016 1017 intrc->cntxt_id = cntxt_id; 1018 1019 if (tenable) { 1020 intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC; 1021 intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC; 1022 1023 for (i = 0; i < ha->hw.num_sds_rings; i++) { 1024 intrc->sds_ring_mask |= (1 << i); 1025 } 1026 intrc->ms_timeout = 1000; 1027 } 1028 1029 if (qla_mbx_cmd(ha, (uint32_t *)intrc, 1030 (sizeof (q80_config_intr_coalesc_t) >> 2), 1031 ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) { 1032 device_printf(dev, "%s: failed0\n", __func__); 1033 return (-1); 1034 } 1035 intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox; 1036 1037 err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status); 1038 1039 if (err) { 1040 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 1041 return (-1); 1042 } 1043 1044 return 0; 1045 } 1046 1047 1048 /* 1049 * Name: qla_config_mac_addr 1050 * Function: binds a MAC address to the context/interface. 1051 * Can be unicast, multicast or broadcast. 1052 */ 1053 static int 1054 qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac) 1055 { 1056 q80_config_mac_addr_t *cmac; 1057 q80_config_mac_addr_rsp_t *cmac_rsp; 1058 uint32_t err; 1059 device_t dev = ha->pci_dev; 1060 1061 cmac = (q80_config_mac_addr_t *)ha->hw.mbox; 1062 bzero(cmac, (sizeof (q80_config_mac_addr_t))); 1063 1064 cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR; 1065 cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2; 1066 cmac->count_version |= Q8_MBX_CMD_VERSION; 1067 1068 if (add_mac) 1069 cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR; 1070 else 1071 cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR; 1072 1073 cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS; 1074 1075 cmac->nmac_entries = 1; 1076 cmac->cntxt_id = ha->hw.rcv_cntxt_id; 1077 bcopy(mac_addr, cmac->mac_addr[0].addr, 6); 1078 1079 if (qla_mbx_cmd(ha, (uint32_t *)cmac, 1080 (sizeof (q80_config_mac_addr_t) >> 2), 1081 ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) { 1082 device_printf(dev, "%s: %s failed0\n", __func__, 1083 (add_mac ? "Add" : "Del")); 1084 return (-1); 1085 } 1086 cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox; 1087 1088 err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status); 1089 1090 if (err) { 1091 device_printf(dev, "%s: %s " 1092 "%02x:%02x:%02x:%02x:%02x:%02x failed1 [0x%08x]\n", 1093 __func__, (add_mac ? "Add" : "Del"), 1094 mac_addr[0], mac_addr[1], mac_addr[2], 1095 mac_addr[3], mac_addr[4], mac_addr[5], err); 1096 return (-1); 1097 } 1098 1099 return 0; 1100 } 1101 1102 1103 /* 1104 * Name: qla_set_mac_rcv_mode 1105 * Function: Enable/Disable AllMulticast and Promiscous Modes. 1106 */ 1107 static int 1108 qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode) 1109 { 1110 q80_config_mac_rcv_mode_t *rcv_mode; 1111 uint32_t err; 1112 q80_config_mac_rcv_mode_rsp_t *rcv_mode_rsp; 1113 device_t dev = ha->pci_dev; 1114 1115 rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox; 1116 bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t))); 1117 1118 rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE; 1119 rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2; 1120 rcv_mode->count_version |= Q8_MBX_CMD_VERSION; 1121 1122 rcv_mode->mode = mode; 1123 1124 rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id; 1125 1126 if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode, 1127 (sizeof (q80_config_mac_rcv_mode_t) >> 2), 1128 ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) { 1129 device_printf(dev, "%s: failed0\n", __func__); 1130 return (-1); 1131 } 1132 rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox; 1133 1134 err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status); 1135 1136 if (err) { 1137 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 1138 return (-1); 1139 } 1140 1141 return 0; 1142 } 1143 1144 int 1145 ql_set_promisc(qla_host_t *ha) 1146 { 1147 int ret; 1148 1149 ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE; 1150 ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode); 1151 return (ret); 1152 } 1153 1154 void 1155 qla_reset_promisc(qla_host_t *ha) 1156 { 1157 ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_RCV_PROMISC_ENABLE; 1158 (void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode); 1159 } 1160 1161 int 1162 ql_set_allmulti(qla_host_t *ha) 1163 { 1164 int ret; 1165 1166 ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE; 1167 ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode); 1168 return (ret); 1169 } 1170 1171 void 1172 qla_reset_allmulti(qla_host_t *ha) 1173 { 1174 ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_ALL_MULTI_ENABLE; 1175 (void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode); 1176 } 1177 1178 /* 1179 * Name: ql_set_max_mtu 1180 * Function: 1181 * Sets the maximum transfer unit size for the specified rcv context. 1182 */ 1183 int 1184 ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id) 1185 { 1186 device_t dev; 1187 q80_set_max_mtu_t *max_mtu; 1188 q80_set_max_mtu_rsp_t *max_mtu_rsp; 1189 uint32_t err; 1190 1191 dev = ha->pci_dev; 1192 1193 max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox; 1194 bzero(max_mtu, (sizeof (q80_set_max_mtu_t))); 1195 1196 max_mtu->opcode = Q8_MBX_SET_MAX_MTU; 1197 max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2); 1198 max_mtu->count_version |= Q8_MBX_CMD_VERSION; 1199 1200 max_mtu->cntxt_id = cntxt_id; 1201 max_mtu->mtu = mtu; 1202 1203 if (qla_mbx_cmd(ha, (uint32_t *)max_mtu, 1204 (sizeof (q80_set_max_mtu_t) >> 2), 1205 ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) { 1206 device_printf(dev, "%s: failed\n", __func__); 1207 return -1; 1208 } 1209 1210 max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox; 1211 1212 err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status); 1213 1214 if (err) { 1215 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 1216 } 1217 1218 return 0; 1219 } 1220 1221 static int 1222 qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id) 1223 { 1224 device_t dev; 1225 q80_link_event_t *lnk; 1226 q80_link_event_rsp_t *lnk_rsp; 1227 uint32_t err; 1228 1229 dev = ha->pci_dev; 1230 1231 lnk = (q80_link_event_t *)ha->hw.mbox; 1232 bzero(lnk, (sizeof (q80_link_event_t))); 1233 1234 lnk->opcode = Q8_MBX_LINK_EVENT_REQ; 1235 lnk->count_version = (sizeof (q80_link_event_t) >> 2); 1236 lnk->count_version |= Q8_MBX_CMD_VERSION; 1237 1238 lnk->cntxt_id = cntxt_id; 1239 lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC; 1240 1241 if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2), 1242 ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) { 1243 device_printf(dev, "%s: failed\n", __func__); 1244 return -1; 1245 } 1246 1247 lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox; 1248 1249 err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status); 1250 1251 if (err) { 1252 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 1253 } 1254 1255 return 0; 1256 } 1257 1258 static int 1259 qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id) 1260 { 1261 device_t dev; 1262 q80_config_fw_lro_t *fw_lro; 1263 q80_config_fw_lro_rsp_t *fw_lro_rsp; 1264 uint32_t err; 1265 1266 dev = ha->pci_dev; 1267 1268 fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox; 1269 bzero(fw_lro, sizeof(q80_config_fw_lro_t)); 1270 1271 fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO; 1272 fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2); 1273 fw_lro->count_version |= Q8_MBX_CMD_VERSION; 1274 1275 fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK; 1276 fw_lro->flags |= Q8_MBX_FW_LRO_IPV6 | Q8_MBX_FW_LRO_IPV6_WO_DST_IP_CHK; 1277 1278 fw_lro->cntxt_id = cntxt_id; 1279 1280 if (qla_mbx_cmd(ha, (uint32_t *)fw_lro, 1281 (sizeof (q80_config_fw_lro_t) >> 2), 1282 ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) { 1283 device_printf(dev, "%s: failed\n", __func__); 1284 return -1; 1285 } 1286 1287 fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox; 1288 1289 err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status); 1290 1291 if (err) { 1292 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 1293 } 1294 1295 return 0; 1296 } 1297 1298 static void 1299 qla_xmt_stats(qla_host_t *ha, q80_xmt_stats_t *xstat, int i) 1300 { 1301 device_t dev = ha->pci_dev; 1302 1303 if (i < ha->hw.num_tx_rings) { 1304 device_printf(dev, "%s[%d]: total_bytes\t\t%" PRIu64 "\n", 1305 __func__, i, xstat->total_bytes); 1306 device_printf(dev, "%s[%d]: total_pkts\t\t%" PRIu64 "\n", 1307 __func__, i, xstat->total_pkts); 1308 device_printf(dev, "%s[%d]: errors\t\t%" PRIu64 "\n", 1309 __func__, i, xstat->errors); 1310 device_printf(dev, "%s[%d]: pkts_dropped\t%" PRIu64 "\n", 1311 __func__, i, xstat->pkts_dropped); 1312 device_printf(dev, "%s[%d]: switch_pkts\t\t%" PRIu64 "\n", 1313 __func__, i, xstat->switch_pkts); 1314 device_printf(dev, "%s[%d]: num_buffers\t\t%" PRIu64 "\n", 1315 __func__, i, xstat->num_buffers); 1316 } else { 1317 device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n", 1318 __func__, xstat->total_bytes); 1319 device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n", 1320 __func__, xstat->total_pkts); 1321 device_printf(dev, "%s: errors\t\t\t%" PRIu64 "\n", 1322 __func__, xstat->errors); 1323 device_printf(dev, "%s: pkts_dropped\t\t\t%" PRIu64 "\n", 1324 __func__, xstat->pkts_dropped); 1325 device_printf(dev, "%s: switch_pkts\t\t\t%" PRIu64 "\n", 1326 __func__, xstat->switch_pkts); 1327 device_printf(dev, "%s: num_buffers\t\t\t%" PRIu64 "\n", 1328 __func__, xstat->num_buffers); 1329 } 1330 } 1331 1332 static void 1333 qla_rcv_stats(qla_host_t *ha, q80_rcv_stats_t *rstat) 1334 { 1335 device_t dev = ha->pci_dev; 1336 1337 device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n", __func__, 1338 rstat->total_bytes); 1339 device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n", __func__, 1340 rstat->total_pkts); 1341 device_printf(dev, "%s: lro_pkt_count\t\t%" PRIu64 "\n", __func__, 1342 rstat->lro_pkt_count); 1343 device_printf(dev, "%s: sw_pkt_count\t\t\t%" PRIu64 "\n", __func__, 1344 rstat->sw_pkt_count); 1345 device_printf(dev, "%s: ip_chksum_err\t\t%" PRIu64 "\n", __func__, 1346 rstat->ip_chksum_err); 1347 device_printf(dev, "%s: pkts_wo_acntxts\t\t%" PRIu64 "\n", __func__, 1348 rstat->pkts_wo_acntxts); 1349 device_printf(dev, "%s: pkts_dropped_no_sds_card\t%" PRIu64 "\n", 1350 __func__, rstat->pkts_dropped_no_sds_card); 1351 device_printf(dev, "%s: pkts_dropped_no_sds_host\t%" PRIu64 "\n", 1352 __func__, rstat->pkts_dropped_no_sds_host); 1353 device_printf(dev, "%s: oversized_pkts\t\t%" PRIu64 "\n", __func__, 1354 rstat->oversized_pkts); 1355 device_printf(dev, "%s: pkts_dropped_no_rds\t\t%" PRIu64 "\n", 1356 __func__, rstat->pkts_dropped_no_rds); 1357 device_printf(dev, "%s: unxpctd_mcast_pkts\t\t%" PRIu64 "\n", 1358 __func__, rstat->unxpctd_mcast_pkts); 1359 device_printf(dev, "%s: re1_fbq_error\t\t%" PRIu64 "\n", __func__, 1360 rstat->re1_fbq_error); 1361 device_printf(dev, "%s: invalid_mac_addr\t\t%" PRIu64 "\n", __func__, 1362 rstat->invalid_mac_addr); 1363 device_printf(dev, "%s: rds_prime_trys\t\t%" PRIu64 "\n", __func__, 1364 rstat->rds_prime_trys); 1365 device_printf(dev, "%s: rds_prime_success\t\t%" PRIu64 "\n", __func__, 1366 rstat->rds_prime_success); 1367 device_printf(dev, "%s: lro_flows_added\t\t%" PRIu64 "\n", __func__, 1368 rstat->lro_flows_added); 1369 device_printf(dev, "%s: lro_flows_deleted\t\t%" PRIu64 "\n", __func__, 1370 rstat->lro_flows_deleted); 1371 device_printf(dev, "%s: lro_flows_active\t\t%" PRIu64 "\n", __func__, 1372 rstat->lro_flows_active); 1373 device_printf(dev, "%s: pkts_droped_unknown\t\t%" PRIu64 "\n", 1374 __func__, rstat->pkts_droped_unknown); 1375 } 1376 1377 static void 1378 qla_mac_stats(qla_host_t *ha, q80_mac_stats_t *mstat) 1379 { 1380 device_t dev = ha->pci_dev; 1381 1382 device_printf(dev, "%s: xmt_frames\t\t\t%" PRIu64 "\n", __func__, 1383 mstat->xmt_frames); 1384 device_printf(dev, "%s: xmt_bytes\t\t\t%" PRIu64 "\n", __func__, 1385 mstat->xmt_bytes); 1386 device_printf(dev, "%s: xmt_mcast_pkts\t\t%" PRIu64 "\n", __func__, 1387 mstat->xmt_mcast_pkts); 1388 device_printf(dev, "%s: xmt_bcast_pkts\t\t%" PRIu64 "\n", __func__, 1389 mstat->xmt_bcast_pkts); 1390 device_printf(dev, "%s: xmt_pause_frames\t\t%" PRIu64 "\n", __func__, 1391 mstat->xmt_pause_frames); 1392 device_printf(dev, "%s: xmt_cntrl_pkts\t\t%" PRIu64 "\n", __func__, 1393 mstat->xmt_cntrl_pkts); 1394 device_printf(dev, "%s: xmt_pkt_lt_64bytes\t\t%" PRIu64 "\n", 1395 __func__, mstat->xmt_pkt_lt_64bytes); 1396 device_printf(dev, "%s: xmt_pkt_lt_127bytes\t\t%" PRIu64 "\n", 1397 __func__, mstat->xmt_pkt_lt_127bytes); 1398 device_printf(dev, "%s: xmt_pkt_lt_255bytes\t\t%" PRIu64 "\n", 1399 __func__, mstat->xmt_pkt_lt_255bytes); 1400 device_printf(dev, "%s: xmt_pkt_lt_511bytes\t\t%" PRIu64 "\n", 1401 __func__, mstat->xmt_pkt_lt_511bytes); 1402 device_printf(dev, "%s: xmt_pkt_lt_1023bytes\t\t%" PRIu64 "\n", 1403 __func__, mstat->xmt_pkt_lt_1023bytes); 1404 device_printf(dev, "%s: xmt_pkt_lt_1518bytes\t\t%" PRIu64 "\n", 1405 __func__, mstat->xmt_pkt_lt_1518bytes); 1406 device_printf(dev, "%s: xmt_pkt_gt_1518bytes\t\t%" PRIu64 "\n", 1407 __func__, mstat->xmt_pkt_gt_1518bytes); 1408 1409 device_printf(dev, "%s: rcv_frames\t\t\t%" PRIu64 "\n", __func__, 1410 mstat->rcv_frames); 1411 device_printf(dev, "%s: rcv_bytes\t\t\t%" PRIu64 "\n", __func__, 1412 mstat->rcv_bytes); 1413 device_printf(dev, "%s: rcv_mcast_pkts\t\t%" PRIu64 "\n", __func__, 1414 mstat->rcv_mcast_pkts); 1415 device_printf(dev, "%s: rcv_bcast_pkts\t\t%" PRIu64 "\n", __func__, 1416 mstat->rcv_bcast_pkts); 1417 device_printf(dev, "%s: rcv_pause_frames\t\t%" PRIu64 "\n", __func__, 1418 mstat->rcv_pause_frames); 1419 device_printf(dev, "%s: rcv_cntrl_pkts\t\t%" PRIu64 "\n", __func__, 1420 mstat->rcv_cntrl_pkts); 1421 device_printf(dev, "%s: rcv_pkt_lt_64bytes\t\t%" PRIu64 "\n", 1422 __func__, mstat->rcv_pkt_lt_64bytes); 1423 device_printf(dev, "%s: rcv_pkt_lt_127bytes\t\t%" PRIu64 "\n", 1424 __func__, mstat->rcv_pkt_lt_127bytes); 1425 device_printf(dev, "%s: rcv_pkt_lt_255bytes\t\t%" PRIu64 "\n", 1426 __func__, mstat->rcv_pkt_lt_255bytes); 1427 device_printf(dev, "%s: rcv_pkt_lt_511bytes\t\t%" PRIu64 "\n", 1428 __func__, mstat->rcv_pkt_lt_511bytes); 1429 device_printf(dev, "%s: rcv_pkt_lt_1023bytes\t\t%" PRIu64 "\n", 1430 __func__, mstat->rcv_pkt_lt_1023bytes); 1431 device_printf(dev, "%s: rcv_pkt_lt_1518bytes\t\t%" PRIu64 "\n", 1432 __func__, mstat->rcv_pkt_lt_1518bytes); 1433 device_printf(dev, "%s: rcv_pkt_gt_1518bytes\t\t%" PRIu64 "\n", 1434 __func__, mstat->rcv_pkt_gt_1518bytes); 1435 1436 device_printf(dev, "%s: rcv_len_error\t\t%" PRIu64 "\n", __func__, 1437 mstat->rcv_len_error); 1438 device_printf(dev, "%s: rcv_len_small\t\t%" PRIu64 "\n", __func__, 1439 mstat->rcv_len_small); 1440 device_printf(dev, "%s: rcv_len_large\t\t%" PRIu64 "\n", __func__, 1441 mstat->rcv_len_large); 1442 device_printf(dev, "%s: rcv_jabber\t\t\t%" PRIu64 "\n", __func__, 1443 mstat->rcv_jabber); 1444 device_printf(dev, "%s: rcv_dropped\t\t\t%" PRIu64 "\n", __func__, 1445 mstat->rcv_dropped); 1446 device_printf(dev, "%s: fcs_error\t\t\t%" PRIu64 "\n", __func__, 1447 mstat->fcs_error); 1448 device_printf(dev, "%s: align_error\t\t\t%" PRIu64 "\n", __func__, 1449 mstat->align_error); 1450 } 1451 1452 1453 static int 1454 qla_get_hw_stats(qla_host_t *ha, uint32_t cmd, uint32_t rsp_size) 1455 { 1456 device_t dev; 1457 q80_get_stats_t *stat; 1458 q80_get_stats_rsp_t *stat_rsp; 1459 uint32_t err; 1460 1461 dev = ha->pci_dev; 1462 1463 stat = (q80_get_stats_t *)ha->hw.mbox; 1464 bzero(stat, (sizeof (q80_get_stats_t))); 1465 1466 stat->opcode = Q8_MBX_GET_STATS; 1467 stat->count_version = 2; 1468 stat->count_version |= Q8_MBX_CMD_VERSION; 1469 1470 stat->cmd = cmd; 1471 1472 if (qla_mbx_cmd(ha, (uint32_t *)stat, 2, 1473 ha->hw.mbox, (rsp_size >> 2), 0)) { 1474 device_printf(dev, "%s: failed\n", __func__); 1475 return -1; 1476 } 1477 1478 stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox; 1479 1480 err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status); 1481 1482 if (err) { 1483 return -1; 1484 } 1485 1486 return 0; 1487 } 1488 1489 void 1490 ql_get_stats(qla_host_t *ha) 1491 { 1492 q80_get_stats_rsp_t *stat_rsp; 1493 q80_mac_stats_t *mstat; 1494 q80_xmt_stats_t *xstat; 1495 q80_rcv_stats_t *rstat; 1496 uint32_t cmd; 1497 int i; 1498 1499 stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox; 1500 /* 1501 * Get MAC Statistics 1502 */ 1503 cmd = Q8_GET_STATS_CMD_TYPE_MAC; 1504 // cmd |= Q8_GET_STATS_CMD_CLEAR; 1505 1506 cmd |= ((ha->pci_func & 0x1) << 16); 1507 1508 if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) { 1509 mstat = (q80_mac_stats_t *)&stat_rsp->u.mac; 1510 qla_mac_stats(ha, mstat); 1511 } else { 1512 device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n", 1513 __func__, ha->hw.mbox[0]); 1514 } 1515 /* 1516 * Get RCV Statistics 1517 */ 1518 cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT; 1519 // cmd |= Q8_GET_STATS_CMD_CLEAR; 1520 cmd |= (ha->hw.rcv_cntxt_id << 16); 1521 1522 if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) { 1523 rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv; 1524 qla_rcv_stats(ha, rstat); 1525 } else { 1526 device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n", 1527 __func__, ha->hw.mbox[0]); 1528 } 1529 /* 1530 * Get XMT Statistics 1531 */ 1532 for (i = 0 ; i < ha->hw.num_tx_rings; i++) { 1533 cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT; 1534 // cmd |= Q8_GET_STATS_CMD_CLEAR; 1535 cmd |= (ha->hw.tx_cntxt[i].tx_cntxt_id << 16); 1536 1537 if (qla_get_hw_stats(ha, cmd, sizeof(q80_get_stats_rsp_t)) 1538 == 0) { 1539 xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt; 1540 qla_xmt_stats(ha, xstat, i); 1541 } else { 1542 device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n", 1543 __func__, ha->hw.mbox[0]); 1544 } 1545 } 1546 return; 1547 } 1548 1549 static void 1550 qla_get_quick_stats(qla_host_t *ha) 1551 { 1552 q80_get_mac_rcv_xmt_stats_rsp_t *stat_rsp; 1553 q80_mac_stats_t *mstat; 1554 q80_xmt_stats_t *xstat; 1555 q80_rcv_stats_t *rstat; 1556 uint32_t cmd; 1557 1558 stat_rsp = (q80_get_mac_rcv_xmt_stats_rsp_t *)ha->hw.mbox; 1559 1560 cmd = Q8_GET_STATS_CMD_TYPE_ALL; 1561 // cmd |= Q8_GET_STATS_CMD_CLEAR; 1562 1563 // cmd |= ((ha->pci_func & 0x3) << 16); 1564 cmd |= (0xFFFF << 16); 1565 1566 if (qla_get_hw_stats(ha, cmd, 1567 sizeof (q80_get_mac_rcv_xmt_stats_rsp_t)) == 0) { 1568 1569 mstat = (q80_mac_stats_t *)&stat_rsp->mac; 1570 rstat = (q80_rcv_stats_t *)&stat_rsp->rcv; 1571 xstat = (q80_xmt_stats_t *)&stat_rsp->xmt; 1572 qla_mac_stats(ha, mstat); 1573 qla_rcv_stats(ha, rstat); 1574 qla_xmt_stats(ha, xstat, ha->hw.num_tx_rings); 1575 } else { 1576 device_printf(ha->pci_dev, "%s: failed [0x%08x]\n", 1577 __func__, ha->hw.mbox[0]); 1578 } 1579 return; 1580 } 1581 1582 /* 1583 * Name: qla_tx_tso 1584 * Function: Checks if the packet to be transmitted is a candidate for 1585 * Large TCP Segment Offload. If yes, the appropriate fields in the Tx 1586 * Ring Structure are plugged in. 1587 */ 1588 static int 1589 qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr) 1590 { 1591 struct ether_vlan_header *eh; 1592 struct ip *ip = NULL; 1593 struct ip6_hdr *ip6 = NULL; 1594 struct tcphdr *th = NULL; 1595 uint32_t ehdrlen, hdrlen, ip_hlen, tcp_hlen, tcp_opt_off; 1596 uint16_t etype, opcode, offload = 1; 1597 device_t dev; 1598 1599 dev = ha->pci_dev; 1600 1601 1602 eh = mtod(mp, struct ether_vlan_header *); 1603 1604 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 1605 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 1606 etype = ntohs(eh->evl_proto); 1607 } else { 1608 ehdrlen = ETHER_HDR_LEN; 1609 etype = ntohs(eh->evl_encap_proto); 1610 } 1611 1612 hdrlen = 0; 1613 1614 switch (etype) { 1615 case ETHERTYPE_IP: 1616 1617 tcp_opt_off = ehdrlen + sizeof(struct ip) + 1618 sizeof(struct tcphdr); 1619 1620 if (mp->m_len < tcp_opt_off) { 1621 m_copydata(mp, 0, tcp_opt_off, hdr); 1622 ip = (struct ip *)(hdr + ehdrlen); 1623 } else { 1624 ip = (struct ip *)(mp->m_data + ehdrlen); 1625 } 1626 1627 ip_hlen = ip->ip_hl << 2; 1628 opcode = Q8_TX_CMD_OP_XMT_TCP_LSO; 1629 1630 1631 if ((ip->ip_p != IPPROTO_TCP) || 1632 (ip_hlen != sizeof (struct ip))){ 1633 /* IP Options are not supported */ 1634 1635 offload = 0; 1636 } else 1637 th = (struct tcphdr *)((caddr_t)ip + ip_hlen); 1638 1639 break; 1640 1641 case ETHERTYPE_IPV6: 1642 1643 tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) + 1644 sizeof (struct tcphdr); 1645 1646 if (mp->m_len < tcp_opt_off) { 1647 m_copydata(mp, 0, tcp_opt_off, hdr); 1648 ip6 = (struct ip6_hdr *)(hdr + ehdrlen); 1649 } else { 1650 ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); 1651 } 1652 1653 ip_hlen = sizeof(struct ip6_hdr); 1654 opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6; 1655 1656 if (ip6->ip6_nxt != IPPROTO_TCP) { 1657 //device_printf(dev, "%s: ipv6\n", __func__); 1658 offload = 0; 1659 } else 1660 th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen); 1661 break; 1662 1663 default: 1664 QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__)); 1665 offload = 0; 1666 break; 1667 } 1668 1669 if (!offload) 1670 return (-1); 1671 1672 tcp_hlen = th->th_off << 2; 1673 hdrlen = ehdrlen + ip_hlen + tcp_hlen; 1674 1675 if (mp->m_len < hdrlen) { 1676 if (mp->m_len < tcp_opt_off) { 1677 if (tcp_hlen > sizeof(struct tcphdr)) { 1678 m_copydata(mp, tcp_opt_off, 1679 (tcp_hlen - sizeof(struct tcphdr)), 1680 &hdr[tcp_opt_off]); 1681 } 1682 } else { 1683 m_copydata(mp, 0, hdrlen, hdr); 1684 } 1685 } 1686 1687 tx_cmd->mss = mp->m_pkthdr.tso_segsz; 1688 1689 tx_cmd->flags_opcode = opcode ; 1690 tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen; 1691 tx_cmd->total_hdr_len = hdrlen; 1692 1693 /* Check for Multicast least significant bit of MSB == 1 */ 1694 if (eh->evl_dhost[0] & 0x01) { 1695 tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST; 1696 } 1697 1698 if (mp->m_len < hdrlen) { 1699 printf("%d\n", hdrlen); 1700 return (1); 1701 } 1702 1703 return (0); 1704 } 1705 1706 /* 1707 * Name: qla_tx_chksum 1708 * Function: Checks if the packet to be transmitted is a candidate for 1709 * TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx 1710 * Ring Structure are plugged in. 1711 */ 1712 static int 1713 qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code, 1714 uint32_t *tcp_hdr_off) 1715 { 1716 struct ether_vlan_header *eh; 1717 struct ip *ip; 1718 struct ip6_hdr *ip6; 1719 uint32_t ehdrlen, ip_hlen; 1720 uint16_t etype, opcode, offload = 1; 1721 device_t dev; 1722 uint8_t buf[sizeof(struct ip6_hdr)]; 1723 1724 dev = ha->pci_dev; 1725 1726 *op_code = 0; 1727 1728 if ((mp->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) == 0) 1729 return (-1); 1730 1731 eh = mtod(mp, struct ether_vlan_header *); 1732 1733 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 1734 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 1735 etype = ntohs(eh->evl_proto); 1736 } else { 1737 ehdrlen = ETHER_HDR_LEN; 1738 etype = ntohs(eh->evl_encap_proto); 1739 } 1740 1741 1742 switch (etype) { 1743 case ETHERTYPE_IP: 1744 ip = (struct ip *)(mp->m_data + ehdrlen); 1745 1746 ip_hlen = sizeof (struct ip); 1747 1748 if (mp->m_len < (ehdrlen + ip_hlen)) { 1749 m_copydata(mp, ehdrlen, sizeof(struct ip), buf); 1750 ip = (struct ip *)buf; 1751 } 1752 1753 if (ip->ip_p == IPPROTO_TCP) 1754 opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM; 1755 else if (ip->ip_p == IPPROTO_UDP) 1756 opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM; 1757 else { 1758 //device_printf(dev, "%s: ipv4\n", __func__); 1759 offload = 0; 1760 } 1761 break; 1762 1763 case ETHERTYPE_IPV6: 1764 ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); 1765 1766 ip_hlen = sizeof(struct ip6_hdr); 1767 1768 if (mp->m_len < (ehdrlen + ip_hlen)) { 1769 m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr), 1770 buf); 1771 ip6 = (struct ip6_hdr *)buf; 1772 } 1773 1774 if (ip6->ip6_nxt == IPPROTO_TCP) 1775 opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6; 1776 else if (ip6->ip6_nxt == IPPROTO_UDP) 1777 opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6; 1778 else { 1779 //device_printf(dev, "%s: ipv6\n", __func__); 1780 offload = 0; 1781 } 1782 break; 1783 1784 default: 1785 offload = 0; 1786 break; 1787 } 1788 if (!offload) 1789 return (-1); 1790 1791 *op_code = opcode; 1792 *tcp_hdr_off = (ip_hlen + ehdrlen); 1793 1794 return (0); 1795 } 1796 1797 #define QLA_TX_MIN_FREE 2 1798 /* 1799 * Name: ql_hw_send 1800 * Function: Transmits a packet. It first checks if the packet is a 1801 * candidate for Large TCP Segment Offload and then for UDP/TCP checksum 1802 * offload. If either of these creteria are not met, it is transmitted 1803 * as a regular ethernet frame. 1804 */ 1805 int 1806 ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs, 1807 uint32_t tx_idx, struct mbuf *mp, uint32_t txr_idx, uint32_t iscsi_pdu) 1808 { 1809 struct ether_vlan_header *eh; 1810 qla_hw_t *hw = &ha->hw; 1811 q80_tx_cmd_t *tx_cmd, tso_cmd; 1812 bus_dma_segment_t *c_seg; 1813 uint32_t num_tx_cmds, hdr_len = 0; 1814 uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next; 1815 device_t dev; 1816 int i, ret; 1817 uint8_t *src = NULL, *dst = NULL; 1818 uint8_t frame_hdr[QL_FRAME_HDR_SIZE]; 1819 uint32_t op_code = 0; 1820 uint32_t tcp_hdr_off = 0; 1821 1822 dev = ha->pci_dev; 1823 1824 /* 1825 * Always make sure there is atleast one empty slot in the tx_ring 1826 * tx_ring is considered full when there only one entry available 1827 */ 1828 num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2; 1829 1830 total_length = mp->m_pkthdr.len; 1831 if (total_length > QLA_MAX_TSO_FRAME_SIZE) { 1832 device_printf(dev, "%s: total length exceeds maxlen(%d)\n", 1833 __func__, total_length); 1834 return (-1); 1835 } 1836 eh = mtod(mp, struct ether_vlan_header *); 1837 1838 if (mp->m_pkthdr.csum_flags & CSUM_TSO) { 1839 1840 bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t)); 1841 1842 src = frame_hdr; 1843 ret = qla_tx_tso(ha, mp, &tso_cmd, src); 1844 1845 if (!(ret & ~1)) { 1846 /* find the additional tx_cmd descriptors required */ 1847 1848 if (mp->m_flags & M_VLANTAG) 1849 tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN; 1850 1851 hdr_len = tso_cmd.total_hdr_len; 1852 1853 bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN; 1854 bytes = QL_MIN(bytes, hdr_len); 1855 1856 num_tx_cmds++; 1857 hdr_len -= bytes; 1858 1859 while (hdr_len) { 1860 bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len); 1861 hdr_len -= bytes; 1862 num_tx_cmds++; 1863 } 1864 hdr_len = tso_cmd.total_hdr_len; 1865 1866 if (ret == 0) 1867 src = (uint8_t *)eh; 1868 } else 1869 return (EINVAL); 1870 } else { 1871 (void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off); 1872 } 1873 1874 if (iscsi_pdu) 1875 ha->hw.iscsi_pkt_count++; 1876 1877 if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) { 1878 qla_hw_tx_done_locked(ha, txr_idx); 1879 if (hw->tx_cntxt[txr_idx].txr_free <= 1880 (num_tx_cmds + QLA_TX_MIN_FREE)) { 1881 QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= " 1882 "(num_tx_cmds + QLA_TX_MIN_FREE))\n", 1883 __func__)); 1884 return (-1); 1885 } 1886 } 1887 1888 tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx]; 1889 1890 if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) { 1891 1892 if (nsegs > ha->hw.max_tx_segs) 1893 ha->hw.max_tx_segs = nsegs; 1894 1895 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 1896 1897 if (op_code) { 1898 tx_cmd->flags_opcode = op_code; 1899 tx_cmd->tcp_hdr_off = tcp_hdr_off; 1900 1901 } else { 1902 tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER; 1903 } 1904 } else { 1905 bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t)); 1906 ha->tx_tso_frames++; 1907 } 1908 1909 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 1910 tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED; 1911 1912 if (iscsi_pdu) 1913 eh->evl_tag |= ha->hw.user_pri_iscsi << 13; 1914 1915 } else if (mp->m_flags & M_VLANTAG) { 1916 1917 if (hdr_len) { /* TSO */ 1918 tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED | 1919 Q8_TX_CMD_FLAGS_HW_VLAN_ID); 1920 tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN; 1921 } else 1922 tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID; 1923 1924 ha->hw_vlan_tx_frames++; 1925 tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag; 1926 1927 if (iscsi_pdu) { 1928 tx_cmd->vlan_tci |= ha->hw.user_pri_iscsi << 13; 1929 mp->m_pkthdr.ether_vtag = tx_cmd->vlan_tci; 1930 } 1931 } 1932 1933 1934 tx_cmd->n_bufs = (uint8_t)nsegs; 1935 tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF); 1936 tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8))); 1937 tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func); 1938 1939 c_seg = segs; 1940 1941 while (1) { 1942 for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) { 1943 1944 switch (i) { 1945 case 0: 1946 tx_cmd->buf1_addr = c_seg->ds_addr; 1947 tx_cmd->buf1_len = c_seg->ds_len; 1948 break; 1949 1950 case 1: 1951 tx_cmd->buf2_addr = c_seg->ds_addr; 1952 tx_cmd->buf2_len = c_seg->ds_len; 1953 break; 1954 1955 case 2: 1956 tx_cmd->buf3_addr = c_seg->ds_addr; 1957 tx_cmd->buf3_len = c_seg->ds_len; 1958 break; 1959 1960 case 3: 1961 tx_cmd->buf4_addr = c_seg->ds_addr; 1962 tx_cmd->buf4_len = c_seg->ds_len; 1963 break; 1964 } 1965 1966 c_seg++; 1967 nsegs--; 1968 } 1969 1970 txr_next = hw->tx_cntxt[txr_idx].txr_next = 1971 (hw->tx_cntxt[txr_idx].txr_next + 1) & 1972 (NUM_TX_DESCRIPTORS - 1); 1973 tx_cmd_count++; 1974 1975 if (!nsegs) 1976 break; 1977 1978 tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next]; 1979 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 1980 } 1981 1982 if (mp->m_pkthdr.csum_flags & CSUM_TSO) { 1983 1984 /* TSO : Copy the header in the following tx cmd descriptors */ 1985 1986 txr_next = hw->tx_cntxt[txr_idx].txr_next; 1987 1988 tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next]; 1989 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 1990 1991 bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN; 1992 bytes = QL_MIN(bytes, hdr_len); 1993 1994 dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN; 1995 1996 if (mp->m_flags & M_VLANTAG) { 1997 /* first copy the src/dst MAC addresses */ 1998 bcopy(src, dst, (ETHER_ADDR_LEN * 2)); 1999 dst += (ETHER_ADDR_LEN * 2); 2000 src += (ETHER_ADDR_LEN * 2); 2001 2002 *((uint16_t *)dst) = htons(ETHERTYPE_VLAN); 2003 dst += 2; 2004 *((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag); 2005 dst += 2; 2006 2007 /* bytes left in src header */ 2008 hdr_len -= ((ETHER_ADDR_LEN * 2) + 2009 ETHER_VLAN_ENCAP_LEN); 2010 2011 /* bytes left in TxCmd Entry */ 2012 bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN); 2013 2014 2015 bcopy(src, dst, bytes); 2016 src += bytes; 2017 hdr_len -= bytes; 2018 } else { 2019 bcopy(src, dst, bytes); 2020 src += bytes; 2021 hdr_len -= bytes; 2022 } 2023 2024 txr_next = hw->tx_cntxt[txr_idx].txr_next = 2025 (hw->tx_cntxt[txr_idx].txr_next + 1) & 2026 (NUM_TX_DESCRIPTORS - 1); 2027 tx_cmd_count++; 2028 2029 while (hdr_len) { 2030 tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next]; 2031 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 2032 2033 bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len); 2034 2035 bcopy(src, tx_cmd, bytes); 2036 src += bytes; 2037 hdr_len -= bytes; 2038 2039 txr_next = hw->tx_cntxt[txr_idx].txr_next = 2040 (hw->tx_cntxt[txr_idx].txr_next + 1) & 2041 (NUM_TX_DESCRIPTORS - 1); 2042 tx_cmd_count++; 2043 } 2044 } 2045 2046 hw->tx_cntxt[txr_idx].txr_free = 2047 hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count; 2048 2049 QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\ 2050 txr_idx); 2051 QL_DPRINT8(ha, (dev, "%s: return\n", __func__)); 2052 2053 return (0); 2054 } 2055 2056 2057 2058 #define Q8_CONFIG_IND_TBL_SIZE 32 /* < Q8_RSS_IND_TBL_SIZE and power of 2 */ 2059 static int 2060 qla_config_rss_ind_table(qla_host_t *ha) 2061 { 2062 uint32_t i, count; 2063 uint8_t rss_ind_tbl[Q8_CONFIG_IND_TBL_SIZE]; 2064 2065 2066 for (i = 0; i < Q8_CONFIG_IND_TBL_SIZE; i++) { 2067 rss_ind_tbl[i] = i % ha->hw.num_sds_rings; 2068 } 2069 2070 for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ; 2071 i = i + Q8_CONFIG_IND_TBL_SIZE) { 2072 2073 if ((i + Q8_CONFIG_IND_TBL_SIZE) > Q8_RSS_IND_TBL_MAX_IDX) { 2074 count = Q8_RSS_IND_TBL_MAX_IDX - i + 1; 2075 } else { 2076 count = Q8_CONFIG_IND_TBL_SIZE; 2077 } 2078 2079 if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id, 2080 rss_ind_tbl)) 2081 return (-1); 2082 } 2083 2084 return (0); 2085 } 2086 2087 /* 2088 * Name: ql_del_hw_if 2089 * Function: Destroys the hardware specific entities corresponding to an 2090 * Ethernet Interface 2091 */ 2092 void 2093 ql_del_hw_if(qla_host_t *ha) 2094 { 2095 uint32_t i; 2096 uint32_t num_msix; 2097 2098 (void)qla_stop_nic_func(ha); 2099 2100 qla_del_rcv_cntxt(ha); 2101 qla_del_xmt_cntxt(ha); 2102 2103 if (ha->hw.flags.init_intr_cnxt) { 2104 for (i = 0; i < ha->hw.num_sds_rings; ) { 2105 2106 if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings) 2107 num_msix = Q8_MAX_INTR_VECTORS; 2108 else 2109 num_msix = ha->hw.num_sds_rings - i; 2110 qla_config_intr_cntxt(ha, i, num_msix, 0); 2111 2112 i += num_msix; 2113 } 2114 2115 ha->hw.flags.init_intr_cnxt = 0; 2116 } 2117 return; 2118 } 2119 2120 void 2121 qla_confirm_9kb_enable(qla_host_t *ha) 2122 { 2123 uint32_t supports_9kb = 0; 2124 2125 ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX); 2126 2127 /* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */ 2128 WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2); 2129 WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0); 2130 2131 qla_get_nic_partition(ha, &supports_9kb, NULL); 2132 2133 if (!supports_9kb) 2134 ha->hw.enable_9kb = 0; 2135 2136 return; 2137 } 2138 2139 2140 /* 2141 * Name: ql_init_hw_if 2142 * Function: Creates the hardware specific entities corresponding to an 2143 * Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address 2144 * corresponding to the interface. Enables LRO if allowed. 2145 */ 2146 int 2147 ql_init_hw_if(qla_host_t *ha) 2148 { 2149 device_t dev; 2150 uint32_t i; 2151 uint8_t bcast_mac[6]; 2152 qla_rdesc_t *rdesc; 2153 uint32_t num_msix; 2154 2155 dev = ha->pci_dev; 2156 2157 for (i = 0; i < ha->hw.num_sds_rings; i++) { 2158 bzero(ha->hw.dma_buf.sds_ring[i].dma_b, 2159 ha->hw.dma_buf.sds_ring[i].size); 2160 } 2161 2162 for (i = 0; i < ha->hw.num_sds_rings; ) { 2163 2164 if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings) 2165 num_msix = Q8_MAX_INTR_VECTORS; 2166 else 2167 num_msix = ha->hw.num_sds_rings - i; 2168 2169 if (qla_config_intr_cntxt(ha, i, num_msix, 1)) { 2170 2171 if (i > 0) { 2172 2173 num_msix = i; 2174 2175 for (i = 0; i < num_msix; ) { 2176 qla_config_intr_cntxt(ha, i, 2177 Q8_MAX_INTR_VECTORS, 0); 2178 i += Q8_MAX_INTR_VECTORS; 2179 } 2180 } 2181 return (-1); 2182 } 2183 2184 i = i + num_msix; 2185 } 2186 2187 ha->hw.flags.init_intr_cnxt = 1; 2188 2189 if (ha->hw.mdump_init == 0) { 2190 qla_minidump_init(ha); 2191 } 2192 2193 /* 2194 * Create Receive Context 2195 */ 2196 if (qla_init_rcv_cntxt(ha)) { 2197 return (-1); 2198 } 2199 2200 for (i = 0; i < ha->hw.num_rds_rings; i++) { 2201 rdesc = &ha->hw.rds[i]; 2202 rdesc->rx_next = NUM_RX_DESCRIPTORS - 2; 2203 rdesc->rx_in = 0; 2204 /* Update the RDS Producer Indices */ 2205 QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\ 2206 rdesc->rx_next); 2207 } 2208 2209 2210 /* 2211 * Create Transmit Context 2212 */ 2213 if (qla_init_xmt_cntxt(ha)) { 2214 qla_del_rcv_cntxt(ha); 2215 return (-1); 2216 } 2217 ha->hw.max_tx_segs = 0; 2218 2219 if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1)) 2220 return(-1); 2221 2222 ha->hw.flags.unicast_mac = 1; 2223 2224 bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF; 2225 bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF; 2226 2227 if (qla_config_mac_addr(ha, bcast_mac, 1)) 2228 return (-1); 2229 2230 ha->hw.flags.bcast_mac = 1; 2231 2232 /* 2233 * program any cached multicast addresses 2234 */ 2235 if (qla_hw_add_all_mcast(ha)) 2236 return (-1); 2237 2238 if (qla_config_rss(ha, ha->hw.rcv_cntxt_id)) 2239 return (-1); 2240 2241 if (qla_config_rss_ind_table(ha)) 2242 return (-1); 2243 2244 if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0, 1)) 2245 return (-1); 2246 2247 if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id)) 2248 return (-1); 2249 2250 if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id)) 2251 return (-1); 2252 2253 if (qla_init_nic_func(ha)) 2254 return (-1); 2255 2256 if (qla_query_fw_dcbx_caps(ha)) 2257 return (-1); 2258 2259 for (i = 0; i < ha->hw.num_sds_rings; i++) 2260 QL_ENABLE_INTERRUPTS(ha, i); 2261 2262 return (0); 2263 } 2264 2265 static int 2266 qla_map_sds_to_rds(qla_host_t *ha, uint32_t start_idx, uint32_t num_idx) 2267 { 2268 device_t dev = ha->pci_dev; 2269 q80_rq_map_sds_to_rds_t *map_rings; 2270 q80_rsp_map_sds_to_rds_t *map_rings_rsp; 2271 uint32_t i, err; 2272 qla_hw_t *hw = &ha->hw; 2273 2274 map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox; 2275 bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t)); 2276 2277 map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS; 2278 map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2); 2279 map_rings->count_version |= Q8_MBX_CMD_VERSION; 2280 2281 map_rings->cntxt_id = hw->rcv_cntxt_id; 2282 map_rings->num_rings = num_idx; 2283 2284 for (i = 0; i < num_idx; i++) { 2285 map_rings->sds_rds[i].sds_ring = i + start_idx; 2286 map_rings->sds_rds[i].rds_ring = i + start_idx; 2287 } 2288 2289 if (qla_mbx_cmd(ha, (uint32_t *)map_rings, 2290 (sizeof (q80_rq_map_sds_to_rds_t) >> 2), 2291 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) { 2292 device_printf(dev, "%s: failed0\n", __func__); 2293 return (-1); 2294 } 2295 2296 map_rings_rsp = (q80_rsp_map_sds_to_rds_t *)ha->hw.mbox; 2297 2298 err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status); 2299 2300 if (err) { 2301 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2302 return (-1); 2303 } 2304 2305 return (0); 2306 } 2307 2308 /* 2309 * Name: qla_init_rcv_cntxt 2310 * Function: Creates the Receive Context. 2311 */ 2312 static int 2313 qla_init_rcv_cntxt(qla_host_t *ha) 2314 { 2315 q80_rq_rcv_cntxt_t *rcntxt; 2316 q80_rsp_rcv_cntxt_t *rcntxt_rsp; 2317 q80_stat_desc_t *sdesc; 2318 int i, j; 2319 qla_hw_t *hw = &ha->hw; 2320 device_t dev; 2321 uint32_t err; 2322 uint32_t rcntxt_sds_rings; 2323 uint32_t rcntxt_rds_rings; 2324 uint32_t max_idx; 2325 2326 dev = ha->pci_dev; 2327 2328 /* 2329 * Create Receive Context 2330 */ 2331 2332 for (i = 0; i < hw->num_sds_rings; i++) { 2333 sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0]; 2334 2335 for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) { 2336 sdesc->data[0] = 1ULL; 2337 sdesc->data[1] = 1ULL; 2338 } 2339 } 2340 2341 rcntxt_sds_rings = hw->num_sds_rings; 2342 if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) 2343 rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS; 2344 2345 rcntxt_rds_rings = hw->num_rds_rings; 2346 2347 if (hw->num_rds_rings > MAX_RDS_RING_SETS) 2348 rcntxt_rds_rings = MAX_RDS_RING_SETS; 2349 2350 rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox; 2351 bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t))); 2352 2353 rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT; 2354 rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2); 2355 rcntxt->count_version |= Q8_MBX_CMD_VERSION; 2356 2357 rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW | 2358 Q8_RCV_CNTXT_CAP0_LRO | 2359 Q8_RCV_CNTXT_CAP0_HW_LRO | 2360 Q8_RCV_CNTXT_CAP0_RSS | 2361 Q8_RCV_CNTXT_CAP0_SGL_LRO; 2362 2363 if (ha->hw.enable_9kb) 2364 rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SINGLE_JUMBO; 2365 else 2366 rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SGL_JUMBO; 2367 2368 if (ha->hw.num_rds_rings > 1) { 2369 rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5); 2370 rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS; 2371 } else 2372 rcntxt->nrds_sets_rings = 0x1 | (1 << 5); 2373 2374 rcntxt->nsds_rings = rcntxt_sds_rings; 2375 2376 rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE; 2377 2378 rcntxt->rcv_vpid = 0; 2379 2380 for (i = 0; i < rcntxt_sds_rings; i++) { 2381 rcntxt->sds[i].paddr = 2382 qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr); 2383 rcntxt->sds[i].size = 2384 qla_host_to_le32(NUM_STATUS_DESCRIPTORS); 2385 if (ha->msix_count == 2) { 2386 rcntxt->sds[i].intr_id = 2387 qla_host_to_le16(hw->intr_id[0]); 2388 rcntxt->sds[i].intr_src_bit = qla_host_to_le16((i)); 2389 } else { 2390 rcntxt->sds[i].intr_id = 2391 qla_host_to_le16(hw->intr_id[i]); 2392 rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0); 2393 } 2394 } 2395 2396 for (i = 0; i < rcntxt_rds_rings; i++) { 2397 rcntxt->rds[i].paddr_std = 2398 qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr); 2399 2400 if (ha->hw.enable_9kb) 2401 rcntxt->rds[i].std_bsize = 2402 qla_host_to_le64(MJUM9BYTES); 2403 else 2404 rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES); 2405 2406 rcntxt->rds[i].std_nentries = 2407 qla_host_to_le32(NUM_RX_DESCRIPTORS); 2408 } 2409 2410 if (qla_mbx_cmd(ha, (uint32_t *)rcntxt, 2411 (sizeof (q80_rq_rcv_cntxt_t) >> 2), 2412 ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) { 2413 device_printf(dev, "%s: failed0\n", __func__); 2414 return (-1); 2415 } 2416 2417 rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox; 2418 2419 err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status); 2420 2421 if (err) { 2422 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2423 return (-1); 2424 } 2425 2426 for (i = 0; i < rcntxt_sds_rings; i++) { 2427 hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i]; 2428 } 2429 2430 for (i = 0; i < rcntxt_rds_rings; i++) { 2431 hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std; 2432 } 2433 2434 hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id; 2435 2436 ha->hw.flags.init_rx_cnxt = 1; 2437 2438 if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) { 2439 2440 for (i = MAX_RCNTXT_SDS_RINGS; i < hw->num_sds_rings;) { 2441 2442 if ((i + MAX_RCNTXT_SDS_RINGS) < hw->num_sds_rings) 2443 max_idx = MAX_RCNTXT_SDS_RINGS; 2444 else 2445 max_idx = hw->num_sds_rings - i; 2446 2447 err = qla_add_rcv_rings(ha, i, max_idx); 2448 if (err) 2449 return -1; 2450 2451 i += max_idx; 2452 } 2453 } 2454 2455 if (hw->num_rds_rings > 1) { 2456 2457 for (i = 0; i < hw->num_rds_rings; ) { 2458 2459 if ((i + MAX_SDS_TO_RDS_MAP) < hw->num_rds_rings) 2460 max_idx = MAX_SDS_TO_RDS_MAP; 2461 else 2462 max_idx = hw->num_rds_rings - i; 2463 2464 err = qla_map_sds_to_rds(ha, i, max_idx); 2465 if (err) 2466 return -1; 2467 2468 i += max_idx; 2469 } 2470 } 2471 2472 return (0); 2473 } 2474 2475 static int 2476 qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds) 2477 { 2478 device_t dev = ha->pci_dev; 2479 q80_rq_add_rcv_rings_t *add_rcv; 2480 q80_rsp_add_rcv_rings_t *add_rcv_rsp; 2481 uint32_t i,j, err; 2482 qla_hw_t *hw = &ha->hw; 2483 2484 add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox; 2485 bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t)); 2486 2487 add_rcv->opcode = Q8_MBX_ADD_RX_RINGS; 2488 add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2); 2489 add_rcv->count_version |= Q8_MBX_CMD_VERSION; 2490 2491 add_rcv->nrds_sets_rings = nsds | (1 << 5); 2492 add_rcv->nsds_rings = nsds; 2493 add_rcv->cntxt_id = hw->rcv_cntxt_id; 2494 2495 for (i = 0; i < nsds; i++) { 2496 2497 j = i + sds_idx; 2498 2499 add_rcv->sds[i].paddr = 2500 qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr); 2501 2502 add_rcv->sds[i].size = 2503 qla_host_to_le32(NUM_STATUS_DESCRIPTORS); 2504 2505 if (ha->msix_count == 2) { 2506 add_rcv->sds[i].intr_id = 2507 qla_host_to_le16(hw->intr_id[0]); 2508 add_rcv->sds[i].intr_src_bit = qla_host_to_le16(j); 2509 } else { 2510 add_rcv->sds[i].intr_id = 2511 qla_host_to_le16(hw->intr_id[j]); 2512 add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0); 2513 } 2514 2515 } 2516 for (i = 0; (i < nsds); i++) { 2517 j = i + sds_idx; 2518 2519 add_rcv->rds[i].paddr_std = 2520 qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr); 2521 2522 if (ha->hw.enable_9kb) 2523 add_rcv->rds[i].std_bsize = 2524 qla_host_to_le64(MJUM9BYTES); 2525 else 2526 add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES); 2527 2528 add_rcv->rds[i].std_nentries = 2529 qla_host_to_le32(NUM_RX_DESCRIPTORS); 2530 } 2531 2532 2533 if (qla_mbx_cmd(ha, (uint32_t *)add_rcv, 2534 (sizeof (q80_rq_add_rcv_rings_t) >> 2), 2535 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) { 2536 device_printf(dev, "%s: failed0\n", __func__); 2537 return (-1); 2538 } 2539 2540 add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox; 2541 2542 err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status); 2543 2544 if (err) { 2545 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2546 return (-1); 2547 } 2548 2549 for (i = 0; i < nsds; i++) { 2550 hw->sds[(i + sds_idx)].sds_consumer = add_rcv_rsp->sds_cons[i]; 2551 } 2552 2553 for (i = 0; i < nsds; i++) { 2554 hw->rds[(i + sds_idx)].prod_std = add_rcv_rsp->rds[i].prod_std; 2555 } 2556 2557 return (0); 2558 } 2559 2560 /* 2561 * Name: qla_del_rcv_cntxt 2562 * Function: Destroys the Receive Context. 2563 */ 2564 static void 2565 qla_del_rcv_cntxt(qla_host_t *ha) 2566 { 2567 device_t dev = ha->pci_dev; 2568 q80_rcv_cntxt_destroy_t *rcntxt; 2569 q80_rcv_cntxt_destroy_rsp_t *rcntxt_rsp; 2570 uint32_t err; 2571 uint8_t bcast_mac[6]; 2572 2573 if (!ha->hw.flags.init_rx_cnxt) 2574 return; 2575 2576 if (qla_hw_del_all_mcast(ha)) 2577 return; 2578 2579 if (ha->hw.flags.bcast_mac) { 2580 2581 bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF; 2582 bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF; 2583 2584 if (qla_config_mac_addr(ha, bcast_mac, 0)) 2585 return; 2586 ha->hw.flags.bcast_mac = 0; 2587 2588 } 2589 2590 if (ha->hw.flags.unicast_mac) { 2591 if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0)) 2592 return; 2593 ha->hw.flags.unicast_mac = 0; 2594 } 2595 2596 rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox; 2597 bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t))); 2598 2599 rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT; 2600 rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2); 2601 rcntxt->count_version |= Q8_MBX_CMD_VERSION; 2602 2603 rcntxt->cntxt_id = ha->hw.rcv_cntxt_id; 2604 2605 if (qla_mbx_cmd(ha, (uint32_t *)rcntxt, 2606 (sizeof (q80_rcv_cntxt_destroy_t) >> 2), 2607 ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) { 2608 device_printf(dev, "%s: failed0\n", __func__); 2609 return; 2610 } 2611 rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox; 2612 2613 err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status); 2614 2615 if (err) { 2616 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2617 } 2618 2619 ha->hw.flags.init_rx_cnxt = 0; 2620 return; 2621 } 2622 2623 /* 2624 * Name: qla_init_xmt_cntxt 2625 * Function: Creates the Transmit Context. 2626 */ 2627 static int 2628 qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx) 2629 { 2630 device_t dev; 2631 qla_hw_t *hw = &ha->hw; 2632 q80_rq_tx_cntxt_t *tcntxt; 2633 q80_rsp_tx_cntxt_t *tcntxt_rsp; 2634 uint32_t err; 2635 qla_hw_tx_cntxt_t *hw_tx_cntxt; 2636 2637 hw_tx_cntxt = &hw->tx_cntxt[txr_idx]; 2638 2639 dev = ha->pci_dev; 2640 2641 /* 2642 * Create Transmit Context 2643 */ 2644 tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox; 2645 bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t))); 2646 2647 tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT; 2648 tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2); 2649 tcntxt->count_version |= Q8_MBX_CMD_VERSION; 2650 2651 #ifdef QL_ENABLE_ISCSI_TLV 2652 2653 tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO | 2654 Q8_TX_CNTXT_CAP0_TC; 2655 2656 if (txr_idx >= (ha->hw.num_tx_rings >> 1)) { 2657 tcntxt->traffic_class = 1; 2658 } 2659 2660 #else 2661 2662 tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO; 2663 2664 #endif /* #ifdef QL_ENABLE_ISCSI_TLV */ 2665 2666 tcntxt->ntx_rings = 1; 2667 2668 tcntxt->tx_ring[0].paddr = 2669 qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr); 2670 tcntxt->tx_ring[0].tx_consumer = 2671 qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr); 2672 tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS); 2673 2674 tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[0]); 2675 tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0); 2676 2677 2678 hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS; 2679 hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0; 2680 2681 if (qla_mbx_cmd(ha, (uint32_t *)tcntxt, 2682 (sizeof (q80_rq_tx_cntxt_t) >> 2), 2683 ha->hw.mbox, 2684 (sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) { 2685 device_printf(dev, "%s: failed0\n", __func__); 2686 return (-1); 2687 } 2688 tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox; 2689 2690 err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status); 2691 2692 if (err) { 2693 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2694 return -1; 2695 } 2696 2697 hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index; 2698 hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id; 2699 2700 if (qla_config_intr_coalesce(ha, hw_tx_cntxt->tx_cntxt_id, 0, 0)) 2701 return (-1); 2702 2703 return (0); 2704 } 2705 2706 2707 /* 2708 * Name: qla_del_xmt_cntxt 2709 * Function: Destroys the Transmit Context. 2710 */ 2711 static int 2712 qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx) 2713 { 2714 device_t dev = ha->pci_dev; 2715 q80_tx_cntxt_destroy_t *tcntxt; 2716 q80_tx_cntxt_destroy_rsp_t *tcntxt_rsp; 2717 uint32_t err; 2718 2719 tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox; 2720 bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t))); 2721 2722 tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT; 2723 tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2); 2724 tcntxt->count_version |= Q8_MBX_CMD_VERSION; 2725 2726 tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id; 2727 2728 if (qla_mbx_cmd(ha, (uint32_t *)tcntxt, 2729 (sizeof (q80_tx_cntxt_destroy_t) >> 2), 2730 ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) { 2731 device_printf(dev, "%s: failed0\n", __func__); 2732 return (-1); 2733 } 2734 tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox; 2735 2736 err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status); 2737 2738 if (err) { 2739 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2740 return (-1); 2741 } 2742 2743 return (0); 2744 } 2745 static void 2746 qla_del_xmt_cntxt(qla_host_t *ha) 2747 { 2748 uint32_t i; 2749 2750 if (!ha->hw.flags.init_tx_cnxt) 2751 return; 2752 2753 for (i = 0; i < ha->hw.num_tx_rings; i++) { 2754 if (qla_del_xmt_cntxt_i(ha, i)) 2755 break; 2756 } 2757 ha->hw.flags.init_tx_cnxt = 0; 2758 } 2759 2760 static int 2761 qla_init_xmt_cntxt(qla_host_t *ha) 2762 { 2763 uint32_t i, j; 2764 2765 for (i = 0; i < ha->hw.num_tx_rings; i++) { 2766 if (qla_init_xmt_cntxt_i(ha, i) != 0) { 2767 for (j = 0; j < i; j++) 2768 qla_del_xmt_cntxt_i(ha, j); 2769 return (-1); 2770 } 2771 } 2772 ha->hw.flags.init_tx_cnxt = 1; 2773 return (0); 2774 } 2775 2776 static int 2777 qla_hw_add_all_mcast(qla_host_t *ha) 2778 { 2779 int i, nmcast; 2780 2781 nmcast = ha->hw.nmcast; 2782 2783 for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) { 2784 if ((ha->hw.mcast[i].addr[0] != 0) || 2785 (ha->hw.mcast[i].addr[1] != 0) || 2786 (ha->hw.mcast[i].addr[2] != 0) || 2787 (ha->hw.mcast[i].addr[3] != 0) || 2788 (ha->hw.mcast[i].addr[4] != 0) || 2789 (ha->hw.mcast[i].addr[5] != 0)) { 2790 2791 if (qla_config_mac_addr(ha, ha->hw.mcast[i].addr, 1)) { 2792 device_printf(ha->pci_dev, "%s: failed\n", 2793 __func__); 2794 return (-1); 2795 } 2796 2797 nmcast--; 2798 } 2799 } 2800 return 0; 2801 } 2802 2803 static int 2804 qla_hw_del_all_mcast(qla_host_t *ha) 2805 { 2806 int i, nmcast; 2807 2808 nmcast = ha->hw.nmcast; 2809 2810 for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) { 2811 if ((ha->hw.mcast[i].addr[0] != 0) || 2812 (ha->hw.mcast[i].addr[1] != 0) || 2813 (ha->hw.mcast[i].addr[2] != 0) || 2814 (ha->hw.mcast[i].addr[3] != 0) || 2815 (ha->hw.mcast[i].addr[4] != 0) || 2816 (ha->hw.mcast[i].addr[5] != 0)) { 2817 2818 if (qla_config_mac_addr(ha, ha->hw.mcast[i].addr, 0)) 2819 return (-1); 2820 2821 nmcast--; 2822 } 2823 } 2824 return 0; 2825 } 2826 2827 static int 2828 qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta) 2829 { 2830 int i; 2831 2832 for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) { 2833 2834 if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) 2835 return 0; /* its been already added */ 2836 } 2837 2838 for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) { 2839 2840 if ((ha->hw.mcast[i].addr[0] == 0) && 2841 (ha->hw.mcast[i].addr[1] == 0) && 2842 (ha->hw.mcast[i].addr[2] == 0) && 2843 (ha->hw.mcast[i].addr[3] == 0) && 2844 (ha->hw.mcast[i].addr[4] == 0) && 2845 (ha->hw.mcast[i].addr[5] == 0)) { 2846 2847 if (qla_config_mac_addr(ha, mta, 1)) 2848 return (-1); 2849 2850 bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN); 2851 ha->hw.nmcast++; 2852 2853 return 0; 2854 } 2855 } 2856 return 0; 2857 } 2858 2859 static int 2860 qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta) 2861 { 2862 int i; 2863 2864 for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) { 2865 if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) { 2866 2867 if (qla_config_mac_addr(ha, mta, 0)) 2868 return (-1); 2869 2870 ha->hw.mcast[i].addr[0] = 0; 2871 ha->hw.mcast[i].addr[1] = 0; 2872 ha->hw.mcast[i].addr[2] = 0; 2873 ha->hw.mcast[i].addr[3] = 0; 2874 ha->hw.mcast[i].addr[4] = 0; 2875 ha->hw.mcast[i].addr[5] = 0; 2876 2877 ha->hw.nmcast--; 2878 2879 return 0; 2880 } 2881 } 2882 return 0; 2883 } 2884 2885 /* 2886 * Name: ql_hw_set_multi 2887 * Function: Sets the Multicast Addresses provided the host O.S into the 2888 * hardware (for the given interface) 2889 */ 2890 int 2891 ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast, uint32_t mcnt, 2892 uint32_t add_mac) 2893 { 2894 int i; 2895 uint8_t *mta = mcast; 2896 int ret = 0; 2897 2898 for (i = 0; i < mcnt; i++) { 2899 if (add_mac) { 2900 ret = qla_hw_add_mcast(ha, mta); 2901 if (ret) 2902 break; 2903 } else { 2904 ret = qla_hw_del_mcast(ha, mta); 2905 if (ret) 2906 break; 2907 } 2908 2909 mta += Q8_MAC_ADDR_LEN; 2910 } 2911 return (ret); 2912 } 2913 2914 /* 2915 * Name: qla_hw_tx_done_locked 2916 * Function: Handle Transmit Completions 2917 */ 2918 static void 2919 qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx) 2920 { 2921 qla_tx_buf_t *txb; 2922 qla_hw_t *hw = &ha->hw; 2923 uint32_t comp_idx, comp_count = 0; 2924 qla_hw_tx_cntxt_t *hw_tx_cntxt; 2925 2926 hw_tx_cntxt = &hw->tx_cntxt[txr_idx]; 2927 2928 /* retrieve index of last entry in tx ring completed */ 2929 comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons)); 2930 2931 while (comp_idx != hw_tx_cntxt->txr_comp) { 2932 2933 txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp]; 2934 2935 hw_tx_cntxt->txr_comp++; 2936 if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS) 2937 hw_tx_cntxt->txr_comp = 0; 2938 2939 comp_count++; 2940 2941 if (txb->m_head) { 2942 if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1); 2943 2944 bus_dmamap_sync(ha->tx_tag, txb->map, 2945 BUS_DMASYNC_POSTWRITE); 2946 bus_dmamap_unload(ha->tx_tag, txb->map); 2947 m_freem(txb->m_head); 2948 2949 txb->m_head = NULL; 2950 } 2951 } 2952 2953 hw_tx_cntxt->txr_free += comp_count; 2954 return; 2955 } 2956 2957 /* 2958 * Name: ql_hw_tx_done 2959 * Function: Handle Transmit Completions 2960 */ 2961 void 2962 ql_hw_tx_done(qla_host_t *ha) 2963 { 2964 int i; 2965 uint32_t flag = 0; 2966 2967 if (!mtx_trylock(&ha->tx_lock)) { 2968 QL_DPRINT8(ha, (ha->pci_dev, 2969 "%s: !mtx_trylock(&ha->tx_lock)\n", __func__)); 2970 return; 2971 } 2972 for (i = 0; i < ha->hw.num_tx_rings; i++) { 2973 qla_hw_tx_done_locked(ha, i); 2974 if (ha->hw.tx_cntxt[i].txr_free <= (NUM_TX_DESCRIPTORS >> 1)) 2975 flag = 1; 2976 } 2977 2978 if (!flag) 2979 ha->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2980 2981 QLA_TX_UNLOCK(ha); 2982 return; 2983 } 2984 2985 void 2986 ql_update_link_state(qla_host_t *ha) 2987 { 2988 uint32_t link_state; 2989 uint32_t prev_link_state; 2990 2991 if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) { 2992 ha->hw.link_up = 0; 2993 return; 2994 } 2995 link_state = READ_REG32(ha, Q8_LINK_STATE); 2996 2997 prev_link_state = ha->hw.link_up; 2998 2999 if (ha->pci_func == 0) 3000 ha->hw.link_up = (((link_state & 0xF) == 1)? 1 : 0); 3001 else 3002 ha->hw.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0); 3003 3004 if (prev_link_state != ha->hw.link_up) { 3005 if (ha->hw.link_up) { 3006 if_link_state_change(ha->ifp, LINK_STATE_UP); 3007 } else { 3008 if_link_state_change(ha->ifp, LINK_STATE_DOWN); 3009 } 3010 } 3011 return; 3012 } 3013 3014 void 3015 ql_hw_stop_rcv(qla_host_t *ha) 3016 { 3017 int i, done, count = 100; 3018 3019 while (count) { 3020 done = 1; 3021 for (i = 0; i < ha->hw.num_sds_rings; i++) { 3022 if (ha->hw.sds[i].rcv_active) 3023 done = 0; 3024 } 3025 if (done) 3026 break; 3027 else 3028 qla_mdelay(__func__, 10); 3029 count--; 3030 } 3031 if (!count) 3032 device_printf(ha->pci_dev, "%s: Counter expired.\n", __func__); 3033 3034 return; 3035 } 3036 3037 int 3038 ql_hw_check_health(qla_host_t *ha) 3039 { 3040 uint32_t val; 3041 3042 ha->hw.health_count++; 3043 3044 if (ha->hw.health_count < 1000) 3045 return 0; 3046 3047 ha->hw.health_count = 0; 3048 3049 val = READ_REG32(ha, Q8_ASIC_TEMPERATURE); 3050 3051 if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) || 3052 (QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) { 3053 device_printf(ha->pci_dev, "%s: Temperature Alert [0x%08x]\n", 3054 __func__, val); 3055 return -1; 3056 } 3057 3058 val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT); 3059 3060 if ((val != ha->hw.hbeat_value) && 3061 (!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) { 3062 ha->hw.hbeat_value = val; 3063 return 0; 3064 } 3065 device_printf(ha->pci_dev, "%s: Heartbeat Failue [0x%08x]\n", 3066 __func__, val); 3067 3068 return -1; 3069 } 3070 3071 static int 3072 qla_init_nic_func(qla_host_t *ha) 3073 { 3074 device_t dev; 3075 q80_init_nic_func_t *init_nic; 3076 q80_init_nic_func_rsp_t *init_nic_rsp; 3077 uint32_t err; 3078 3079 dev = ha->pci_dev; 3080 3081 init_nic = (q80_init_nic_func_t *)ha->hw.mbox; 3082 bzero(init_nic, sizeof(q80_init_nic_func_t)); 3083 3084 init_nic->opcode = Q8_MBX_INIT_NIC_FUNC; 3085 init_nic->count_version = (sizeof (q80_init_nic_func_t) >> 2); 3086 init_nic->count_version |= Q8_MBX_CMD_VERSION; 3087 3088 init_nic->options = Q8_INIT_NIC_REG_DCBX_CHNG_AEN; 3089 init_nic->options |= Q8_INIT_NIC_REG_SFP_CHNG_AEN; 3090 init_nic->options |= Q8_INIT_NIC_REG_IDC_AEN; 3091 3092 //qla_dump_buf8(ha, __func__, init_nic, sizeof (q80_init_nic_func_t)); 3093 if (qla_mbx_cmd(ha, (uint32_t *)init_nic, 3094 (sizeof (q80_init_nic_func_t) >> 2), 3095 ha->hw.mbox, (sizeof (q80_init_nic_func_rsp_t) >> 2), 0)) { 3096 device_printf(dev, "%s: failed\n", __func__); 3097 return -1; 3098 } 3099 3100 init_nic_rsp = (q80_init_nic_func_rsp_t *)ha->hw.mbox; 3101 // qla_dump_buf8(ha, __func__, init_nic_rsp, sizeof (q80_init_nic_func_rsp_t)); 3102 3103 err = Q8_MBX_RSP_STATUS(init_nic_rsp->regcnt_status); 3104 3105 if (err) { 3106 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 3107 } 3108 3109 return 0; 3110 } 3111 3112 static int 3113 qla_stop_nic_func(qla_host_t *ha) 3114 { 3115 device_t dev; 3116 q80_stop_nic_func_t *stop_nic; 3117 q80_stop_nic_func_rsp_t *stop_nic_rsp; 3118 uint32_t err; 3119 3120 dev = ha->pci_dev; 3121 3122 stop_nic = (q80_stop_nic_func_t *)ha->hw.mbox; 3123 bzero(stop_nic, sizeof(q80_stop_nic_func_t)); 3124 3125 stop_nic->opcode = Q8_MBX_STOP_NIC_FUNC; 3126 stop_nic->count_version = (sizeof (q80_stop_nic_func_t) >> 2); 3127 stop_nic->count_version |= Q8_MBX_CMD_VERSION; 3128 3129 stop_nic->options = Q8_STOP_NIC_DEREG_DCBX_CHNG_AEN; 3130 stop_nic->options |= Q8_STOP_NIC_DEREG_SFP_CHNG_AEN; 3131 3132 //qla_dump_buf8(ha, __func__, stop_nic, sizeof (q80_stop_nic_func_t)); 3133 if (qla_mbx_cmd(ha, (uint32_t *)stop_nic, 3134 (sizeof (q80_stop_nic_func_t) >> 2), 3135 ha->hw.mbox, (sizeof (q80_stop_nic_func_rsp_t) >> 2), 0)) { 3136 device_printf(dev, "%s: failed\n", __func__); 3137 return -1; 3138 } 3139 3140 stop_nic_rsp = (q80_stop_nic_func_rsp_t *)ha->hw.mbox; 3141 //qla_dump_buf8(ha, __func__, stop_nic_rsp, sizeof (q80_stop_nic_func_rsp_ t)); 3142 3143 err = Q8_MBX_RSP_STATUS(stop_nic_rsp->regcnt_status); 3144 3145 if (err) { 3146 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 3147 } 3148 3149 return 0; 3150 } 3151 3152 static int 3153 qla_query_fw_dcbx_caps(qla_host_t *ha) 3154 { 3155 device_t dev; 3156 q80_query_fw_dcbx_caps_t *fw_dcbx; 3157 q80_query_fw_dcbx_caps_rsp_t *fw_dcbx_rsp; 3158 uint32_t err; 3159 3160 dev = ha->pci_dev; 3161 3162 fw_dcbx = (q80_query_fw_dcbx_caps_t *)ha->hw.mbox; 3163 bzero(fw_dcbx, sizeof(q80_query_fw_dcbx_caps_t)); 3164 3165 fw_dcbx->opcode = Q8_MBX_GET_FW_DCBX_CAPS; 3166 fw_dcbx->count_version = (sizeof (q80_query_fw_dcbx_caps_t) >> 2); 3167 fw_dcbx->count_version |= Q8_MBX_CMD_VERSION; 3168 3169 ql_dump_buf8(ha, __func__, fw_dcbx, sizeof (q80_query_fw_dcbx_caps_t)); 3170 if (qla_mbx_cmd(ha, (uint32_t *)fw_dcbx, 3171 (sizeof (q80_query_fw_dcbx_caps_t) >> 2), 3172 ha->hw.mbox, (sizeof (q80_query_fw_dcbx_caps_rsp_t) >> 2), 0)) { 3173 device_printf(dev, "%s: failed\n", __func__); 3174 return -1; 3175 } 3176 3177 fw_dcbx_rsp = (q80_query_fw_dcbx_caps_rsp_t *)ha->hw.mbox; 3178 ql_dump_buf8(ha, __func__, fw_dcbx_rsp, 3179 sizeof (q80_query_fw_dcbx_caps_rsp_t)); 3180 3181 err = Q8_MBX_RSP_STATUS(fw_dcbx_rsp->regcnt_status); 3182 3183 if (err) { 3184 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 3185 } 3186 3187 return 0; 3188 } 3189 3190 static int 3191 qla_idc_ack(qla_host_t *ha, uint32_t aen_mb1, uint32_t aen_mb2, 3192 uint32_t aen_mb3, uint32_t aen_mb4) 3193 { 3194 device_t dev; 3195 q80_idc_ack_t *idc_ack; 3196 q80_idc_ack_rsp_t *idc_ack_rsp; 3197 uint32_t err; 3198 int count = 300; 3199 3200 dev = ha->pci_dev; 3201 3202 idc_ack = (q80_idc_ack_t *)ha->hw.mbox; 3203 bzero(idc_ack, sizeof(q80_idc_ack_t)); 3204 3205 idc_ack->opcode = Q8_MBX_IDC_ACK; 3206 idc_ack->count_version = (sizeof (q80_idc_ack_t) >> 2); 3207 idc_ack->count_version |= Q8_MBX_CMD_VERSION; 3208 3209 idc_ack->aen_mb1 = aen_mb1; 3210 idc_ack->aen_mb2 = aen_mb2; 3211 idc_ack->aen_mb3 = aen_mb3; 3212 idc_ack->aen_mb4 = aen_mb4; 3213 3214 ha->hw.imd_compl= 0; 3215 3216 if (qla_mbx_cmd(ha, (uint32_t *)idc_ack, 3217 (sizeof (q80_idc_ack_t) >> 2), 3218 ha->hw.mbox, (sizeof (q80_idc_ack_rsp_t) >> 2), 0)) { 3219 device_printf(dev, "%s: failed\n", __func__); 3220 return -1; 3221 } 3222 3223 idc_ack_rsp = (q80_idc_ack_rsp_t *)ha->hw.mbox; 3224 3225 err = Q8_MBX_RSP_STATUS(idc_ack_rsp->regcnt_status); 3226 3227 if (err) { 3228 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 3229 return(-1); 3230 } 3231 3232 while (count && !ha->hw.imd_compl) { 3233 qla_mdelay(__func__, 100); 3234 count--; 3235 } 3236 3237 if (!count) 3238 return -1; 3239 else 3240 device_printf(dev, "%s: count %d\n", __func__, count); 3241 3242 return (0); 3243 } 3244 3245 static int 3246 qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits) 3247 { 3248 device_t dev; 3249 q80_set_port_cfg_t *pcfg; 3250 q80_set_port_cfg_rsp_t *pfg_rsp; 3251 uint32_t err; 3252 int count = 300; 3253 3254 dev = ha->pci_dev; 3255 3256 pcfg = (q80_set_port_cfg_t *)ha->hw.mbox; 3257 bzero(pcfg, sizeof(q80_set_port_cfg_t)); 3258 3259 pcfg->opcode = Q8_MBX_SET_PORT_CONFIG; 3260 pcfg->count_version = (sizeof (q80_set_port_cfg_t) >> 2); 3261 pcfg->count_version |= Q8_MBX_CMD_VERSION; 3262 3263 pcfg->cfg_bits = cfg_bits; 3264 3265 device_printf(dev, "%s: cfg_bits" 3266 " [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]" 3267 " [0x%x, 0x%x, 0x%x]\n", __func__, 3268 ((cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20), 3269 ((cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5), 3270 ((cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0)); 3271 3272 ha->hw.imd_compl= 0; 3273 3274 if (qla_mbx_cmd(ha, (uint32_t *)pcfg, 3275 (sizeof (q80_set_port_cfg_t) >> 2), 3276 ha->hw.mbox, (sizeof (q80_set_port_cfg_rsp_t) >> 2), 0)) { 3277 device_printf(dev, "%s: failed\n", __func__); 3278 return -1; 3279 } 3280 3281 pfg_rsp = (q80_set_port_cfg_rsp_t *)ha->hw.mbox; 3282 3283 err = Q8_MBX_RSP_STATUS(pfg_rsp->regcnt_status); 3284 3285 if (err == Q8_MBX_RSP_IDC_INTRMD_RSP) { 3286 while (count && !ha->hw.imd_compl) { 3287 qla_mdelay(__func__, 100); 3288 count--; 3289 } 3290 if (count) { 3291 device_printf(dev, "%s: count %d\n", __func__, count); 3292 3293 err = 0; 3294 } 3295 } 3296 3297 if (err) { 3298 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 3299 return(-1); 3300 } 3301 3302 return (0); 3303 } 3304 3305 3306 static int 3307 qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size) 3308 { 3309 uint32_t err; 3310 device_t dev = ha->pci_dev; 3311 q80_config_md_templ_size_t *md_size; 3312 q80_config_md_templ_size_rsp_t *md_size_rsp; 3313 3314 #ifdef QL_LDFLASH_FW 3315 3316 *size = ql83xx_minidump_len; 3317 return (0); 3318 3319 #endif /* #ifdef QL_LDFLASH_FW */ 3320 3321 md_size = (q80_config_md_templ_size_t *) ha->hw.mbox; 3322 bzero(md_size, sizeof(q80_config_md_templ_size_t)); 3323 3324 md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE; 3325 md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2); 3326 md_size->count_version |= Q8_MBX_CMD_VERSION; 3327 3328 if (qla_mbx_cmd(ha, (uint32_t *) md_size, 3329 (sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox, 3330 (sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) { 3331 3332 device_printf(dev, "%s: failed\n", __func__); 3333 3334 return (-1); 3335 } 3336 3337 md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox; 3338 3339 err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status); 3340 3341 if (err) { 3342 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 3343 return(-1); 3344 } 3345 3346 *size = md_size_rsp->templ_size; 3347 3348 return (0); 3349 } 3350 3351 static int 3352 qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits) 3353 { 3354 device_t dev; 3355 q80_get_port_cfg_t *pcfg; 3356 q80_get_port_cfg_rsp_t *pcfg_rsp; 3357 uint32_t err; 3358 3359 dev = ha->pci_dev; 3360 3361 pcfg = (q80_get_port_cfg_t *)ha->hw.mbox; 3362 bzero(pcfg, sizeof(q80_get_port_cfg_t)); 3363 3364 pcfg->opcode = Q8_MBX_GET_PORT_CONFIG; 3365 pcfg->count_version = (sizeof (q80_get_port_cfg_t) >> 2); 3366 pcfg->count_version |= Q8_MBX_CMD_VERSION; 3367 3368 if (qla_mbx_cmd(ha, (uint32_t *)pcfg, 3369 (sizeof (q80_get_port_cfg_t) >> 2), 3370 ha->hw.mbox, (sizeof (q80_get_port_cfg_rsp_t) >> 2), 0)) { 3371 device_printf(dev, "%s: failed\n", __func__); 3372 return -1; 3373 } 3374 3375 pcfg_rsp = (q80_get_port_cfg_rsp_t *)ha->hw.mbox; 3376 3377 err = Q8_MBX_RSP_STATUS(pcfg_rsp->regcnt_status); 3378 3379 if (err) { 3380 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 3381 return(-1); 3382 } 3383 3384 device_printf(dev, "%s: [cfg_bits, port type]" 3385 " [0x%08x, 0x%02x] [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]" 3386 " [0x%x, 0x%x, 0x%x]\n", __func__, 3387 pcfg_rsp->cfg_bits, pcfg_rsp->phys_port_type, 3388 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20), 3389 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5), 3390 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0) 3391 ); 3392 3393 *cfg_bits = pcfg_rsp->cfg_bits; 3394 3395 return (0); 3396 } 3397 3398 int 3399 qla_iscsi_pdu(qla_host_t *ha, struct mbuf *mp) 3400 { 3401 struct ether_vlan_header *eh; 3402 uint16_t etype; 3403 struct ip *ip = NULL; 3404 struct ip6_hdr *ip6 = NULL; 3405 struct tcphdr *th = NULL; 3406 uint32_t hdrlen; 3407 uint32_t offset; 3408 uint8_t buf[sizeof(struct ip6_hdr)]; 3409 3410 eh = mtod(mp, struct ether_vlan_header *); 3411 3412 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 3413 hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 3414 etype = ntohs(eh->evl_proto); 3415 } else { 3416 hdrlen = ETHER_HDR_LEN; 3417 etype = ntohs(eh->evl_encap_proto); 3418 } 3419 3420 if (etype == ETHERTYPE_IP) { 3421 3422 offset = (hdrlen + sizeof (struct ip)); 3423 3424 if (mp->m_len >= offset) { 3425 ip = (struct ip *)(mp->m_data + hdrlen); 3426 } else { 3427 m_copydata(mp, hdrlen, sizeof (struct ip), buf); 3428 ip = (struct ip *)buf; 3429 } 3430 3431 if (ip->ip_p == IPPROTO_TCP) { 3432 3433 hdrlen += ip->ip_hl << 2; 3434 offset = hdrlen + 4; 3435 3436 if (mp->m_len >= offset) { 3437 th = (struct tcphdr *)(mp->m_data + hdrlen);; 3438 } else { 3439 m_copydata(mp, hdrlen, 4, buf); 3440 th = (struct tcphdr *)buf; 3441 } 3442 } 3443 3444 } else if (etype == ETHERTYPE_IPV6) { 3445 3446 offset = (hdrlen + sizeof (struct ip6_hdr)); 3447 3448 if (mp->m_len >= offset) { 3449 ip6 = (struct ip6_hdr *)(mp->m_data + hdrlen); 3450 } else { 3451 m_copydata(mp, hdrlen, sizeof (struct ip6_hdr), buf); 3452 ip6 = (struct ip6_hdr *)buf; 3453 } 3454 3455 if (ip6->ip6_nxt == IPPROTO_TCP) { 3456 3457 hdrlen += sizeof(struct ip6_hdr); 3458 offset = hdrlen + 4; 3459 3460 if (mp->m_len >= offset) { 3461 th = (struct tcphdr *)(mp->m_data + hdrlen);; 3462 } else { 3463 m_copydata(mp, hdrlen, 4, buf); 3464 th = (struct tcphdr *)buf; 3465 } 3466 } 3467 } 3468 3469 if (th != NULL) { 3470 if ((th->th_sport == htons(3260)) || 3471 (th->th_dport == htons(3260))) 3472 return 0; 3473 } 3474 return (-1); 3475 } 3476 3477 void 3478 qla_hw_async_event(qla_host_t *ha) 3479 { 3480 switch (ha->hw.aen_mb0) { 3481 case 0x8101: 3482 (void)qla_idc_ack(ha, ha->hw.aen_mb1, ha->hw.aen_mb2, 3483 ha->hw.aen_mb3, ha->hw.aen_mb4); 3484 3485 break; 3486 3487 default: 3488 break; 3489 } 3490 3491 return; 3492 } 3493 3494 #ifdef QL_LDFLASH_FW 3495 static int 3496 qla_get_minidump_template(qla_host_t *ha) 3497 { 3498 uint32_t err; 3499 device_t dev = ha->pci_dev; 3500 q80_config_md_templ_cmd_t *md_templ; 3501 q80_config_md_templ_cmd_rsp_t *md_templ_rsp; 3502 3503 md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox; 3504 bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t))); 3505 3506 md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT; 3507 md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2); 3508 md_templ->count_version |= Q8_MBX_CMD_VERSION; 3509 3510 md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr; 3511 md_templ->buff_size = ha->hw.dma_buf.minidump.size; 3512 3513 if (qla_mbx_cmd(ha, (uint32_t *) md_templ, 3514 (sizeof(q80_config_md_templ_cmd_t) >> 2), 3515 ha->hw.mbox, 3516 (sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) { 3517 3518 device_printf(dev, "%s: failed\n", __func__); 3519 3520 return (-1); 3521 } 3522 3523 md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox; 3524 3525 err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status); 3526 3527 if (err) { 3528 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 3529 return (-1); 3530 } 3531 3532 return (0); 3533 3534 } 3535 #endif /* #ifdef QL_LDFLASH_FW */ 3536 3537 static int 3538 qla_minidump_init(qla_host_t *ha) 3539 { 3540 int ret = 0; 3541 uint32_t template_size = 0; 3542 device_t dev = ha->pci_dev; 3543 3544 /* 3545 * Get Minidump Template Size 3546 */ 3547 ret = qla_get_minidump_tmplt_size(ha, &template_size); 3548 3549 if (ret || (template_size == 0)) { 3550 device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret, 3551 template_size); 3552 return (-1); 3553 } 3554 3555 /* 3556 * Allocate Memory for Minidump Template 3557 */ 3558 3559 ha->hw.dma_buf.minidump.alignment = 8; 3560 ha->hw.dma_buf.minidump.size = template_size; 3561 3562 #ifdef QL_LDFLASH_FW 3563 if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) { 3564 3565 device_printf(dev, "%s: minidump dma alloc failed\n", __func__); 3566 3567 return (-1); 3568 } 3569 ha->hw.dma_buf.flags.minidump = 1; 3570 3571 /* 3572 * Retrieve Minidump Template 3573 */ 3574 ret = qla_get_minidump_template(ha); 3575 #else 3576 ha->hw.dma_buf.minidump.dma_b = ql83xx_minidump; 3577 #endif /* #ifdef QL_LDFLASH_FW */ 3578 3579 if (ret) { 3580 qla_minidump_free(ha); 3581 } else { 3582 ha->hw.mdump_init = 1; 3583 } 3584 3585 return (ret); 3586 } 3587 3588 3589 static void 3590 qla_minidump_free(qla_host_t *ha) 3591 { 3592 ha->hw.mdump_init = 0; 3593 if (ha->hw.dma_buf.flags.minidump) { 3594 ha->hw.dma_buf.flags.minidump = 0; 3595 ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump); 3596 } 3597 return; 3598 } 3599 3600 void 3601 ql_minidump(qla_host_t *ha) 3602 { 3603 uint32_t delay = 6000; 3604 3605 if (!ha->hw.mdump_init) 3606 return; 3607 3608 if (!ha->hw.mdump_active) 3609 return; 3610 3611 if (ha->hw.mdump_active == 1) { 3612 ha->hw.mdump_start_seq_index = ql_stop_sequence(ha); 3613 ha->hw.mdump_start = 1; 3614 } 3615 3616 while (delay-- && ha->hw.mdump_active) { 3617 qla_mdelay(__func__, 100); 3618 } 3619 ha->hw.mdump_start = 0; 3620 ql_start_sequence(ha, ha->hw.mdump_start_seq_index); 3621 3622 return; 3623 } 3624