| .. | .. |
|---|
| 1 | 1 | /* |
|---|
| 2 | | - * Copyright(c) 2017 - 2018 Intel Corporation. |
|---|
| 2 | + * Copyright(c) 2017 - 2020 Intel Corporation. |
|---|
| 3 | 3 | * |
|---|
| 4 | 4 | * This file is provided under a dual BSD/GPLv2 license. When using or |
|---|
| 5 | 5 | * redistributing this file, you may do so under either license. |
|---|
| .. | .. |
|---|
| 53 | 53 | #include <linux/if_vlan.h> |
|---|
| 54 | 54 | |
|---|
| 55 | 55 | #include "vnic.h" |
|---|
| 56 | +#include "netdev.h" |
|---|
| 56 | 57 | |
|---|
| 57 | 58 | #define HFI_TX_TIMEOUT_MS 1000 |
|---|
| 58 | 59 | |
|---|
| .. | .. |
|---|
| 62 | 63 | |
|---|
| 63 | 64 | static DEFINE_SPINLOCK(vport_cntr_lock); |
|---|
| 64 | 65 | |
|---|
| 65 | | -static int setup_vnic_ctxt(struct hfi1_devdata *dd, struct hfi1_ctxtdata *uctxt) |
|---|
| 66 | | -{ |
|---|
| 67 | | - unsigned int rcvctrl_ops = 0; |
|---|
| 68 | | - int ret; |
|---|
| 69 | | - |
|---|
| 70 | | - uctxt->do_interrupt = &handle_receive_interrupt; |
|---|
| 71 | | - |
|---|
| 72 | | - /* Now allocate the RcvHdr queue and eager buffers. */ |
|---|
| 73 | | - ret = hfi1_create_rcvhdrq(dd, uctxt); |
|---|
| 74 | | - if (ret) |
|---|
| 75 | | - goto done; |
|---|
| 76 | | - |
|---|
| 77 | | - ret = hfi1_setup_eagerbufs(uctxt); |
|---|
| 78 | | - if (ret) |
|---|
| 79 | | - goto done; |
|---|
| 80 | | - |
|---|
| 81 | | - if (uctxt->rcvhdrtail_kvaddr) |
|---|
| 82 | | - clear_rcvhdrtail(uctxt); |
|---|
| 83 | | - |
|---|
| 84 | | - rcvctrl_ops = HFI1_RCVCTRL_CTXT_ENB; |
|---|
| 85 | | - rcvctrl_ops |= HFI1_RCVCTRL_INTRAVAIL_ENB; |
|---|
| 86 | | - |
|---|
| 87 | | - if (!HFI1_CAP_KGET_MASK(uctxt->flags, MULTI_PKT_EGR)) |
|---|
| 88 | | - rcvctrl_ops |= HFI1_RCVCTRL_ONE_PKT_EGR_ENB; |
|---|
| 89 | | - if (HFI1_CAP_KGET_MASK(uctxt->flags, NODROP_EGR_FULL)) |
|---|
| 90 | | - rcvctrl_ops |= HFI1_RCVCTRL_NO_EGR_DROP_ENB; |
|---|
| 91 | | - if (HFI1_CAP_KGET_MASK(uctxt->flags, NODROP_RHQ_FULL)) |
|---|
| 92 | | - rcvctrl_ops |= HFI1_RCVCTRL_NO_RHQ_DROP_ENB; |
|---|
| 93 | | - if (HFI1_CAP_KGET_MASK(uctxt->flags, DMA_RTAIL)) |
|---|
| 94 | | - rcvctrl_ops |= HFI1_RCVCTRL_TAILUPD_ENB; |
|---|
| 95 | | - |
|---|
| 96 | | - hfi1_rcvctrl(uctxt->dd, rcvctrl_ops, uctxt); |
|---|
| 97 | | -done: |
|---|
| 98 | | - return ret; |
|---|
| 99 | | -} |
|---|
| 100 | | - |
|---|
| 101 | | -static int allocate_vnic_ctxt(struct hfi1_devdata *dd, |
|---|
| 102 | | - struct hfi1_ctxtdata **vnic_ctxt) |
|---|
| 103 | | -{ |
|---|
| 104 | | - struct hfi1_ctxtdata *uctxt; |
|---|
| 105 | | - int ret; |
|---|
| 106 | | - |
|---|
| 107 | | - if (dd->flags & HFI1_FROZEN) |
|---|
| 108 | | - return -EIO; |
|---|
| 109 | | - |
|---|
| 110 | | - ret = hfi1_create_ctxtdata(dd->pport, dd->node, &uctxt); |
|---|
| 111 | | - if (ret < 0) { |
|---|
| 112 | | - dd_dev_err(dd, "Unable to create ctxtdata, failing open\n"); |
|---|
| 113 | | - return -ENOMEM; |
|---|
| 114 | | - } |
|---|
| 115 | | - |
|---|
| 116 | | - uctxt->flags = HFI1_CAP_KGET(MULTI_PKT_EGR) | |
|---|
| 117 | | - HFI1_CAP_KGET(NODROP_RHQ_FULL) | |
|---|
| 118 | | - HFI1_CAP_KGET(NODROP_EGR_FULL) | |
|---|
| 119 | | - HFI1_CAP_KGET(DMA_RTAIL); |
|---|
| 120 | | - uctxt->seq_cnt = 1; |
|---|
| 121 | | - uctxt->is_vnic = true; |
|---|
| 122 | | - |
|---|
| 123 | | - hfi1_set_vnic_msix_info(uctxt); |
|---|
| 124 | | - |
|---|
| 125 | | - hfi1_stats.sps_ctxts++; |
|---|
| 126 | | - dd_dev_dbg(dd, "created vnic context %d\n", uctxt->ctxt); |
|---|
| 127 | | - *vnic_ctxt = uctxt; |
|---|
| 128 | | - |
|---|
| 129 | | - return 0; |
|---|
| 130 | | -} |
|---|
| 131 | | - |
|---|
| 132 | | -static void deallocate_vnic_ctxt(struct hfi1_devdata *dd, |
|---|
| 133 | | - struct hfi1_ctxtdata *uctxt) |
|---|
| 134 | | -{ |
|---|
| 135 | | - dd_dev_dbg(dd, "closing vnic context %d\n", uctxt->ctxt); |
|---|
| 136 | | - flush_wc(); |
|---|
| 137 | | - |
|---|
| 138 | | - hfi1_reset_vnic_msix_info(uctxt); |
|---|
| 139 | | - |
|---|
| 140 | | - /* |
|---|
| 141 | | - * Disable receive context and interrupt available, reset all |
|---|
| 142 | | - * RcvCtxtCtrl bits to default values. |
|---|
| 143 | | - */ |
|---|
| 144 | | - hfi1_rcvctrl(dd, HFI1_RCVCTRL_CTXT_DIS | |
|---|
| 145 | | - HFI1_RCVCTRL_TIDFLOW_DIS | |
|---|
| 146 | | - HFI1_RCVCTRL_INTRAVAIL_DIS | |
|---|
| 147 | | - HFI1_RCVCTRL_ONE_PKT_EGR_DIS | |
|---|
| 148 | | - HFI1_RCVCTRL_NO_RHQ_DROP_DIS | |
|---|
| 149 | | - HFI1_RCVCTRL_NO_EGR_DROP_DIS, uctxt); |
|---|
| 150 | | - |
|---|
| 151 | | - uctxt->event_flags = 0; |
|---|
| 152 | | - |
|---|
| 153 | | - hfi1_clear_tids(uctxt); |
|---|
| 154 | | - hfi1_clear_ctxt_pkey(dd, uctxt); |
|---|
| 155 | | - |
|---|
| 156 | | - hfi1_stats.sps_ctxts--; |
|---|
| 157 | | - |
|---|
| 158 | | - hfi1_free_ctxt(uctxt); |
|---|
| 159 | | -} |
|---|
| 160 | | - |
|---|
| 161 | | -void hfi1_vnic_setup(struct hfi1_devdata *dd) |
|---|
| 162 | | -{ |
|---|
| 163 | | - idr_init(&dd->vnic.vesw_idr); |
|---|
| 164 | | -} |
|---|
| 165 | | - |
|---|
| 166 | | -void hfi1_vnic_cleanup(struct hfi1_devdata *dd) |
|---|
| 167 | | -{ |
|---|
| 168 | | - idr_destroy(&dd->vnic.vesw_idr); |
|---|
| 169 | | -} |
|---|
| 170 | | - |
|---|
| 171 | 66 | #define SUM_GRP_COUNTERS(stats, qstats, x_grp) do { \ |
|---|
| 172 | 67 | u64 *src64, *dst64; \ |
|---|
| 173 | 68 | for (src64 = &qstats->x_grp.unicast, \ |
|---|
| .. | .. |
|---|
| 176 | 71 | *dst64++ += *src64++; \ |
|---|
| 177 | 72 | } \ |
|---|
| 178 | 73 | } while (0) |
|---|
| 74 | + |
|---|
| 75 | +#define VNIC_MASK (0xFF) |
|---|
| 76 | +#define VNIC_ID(val) ((1ull << 24) | ((val) & VNIC_MASK)) |
|---|
| 179 | 77 | |
|---|
| 180 | 78 | /* hfi1_vnic_update_stats - update statistics */ |
|---|
| 181 | 79 | static void hfi1_vnic_update_stats(struct hfi1_vnic_vport_info *vinfo, |
|---|
| .. | .. |
|---|
| 421 | 319 | |
|---|
| 422 | 320 | static u16 hfi1_vnic_select_queue(struct net_device *netdev, |
|---|
| 423 | 321 | struct sk_buff *skb, |
|---|
| 424 | | - struct net_device *sb_dev, |
|---|
| 425 | | - select_queue_fallback_t fallback) |
|---|
| 322 | + struct net_device *sb_dev) |
|---|
| 426 | 323 | { |
|---|
| 427 | 324 | struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); |
|---|
| 428 | 325 | struct opa_vnic_skb_mdata *mdata; |
|---|
| .. | .. |
|---|
| 453 | 350 | return rc; |
|---|
| 454 | 351 | } |
|---|
| 455 | 352 | |
|---|
| 456 | | -static inline struct sk_buff *hfi1_vnic_get_skb(struct hfi1_vnic_rx_queue *rxq) |
|---|
| 353 | +static struct hfi1_vnic_vport_info *get_vnic_port(struct hfi1_devdata *dd, |
|---|
| 354 | + int vesw_id) |
|---|
| 457 | 355 | { |
|---|
| 458 | | - unsigned char *pad_info; |
|---|
| 459 | | - struct sk_buff *skb; |
|---|
| 356 | + int vnic_id = VNIC_ID(vesw_id); |
|---|
| 460 | 357 | |
|---|
| 461 | | - skb = skb_dequeue(&rxq->skbq); |
|---|
| 462 | | - if (unlikely(!skb)) |
|---|
| 358 | + return hfi1_netdev_get_data(dd, vnic_id); |
|---|
| 359 | +} |
|---|
| 360 | + |
|---|
| 361 | +static struct hfi1_vnic_vport_info *get_first_vnic_port(struct hfi1_devdata *dd) |
|---|
| 362 | +{ |
|---|
| 363 | + struct hfi1_vnic_vport_info *vinfo; |
|---|
| 364 | + int next_id = VNIC_ID(0); |
|---|
| 365 | + |
|---|
| 366 | + vinfo = hfi1_netdev_get_first_data(dd, &next_id); |
|---|
| 367 | + |
|---|
| 368 | + if (next_id > VNIC_ID(VNIC_MASK)) |
|---|
| 463 | 369 | return NULL; |
|---|
| 464 | 370 | |
|---|
| 465 | | - /* remove tail padding and icrc */ |
|---|
| 466 | | - pad_info = skb->data + skb->len - 1; |
|---|
| 467 | | - skb_trim(skb, (skb->len - OPA_VNIC_ICRC_TAIL_LEN - |
|---|
| 468 | | - ((*pad_info) & 0x7))); |
|---|
| 469 | | - |
|---|
| 470 | | - return skb; |
|---|
| 471 | | -} |
|---|
| 472 | | - |
|---|
| 473 | | -/* hfi1_vnic_handle_rx - handle skb receive */ |
|---|
| 474 | | -static void hfi1_vnic_handle_rx(struct hfi1_vnic_rx_queue *rxq, |
|---|
| 475 | | - int *work_done, int work_to_do) |
|---|
| 476 | | -{ |
|---|
| 477 | | - struct hfi1_vnic_vport_info *vinfo = rxq->vinfo; |
|---|
| 478 | | - struct sk_buff *skb; |
|---|
| 479 | | - int rc; |
|---|
| 480 | | - |
|---|
| 481 | | - while (1) { |
|---|
| 482 | | - if (*work_done >= work_to_do) |
|---|
| 483 | | - break; |
|---|
| 484 | | - |
|---|
| 485 | | - skb = hfi1_vnic_get_skb(rxq); |
|---|
| 486 | | - if (unlikely(!skb)) |
|---|
| 487 | | - break; |
|---|
| 488 | | - |
|---|
| 489 | | - rc = hfi1_vnic_decap_skb(rxq, skb); |
|---|
| 490 | | - /* update rx counters */ |
|---|
| 491 | | - hfi1_vnic_update_rx_counters(vinfo, rxq->idx, skb, rc); |
|---|
| 492 | | - if (unlikely(rc)) { |
|---|
| 493 | | - dev_kfree_skb_any(skb); |
|---|
| 494 | | - continue; |
|---|
| 495 | | - } |
|---|
| 496 | | - |
|---|
| 497 | | - skb_checksum_none_assert(skb); |
|---|
| 498 | | - skb->protocol = eth_type_trans(skb, rxq->netdev); |
|---|
| 499 | | - |
|---|
| 500 | | - napi_gro_receive(&rxq->napi, skb); |
|---|
| 501 | | - (*work_done)++; |
|---|
| 502 | | - } |
|---|
| 503 | | -} |
|---|
| 504 | | - |
|---|
| 505 | | -/* hfi1_vnic_napi - napi receive polling callback function */ |
|---|
| 506 | | -static int hfi1_vnic_napi(struct napi_struct *napi, int budget) |
|---|
| 507 | | -{ |
|---|
| 508 | | - struct hfi1_vnic_rx_queue *rxq = container_of(napi, |
|---|
| 509 | | - struct hfi1_vnic_rx_queue, napi); |
|---|
| 510 | | - struct hfi1_vnic_vport_info *vinfo = rxq->vinfo; |
|---|
| 511 | | - int work_done = 0; |
|---|
| 512 | | - |
|---|
| 513 | | - v_dbg("napi %d budget %d\n", rxq->idx, budget); |
|---|
| 514 | | - hfi1_vnic_handle_rx(rxq, &work_done, budget); |
|---|
| 515 | | - |
|---|
| 516 | | - v_dbg("napi %d work_done %d\n", rxq->idx, work_done); |
|---|
| 517 | | - if (work_done < budget) |
|---|
| 518 | | - napi_complete(napi); |
|---|
| 519 | | - |
|---|
| 520 | | - return work_done; |
|---|
| 371 | + return vinfo; |
|---|
| 521 | 372 | } |
|---|
| 522 | 373 | |
|---|
| 523 | 374 | void hfi1_vnic_bypass_rcv(struct hfi1_packet *packet) |
|---|
| .. | .. |
|---|
| 526 | 377 | struct hfi1_vnic_vport_info *vinfo = NULL; |
|---|
| 527 | 378 | struct hfi1_vnic_rx_queue *rxq; |
|---|
| 528 | 379 | struct sk_buff *skb; |
|---|
| 529 | | - int l4_type, vesw_id = -1; |
|---|
| 380 | + int l4_type, vesw_id = -1, rc; |
|---|
| 530 | 381 | u8 q_idx; |
|---|
| 382 | + unsigned char *pad_info; |
|---|
| 531 | 383 | |
|---|
| 532 | 384 | l4_type = hfi1_16B_get_l4(packet->ebuf); |
|---|
| 533 | 385 | if (likely(l4_type == OPA_16B_L4_ETHR)) { |
|---|
| 534 | 386 | vesw_id = HFI1_VNIC_GET_VESWID(packet->ebuf); |
|---|
| 535 | | - vinfo = idr_find(&dd->vnic.vesw_idr, vesw_id); |
|---|
| 387 | + vinfo = get_vnic_port(dd, vesw_id); |
|---|
| 536 | 388 | |
|---|
| 537 | 389 | /* |
|---|
| 538 | 390 | * In case of invalid vesw id, count the error on |
|---|
| .. | .. |
|---|
| 540 | 392 | */ |
|---|
| 541 | 393 | if (unlikely(!vinfo)) { |
|---|
| 542 | 394 | struct hfi1_vnic_vport_info *vinfo_tmp; |
|---|
| 543 | | - int id_tmp = 0; |
|---|
| 544 | 395 | |
|---|
| 545 | | - vinfo_tmp = idr_get_next(&dd->vnic.vesw_idr, &id_tmp); |
|---|
| 396 | + vinfo_tmp = get_first_vnic_port(dd); |
|---|
| 546 | 397 | if (vinfo_tmp) { |
|---|
| 547 | 398 | spin_lock(&vport_cntr_lock); |
|---|
| 548 | 399 | vinfo_tmp->stats[0].netstats.rx_nohandler++; |
|---|
| .. | .. |
|---|
| 561 | 412 | rxq = &vinfo->rxq[q_idx]; |
|---|
| 562 | 413 | if (unlikely(!netif_oper_up(vinfo->netdev))) { |
|---|
| 563 | 414 | vinfo->stats[q_idx].rx_drop_state++; |
|---|
| 564 | | - skb_queue_purge(&rxq->skbq); |
|---|
| 565 | | - return; |
|---|
| 566 | | - } |
|---|
| 567 | | - |
|---|
| 568 | | - if (unlikely(skb_queue_len(&rxq->skbq) > HFI1_VNIC_RCV_Q_SIZE)) { |
|---|
| 569 | | - vinfo->stats[q_idx].netstats.rx_fifo_errors++; |
|---|
| 570 | 415 | return; |
|---|
| 571 | 416 | } |
|---|
| 572 | 417 | |
|---|
| .. | .. |
|---|
| 578 | 423 | |
|---|
| 579 | 424 | memcpy(skb->data, packet->ebuf, packet->tlen); |
|---|
| 580 | 425 | skb_put(skb, packet->tlen); |
|---|
| 581 | | - skb_queue_tail(&rxq->skbq, skb); |
|---|
| 582 | 426 | |
|---|
| 583 | | - if (napi_schedule_prep(&rxq->napi)) { |
|---|
| 584 | | - v_dbg("napi %d scheduling\n", q_idx); |
|---|
| 585 | | - __napi_schedule(&rxq->napi); |
|---|
| 427 | + pad_info = skb->data + skb->len - 1; |
|---|
| 428 | + skb_trim(skb, (skb->len - OPA_VNIC_ICRC_TAIL_LEN - |
|---|
| 429 | + ((*pad_info) & 0x7))); |
|---|
| 430 | + |
|---|
| 431 | + rc = hfi1_vnic_decap_skb(rxq, skb); |
|---|
| 432 | + |
|---|
| 433 | + /* update rx counters */ |
|---|
| 434 | + hfi1_vnic_update_rx_counters(vinfo, rxq->idx, skb, rc); |
|---|
| 435 | + if (unlikely(rc)) { |
|---|
| 436 | + dev_kfree_skb_any(skb); |
|---|
| 437 | + return; |
|---|
| 586 | 438 | } |
|---|
| 439 | + |
|---|
| 440 | + skb_checksum_none_assert(skb); |
|---|
| 441 | + skb->protocol = eth_type_trans(skb, rxq->netdev); |
|---|
| 442 | + |
|---|
| 443 | + napi_gro_receive(&rxq->napi, skb); |
|---|
| 587 | 444 | } |
|---|
| 588 | 445 | |
|---|
| 589 | 446 | static int hfi1_vnic_up(struct hfi1_vnic_vport_info *vinfo) |
|---|
| 590 | 447 | { |
|---|
| 591 | 448 | struct hfi1_devdata *dd = vinfo->dd; |
|---|
| 592 | 449 | struct net_device *netdev = vinfo->netdev; |
|---|
| 593 | | - int i, rc; |
|---|
| 450 | + int rc; |
|---|
| 594 | 451 | |
|---|
| 595 | 452 | /* ensure virtual eth switch id is valid */ |
|---|
| 596 | 453 | if (!vinfo->vesw_id) |
|---|
| 597 | 454 | return -EINVAL; |
|---|
| 598 | 455 | |
|---|
| 599 | | - rc = idr_alloc(&dd->vnic.vesw_idr, vinfo, vinfo->vesw_id, |
|---|
| 600 | | - vinfo->vesw_id + 1, GFP_NOWAIT); |
|---|
| 456 | + rc = hfi1_netdev_add_data(dd, VNIC_ID(vinfo->vesw_id), vinfo); |
|---|
| 601 | 457 | if (rc < 0) |
|---|
| 602 | 458 | return rc; |
|---|
| 603 | 459 | |
|---|
| 604 | | - for (i = 0; i < vinfo->num_rx_q; i++) { |
|---|
| 605 | | - struct hfi1_vnic_rx_queue *rxq = &vinfo->rxq[i]; |
|---|
| 606 | | - |
|---|
| 607 | | - skb_queue_head_init(&rxq->skbq); |
|---|
| 608 | | - napi_enable(&rxq->napi); |
|---|
| 609 | | - } |
|---|
| 460 | + rc = hfi1_netdev_rx_init(dd); |
|---|
| 461 | + if (rc) |
|---|
| 462 | + goto err_remove; |
|---|
| 610 | 463 | |
|---|
| 611 | 464 | netif_carrier_on(netdev); |
|---|
| 612 | 465 | netif_tx_start_all_queues(netdev); |
|---|
| 613 | 466 | set_bit(HFI1_VNIC_UP, &vinfo->flags); |
|---|
| 614 | 467 | |
|---|
| 615 | 468 | return 0; |
|---|
| 469 | + |
|---|
| 470 | +err_remove: |
|---|
| 471 | + hfi1_netdev_remove_data(dd, VNIC_ID(vinfo->vesw_id)); |
|---|
| 472 | + return rc; |
|---|
| 616 | 473 | } |
|---|
| 617 | 474 | |
|---|
| 618 | 475 | static void hfi1_vnic_down(struct hfi1_vnic_vport_info *vinfo) |
|---|
| 619 | 476 | { |
|---|
| 620 | 477 | struct hfi1_devdata *dd = vinfo->dd; |
|---|
| 621 | | - u8 i; |
|---|
| 622 | 478 | |
|---|
| 623 | 479 | clear_bit(HFI1_VNIC_UP, &vinfo->flags); |
|---|
| 624 | 480 | netif_carrier_off(vinfo->netdev); |
|---|
| 625 | 481 | netif_tx_disable(vinfo->netdev); |
|---|
| 626 | | - idr_remove(&dd->vnic.vesw_idr, vinfo->vesw_id); |
|---|
| 482 | + hfi1_netdev_remove_data(dd, VNIC_ID(vinfo->vesw_id)); |
|---|
| 627 | 483 | |
|---|
| 628 | | - /* ensure irqs see the change */ |
|---|
| 629 | | - hfi1_vnic_synchronize_irq(dd); |
|---|
| 630 | | - |
|---|
| 631 | | - /* remove unread skbs */ |
|---|
| 632 | | - for (i = 0; i < vinfo->num_rx_q; i++) { |
|---|
| 633 | | - struct hfi1_vnic_rx_queue *rxq = &vinfo->rxq[i]; |
|---|
| 634 | | - |
|---|
| 635 | | - napi_disable(&rxq->napi); |
|---|
| 636 | | - skb_queue_purge(&rxq->skbq); |
|---|
| 637 | | - } |
|---|
| 484 | + hfi1_netdev_rx_destroy(dd); |
|---|
| 638 | 485 | } |
|---|
| 639 | 486 | |
|---|
| 640 | 487 | static int hfi1_netdev_open(struct net_device *netdev) |
|---|
| .. | .. |
|---|
| 659 | 506 | return 0; |
|---|
| 660 | 507 | } |
|---|
| 661 | 508 | |
|---|
| 662 | | -static int hfi1_vnic_allot_ctxt(struct hfi1_devdata *dd, |
|---|
| 663 | | - struct hfi1_ctxtdata **vnic_ctxt) |
|---|
| 664 | | -{ |
|---|
| 665 | | - int rc; |
|---|
| 666 | | - |
|---|
| 667 | | - rc = allocate_vnic_ctxt(dd, vnic_ctxt); |
|---|
| 668 | | - if (rc) { |
|---|
| 669 | | - dd_dev_err(dd, "vnic ctxt alloc failed %d\n", rc); |
|---|
| 670 | | - return rc; |
|---|
| 671 | | - } |
|---|
| 672 | | - |
|---|
| 673 | | - rc = setup_vnic_ctxt(dd, *vnic_ctxt); |
|---|
| 674 | | - if (rc) { |
|---|
| 675 | | - dd_dev_err(dd, "vnic ctxt setup failed %d\n", rc); |
|---|
| 676 | | - deallocate_vnic_ctxt(dd, *vnic_ctxt); |
|---|
| 677 | | - *vnic_ctxt = NULL; |
|---|
| 678 | | - } |
|---|
| 679 | | - |
|---|
| 680 | | - return rc; |
|---|
| 681 | | -} |
|---|
| 682 | | - |
|---|
| 683 | 509 | static int hfi1_vnic_init(struct hfi1_vnic_vport_info *vinfo) |
|---|
| 684 | 510 | { |
|---|
| 685 | 511 | struct hfi1_devdata *dd = vinfo->dd; |
|---|
| 686 | | - int i, rc = 0; |
|---|
| 512 | + int rc = 0; |
|---|
| 687 | 513 | |
|---|
| 688 | 514 | mutex_lock(&hfi1_mutex); |
|---|
| 689 | | - if (!dd->vnic.num_vports) { |
|---|
| 515 | + if (!dd->vnic_num_vports) { |
|---|
| 690 | 516 | rc = hfi1_vnic_txreq_init(dd); |
|---|
| 691 | 517 | if (rc) |
|---|
| 692 | 518 | goto txreq_fail; |
|---|
| 693 | | - |
|---|
| 694 | | - dd->vnic.msix_idx = dd->first_dyn_msix_idx; |
|---|
| 695 | 519 | } |
|---|
| 696 | 520 | |
|---|
| 697 | | - for (i = dd->vnic.num_ctxt; i < vinfo->num_rx_q; i++) { |
|---|
| 698 | | - rc = hfi1_vnic_allot_ctxt(dd, &dd->vnic.ctxt[i]); |
|---|
| 699 | | - if (rc) |
|---|
| 700 | | - break; |
|---|
| 701 | | - hfi1_rcd_get(dd->vnic.ctxt[i]); |
|---|
| 702 | | - dd->vnic.ctxt[i]->vnic_q_idx = i; |
|---|
| 703 | | - } |
|---|
| 704 | | - |
|---|
| 705 | | - if (i < vinfo->num_rx_q) { |
|---|
| 706 | | - /* |
|---|
| 707 | | - * If required amount of contexts is not |
|---|
| 708 | | - * allocated successfully then remaining contexts |
|---|
| 709 | | - * are released. |
|---|
| 710 | | - */ |
|---|
| 711 | | - while (i-- > dd->vnic.num_ctxt) { |
|---|
| 712 | | - deallocate_vnic_ctxt(dd, dd->vnic.ctxt[i]); |
|---|
| 713 | | - hfi1_rcd_put(dd->vnic.ctxt[i]); |
|---|
| 714 | | - dd->vnic.ctxt[i] = NULL; |
|---|
| 715 | | - } |
|---|
| 521 | + rc = hfi1_netdev_rx_init(dd); |
|---|
| 522 | + if (rc) { |
|---|
| 523 | + dd_dev_err(dd, "Unable to initialize netdev contexts\n"); |
|---|
| 716 | 524 | goto alloc_fail; |
|---|
| 717 | 525 | } |
|---|
| 718 | 526 | |
|---|
| 719 | | - if (dd->vnic.num_ctxt != i) { |
|---|
| 720 | | - dd->vnic.num_ctxt = i; |
|---|
| 721 | | - hfi1_init_vnic_rsm(dd); |
|---|
| 722 | | - } |
|---|
| 527 | + hfi1_init_vnic_rsm(dd); |
|---|
| 723 | 528 | |
|---|
| 724 | | - dd->vnic.num_vports++; |
|---|
| 529 | + dd->vnic_num_vports++; |
|---|
| 725 | 530 | hfi1_vnic_sdma_init(vinfo); |
|---|
| 531 | + |
|---|
| 726 | 532 | alloc_fail: |
|---|
| 727 | | - if (!dd->vnic.num_vports) |
|---|
| 533 | + if (!dd->vnic_num_vports) |
|---|
| 728 | 534 | hfi1_vnic_txreq_deinit(dd); |
|---|
| 729 | 535 | txreq_fail: |
|---|
| 730 | 536 | mutex_unlock(&hfi1_mutex); |
|---|
| .. | .. |
|---|
| 734 | 540 | static void hfi1_vnic_deinit(struct hfi1_vnic_vport_info *vinfo) |
|---|
| 735 | 541 | { |
|---|
| 736 | 542 | struct hfi1_devdata *dd = vinfo->dd; |
|---|
| 737 | | - int i; |
|---|
| 738 | 543 | |
|---|
| 739 | 544 | mutex_lock(&hfi1_mutex); |
|---|
| 740 | | - if (--dd->vnic.num_vports == 0) { |
|---|
| 741 | | - for (i = 0; i < dd->vnic.num_ctxt; i++) { |
|---|
| 742 | | - deallocate_vnic_ctxt(dd, dd->vnic.ctxt[i]); |
|---|
| 743 | | - hfi1_rcd_put(dd->vnic.ctxt[i]); |
|---|
| 744 | | - dd->vnic.ctxt[i] = NULL; |
|---|
| 745 | | - } |
|---|
| 545 | + if (--dd->vnic_num_vports == 0) { |
|---|
| 746 | 546 | hfi1_deinit_vnic_rsm(dd); |
|---|
| 747 | | - dd->vnic.num_ctxt = 0; |
|---|
| 748 | 547 | hfi1_vnic_txreq_deinit(dd); |
|---|
| 749 | 548 | } |
|---|
| 750 | 549 | mutex_unlock(&hfi1_mutex); |
|---|
| 550 | + hfi1_netdev_rx_destroy(dd); |
|---|
| 751 | 551 | } |
|---|
| 752 | 552 | |
|---|
| 753 | 553 | static void hfi1_vnic_set_vesw_id(struct net_device *netdev, int id) |
|---|
| .. | .. |
|---|
| 805 | 605 | struct rdma_netdev *rn; |
|---|
| 806 | 606 | int i, size, rc; |
|---|
| 807 | 607 | |
|---|
| 808 | | - if (!dd->num_vnic_contexts) |
|---|
| 608 | + if (!dd->num_netdev_contexts) |
|---|
| 809 | 609 | return ERR_PTR(-ENOMEM); |
|---|
| 810 | 610 | |
|---|
| 811 | 611 | if (!port_num || (port_num > dd->num_pports)) |
|---|
| .. | .. |
|---|
| 816 | 616 | |
|---|
| 817 | 617 | size = sizeof(struct opa_vnic_rdma_netdev) + sizeof(*vinfo); |
|---|
| 818 | 618 | netdev = alloc_netdev_mqs(size, name, name_assign_type, setup, |
|---|
| 819 | | - chip_sdma_engines(dd), dd->num_vnic_contexts); |
|---|
| 619 | + chip_sdma_engines(dd), |
|---|
| 620 | + dd->num_netdev_contexts); |
|---|
| 820 | 621 | if (!netdev) |
|---|
| 821 | 622 | return ERR_PTR(-ENOMEM); |
|---|
| 822 | 623 | |
|---|
| .. | .. |
|---|
| 824 | 625 | vinfo = opa_vnic_dev_priv(netdev); |
|---|
| 825 | 626 | vinfo->dd = dd; |
|---|
| 826 | 627 | vinfo->num_tx_q = chip_sdma_engines(dd); |
|---|
| 827 | | - vinfo->num_rx_q = dd->num_vnic_contexts; |
|---|
| 628 | + vinfo->num_rx_q = dd->num_netdev_contexts; |
|---|
| 828 | 629 | vinfo->netdev = netdev; |
|---|
| 829 | 630 | rn->free_rdma_netdev = hfi1_vnic_free_rn; |
|---|
| 830 | 631 | rn->set_id = hfi1_vnic_set_vesw_id; |
|---|
| .. | .. |
|---|
| 842 | 643 | rxq->idx = i; |
|---|
| 843 | 644 | rxq->vinfo = vinfo; |
|---|
| 844 | 645 | rxq->netdev = netdev; |
|---|
| 845 | | - netif_napi_add(netdev, &rxq->napi, hfi1_vnic_napi, 64); |
|---|
| 846 | 646 | } |
|---|
| 847 | 647 | |
|---|
| 848 | 648 | rc = hfi1_vnic_init(vinfo); |
|---|