1 /* 2 * BSD LICENSE 3 * 4 * Copyright(c) 2017 Cavium, Inc.. All rights reserved. 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 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Cavium, Inc. nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 /*$FreeBSD$*/ 34 35 #include "lio_bsd.h" 36 #include "lio_common.h" 37 #include "lio_droq.h" 38 #include "lio_iq.h" 39 #include "lio_response_manager.h" 40 #include "lio_device.h" 41 #include "lio_ctrl.h" 42 #include "lio_main.h" 43 #include "lio_rxtx.h" 44 #include "lio_network.h" 45 46 int 47 lio_set_feature(struct ifnet *ifp, int cmd, uint16_t param1) 48 { 49 struct lio_ctrl_pkt nctrl; 50 struct lio *lio = if_getsoftc(ifp); 51 struct octeon_device *oct = lio->oct_dev; 52 int ret = 0; 53 54 bzero(&nctrl, sizeof(struct lio_ctrl_pkt)); 55 56 nctrl.ncmd.cmd64 = 0; 57 nctrl.ncmd.s.cmd = cmd; 58 nctrl.ncmd.s.param1 = param1; 59 nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; 60 nctrl.wait_time = 100; 61 nctrl.lio = lio; 62 nctrl.cb_fn = lio_ctrl_cmd_completion; 63 64 ret = lio_send_ctrl_pkt(lio->oct_dev, &nctrl); 65 if (ret < 0) { 66 lio_dev_err(oct, "Feature change failed in core (ret: 0x%x)\n", 67 ret); 68 } 69 70 return (ret); 71 } 72 73 void 74 lio_ctrl_cmd_completion(void *nctrl_ptr) 75 { 76 struct lio_ctrl_pkt *nctrl = (struct lio_ctrl_pkt *)nctrl_ptr; 77 struct lio *lio; 78 struct octeon_device *oct; 79 uint8_t *mac; 80 81 lio = nctrl->lio; 82 83 if (lio->oct_dev == NULL) 84 return; 85 86 oct = lio->oct_dev; 87 88 switch (nctrl->ncmd.s.cmd) { 89 case LIO_CMD_CHANGE_DEVFLAGS: 90 case LIO_CMD_SET_MULTI_LIST: 91 break; 92 93 case LIO_CMD_CHANGE_MACADDR: 94 mac = ((uint8_t *)&nctrl->udd[0]) + 2; 95 if (nctrl->ncmd.s.param1) { 96 /* vfidx is 0 based, but vf_num (param1) is 1 based */ 97 int vfidx = nctrl->ncmd.s.param1 - 1; 98 bool mac_is_admin_assigned = nctrl->ncmd.s.param2; 99 100 if (mac_is_admin_assigned) 101 lio_dev_info(oct, "MAC Address %pM is configured for VF %d\n", 102 mac, vfidx); 103 } else { 104 lio_dev_info(oct, "MAC Address changed to %02x:%02x:%02x:%02x:%02x:%02x\n", 105 mac[0], mac[1], mac[2], mac[3], mac[4], 106 mac[5]); 107 } 108 break; 109 110 case LIO_CMD_GPIO_ACCESS: 111 lio_dev_info(oct, "LED Flashing visual identification\n"); 112 break; 113 114 case LIO_CMD_ID_ACTIVE: 115 lio_dev_info(oct, "LED Flashing visual identification\n"); 116 break; 117 118 case LIO_CMD_LRO_ENABLE: 119 lio_dev_info(oct, "HW LRO Enabled\n"); 120 break; 121 122 case LIO_CMD_LRO_DISABLE: 123 lio_dev_info(oct, "HW LRO Disabled\n"); 124 break; 125 126 case LIO_CMD_VERBOSE_ENABLE: 127 lio_dev_info(oct, "Firmware debug enabled\n"); 128 break; 129 130 case LIO_CMD_VERBOSE_DISABLE: 131 lio_dev_info(oct, "Firmware debug disabled\n"); 132 break; 133 134 case LIO_CMD_VLAN_FILTER_CTL: 135 if (nctrl->ncmd.s.param1) 136 lio_dev_info(oct, "VLAN filter enabled\n"); 137 else 138 lio_dev_info(oct, "VLAN filter disabled\n"); 139 break; 140 141 case LIO_CMD_ADD_VLAN_FILTER: 142 lio_dev_info(oct, "VLAN filter %d added\n", 143 nctrl->ncmd.s.param1); 144 break; 145 146 case LIO_CMD_DEL_VLAN_FILTER: 147 lio_dev_info(oct, "VLAN filter %d removed\n", 148 nctrl->ncmd.s.param1); 149 break; 150 151 case LIO_CMD_SET_SETTINGS: 152 lio_dev_info(oct, "Settings changed\n"); 153 break; 154 155 /* 156 * Case to handle "LIO_CMD_TNL_RX_CSUM_CTL" 157 * Command passed by NIC driver 158 */ 159 case LIO_CMD_TNL_RX_CSUM_CTL: 160 if (nctrl->ncmd.s.param1 == LIO_CMD_RXCSUM_ENABLE) { 161 lio_dev_info(oct, "RX Checksum Offload Enabled\n"); 162 } else if (nctrl->ncmd.s.param1 == LIO_CMD_RXCSUM_DISABLE) { 163 lio_dev_info(oct, "RX Checksum Offload Disabled\n"); 164 } 165 break; 166 167 /* 168 * Case to handle "LIO_CMD_TNL_TX_CSUM_CTL" 169 * Command passed by NIC driver 170 */ 171 case LIO_CMD_TNL_TX_CSUM_CTL: 172 if (nctrl->ncmd.s.param1 == LIO_CMD_TXCSUM_ENABLE) { 173 lio_dev_info(oct, "TX Checksum Offload Enabled\n"); 174 } else if (nctrl->ncmd.s.param1 == LIO_CMD_TXCSUM_DISABLE) { 175 lio_dev_info(oct, "TX Checksum Offload Disabled\n"); 176 } 177 break; 178 179 /* 180 * Case to handle "LIO_CMD_VXLAN_PORT_CONFIG" 181 * Command passed by NIC driver 182 */ 183 case LIO_CMD_VXLAN_PORT_CONFIG: 184 if (nctrl->ncmd.s.more == LIO_CMD_VXLAN_PORT_ADD) { 185 lio_dev_info(oct, "VxLAN Destination UDP PORT:%d ADDED\n", 186 nctrl->ncmd.s.param1); 187 } else if (nctrl->ncmd.s.more == LIO_CMD_VXLAN_PORT_DEL) { 188 lio_dev_info(oct, "VxLAN Destination UDP PORT:%d DELETED\n", 189 nctrl->ncmd.s.param1); 190 } 191 break; 192 193 case LIO_CMD_SET_FLOW_CTL: 194 lio_dev_info(oct, "Set RX/TX flow control parameters\n"); 195 break; 196 197 case LIO_CMD_SET_FNV: 198 if (nctrl->ncmd.s.param1 == LIO_CMD_FNV_ENABLE) 199 lio_dev_info(oct, "FNV Enabled\n"); 200 else if (nctrl->ncmd.s.param1 == LIO_CMD_FNV_DISABLE) 201 lio_dev_info(oct, "FNV Disabled\n"); 202 break; 203 204 case LIO_CMD_PKT_STEERING_CTL: 205 if (nctrl->ncmd.s.param1 == LIO_CMD_PKT_STEERING_ENABLE) { 206 lio_dev_info(oct, "Packet Steering Enabled\n"); 207 } else if (nctrl->ncmd.s.param1 == 208 LIO_CMD_PKT_STEERING_DISABLE) { 209 lio_dev_info(oct, "Packet Steering Disabled\n"); 210 } 211 212 break; 213 214 case LIO_CMD_QUEUE_COUNT_CTL: 215 lio_dev_info(oct, "Queue count updated to %d\n", 216 nctrl->ncmd.s.param1); 217 break; 218 219 default: 220 lio_dev_err(oct, "%s Unknown cmd %d\n", __func__, 221 nctrl->ncmd.s.cmd); 222 } 223 } 224 225 226 /* 227 * \brief Setup output queue 228 * @param oct octeon device 229 * @param q_no which queue 230 * @param num_descs how many descriptors 231 * @param desc_size size of each descriptor 232 * @param app_ctx application context 233 */ 234 static int 235 lio_setup_droq(struct octeon_device *oct, int q_no, int num_descs, 236 int desc_size, void *app_ctx) 237 { 238 int ret_val = 0; 239 240 lio_dev_dbg(oct, "Creating Droq: %d\n", q_no); 241 /* droq creation and local register settings. */ 242 ret_val = lio_create_droq(oct, q_no, num_descs, desc_size, app_ctx); 243 if (ret_val < 0) 244 return (ret_val); 245 246 if (ret_val == 1) { 247 lio_dev_dbg(oct, "Using default droq %d\n", q_no); 248 return (0); 249 } 250 251 /* 252 * Send Credit for Octeon Output queues. Credits are always 253 * sent after the output queue is enabled. 254 */ 255 lio_write_csr32(oct, oct->droq[q_no]->pkts_credit_reg, 256 oct->droq[q_no]->max_count); 257 258 return (ret_val); 259 } 260 261 static void 262 lio_push_packet(void *m_buff, uint32_t len, union octeon_rh *rh, void *rxq, 263 void *arg) 264 { 265 struct mbuf *mbuf = m_buff; 266 struct ifnet *ifp = arg; 267 struct lio_droq *droq = rxq; 268 269 if (ifp != NULL) { 270 struct lio *lio = if_getsoftc(ifp); 271 272 /* Do not proceed if the interface is not in RUNNING state. */ 273 if (!lio_ifstate_check(lio, LIO_IFSTATE_RUNNING)) { 274 lio_recv_buffer_free(mbuf); 275 droq->stats.rx_dropped++; 276 return; 277 } 278 279 if (rh->r_dh.has_hash) { 280 uint32_t hashtype, hashval; 281 282 if (rh->r_dh.has_hwtstamp) { 283 hashval = htobe32(*(uint32_t *) 284 (((uint8_t *)mbuf->m_data) + 285 ((rh->r_dh.len - 2) * 286 BYTES_PER_DHLEN_UNIT))); 287 hashtype = 288 htobe32(*(((uint32_t *) 289 (((uint8_t *)mbuf->m_data) + 290 ((rh->r_dh.len - 2) * 291 BYTES_PER_DHLEN_UNIT))) + 1)); 292 } else { 293 hashval = htobe32(*(uint32_t *) 294 (((uint8_t *)mbuf->m_data) + 295 ((rh->r_dh.len - 1) * 296 BYTES_PER_DHLEN_UNIT))); 297 hashtype = 298 htobe32(*(((uint32_t *) 299 (((uint8_t *)mbuf->m_data) + 300 ((rh->r_dh.len - 1) * 301 BYTES_PER_DHLEN_UNIT))) + 1)); 302 } 303 304 mbuf->m_pkthdr.flowid = hashval; 305 306 switch (hashtype) { 307 case LIO_RSS_HASH_IPV4: 308 M_HASHTYPE_SET(mbuf, M_HASHTYPE_RSS_IPV4); 309 break; 310 case LIO_RSS_HASH_TCP_IPV4: 311 M_HASHTYPE_SET(mbuf, M_HASHTYPE_RSS_TCP_IPV4); 312 break; 313 case LIO_RSS_HASH_IPV6: 314 M_HASHTYPE_SET(mbuf, M_HASHTYPE_RSS_IPV6); 315 break; 316 case LIO_RSS_HASH_TCP_IPV6: 317 M_HASHTYPE_SET(mbuf, M_HASHTYPE_RSS_TCP_IPV6); 318 break; 319 case LIO_RSS_HASH_IPV6_EX: 320 M_HASHTYPE_SET(mbuf, M_HASHTYPE_RSS_IPV6_EX); 321 break; 322 case LIO_RSS_HASH_TCP_IPV6_EX: 323 M_HASHTYPE_SET(mbuf, 324 M_HASHTYPE_RSS_TCP_IPV6_EX); 325 break; 326 default: 327 M_HASHTYPE_SET(mbuf, M_HASHTYPE_OPAQUE_HASH); 328 } 329 330 } else { 331 /* 332 * This case won't hit as FW will always set has_hash 333 * in rh. 334 */ 335 M_HASHTYPE_SET(mbuf, M_HASHTYPE_OPAQUE); 336 mbuf->m_pkthdr.flowid = droq->q_no; 337 } 338 339 m_adj(mbuf, rh->r_dh.len * 8); 340 len -= rh->r_dh.len * 8; 341 mbuf->m_flags |= M_PKTHDR; 342 343 if ((if_getcapenable(ifp) & IFCAP_VLAN_HWTAGGING) && 344 (rh->r_dh.priority || rh->r_dh.vlan)) { 345 uint16_t priority = rh->r_dh.priority; 346 uint16_t vid = rh->r_dh.vlan; 347 uint16_t vtag; 348 349 vtag = priority << 13 | vid; 350 mbuf->m_pkthdr.ether_vtag = vtag; 351 mbuf->m_flags |= M_VLANTAG; 352 } 353 354 if (rh->r_dh.csum_verified & LIO_IPSUM_VERIFIED) 355 mbuf->m_pkthdr.csum_flags |= (CSUM_L3_CALC | 356 CSUM_L3_VALID); 357 358 if (rh->r_dh.csum_verified & LIO_L4SUM_VERIFIED) { 359 mbuf->m_pkthdr.csum_flags |= (CSUM_L4_CALC | 360 CSUM_L4_VALID); 361 mbuf->m_pkthdr.csum_flags |= (CSUM_DATA_VALID | 362 CSUM_PSEUDO_HDR); 363 mbuf->m_pkthdr.csum_data = htons(0xffff); 364 } 365 366 mbuf->m_pkthdr.rcvif = ifp; 367 mbuf->m_pkthdr.len = len; 368 369 if ((lio_hwlro == 0) && 370 (if_getcapenable(ifp) & IFCAP_LRO) && 371 (mbuf->m_pkthdr.csum_flags & 372 (CSUM_L3_VALID | CSUM_L4_VALID | CSUM_DATA_VALID | 373 CSUM_PSEUDO_HDR)) == (CSUM_L3_VALID | CSUM_L4_VALID | 374 CSUM_DATA_VALID | 375 CSUM_PSEUDO_HDR)) { 376 if (droq->lro.lro_cnt) { 377 if (tcp_lro_rx(&droq->lro, mbuf, 0) == 0) { 378 droq->stats.rx_bytes_received += len; 379 droq->stats.rx_pkts_received++; 380 return; 381 } 382 } 383 } 384 385 if_input(ifp, mbuf); 386 387 droq->stats.rx_bytes_received += len; 388 droq->stats.rx_pkts_received++; 389 390 } else { 391 lio_recv_buffer_free(mbuf); 392 droq->stats.rx_dropped++; 393 } 394 } 395 396 /* 397 * \brief Setup input and output queues 398 * @param octeon_dev octeon device 399 * @param ifidx Interface Index 400 * 401 * Note: Queues are with respect to the octeon device. Thus 402 * an input queue is for egress packets, and output queues 403 * are for ingress packets. 404 */ 405 int 406 lio_setup_io_queues(struct octeon_device *octeon_dev, int ifidx, 407 uint32_t num_iqs, uint32_t num_oqs) 408 { 409 struct lio_droq_ops droq_ops; 410 struct ifnet *ifp; 411 struct lio_droq *droq; 412 struct lio *lio; 413 static int cpu_id, cpu_id_modulus; 414 int num_tx_descs, q, q_no, retval = 0; 415 416 ifp = octeon_dev->props.ifp; 417 418 lio = if_getsoftc(ifp); 419 420 bzero(&droq_ops, sizeof(struct lio_droq_ops)); 421 422 droq_ops.fptr = lio_push_packet; 423 droq_ops.farg = (void *)ifp; 424 425 cpu_id = 0; 426 cpu_id_modulus = mp_ncpus; 427 /* set up DROQs. */ 428 for (q = 0; q < num_oqs; q++) { 429 q_no = lio->linfo.rxpciq[q].s.q_no; 430 lio_dev_dbg(octeon_dev, "lio_setup_io_queues index:%d linfo.rxpciq.s.q_no:%d\n", 431 q, q_no); 432 retval = lio_setup_droq(octeon_dev, q_no, 433 LIO_GET_NUM_RX_DESCS_NIC_IF_CFG( 434 lio_get_conf(octeon_dev), 435 lio->ifidx), 436 LIO_GET_NUM_RX_BUF_SIZE_NIC_IF_CFG( 437 lio_get_conf(octeon_dev), 438 lio->ifidx), NULL); 439 if (retval) { 440 lio_dev_err(octeon_dev, "%s : Runtime DROQ(RxQ) creation failed.\n", 441 __func__); 442 return (1); 443 } 444 445 droq = octeon_dev->droq[q_no]; 446 447 /* designate a CPU for this droq */ 448 droq->cpu_id = cpu_id; 449 cpu_id++; 450 if (cpu_id >= cpu_id_modulus) 451 cpu_id = 0; 452 453 lio_register_droq_ops(octeon_dev, q_no, &droq_ops); 454 } 455 456 /* set up IQs. */ 457 for (q = 0; q < num_iqs; q++) { 458 num_tx_descs = LIO_GET_NUM_TX_DESCS_NIC_IF_CFG( 459 lio_get_conf(octeon_dev), 460 lio->ifidx); 461 retval = lio_setup_iq(octeon_dev, ifidx, q, 462 lio->linfo.txpciq[q], num_tx_descs); 463 if (retval) { 464 lio_dev_err(octeon_dev, " %s : Runtime IQ(TxQ) creation failed.\n", 465 __func__); 466 return (1); 467 } 468 } 469 470 return (0); 471 } 472 473 /* 474 * \brief Droq packet processor sceduler 475 * @param oct octeon device 476 */ 477 static void 478 lio_schedule_droq_pkt_handlers(struct octeon_device *oct) 479 { 480 struct lio_droq *droq; 481 uint64_t oq_no; 482 483 if (oct->int_status & LIO_DEV_INTR_PKT_DATA) { 484 for (oq_no = 0; oq_no < LIO_MAX_OUTPUT_QUEUES(oct); oq_no++) { 485 if (!(oct->io_qmask.oq & BIT_ULL(oq_no))) 486 continue; 487 488 droq = oct->droq[oq_no]; 489 490 taskqueue_enqueue(droq->droq_taskqueue, 491 &droq->droq_task); 492 } 493 } 494 } 495 496 static void 497 lio_msix_intr_handler(void *vector) 498 { 499 struct lio_ioq_vector *ioq_vector = (struct lio_ioq_vector *)vector; 500 struct octeon_device *oct = ioq_vector->oct_dev; 501 struct lio_droq *droq = oct->droq[ioq_vector->droq_index]; 502 uint64_t ret; 503 504 ret = oct->fn_list.msix_interrupt_handler(ioq_vector); 505 506 if ((ret & LIO_MSIX_PO_INT) || (ret & LIO_MSIX_PI_INT)) { 507 struct lio_instr_queue *iq = oct->instr_queue[droq->q_no]; 508 int reschedule, tx_done = 1; 509 510 reschedule = lio_droq_process_packets(oct, droq, oct->rx_budget); 511 512 if (atomic_load_acq_int(&iq->instr_pending)) 513 tx_done = lio_flush_iq(oct, iq, oct->tx_budget); 514 515 if ((oct->props.ifp != NULL) && (iq->br != NULL)) { 516 if (mtx_trylock(&iq->enq_lock)) { 517 if (!drbr_empty(oct->props.ifp, iq->br)) 518 lio_mq_start_locked(oct->props.ifp, 519 iq); 520 mtx_unlock(&iq->enq_lock); 521 } 522 } 523 524 if (reschedule || !tx_done) 525 taskqueue_enqueue(droq->droq_taskqueue, &droq->droq_task); 526 else 527 lio_enable_irq(droq, iq); 528 } 529 } 530 531 static void 532 lio_intr_handler(void *dev) 533 { 534 struct octeon_device *oct = (struct octeon_device *)dev; 535 536 /* Disable our interrupts for the duration of ISR */ 537 oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR); 538 539 oct->fn_list.process_interrupt_regs(oct); 540 541 lio_schedule_droq_pkt_handlers(oct); 542 543 /* Re-enable our interrupts */ 544 if (!(atomic_load_acq_int(&oct->status) == LIO_DEV_IN_RESET)) 545 oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR); 546 } 547 548 int 549 lio_setup_interrupt(struct octeon_device *oct, uint32_t num_ioqs) 550 { 551 device_t device; 552 struct lio_ioq_vector *ioq_vector; 553 int cpu_id, err, i; 554 int num_alloc_ioq_vectors; 555 int num_ioq_vectors; 556 int res_id; 557 558 if (!oct->msix_on) 559 return (1); 560 561 ioq_vector = oct->ioq_vector; 562 563 #ifdef RSS 564 if (oct->sriov_info.num_pf_rings != rss_getnumbuckets()) { 565 lio_dev_info(oct, "IOQ vectors (%d) are not equal number of RSS buckets (%d)\n", 566 oct->sriov_info.num_pf_rings, rss_getnumbuckets()); 567 } 568 #endif 569 570 device = oct->device; 571 572 oct->num_msix_irqs = num_ioqs; 573 /* one non ioq interrupt for handling sli_mac_pf_int_sum */ 574 oct->num_msix_irqs += 1; 575 num_alloc_ioq_vectors = oct->num_msix_irqs; 576 577 if (pci_alloc_msix(device, &num_alloc_ioq_vectors) || 578 (num_alloc_ioq_vectors != oct->num_msix_irqs)) 579 goto err; 580 581 num_ioq_vectors = oct->num_msix_irqs; 582 583 /* For PF, there is one non-ioq interrupt handler */ 584 for (i = 0; i < num_ioq_vectors - 1; i++, ioq_vector++) { 585 res_id = i + 1; 586 587 ioq_vector->msix_res = 588 bus_alloc_resource_any(device, SYS_RES_IRQ, &res_id, 589 RF_SHAREABLE | RF_ACTIVE); 590 if (ioq_vector->msix_res == NULL) { 591 lio_dev_err(oct, 592 "Unable to allocate bus res msix[%d]\n", i); 593 goto err_1; 594 } 595 596 err = bus_setup_intr(device, ioq_vector->msix_res, 597 INTR_TYPE_NET | INTR_MPSAFE, NULL, 598 lio_msix_intr_handler, ioq_vector, 599 &ioq_vector->tag); 600 if (err) { 601 bus_release_resource(device, SYS_RES_IRQ, res_id, 602 ioq_vector->msix_res); 603 ioq_vector->msix_res = NULL; 604 lio_dev_err(oct, "Failed to register intr handler"); 605 goto err_1; 606 } 607 608 bus_describe_intr(device, ioq_vector->msix_res, ioq_vector->tag, 609 "rxtx%u", i); 610 ioq_vector->vector = res_id; 611 612 #ifdef RSS 613 cpu_id = rss_getcpu(i % rss_getnumbuckets()); 614 #else 615 cpu_id = i % mp_ncpus; 616 #endif 617 CPU_SETOF(cpu_id, &ioq_vector->affinity_mask); 618 619 /* Setting the IRQ affinity. */ 620 err = bus_bind_intr(device, ioq_vector->msix_res, cpu_id); 621 if (err) 622 lio_dev_err(oct, "bus bind interrupt fail"); 623 #ifdef RSS 624 lio_dev_dbg(oct, "Bound RSS bucket %d to CPU %d\n", i, cpu_id); 625 #else 626 lio_dev_dbg(oct, "Bound Queue %d to CPU %d\n", i, cpu_id); 627 #endif 628 } 629 630 lio_dev_dbg(oct, "MSI-X enabled\n"); 631 632 res_id = num_ioq_vectors; 633 oct->msix_res = bus_alloc_resource_any(device, SYS_RES_IRQ, &res_id, 634 RF_SHAREABLE | RF_ACTIVE); 635 if (oct->msix_res == NULL) { 636 lio_dev_err(oct, "Unable to allocate bus res msix for non-ioq interrupt\n"); 637 goto err_1; 638 } 639 640 err = bus_setup_intr(device, oct->msix_res, INTR_TYPE_NET | INTR_MPSAFE, 641 NULL, lio_intr_handler, oct, &oct->tag); 642 if (err) { 643 bus_release_resource(device, SYS_RES_IRQ, res_id, 644 oct->msix_res); 645 oct->msix_res = NULL; 646 lio_dev_err(oct, "Failed to register intr handler"); 647 goto err_1; 648 } 649 650 bus_describe_intr(device, oct->msix_res, oct->tag, "aux"); 651 oct->aux_vector = res_id; 652 653 return (0); 654 err_1: 655 if (oct->tag != NULL) { 656 bus_teardown_intr(device, oct->msix_res, oct->tag); 657 oct->tag = NULL; 658 } 659 660 while (i) { 661 i--; 662 ioq_vector--; 663 664 if (ioq_vector->tag != NULL) { 665 bus_teardown_intr(device, ioq_vector->msix_res, 666 ioq_vector->tag); 667 ioq_vector->tag = NULL; 668 } 669 670 if (ioq_vector->msix_res != NULL) { 671 bus_release_resource(device, SYS_RES_IRQ, 672 ioq_vector->vector, 673 ioq_vector->msix_res); 674 ioq_vector->msix_res = NULL; 675 } 676 } 677 678 if (oct->msix_res != NULL) { 679 bus_release_resource(device, SYS_RES_IRQ, oct->aux_vector, 680 oct->msix_res); 681 oct->msix_res = NULL; 682 } 683 err: 684 pci_release_msi(device); 685 lio_dev_err(oct, "MSI-X disabled\n"); 686 return (1); 687 } 688