1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2011-2012 Qlogic Corporation 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * File: qla_hw.c 32 * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656. 33 * Content: Contains Hardware dependent functions 34 */ 35 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 #include "qla_os.h" 40 #include "qla_reg.h" 41 #include "qla_hw.h" 42 #include "qla_def.h" 43 #include "qla_inline.h" 44 #include "qla_ver.h" 45 #include "qla_glbl.h" 46 #include "qla_dbg.h" 47 48 static uint32_t sysctl_num_rds_rings = 2; 49 static uint32_t sysctl_num_sds_rings = 4; 50 51 /* 52 * Static Functions 53 */ 54 55 static void qla_init_cntxt_regions(qla_host_t *ha); 56 static int qla_issue_cmd(qla_host_t *ha, qla_cdrp_t *cdrp); 57 static int qla_fw_cmd(qla_host_t *ha, void *fw_cmd, uint32_t size); 58 static int qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, 59 uint16_t cntxt_id, uint32_t add_multi); 60 static void qla_del_rcv_cntxt(qla_host_t *ha); 61 static int qla_init_rcv_cntxt(qla_host_t *ha); 62 static void qla_del_xmt_cntxt(qla_host_t *ha); 63 static int qla_init_xmt_cntxt(qla_host_t *ha); 64 static int qla_get_max_rds(qla_host_t *ha); 65 static int qla_get_max_sds(qla_host_t *ha); 66 static int qla_get_max_rules(qla_host_t *ha); 67 static int qla_get_max_rcv_cntxts(qla_host_t *ha); 68 static int qla_get_max_tx_cntxts(qla_host_t *ha); 69 static int qla_get_max_mtu(qla_host_t *ha); 70 static int qla_get_max_lro(qla_host_t *ha); 71 static int qla_get_flow_control(qla_host_t *ha); 72 static void qla_hw_tx_done_locked(qla_host_t *ha); 73 74 int 75 qla_get_msix_count(qla_host_t *ha) 76 { 77 return (sysctl_num_sds_rings); 78 } 79 80 /* 81 * Name: qla_hw_add_sysctls 82 * Function: Add P3Plus specific sysctls 83 */ 84 void 85 qla_hw_add_sysctls(qla_host_t *ha) 86 { 87 device_t dev; 88 89 dev = ha->pci_dev; 90 91 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 92 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 93 OID_AUTO, "num_rds_rings", CTLFLAG_RD, &sysctl_num_rds_rings, 94 sysctl_num_rds_rings, "Number of Rcv Descriptor Rings"); 95 96 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 97 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 98 OID_AUTO, "num_sds_rings", CTLFLAG_RD, &sysctl_num_sds_rings, 99 sysctl_num_sds_rings, "Number of Status Descriptor Rings"); 100 } 101 102 /* 103 * Name: qla_free_dma 104 * Function: Frees the DMA'able memory allocated in qla_alloc_dma() 105 */ 106 void 107 qla_free_dma(qla_host_t *ha) 108 { 109 uint32_t i; 110 111 if (ha->hw.dma_buf.flags.context) { 112 qla_free_dmabuf(ha, &ha->hw.dma_buf.context); 113 ha->hw.dma_buf.flags.context = 0; 114 } 115 116 if (ha->hw.dma_buf.flags.sds_ring) { 117 for (i = 0; i < ha->hw.num_sds_rings; i++) 118 qla_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]); 119 ha->hw.dma_buf.flags.sds_ring = 0; 120 } 121 122 if (ha->hw.dma_buf.flags.rds_ring) { 123 for (i = 0; i < ha->hw.num_rds_rings; i++) 124 qla_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]); 125 ha->hw.dma_buf.flags.rds_ring = 0; 126 } 127 128 if (ha->hw.dma_buf.flags.tx_ring) { 129 qla_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring); 130 ha->hw.dma_buf.flags.tx_ring = 0; 131 } 132 } 133 134 /* 135 * Name: qla_alloc_dma 136 * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts. 137 */ 138 int 139 qla_alloc_dma(qla_host_t *ha) 140 { 141 device_t dev; 142 uint32_t i, j, size; 143 144 dev = ha->pci_dev; 145 146 QL_DPRINT2((dev, "%s: enter\n", __func__)); 147 148 ha->hw.num_rds_rings = (uint16_t)sysctl_num_rds_rings; 149 ha->hw.num_sds_rings = (uint16_t)sysctl_num_sds_rings; 150 151 /* 152 * Allocate Transmit Ring 153 */ 154 155 ha->hw.dma_buf.tx_ring.alignment = 8; 156 ha->hw.dma_buf.tx_ring.size = 157 (sizeof(q80_tx_cmd_t)) * NUM_TX_DESCRIPTORS; 158 159 if (qla_alloc_dmabuf(ha, &ha->hw.dma_buf.tx_ring)) { 160 device_printf(dev, "%s: tx ring alloc failed\n", __func__); 161 goto qla_alloc_dma_exit; 162 } 163 ha->hw.dma_buf.flags.tx_ring = 1; 164 165 QL_DPRINT2((dev, "%s: tx_ring phys %p virt %p\n", 166 __func__, (void *)(ha->hw.dma_buf.tx_ring.dma_addr), 167 ha->hw.dma_buf.tx_ring.dma_b)); 168 /* 169 * Allocate Receive Descriptor Rings 170 */ 171 172 for (i = 0; i < ha->hw.num_rds_rings; i++) { 173 ha->hw.dma_buf.rds_ring[i].alignment = 8; 174 175 if (i == RDS_RING_INDEX_NORMAL) { 176 ha->hw.dma_buf.rds_ring[i].size = 177 (sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS; 178 } else if (i == RDS_RING_INDEX_JUMBO) { 179 ha->hw.dma_buf.rds_ring[i].size = 180 (sizeof(q80_recv_desc_t)) * 181 NUM_RX_JUMBO_DESCRIPTORS; 182 } else 183 break; 184 185 if (qla_alloc_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i])) { 186 QL_DPRINT4((dev, "%s: rds ring alloc failed\n", 187 __func__)); 188 189 for (j = 0; j < i; j++) 190 qla_free_dmabuf(ha, 191 &ha->hw.dma_buf.rds_ring[j]); 192 193 goto qla_alloc_dma_exit; 194 } 195 QL_DPRINT4((dev, "%s: rx_ring[%d] phys %p virt %p\n", 196 __func__, i, 197 (void *)(ha->hw.dma_buf.rds_ring[i].dma_addr), 198 ha->hw.dma_buf.rds_ring[i].dma_b)); 199 } 200 ha->hw.dma_buf.flags.rds_ring = 1; 201 202 /* 203 * Allocate Status Descriptor Rings 204 */ 205 206 for (i = 0; i < ha->hw.num_sds_rings; i++) { 207 ha->hw.dma_buf.sds_ring[i].alignment = 8; 208 ha->hw.dma_buf.sds_ring[i].size = 209 (sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS; 210 211 if (qla_alloc_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i])) { 212 device_printf(dev, "%s: sds ring alloc failed\n", 213 __func__); 214 215 for (j = 0; j < i; j++) 216 qla_free_dmabuf(ha, 217 &ha->hw.dma_buf.sds_ring[j]); 218 219 goto qla_alloc_dma_exit; 220 } 221 QL_DPRINT4((dev, "%s: sds_ring[%d] phys %p virt %p\n", 222 __func__, i, 223 (void *)(ha->hw.dma_buf.sds_ring[i].dma_addr), 224 ha->hw.dma_buf.sds_ring[i].dma_b)); 225 } 226 ha->hw.dma_buf.flags.sds_ring = 1; 227 228 /* 229 * Allocate Context Area 230 */ 231 size = QL_ALIGN((sizeof (q80_tx_cntxt_req_t)), QL_BUFFER_ALIGN); 232 233 size += QL_ALIGN((sizeof (q80_tx_cntxt_rsp_t)), QL_BUFFER_ALIGN); 234 235 size += QL_ALIGN((sizeof (q80_rcv_cntxt_req_t)), QL_BUFFER_ALIGN); 236 237 size += QL_ALIGN((sizeof (q80_rcv_cntxt_rsp_t)), QL_BUFFER_ALIGN); 238 239 size += sizeof (uint32_t); /* for tx consumer index */ 240 241 size = QL_ALIGN(size, PAGE_SIZE); 242 243 ha->hw.dma_buf.context.alignment = 8; 244 ha->hw.dma_buf.context.size = size; 245 246 if (qla_alloc_dmabuf(ha, &ha->hw.dma_buf.context)) { 247 device_printf(dev, "%s: context alloc failed\n", __func__); 248 goto qla_alloc_dma_exit; 249 } 250 ha->hw.dma_buf.flags.context = 1; 251 QL_DPRINT2((dev, "%s: context phys %p virt %p\n", 252 __func__, (void *)(ha->hw.dma_buf.context.dma_addr), 253 ha->hw.dma_buf.context.dma_b)); 254 255 qla_init_cntxt_regions(ha); 256 257 return 0; 258 259 qla_alloc_dma_exit: 260 qla_free_dma(ha); 261 return -1; 262 } 263 264 /* 265 * Name: qla_init_cntxt_regions 266 * Function: Initializes Tx/Rx Contexts. 267 */ 268 static void 269 qla_init_cntxt_regions(qla_host_t *ha) 270 { 271 qla_hw_t *hw; 272 q80_tx_cntxt_req_t *tx_cntxt_req; 273 q80_rcv_cntxt_req_t *rx_cntxt_req; 274 bus_addr_t phys_addr; 275 uint32_t i; 276 uint32_t size; 277 278 hw = &ha->hw; 279 280 hw->tx_ring_base = hw->dma_buf.tx_ring.dma_b; 281 282 for (i = 0; i < ha->hw.num_sds_rings; i++) 283 hw->sds[i].sds_ring_base = 284 (q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b; 285 286 phys_addr = hw->dma_buf.context.dma_addr; 287 288 memset((void *)hw->dma_buf.context.dma_b, 0, 289 ha->hw.dma_buf.context.size); 290 291 hw->tx_cntxt_req = 292 (q80_tx_cntxt_req_t *)hw->dma_buf.context.dma_b; 293 hw->tx_cntxt_req_paddr = phys_addr; 294 295 size = QL_ALIGN((sizeof (q80_tx_cntxt_req_t)), QL_BUFFER_ALIGN); 296 297 hw->tx_cntxt_rsp = 298 (q80_tx_cntxt_rsp_t *)((uint8_t *)hw->tx_cntxt_req + size); 299 hw->tx_cntxt_rsp_paddr = hw->tx_cntxt_req_paddr + size; 300 301 size = QL_ALIGN((sizeof (q80_tx_cntxt_rsp_t)), QL_BUFFER_ALIGN); 302 303 hw->rx_cntxt_req = 304 (q80_rcv_cntxt_req_t *)((uint8_t *)hw->tx_cntxt_rsp + size); 305 hw->rx_cntxt_req_paddr = hw->tx_cntxt_rsp_paddr + size; 306 307 size = QL_ALIGN((sizeof (q80_rcv_cntxt_req_t)), QL_BUFFER_ALIGN); 308 309 hw->rx_cntxt_rsp = 310 (q80_rcv_cntxt_rsp_t *)((uint8_t *)hw->rx_cntxt_req + size); 311 hw->rx_cntxt_rsp_paddr = hw->rx_cntxt_req_paddr + size; 312 313 size = QL_ALIGN((sizeof (q80_rcv_cntxt_rsp_t)), QL_BUFFER_ALIGN); 314 315 hw->tx_cons = (uint32_t *)((uint8_t *)hw->rx_cntxt_rsp + size); 316 hw->tx_cons_paddr = hw->rx_cntxt_rsp_paddr + size; 317 318 /* 319 * Initialize the Transmit Context Request so that we don't need to 320 * do it every time we need to create a context 321 */ 322 tx_cntxt_req = hw->tx_cntxt_req; 323 324 tx_cntxt_req->rsp_dma_addr = qla_host_to_le64(hw->tx_cntxt_rsp_paddr); 325 326 tx_cntxt_req->cmd_cons_dma_addr = qla_host_to_le64(hw->tx_cons_paddr); 327 328 tx_cntxt_req->caps[0] = qla_host_to_le32((CNTXT_CAP0_BASEFW | 329 CNTXT_CAP0_LEGACY_MN | CNTXT_CAP0_LSO)); 330 331 tx_cntxt_req->intr_mode = qla_host_to_le32(CNTXT_INTR_MODE_SHARED); 332 333 tx_cntxt_req->phys_addr = 334 qla_host_to_le64(hw->dma_buf.tx_ring.dma_addr); 335 336 tx_cntxt_req->num_entries = qla_host_to_le32(NUM_TX_DESCRIPTORS); 337 338 /* 339 * Initialize the Receive Context Request 340 */ 341 342 rx_cntxt_req = hw->rx_cntxt_req; 343 344 rx_cntxt_req->rx_req.rsp_dma_addr = 345 qla_host_to_le64(hw->rx_cntxt_rsp_paddr); 346 347 rx_cntxt_req->rx_req.caps[0] = qla_host_to_le32(CNTXT_CAP0_BASEFW | 348 CNTXT_CAP0_LEGACY_MN | 349 CNTXT_CAP0_JUMBO | 350 CNTXT_CAP0_LRO| 351 CNTXT_CAP0_HW_LRO); 352 353 rx_cntxt_req->rx_req.intr_mode = 354 qla_host_to_le32(CNTXT_INTR_MODE_SHARED); 355 356 rx_cntxt_req->rx_req.rds_intr_mode = 357 qla_host_to_le32(CNTXT_INTR_MODE_UNIQUE); 358 359 rx_cntxt_req->rx_req.rds_ring_offset = 0; 360 rx_cntxt_req->rx_req.sds_ring_offset = qla_host_to_le32( 361 (hw->num_rds_rings * sizeof(q80_rq_rds_ring_t))); 362 rx_cntxt_req->rx_req.num_rds_rings = 363 qla_host_to_le16(hw->num_rds_rings); 364 rx_cntxt_req->rx_req.num_sds_rings = 365 qla_host_to_le16(hw->num_sds_rings); 366 367 for (i = 0; i < hw->num_rds_rings; i++) { 368 rx_cntxt_req->rds_req[i].phys_addr = 369 qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr); 370 371 if (i == RDS_RING_INDEX_NORMAL) { 372 rx_cntxt_req->rds_req[i].buf_size = 373 qla_host_to_le64(MCLBYTES); 374 rx_cntxt_req->rds_req[i].size = 375 qla_host_to_le32(NUM_RX_DESCRIPTORS); 376 } else { 377 rx_cntxt_req->rds_req[i].buf_size = 378 qla_host_to_le64(MJUM9BYTES); 379 rx_cntxt_req->rds_req[i].size = 380 qla_host_to_le32(NUM_RX_JUMBO_DESCRIPTORS); 381 } 382 } 383 384 for (i = 0; i < hw->num_sds_rings; i++) { 385 rx_cntxt_req->sds_req[i].phys_addr = 386 qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr); 387 rx_cntxt_req->sds_req[i].size = 388 qla_host_to_le32(NUM_STATUS_DESCRIPTORS); 389 rx_cntxt_req->sds_req[i].msi_index = qla_host_to_le16(i); 390 } 391 392 QL_DPRINT2((ha->pci_dev, "%s: tx_cntxt_req = %p paddr %p\n", 393 __func__, hw->tx_cntxt_req, (void *)hw->tx_cntxt_req_paddr)); 394 QL_DPRINT2((ha->pci_dev, "%s: tx_cntxt_rsp = %p paddr %p\n", 395 __func__, hw->tx_cntxt_rsp, (void *)hw->tx_cntxt_rsp_paddr)); 396 QL_DPRINT2((ha->pci_dev, "%s: rx_cntxt_req = %p paddr %p\n", 397 __func__, hw->rx_cntxt_req, (void *)hw->rx_cntxt_req_paddr)); 398 QL_DPRINT2((ha->pci_dev, "%s: rx_cntxt_rsp = %p paddr %p\n", 399 __func__, hw->rx_cntxt_rsp, (void *)hw->rx_cntxt_rsp_paddr)); 400 QL_DPRINT2((ha->pci_dev, "%s: tx_cons = %p paddr %p\n", 401 __func__, hw->tx_cons, (void *)hw->tx_cons_paddr)); 402 } 403 404 /* 405 * Name: qla_issue_cmd 406 * Function: Issues commands on the CDRP interface and returns responses. 407 */ 408 static int 409 qla_issue_cmd(qla_host_t *ha, qla_cdrp_t *cdrp) 410 { 411 int ret = 0; 412 uint32_t signature; 413 uint32_t count = 400; /* 4 seconds or 400 10ms intervals */ 414 uint32_t data; 415 device_t dev; 416 417 dev = ha->pci_dev; 418 419 signature = 0xcafe0000 | 0x0100 | ha->pci_func; 420 421 ret = qla_sem_lock(ha, Q8_SEM5_LOCK, 0, (uint32_t)ha->pci_func); 422 423 if (ret) { 424 device_printf(dev, "%s: SEM5_LOCK lock failed\n", __func__); 425 return (ret); 426 } 427 428 WRITE_OFFSET32(ha, Q8_NX_CDRP_SIGNATURE, signature); 429 430 WRITE_OFFSET32(ha, Q8_NX_CDRP_ARG1, (cdrp->cmd_arg1)); 431 WRITE_OFFSET32(ha, Q8_NX_CDRP_ARG2, (cdrp->cmd_arg2)); 432 WRITE_OFFSET32(ha, Q8_NX_CDRP_ARG3, (cdrp->cmd_arg3)); 433 434 WRITE_OFFSET32(ha, Q8_NX_CDRP_CMD_RSP, cdrp->cmd); 435 436 while (count) { 437 qla_mdelay(__func__, 10); 438 439 data = READ_REG32(ha, Q8_NX_CDRP_CMD_RSP); 440 441 if ((!(data & 0x80000000))) 442 break; 443 count--; 444 } 445 if ((!count) || (data != 1)) 446 ret = -1; 447 448 cdrp->rsp = READ_REG32(ha, Q8_NX_CDRP_CMD_RSP); 449 cdrp->rsp_arg1 = READ_REG32(ha, Q8_NX_CDRP_ARG1); 450 cdrp->rsp_arg2 = READ_REG32(ha, Q8_NX_CDRP_ARG2); 451 cdrp->rsp_arg3 = READ_REG32(ha, Q8_NX_CDRP_ARG3); 452 453 qla_sem_unlock(ha, Q8_SEM5_UNLOCK); 454 455 if (ret) { 456 device_printf(dev, "%s: " 457 "cmd[0x%08x] = 0x%08x\n" 458 "\tsig[0x%08x] = 0x%08x\n" 459 "\targ1[0x%08x] = 0x%08x\n" 460 "\targ2[0x%08x] = 0x%08x\n" 461 "\targ3[0x%08x] = 0x%08x\n", 462 __func__, Q8_NX_CDRP_CMD_RSP, cdrp->cmd, 463 Q8_NX_CDRP_SIGNATURE, signature, 464 Q8_NX_CDRP_ARG1, cdrp->cmd_arg1, 465 Q8_NX_CDRP_ARG2, cdrp->cmd_arg2, 466 Q8_NX_CDRP_ARG3, cdrp->cmd_arg3); 467 468 device_printf(dev, "%s: exit (ret = 0x%x)\n" 469 "\t\t rsp = 0x%08x\n" 470 "\t\t arg1 = 0x%08x\n" 471 "\t\t arg2 = 0x%08x\n" 472 "\t\t arg3 = 0x%08x\n", 473 __func__, ret, cdrp->rsp, 474 cdrp->rsp_arg1, cdrp->rsp_arg2, cdrp->rsp_arg3); 475 } 476 477 return (ret); 478 } 479 480 #define QLA_TX_MIN_FREE 2 481 482 /* 483 * Name: qla_fw_cmd 484 * Function: Issues firmware control commands on the Tx Ring. 485 */ 486 static int 487 qla_fw_cmd(qla_host_t *ha, void *fw_cmd, uint32_t size) 488 { 489 device_t dev; 490 q80_tx_cmd_t *tx_cmd; 491 qla_hw_t *hw = &ha->hw; 492 int count = 100; 493 494 dev = ha->pci_dev; 495 496 QLA_TX_LOCK(ha); 497 498 if (hw->txr_free <= QLA_TX_MIN_FREE) { 499 while (count--) { 500 qla_hw_tx_done_locked(ha); 501 if (hw->txr_free > QLA_TX_MIN_FREE) 502 break; 503 504 QLA_TX_UNLOCK(ha); 505 qla_mdelay(__func__, 10); 506 QLA_TX_LOCK(ha); 507 } 508 if (hw->txr_free <= QLA_TX_MIN_FREE) { 509 QLA_TX_UNLOCK(ha); 510 device_printf(dev, "%s: xmit queue full\n", __func__); 511 return (-1); 512 } 513 } 514 tx_cmd = &hw->tx_ring_base[hw->txr_next]; 515 516 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 517 518 bcopy(fw_cmd, tx_cmd, size); 519 520 hw->txr_next = (hw->txr_next + 1) & (NUM_TX_DESCRIPTORS - 1); 521 hw->txr_free--; 522 523 QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->txr_next); 524 525 QLA_TX_UNLOCK(ha); 526 527 return (0); 528 } 529 530 /* 531 * Name: qla_config_rss 532 * Function: Configure RSS for the context/interface. 533 */ 534 const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL, 535 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL, 536 0x255b0ec26d5a56daULL }; 537 538 static int 539 qla_config_rss(qla_host_t *ha, uint16_t cntxt_id) 540 { 541 qla_fw_cds_config_rss_t rss_config; 542 int ret, i; 543 544 bzero(&rss_config, sizeof(qla_fw_cds_config_rss_t)); 545 546 rss_config.hdr.cmd = Q8_FWCD_CNTRL_REQ; 547 rss_config.hdr.opcode = Q8_FWCD_OPCODE_CONFIG_RSS; 548 rss_config.hdr.cntxt_id = cntxt_id; 549 550 rss_config.hash_type = (Q8_FWCD_RSS_HASH_TYPE_IPV4_TCP_IP | 551 Q8_FWCD_RSS_HASH_TYPE_IPV6_TCP_IP); 552 rss_config.flags = Q8_FWCD_RSS_FLAGS_ENABLE_RSS; 553 554 rss_config.ind_tbl_mask = 0x7; 555 556 for (i = 0; i < 5; i++) 557 rss_config.rss_key[i] = rss_key[i]; 558 559 ret = qla_fw_cmd(ha, &rss_config, sizeof(qla_fw_cds_config_rss_t)); 560 561 return ret; 562 } 563 564 /* 565 * Name: qla_config_intr_coalesce 566 * Function: Configure Interrupt Coalescing. 567 */ 568 static int 569 qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable) 570 { 571 qla_fw_cds_config_intr_coalesc_t intr_coalesce; 572 int ret; 573 574 bzero(&intr_coalesce, sizeof(qla_fw_cds_config_intr_coalesc_t)); 575 576 intr_coalesce.hdr.cmd = Q8_FWCD_CNTRL_REQ; 577 intr_coalesce.hdr.opcode = Q8_FWCD_OPCODE_CONFIG_INTR_COALESCING; 578 intr_coalesce.hdr.cntxt_id = cntxt_id; 579 580 intr_coalesce.flags = 0x04; 581 intr_coalesce.max_rcv_pkts = 256; 582 intr_coalesce.max_rcv_usecs = 3; 583 intr_coalesce.max_snd_pkts = 64; 584 intr_coalesce.max_snd_usecs = 4; 585 586 if (tenable) { 587 intr_coalesce.usecs_to = 1000; /* 1 millisecond */ 588 intr_coalesce.timer_type = Q8_FWCMD_INTR_COALESC_TIMER_PERIODIC; 589 intr_coalesce.sds_ring_bitmask = 590 Q8_FWCMD_INTR_COALESC_SDS_RING_0; 591 } 592 593 ret = qla_fw_cmd(ha, &intr_coalesce, 594 sizeof(qla_fw_cds_config_intr_coalesc_t)); 595 596 return ret; 597 } 598 599 /* 600 * Name: qla_config_mac_addr 601 * Function: binds a MAC address to the context/interface. 602 * Can be unicast, multicast or broadcast. 603 */ 604 static int 605 qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint16_t cntxt_id, 606 uint32_t add_multi) 607 { 608 qla_fw_cds_config_mac_addr_t mac_config; 609 int ret; 610 611 // device_printf(ha->pci_dev, 612 // "%s: mac_addr %02x:%02x:%02x:%02x:%02x:%02x\n", __func__, 613 // mac_addr[0], mac_addr[1], mac_addr[2], 614 // mac_addr[3], mac_addr[4], mac_addr[5]); 615 616 bzero(&mac_config, sizeof(qla_fw_cds_config_mac_addr_t)); 617 618 mac_config.hdr.cmd = Q8_FWCD_CNTRL_REQ; 619 mac_config.hdr.opcode = Q8_FWCD_OPCODE_CONFIG_MAC_ADDR; 620 mac_config.hdr.cntxt_id = cntxt_id; 621 622 if (add_multi) 623 mac_config.cmd = Q8_FWCD_ADD_MAC_ADDR; 624 else 625 mac_config.cmd = Q8_FWCD_DEL_MAC_ADDR; 626 bcopy(mac_addr, mac_config.mac_addr,6); 627 628 ret = qla_fw_cmd(ha, &mac_config, sizeof(qla_fw_cds_config_mac_addr_t)); 629 630 return ret; 631 } 632 633 /* 634 * Name: qla_set_mac_rcv_mode 635 * Function: Enable/Disable AllMulticast and Promiscuous Modes. 636 */ 637 static int 638 qla_set_mac_rcv_mode(qla_host_t *ha, uint16_t cntxt_id, uint32_t mode) 639 { 640 qla_set_mac_rcv_mode_t rcv_mode; 641 int ret; 642 643 bzero(&rcv_mode, sizeof(qla_set_mac_rcv_mode_t)); 644 645 rcv_mode.hdr.cmd = Q8_FWCD_CNTRL_REQ; 646 rcv_mode.hdr.opcode = Q8_FWCD_OPCODE_CONFIG_MAC_RCV_MODE; 647 rcv_mode.hdr.cntxt_id = cntxt_id; 648 649 rcv_mode.mode = mode; 650 651 ret = qla_fw_cmd(ha, &rcv_mode, sizeof(qla_set_mac_rcv_mode_t)); 652 653 return ret; 654 } 655 656 void 657 qla_set_promisc(qla_host_t *ha) 658 { 659 (void)qla_set_mac_rcv_mode(ha, 660 (ha->hw.rx_cntxt_rsp)->rx_rsp.cntxt_id, 661 Q8_MAC_RCV_ENABLE_PROMISCUOUS); 662 } 663 664 void 665 qla_set_allmulti(qla_host_t *ha) 666 { 667 (void)qla_set_mac_rcv_mode(ha, 668 (ha->hw.rx_cntxt_rsp)->rx_rsp.cntxt_id, 669 Q8_MAC_RCV_ENABLE_ALLMULTI); 670 } 671 672 void 673 qla_reset_promisc_allmulti(qla_host_t *ha) 674 { 675 (void)qla_set_mac_rcv_mode(ha, 676 (ha->hw.rx_cntxt_rsp)->rx_rsp.cntxt_id, 677 Q8_MAC_RCV_RESET_PROMISC_ALLMULTI); 678 } 679 680 /* 681 * Name: qla_config_ipv4_addr 682 * Function: Configures the Destination IP Addr for LRO. 683 */ 684 void 685 qla_config_ipv4_addr(qla_host_t *ha, uint32_t ipv4_addr) 686 { 687 qla_config_ipv4_t ip_conf; 688 689 bzero(&ip_conf, sizeof(qla_config_ipv4_t)); 690 691 ip_conf.hdr.cmd = Q8_FWCD_CNTRL_REQ; 692 ip_conf.hdr.opcode = Q8_FWCD_OPCODE_CONFIG_IPADDR; 693 ip_conf.hdr.cntxt_id = (ha->hw.rx_cntxt_rsp)->rx_rsp.cntxt_id; 694 695 ip_conf.cmd = (uint64_t)Q8_CONFIG_CMD_IP_ENABLE; 696 ip_conf.ipv4_addr = (uint64_t)ipv4_addr; 697 698 (void)qla_fw_cmd(ha, &ip_conf, sizeof(qla_config_ipv4_t)); 699 700 return; 701 } 702 703 /* 704 * Name: qla_tx_tso 705 * Function: Checks if the packet to be transmitted is a candidate for 706 * Large TCP Segment Offload. If yes, the appropriate fields in the Tx 707 * Ring Structure are plugged in. 708 */ 709 static int 710 qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr) 711 { 712 struct ether_vlan_header *eh; 713 struct ip *ip = NULL; 714 struct tcphdr *th = NULL; 715 uint32_t ehdrlen, hdrlen = 0, ip_hlen, tcp_hlen, tcp_opt_off; 716 uint16_t etype, opcode, offload = 1; 717 uint8_t *tcp_opt; 718 device_t dev; 719 720 dev = ha->pci_dev; 721 722 eh = mtod(mp, struct ether_vlan_header *); 723 724 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 725 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 726 etype = ntohs(eh->evl_proto); 727 } else { 728 ehdrlen = ETHER_HDR_LEN; 729 etype = ntohs(eh->evl_encap_proto); 730 } 731 732 switch (etype) { 733 case ETHERTYPE_IP: 734 735 tcp_opt_off = ehdrlen + sizeof(struct ip) + 736 sizeof(struct tcphdr); 737 738 if (mp->m_len < tcp_opt_off) { 739 m_copydata(mp, 0, tcp_opt_off, hdr); 740 ip = (struct ip *)hdr; 741 } else { 742 ip = (struct ip *)(mp->m_data + ehdrlen); 743 } 744 745 ip_hlen = ip->ip_hl << 2; 746 opcode = Q8_TX_CMD_OP_XMT_TCP_LSO; 747 748 if ((ip->ip_p != IPPROTO_TCP) || 749 (ip_hlen != sizeof (struct ip))) { 750 offload = 0; 751 } else { 752 th = (struct tcphdr *)((caddr_t)ip + ip_hlen); 753 } 754 break; 755 756 default: 757 QL_DPRINT8((dev, "%s: type!=ip\n", __func__)); 758 offload = 0; 759 break; 760 } 761 762 if (!offload) 763 return (-1); 764 765 tcp_hlen = th->th_off << 2; 766 767 hdrlen = ehdrlen + ip_hlen + tcp_hlen; 768 769 if (mp->m_len < hdrlen) { 770 if (mp->m_len < tcp_opt_off) { 771 if (tcp_hlen > sizeof(struct tcphdr)) { 772 m_copydata(mp, tcp_opt_off, 773 (tcp_hlen - sizeof(struct tcphdr)), 774 &hdr[tcp_opt_off]); 775 } 776 } else { 777 m_copydata(mp, 0, hdrlen, hdr); 778 } 779 } 780 781 if ((mp->m_pkthdr.csum_flags & CSUM_TSO) == 0) { 782 /* If TCP options are preset only time stamp option is supported */ 783 if ((tcp_hlen - sizeof(struct tcphdr)) != 10) 784 return -1; 785 else { 786 if (mp->m_len < hdrlen) { 787 tcp_opt = &hdr[tcp_opt_off]; 788 } else { 789 tcp_opt = (uint8_t *)(mp->m_data + tcp_opt_off); 790 } 791 792 if ((*tcp_opt != 0x01) || (*(tcp_opt + 1) != 0x01) || 793 (*(tcp_opt + 2) != 0x08) || 794 (*(tcp_opt + 3) != 10)) { 795 return -1; 796 } 797 } 798 799 tx_cmd->mss = ha->max_frame_size - ETHER_CRC_LEN - hdrlen; 800 } else { 801 tx_cmd->mss = mp->m_pkthdr.tso_segsz; 802 } 803 804 tx_cmd->flags_opcode = opcode ; 805 tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen; 806 tx_cmd->ip_hdr_off = ehdrlen; 807 tx_cmd->mss = mp->m_pkthdr.tso_segsz; 808 tx_cmd->total_hdr_len = hdrlen; 809 810 /* Check for Multicast least significant bit of MSB == 1 */ 811 if (eh->evl_dhost[0] & 0x01) { 812 tx_cmd->flags_opcode = Q8_TX_CMD_FLAGS_MULTICAST; 813 } 814 815 if (mp->m_len < hdrlen) { 816 return (1); 817 } 818 819 return (0); 820 } 821 822 /* 823 * Name: qla_tx_chksum 824 * Function: Checks if the packet to be transmitted is a candidate for 825 * TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx 826 * Ring Structure are plugged in. 827 */ 828 static int 829 qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd) 830 { 831 struct ether_vlan_header *eh; 832 struct ip *ip; 833 struct ip6_hdr *ip6; 834 uint32_t ehdrlen, ip_hlen; 835 uint16_t etype, opcode, offload = 1; 836 device_t dev; 837 838 dev = ha->pci_dev; 839 840 if ((mp->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) == 0) 841 return (-1); 842 843 eh = mtod(mp, struct ether_vlan_header *); 844 845 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 846 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 847 etype = ntohs(eh->evl_proto); 848 } else { 849 ehdrlen = ETHER_HDR_LEN; 850 etype = ntohs(eh->evl_encap_proto); 851 } 852 853 854 switch (etype) { 855 case ETHERTYPE_IP: 856 ip = (struct ip *)(mp->m_data + ehdrlen); 857 858 ip_hlen = sizeof (struct ip); 859 860 if (mp->m_len < (ehdrlen + ip_hlen)) { 861 device_printf(dev, "%s: ipv4 mlen\n", __func__); 862 offload = 0; 863 break; 864 } 865 866 if (ip->ip_p == IPPROTO_TCP) 867 opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM; 868 else if (ip->ip_p == IPPROTO_UDP) 869 opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM; 870 else { 871 device_printf(dev, "%s: ipv4\n", __func__); 872 offload = 0; 873 } 874 break; 875 876 case ETHERTYPE_IPV6: 877 ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); 878 879 ip_hlen = sizeof(struct ip6_hdr); 880 881 if (mp->m_len < (ehdrlen + ip_hlen)) { 882 device_printf(dev, "%s: ipv6 mlen\n", __func__); 883 offload = 0; 884 break; 885 } 886 887 if (ip6->ip6_nxt == IPPROTO_TCP) 888 opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6; 889 else if (ip6->ip6_nxt == IPPROTO_UDP) 890 opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6; 891 else { 892 device_printf(dev, "%s: ipv6\n", __func__); 893 offload = 0; 894 } 895 break; 896 897 default: 898 offload = 0; 899 break; 900 } 901 if (!offload) 902 return (-1); 903 904 tx_cmd->flags_opcode = opcode; 905 906 tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen; 907 908 return (0); 909 } 910 911 /* 912 * Name: qla_hw_send 913 * Function: Transmits a packet. It first checks if the packet is a 914 * candidate for Large TCP Segment Offload and then for UDP/TCP checksum 915 * offload. If either of these creteria are not met, it is transmitted 916 * as a regular ethernet frame. 917 */ 918 int 919 qla_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs, 920 uint32_t *tx_idx, struct mbuf *mp) 921 { 922 struct ether_vlan_header *eh; 923 qla_hw_t *hw = &ha->hw; 924 q80_tx_cmd_t *tx_cmd, tso_cmd; 925 bus_dma_segment_t *c_seg; 926 uint32_t num_tx_cmds, hdr_len = 0; 927 uint32_t total_length = 0, bytes, tx_cmd_count = 0; 928 device_t dev; 929 int i, ret; 930 uint8_t *src = NULL, *dst = NULL; 931 932 dev = ha->pci_dev; 933 934 /* 935 * Always make sure there is atleast one empty slot in the tx_ring 936 * tx_ring is considered full when there only one entry available 937 */ 938 num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2; 939 940 total_length = mp->m_pkthdr.len; 941 if (total_length > QLA_MAX_TSO_FRAME_SIZE) { 942 device_printf(dev, "%s: total length exceeds maxlen(%d)\n", 943 __func__, total_length); 944 return (-1); 945 } 946 eh = mtod(mp, struct ether_vlan_header *); 947 948 if ((mp->m_pkthdr.len > ha->max_frame_size)||(nsegs > Q8_TX_MAX_SEGMENTS)) { 949 bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t)); 950 951 src = ha->hw.frame_hdr; 952 ret = qla_tx_tso(ha, mp, &tso_cmd, src); 953 954 if (!(ret & ~1)) { 955 /* find the additional tx_cmd descriptors required */ 956 957 hdr_len = tso_cmd.total_hdr_len; 958 959 bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN; 960 bytes = QL_MIN(bytes, hdr_len); 961 962 num_tx_cmds++; 963 hdr_len -= bytes; 964 965 while (hdr_len) { 966 bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len); 967 hdr_len -= bytes; 968 num_tx_cmds++; 969 } 970 hdr_len = tso_cmd.total_hdr_len; 971 972 if (ret == 0) 973 src = (uint8_t *)eh; 974 } 975 } 976 977 if (hw->txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) { 978 qla_hw_tx_done_locked(ha); 979 if (hw->txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) { 980 QL_DPRINT8((dev, "%s: (hw->txr_free <= " 981 "(num_tx_cmds + QLA_TX_MIN_FREE))\n", 982 __func__)); 983 return (-1); 984 } 985 } 986 987 *tx_idx = hw->txr_next; 988 989 tx_cmd = &hw->tx_ring_base[hw->txr_next]; 990 991 if (hdr_len == 0) { 992 if ((nsegs > Q8_TX_MAX_SEGMENTS) || 993 (mp->m_pkthdr.len > ha->max_frame_size)){ 994 device_printf(dev, 995 "%s: (nsegs[%d, %d, 0x%b] > Q8_TX_MAX_SEGMENTS)\n", 996 __func__, nsegs, mp->m_pkthdr.len, 997 (int)mp->m_pkthdr.csum_flags, CSUM_BITS); 998 qla_dump_buf8(ha, "qla_hw_send: wrong pkt", 999 mtod(mp, char *), mp->m_len); 1000 return (EINVAL); 1001 } 1002 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 1003 if (qla_tx_chksum(ha, mp, tx_cmd) != 0) 1004 tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER; 1005 } else { 1006 bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t)); 1007 } 1008 1009 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) 1010 tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED; 1011 else if (mp->m_flags & M_VLANTAG) { 1012 tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED | 1013 Q8_TX_CMD_FLAGS_HW_VLAN_ID); 1014 tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag; 1015 } 1016 1017 tx_cmd->n_bufs = (uint8_t)nsegs; 1018 tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF); 1019 tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8))); 1020 tx_cmd->port_cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func); 1021 1022 c_seg = segs; 1023 1024 while (1) { 1025 for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) { 1026 switch (i) { 1027 case 0: 1028 tx_cmd->buf1_addr = c_seg->ds_addr; 1029 tx_cmd->buf1_len = c_seg->ds_len; 1030 break; 1031 1032 case 1: 1033 tx_cmd->buf2_addr = c_seg->ds_addr; 1034 tx_cmd->buf2_len = c_seg->ds_len; 1035 break; 1036 1037 case 2: 1038 tx_cmd->buf3_addr = c_seg->ds_addr; 1039 tx_cmd->buf3_len = c_seg->ds_len; 1040 break; 1041 1042 case 3: 1043 tx_cmd->buf4_addr = c_seg->ds_addr; 1044 tx_cmd->buf4_len = c_seg->ds_len; 1045 break; 1046 } 1047 1048 c_seg++; 1049 nsegs--; 1050 } 1051 1052 hw->txr_next = (hw->txr_next + 1) & (NUM_TX_DESCRIPTORS - 1); 1053 tx_cmd_count++; 1054 1055 if (!nsegs) 1056 break; 1057 1058 tx_cmd = &hw->tx_ring_base[hw->txr_next]; 1059 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 1060 } 1061 1062 if (hdr_len) { 1063 /* TSO : Copy the header in the following tx cmd descriptors */ 1064 1065 tx_cmd = &hw->tx_ring_base[hw->txr_next]; 1066 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 1067 1068 bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN; 1069 bytes = QL_MIN(bytes, hdr_len); 1070 1071 dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN; 1072 1073 if (mp->m_flags & M_VLANTAG) { 1074 /* first copy the src/dst MAC addresses */ 1075 bcopy(src, dst, (ETHER_ADDR_LEN * 2)); 1076 dst += (ETHER_ADDR_LEN * 2); 1077 src += (ETHER_ADDR_LEN * 2); 1078 1079 hdr_len -= (ETHER_ADDR_LEN * 2); 1080 1081 *((uint16_t *)dst) = htons(ETHERTYPE_VLAN); 1082 dst += 2; 1083 *((uint16_t *)dst) = mp->m_pkthdr.ether_vtag; 1084 dst += 2; 1085 1086 bytes -= ((ETHER_ADDR_LEN * 2) + 4); 1087 1088 bcopy(src, dst, bytes); 1089 src += bytes; 1090 hdr_len -= bytes; 1091 } else { 1092 bcopy(src, dst, bytes); 1093 src += bytes; 1094 hdr_len -= bytes; 1095 } 1096 1097 hw->txr_next = (hw->txr_next + 1) & (NUM_TX_DESCRIPTORS - 1); 1098 tx_cmd_count++; 1099 1100 while (hdr_len) { 1101 tx_cmd = &hw->tx_ring_base[hw->txr_next]; 1102 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 1103 1104 bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len); 1105 1106 bcopy(src, tx_cmd, bytes); 1107 src += bytes; 1108 hdr_len -= bytes; 1109 hw->txr_next = 1110 (hw->txr_next + 1) & (NUM_TX_DESCRIPTORS - 1); 1111 tx_cmd_count++; 1112 } 1113 } 1114 1115 hw->txr_free = hw->txr_free - tx_cmd_count; 1116 1117 QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->txr_next); 1118 QL_DPRINT8((dev, "%s: return\n", __func__)); 1119 return (0); 1120 } 1121 1122 /* 1123 * Name: qla_del_hw_if 1124 * Function: Destroys the hardware specific entities corresponding to an 1125 * Ethernet Interface 1126 */ 1127 void 1128 qla_del_hw_if(qla_host_t *ha) 1129 { 1130 int i; 1131 1132 for (i = 0; i < ha->hw.num_sds_rings; i++) 1133 QL_DISABLE_INTERRUPTS(ha, i); 1134 1135 qla_del_rcv_cntxt(ha); 1136 qla_del_xmt_cntxt(ha); 1137 1138 ha->hw.flags.lro = 0; 1139 } 1140 1141 /* 1142 * Name: qla_init_hw_if 1143 * Function: Creates the hardware specific entities corresponding to an 1144 * Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address 1145 * corresponding to the interface. Enables LRO if allowed. 1146 */ 1147 int 1148 qla_init_hw_if(qla_host_t *ha) 1149 { 1150 int i; 1151 uint8_t bcast_mac[6]; 1152 1153 qla_get_hw_caps(ha); 1154 1155 for (i = 0; i < ha->hw.num_sds_rings; i++) { 1156 bzero(ha->hw.dma_buf.sds_ring[i].dma_b, 1157 ha->hw.dma_buf.sds_ring[i].size); 1158 } 1159 /* 1160 * Create Receive Context 1161 */ 1162 if (qla_init_rcv_cntxt(ha)) { 1163 return (-1); 1164 } 1165 1166 ha->hw.rx_next = NUM_RX_DESCRIPTORS - 2; 1167 ha->hw.rxj_next = NUM_RX_JUMBO_DESCRIPTORS - 2; 1168 ha->hw.rx_in = ha->hw.rxj_in = 0; 1169 1170 /* Update the RDS Producer Indices */ 1171 QL_UPDATE_RDS_PRODUCER_INDEX(ha, 0, ha->hw.rx_next); 1172 QL_UPDATE_RDS_PRODUCER_INDEX(ha, 1, ha->hw.rxj_next); 1173 1174 /* 1175 * Create Transmit Context 1176 */ 1177 if (qla_init_xmt_cntxt(ha)) { 1178 qla_del_rcv_cntxt(ha); 1179 return (-1); 1180 } 1181 1182 qla_config_mac_addr(ha, ha->hw.mac_addr, 1183 (ha->hw.rx_cntxt_rsp)->rx_rsp.cntxt_id, 1); 1184 1185 bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF; 1186 bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF; 1187 qla_config_mac_addr(ha, bcast_mac, 1188 (ha->hw.rx_cntxt_rsp)->rx_rsp.cntxt_id, 1); 1189 1190 qla_config_rss(ha, (ha->hw.rx_cntxt_rsp)->rx_rsp.cntxt_id); 1191 1192 qla_config_intr_coalesce(ha, (ha->hw.rx_cntxt_rsp)->rx_rsp.cntxt_id, 0); 1193 1194 for (i = 0; i < ha->hw.num_sds_rings; i++) 1195 QL_ENABLE_INTERRUPTS(ha, i); 1196 1197 return (0); 1198 } 1199 1200 /* 1201 * Name: qla_init_rcv_cntxt 1202 * Function: Creates the Receive Context. 1203 */ 1204 static int 1205 qla_init_rcv_cntxt(qla_host_t *ha) 1206 { 1207 device_t dev; 1208 qla_cdrp_t cdrp; 1209 q80_rcv_cntxt_rsp_t *rsp; 1210 q80_stat_desc_t *sdesc; 1211 bus_addr_t phys_addr; 1212 int i, j; 1213 qla_hw_t *hw = &ha->hw; 1214 1215 dev = ha->pci_dev; 1216 1217 /* 1218 * Create Receive Context 1219 */ 1220 1221 for (i = 0; i < hw->num_sds_rings; i++) { 1222 sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0]; 1223 for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) { 1224 sdesc->data[0] = 1225 Q8_STAT_DESC_SET_OWNER(Q8_STAT_DESC_OWNER_FW); 1226 } 1227 } 1228 1229 phys_addr = ha->hw.rx_cntxt_req_paddr; 1230 1231 bzero(&cdrp, sizeof(qla_cdrp_t)); 1232 1233 cdrp.cmd = Q8_CMD_CREATE_RX_CNTXT; 1234 cdrp.cmd_arg1 = (uint32_t)(phys_addr >> 32); 1235 cdrp.cmd_arg2 = (uint32_t)(phys_addr); 1236 cdrp.cmd_arg3 = (uint32_t)(sizeof (q80_rcv_cntxt_req_t)); 1237 1238 if (qla_issue_cmd(ha, &cdrp)) { 1239 device_printf(dev, "%s: Q8_CMD_CREATE_RX_CNTXT failed\n", 1240 __func__); 1241 return (-1); 1242 } else { 1243 rsp = ha->hw.rx_cntxt_rsp; 1244 1245 QL_DPRINT2((dev, "%s: rcv cntxt successful" 1246 " rds_ring_offset = 0x%08x" 1247 " sds_ring_offset = 0x%08x" 1248 " cntxt_state = 0x%08x" 1249 " funcs_per_port = 0x%08x" 1250 " num_rds_rings = 0x%04x" 1251 " num_sds_rings = 0x%04x" 1252 " cntxt_id = 0x%04x" 1253 " phys_port = 0x%02x" 1254 " virt_port = 0x%02x\n", 1255 __func__, 1256 rsp->rx_rsp.rds_ring_offset, 1257 rsp->rx_rsp.sds_ring_offset, 1258 rsp->rx_rsp.cntxt_state, 1259 rsp->rx_rsp.funcs_per_port, 1260 rsp->rx_rsp.num_rds_rings, 1261 rsp->rx_rsp.num_sds_rings, 1262 rsp->rx_rsp.cntxt_id, 1263 rsp->rx_rsp.phys_port, 1264 rsp->rx_rsp.virt_port)); 1265 1266 for (i = 0; i < ha->hw.num_rds_rings; i++) { 1267 QL_DPRINT2((dev, 1268 "%s: rcv cntxt rds[%i].producer_reg = 0x%08x\n", 1269 __func__, i, rsp->rds_rsp[i].producer_reg)); 1270 } 1271 for (i = 0; i < ha->hw.num_sds_rings; i++) { 1272 QL_DPRINT2((dev, 1273 "%s: rcv cntxt sds[%i].consumer_reg = 0x%08x" 1274 " sds[%i].intr_mask_reg = 0x%08x\n", 1275 __func__, i, rsp->sds_rsp[i].consumer_reg, 1276 i, rsp->sds_rsp[i].intr_mask_reg)); 1277 } 1278 } 1279 ha->hw.flags.init_rx_cnxt = 1; 1280 return (0); 1281 } 1282 1283 /* 1284 * Name: qla_del_rcv_cntxt 1285 * Function: Destroys the Receive Context. 1286 */ 1287 void 1288 qla_del_rcv_cntxt(qla_host_t *ha) 1289 { 1290 qla_cdrp_t cdrp; 1291 device_t dev = ha->pci_dev; 1292 1293 if (!ha->hw.flags.init_rx_cnxt) 1294 return; 1295 1296 bzero(&cdrp, sizeof(qla_cdrp_t)); 1297 1298 cdrp.cmd = Q8_CMD_DESTROY_RX_CNTXT; 1299 cdrp.cmd_arg1 = (uint32_t) (ha->hw.rx_cntxt_rsp)->rx_rsp.cntxt_id; 1300 1301 if (qla_issue_cmd(ha, &cdrp)) { 1302 device_printf(dev, "%s: Q8_CMD_DESTROY_RX_CNTXT failed\n", 1303 __func__); 1304 } 1305 ha->hw.flags.init_rx_cnxt = 0; 1306 } 1307 1308 /* 1309 * Name: qla_init_xmt_cntxt 1310 * Function: Creates the Transmit Context. 1311 */ 1312 static int 1313 qla_init_xmt_cntxt(qla_host_t *ha) 1314 { 1315 bus_addr_t phys_addr; 1316 device_t dev; 1317 q80_tx_cntxt_rsp_t *tx_rsp; 1318 qla_cdrp_t cdrp; 1319 qla_hw_t *hw = &ha->hw; 1320 1321 dev = ha->pci_dev; 1322 1323 /* 1324 * Create Transmit Context 1325 */ 1326 phys_addr = ha->hw.tx_cntxt_req_paddr; 1327 tx_rsp = ha->hw.tx_cntxt_rsp; 1328 1329 hw->txr_comp = hw->txr_next = 0; 1330 *(hw->tx_cons) = 0; 1331 1332 bzero(&cdrp, sizeof(qla_cdrp_t)); 1333 1334 cdrp.cmd = Q8_CMD_CREATE_TX_CNTXT; 1335 cdrp.cmd_arg1 = (uint32_t)(phys_addr >> 32); 1336 cdrp.cmd_arg2 = (uint32_t)(phys_addr); 1337 cdrp.cmd_arg3 = (uint32_t)(sizeof (q80_tx_cntxt_req_t)); 1338 1339 if (qla_issue_cmd(ha, &cdrp)) { 1340 device_printf(dev, "%s: Q8_CMD_CREATE_TX_CNTXT failed\n", 1341 __func__); 1342 return (-1); 1343 } else { 1344 ha->hw.tx_prod_reg = tx_rsp->producer_reg; 1345 1346 QL_DPRINT2((dev, "%s: tx cntxt successful" 1347 " cntxt_state = 0x%08x " 1348 " cntxt_id = 0x%04x " 1349 " phys_port_id = 0x%02x " 1350 " virt_port_id = 0x%02x " 1351 " producer_reg = 0x%08x " 1352 " intr_mask_reg = 0x%08x\n", 1353 __func__, tx_rsp->cntxt_state, tx_rsp->cntxt_id, 1354 tx_rsp->phys_port_id, tx_rsp->virt_port_id, 1355 tx_rsp->producer_reg, tx_rsp->intr_mask_reg)); 1356 } 1357 ha->hw.txr_free = NUM_TX_DESCRIPTORS; 1358 1359 ha->hw.flags.init_tx_cnxt = 1; 1360 return (0); 1361 } 1362 1363 /* 1364 * Name: qla_del_xmt_cntxt 1365 * Function: Destroys the Transmit Context. 1366 */ 1367 static void 1368 qla_del_xmt_cntxt(qla_host_t *ha) 1369 { 1370 qla_cdrp_t cdrp; 1371 device_t dev = ha->pci_dev; 1372 1373 if (!ha->hw.flags.init_tx_cnxt) 1374 return; 1375 1376 bzero(&cdrp, sizeof(qla_cdrp_t)); 1377 1378 cdrp.cmd = Q8_CMD_DESTROY_TX_CNTXT; 1379 cdrp.cmd_arg1 = (uint32_t) (ha->hw.tx_cntxt_rsp)->cntxt_id; 1380 1381 if (qla_issue_cmd(ha, &cdrp)) { 1382 device_printf(dev, "%s: Q8_CMD_DESTROY_TX_CNTXT failed\n", 1383 __func__); 1384 } 1385 ha->hw.flags.init_tx_cnxt = 0; 1386 } 1387 1388 /* 1389 * Name: qla_get_max_rds 1390 * Function: Returns the maximum number of Receive Descriptor Rings per context. 1391 */ 1392 static int 1393 qla_get_max_rds(qla_host_t *ha) 1394 { 1395 qla_cdrp_t cdrp; 1396 device_t dev; 1397 1398 dev = ha->pci_dev; 1399 1400 bzero(&cdrp, sizeof(qla_cdrp_t)); 1401 1402 cdrp.cmd = Q8_CMD_RD_MAX_RDS_PER_CNTXT; 1403 1404 if (qla_issue_cmd(ha, &cdrp)) { 1405 device_printf(dev, "%s: Q8_CMD_RD_MAX_RDS_PER_CNTXT failed\n", 1406 __func__); 1407 return (-1); 1408 } else { 1409 ha->hw.max_rds_per_cntxt = cdrp.rsp_arg1; 1410 QL_DPRINT2((dev, "%s: max_rds_per_context 0x%08x\n", 1411 __func__, ha->hw.max_rds_per_cntxt)); 1412 } 1413 return 0; 1414 } 1415 1416 /* 1417 * Name: qla_get_max_sds 1418 * Function: Returns the maximum number of Status Descriptor Rings per context. 1419 */ 1420 static int 1421 qla_get_max_sds(qla_host_t *ha) 1422 { 1423 qla_cdrp_t cdrp; 1424 device_t dev; 1425 1426 dev = ha->pci_dev; 1427 1428 bzero(&cdrp, sizeof(qla_cdrp_t)); 1429 1430 cdrp.cmd = Q8_CMD_RD_MAX_SDS_PER_CNTXT; 1431 1432 if (qla_issue_cmd(ha, &cdrp)) { 1433 device_printf(dev, "%s: Q8_CMD_RD_MAX_RDS_PER_CNTXT failed\n", 1434 __func__); 1435 return (-1); 1436 } else { 1437 ha->hw.max_sds_per_cntxt = cdrp.rsp_arg1; 1438 QL_DPRINT2((dev, "%s: max_sds_per_context 0x%08x\n", 1439 __func__, ha->hw.max_sds_per_cntxt)); 1440 } 1441 return 0; 1442 } 1443 1444 /* 1445 * Name: qla_get_max_rules 1446 * Function: Returns the maximum number of Rules per context. 1447 */ 1448 static int 1449 qla_get_max_rules(qla_host_t *ha) 1450 { 1451 qla_cdrp_t cdrp; 1452 device_t dev; 1453 1454 dev = ha->pci_dev; 1455 1456 bzero(&cdrp, sizeof(qla_cdrp_t)); 1457 1458 cdrp.cmd = Q8_CMD_RD_MAX_RULES_PER_CNTXT; 1459 1460 if (qla_issue_cmd(ha, &cdrp)) { 1461 device_printf(dev, "%s: Q8_CMD_RD_MAX_RULES_PER_CNTXT failed\n", 1462 __func__); 1463 return (-1); 1464 } else { 1465 ha->hw.max_rules_per_cntxt = cdrp.rsp_arg1; 1466 QL_DPRINT2((dev, "%s: max_rules_per_cntxt 0x%08x\n", 1467 __func__, ha->hw.max_rules_per_cntxt)); 1468 } 1469 return 0; 1470 } 1471 1472 /* 1473 * Name: qla_get_max_rcv_cntxts 1474 * Function: Returns the maximum number of Receive Contexts supported. 1475 */ 1476 static int 1477 qla_get_max_rcv_cntxts(qla_host_t *ha) 1478 { 1479 qla_cdrp_t cdrp; 1480 device_t dev; 1481 1482 dev = ha->pci_dev; 1483 1484 bzero(&cdrp, sizeof(qla_cdrp_t)); 1485 1486 cdrp.cmd = Q8_CMD_RD_MAX_RX_CNTXT; 1487 1488 if (qla_issue_cmd(ha, &cdrp)) { 1489 device_printf(dev, "%s: Q8_CMD_RD_MAX_RX_CNTXT failed\n", 1490 __func__); 1491 return (-1); 1492 } else { 1493 ha->hw.max_rcv_cntxts = cdrp.rsp_arg1; 1494 QL_DPRINT2((dev, "%s: max_rcv_cntxts 0x%08x\n", 1495 __func__, ha->hw.max_rcv_cntxts)); 1496 } 1497 return 0; 1498 } 1499 1500 /* 1501 * Name: qla_get_max_tx_cntxts 1502 * Function: Returns the maximum number of Transmit Contexts supported. 1503 */ 1504 static int 1505 qla_get_max_tx_cntxts(qla_host_t *ha) 1506 { 1507 qla_cdrp_t cdrp; 1508 device_t dev; 1509 1510 dev = ha->pci_dev; 1511 1512 bzero(&cdrp, sizeof(qla_cdrp_t)); 1513 1514 cdrp.cmd = Q8_CMD_RD_MAX_TX_CNTXT; 1515 1516 if (qla_issue_cmd(ha, &cdrp)) { 1517 device_printf(dev, "%s: Q8_CMD_RD_MAX_TX_CNTXT failed\n", 1518 __func__); 1519 return (-1); 1520 } else { 1521 ha->hw.max_xmt_cntxts = cdrp.rsp_arg1; 1522 QL_DPRINT2((dev, "%s: max_xmt_cntxts 0x%08x\n", 1523 __func__, ha->hw.max_xmt_cntxts)); 1524 } 1525 return 0; 1526 } 1527 1528 /* 1529 * Name: qla_get_max_mtu 1530 * Function: Returns the MTU supported for a context. 1531 */ 1532 static int 1533 qla_get_max_mtu(qla_host_t *ha) 1534 { 1535 qla_cdrp_t cdrp; 1536 device_t dev; 1537 1538 dev = ha->pci_dev; 1539 1540 bzero(&cdrp, sizeof(qla_cdrp_t)); 1541 1542 cdrp.cmd = Q8_CMD_RD_MAX_MTU; 1543 1544 if (qla_issue_cmd(ha, &cdrp)) { 1545 device_printf(dev, "%s: Q8_CMD_RD_MAX_MTU failed\n", __func__); 1546 return (-1); 1547 } else { 1548 ha->hw.max_mtu = cdrp.rsp_arg1; 1549 QL_DPRINT2((dev, "%s: max_mtu 0x%08x\n", __func__, 1550 ha->hw.max_mtu)); 1551 } 1552 return 0; 1553 } 1554 1555 /* 1556 * Name: qla_set_max_mtu 1557 * Function: 1558 * Sets the maximum transfer unit size for the specified rcv context. 1559 */ 1560 int 1561 qla_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id) 1562 { 1563 qla_cdrp_t cdrp; 1564 device_t dev; 1565 1566 dev = ha->pci_dev; 1567 1568 bzero(&cdrp, sizeof(qla_cdrp_t)); 1569 1570 cdrp.cmd = Q8_CMD_SET_MTU; 1571 cdrp.cmd_arg1 = (uint32_t)cntxt_id; 1572 cdrp.cmd_arg2 = mtu; 1573 1574 if (qla_issue_cmd(ha, &cdrp)) { 1575 device_printf(dev, "%s: Q8_CMD_RD_MAX_MTU failed\n", __func__); 1576 return (-1); 1577 } else { 1578 ha->hw.max_mtu = cdrp.rsp_arg1; 1579 } 1580 return 0; 1581 } 1582 1583 /* 1584 * Name: qla_get_max_lro 1585 * Function: Returns the maximum number of TCP Connection which can be supported 1586 * with LRO. 1587 */ 1588 static int 1589 qla_get_max_lro(qla_host_t *ha) 1590 { 1591 qla_cdrp_t cdrp; 1592 device_t dev; 1593 1594 dev = ha->pci_dev; 1595 1596 bzero(&cdrp, sizeof(qla_cdrp_t)); 1597 1598 cdrp.cmd = Q8_CMD_RD_MAX_LRO; 1599 1600 if (qla_issue_cmd(ha, &cdrp)) { 1601 device_printf(dev, "%s: Q8_CMD_RD_MAX_LRO failed\n", __func__); 1602 return (-1); 1603 } else { 1604 ha->hw.max_lro = cdrp.rsp_arg1; 1605 QL_DPRINT2((dev, "%s: max_lro 0x%08x\n", __func__, 1606 ha->hw.max_lro)); 1607 } 1608 return 0; 1609 } 1610 1611 /* 1612 * Name: qla_get_flow_control 1613 * Function: Returns the Receive/Transmit Flow Control (PAUSE) settings for 1614 * PCI function. 1615 */ 1616 static int 1617 qla_get_flow_control(qla_host_t *ha) 1618 { 1619 qla_cdrp_t cdrp; 1620 device_t dev; 1621 1622 dev = ha->pci_dev; 1623 1624 bzero(&cdrp, sizeof(qla_cdrp_t)); 1625 1626 cdrp.cmd = Q8_CMD_GET_FLOW_CNTRL; 1627 1628 if (qla_issue_cmd(ha, &cdrp)) { 1629 device_printf(dev, "%s: Q8_CMD_GET_FLOW_CNTRL failed\n", 1630 __func__); 1631 return (-1); 1632 } else { 1633 QL_DPRINT2((dev, "%s: flow control 0x%08x\n", __func__, 1634 cdrp.rsp_arg1)); 1635 } 1636 return 0; 1637 } 1638 1639 /* 1640 * Name: qla_get_flow_control 1641 * Function: Retrieves hardware capabilities 1642 */ 1643 void 1644 qla_get_hw_caps(qla_host_t *ha) 1645 { 1646 //qla_read_mac_addr(ha); 1647 qla_get_max_rds(ha); 1648 qla_get_max_sds(ha); 1649 qla_get_max_rules(ha); 1650 qla_get_max_rcv_cntxts(ha); 1651 qla_get_max_tx_cntxts(ha); 1652 qla_get_max_mtu(ha); 1653 qla_get_max_lro(ha); 1654 qla_get_flow_control(ha); 1655 return; 1656 } 1657 1658 /* 1659 * Name: qla_hw_set_multi 1660 * Function: Sets the Multicast Addresses provided the host O.S into the 1661 * hardware (for the given interface) 1662 */ 1663 void 1664 qla_hw_set_multi(qla_host_t *ha, uint8_t *mta, uint32_t mcnt, 1665 uint32_t add_multi) 1666 { 1667 q80_rcv_cntxt_rsp_t *rsp; 1668 int i; 1669 1670 rsp = ha->hw.rx_cntxt_rsp; 1671 for (i = 0; i < mcnt; i++) { 1672 qla_config_mac_addr(ha, mta, rsp->rx_rsp.cntxt_id, add_multi); 1673 mta += Q8_MAC_ADDR_LEN; 1674 } 1675 return; 1676 } 1677 1678 /* 1679 * Name: qla_hw_tx_done_locked 1680 * Function: Handle Transmit Completions 1681 */ 1682 static void 1683 qla_hw_tx_done_locked(qla_host_t *ha) 1684 { 1685 qla_tx_buf_t *txb; 1686 qla_hw_t *hw = &ha->hw; 1687 uint32_t comp_idx, comp_count = 0; 1688 1689 /* retrieve index of last entry in tx ring completed */ 1690 comp_idx = qla_le32_to_host(*(hw->tx_cons)); 1691 1692 while (comp_idx != hw->txr_comp) { 1693 txb = &ha->tx_buf[hw->txr_comp]; 1694 1695 hw->txr_comp++; 1696 if (hw->txr_comp == NUM_TX_DESCRIPTORS) 1697 hw->txr_comp = 0; 1698 1699 comp_count++; 1700 1701 if (txb->m_head) { 1702 bus_dmamap_sync(ha->tx_tag, txb->map, 1703 BUS_DMASYNC_POSTWRITE); 1704 bus_dmamap_unload(ha->tx_tag, txb->map); 1705 bus_dmamap_destroy(ha->tx_tag, txb->map); 1706 m_freem(txb->m_head); 1707 1708 txb->map = (bus_dmamap_t)0; 1709 txb->m_head = NULL; 1710 } 1711 } 1712 1713 hw->txr_free += comp_count; 1714 1715 QL_DPRINT8((ha->pci_dev, "%s: return [c,f, p, pn][%d, %d, %d, %d]\n", __func__, 1716 hw->txr_comp, hw->txr_free, hw->txr_next, READ_REG32(ha, (ha->hw.tx_prod_reg + 0x1b2000)))); 1717 1718 return; 1719 } 1720 1721 /* 1722 * Name: qla_hw_tx_done 1723 * Function: Handle Transmit Completions 1724 */ 1725 void 1726 qla_hw_tx_done(qla_host_t *ha) 1727 { 1728 if (!mtx_trylock(&ha->tx_lock)) { 1729 QL_DPRINT8((ha->pci_dev, 1730 "%s: !mtx_trylock(&ha->tx_lock)\n", __func__)); 1731 return; 1732 } 1733 qla_hw_tx_done_locked(ha); 1734 1735 if (ha->hw.txr_free > free_pkt_thres) 1736 if_setdrvflagbits(ha->ifp, 0, IFF_DRV_OACTIVE); 1737 1738 mtx_unlock(&ha->tx_lock); 1739 return; 1740 } 1741 1742 void 1743 qla_update_link_state(qla_host_t *ha) 1744 { 1745 uint32_t link_state; 1746 uint32_t prev_link_state; 1747 1748 if (!(if_getdrvflags(ha->ifp) & IFF_DRV_RUNNING)) { 1749 ha->hw.flags.link_up = 0; 1750 return; 1751 } 1752 link_state = READ_REG32(ha, Q8_LINK_STATE); 1753 1754 prev_link_state = ha->hw.flags.link_up; 1755 1756 if (ha->pci_func == 0) 1757 ha->hw.flags.link_up = (((link_state & 0xF) == 1)? 1 : 0); 1758 else 1759 ha->hw.flags.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0); 1760 1761 if (prev_link_state != ha->hw.flags.link_up) { 1762 if (ha->hw.flags.link_up) { 1763 if_link_state_change(ha->ifp, LINK_STATE_UP); 1764 } else { 1765 if_link_state_change(ha->ifp, LINK_STATE_DOWN); 1766 } 1767 } 1768 } 1769 1770 int 1771 qla_config_lro(qla_host_t *ha) 1772 { 1773 #if defined(INET) || defined(INET6) 1774 int i; 1775 qla_hw_t *hw = &ha->hw; 1776 struct lro_ctrl *lro; 1777 1778 for (i = 0; i < hw->num_sds_rings; i++) { 1779 lro = &hw->sds[i].lro; 1780 if (tcp_lro_init(lro)) { 1781 device_printf(ha->pci_dev, "%s: tcp_lro_init failed\n", 1782 __func__); 1783 return (-1); 1784 } 1785 lro->ifp = ha->ifp; 1786 } 1787 ha->flags.lro_init = 1; 1788 1789 QL_DPRINT2((ha->pci_dev, "%s: LRO initialized\n", __func__)); 1790 #endif 1791 return (0); 1792 } 1793 1794 void 1795 qla_free_lro(qla_host_t *ha) 1796 { 1797 #if defined(INET) || defined(INET6) 1798 int i; 1799 qla_hw_t *hw = &ha->hw; 1800 struct lro_ctrl *lro; 1801 1802 if (!ha->flags.lro_init) 1803 return; 1804 1805 for (i = 0; i < hw->num_sds_rings; i++) { 1806 lro = &hw->sds[i].lro; 1807 tcp_lro_free(lro); 1808 } 1809 ha->flags.lro_init = 0; 1810 #endif 1811 } 1812 1813 void 1814 qla_hw_stop_rcv(qla_host_t *ha) 1815 { 1816 int i, done, count = 100; 1817 1818 while (count--) { 1819 done = 1; 1820 for (i = 0; i < ha->hw.num_sds_rings; i++) { 1821 if (ha->hw.sds[i].rcv_active) 1822 done = 0; 1823 } 1824 if (done) 1825 break; 1826 else 1827 qla_mdelay(__func__, 10); 1828 } 1829 } 1830