1d4829ea6SVishwanathapura, Niranjana /* 2d4829ea6SVishwanathapura, Niranjana * Copyright(c) 2017 Intel Corporation. 3d4829ea6SVishwanathapura, Niranjana * 4d4829ea6SVishwanathapura, Niranjana * This file is provided under a dual BSD/GPLv2 license. When using or 5d4829ea6SVishwanathapura, Niranjana * redistributing this file, you may do so under either license. 6d4829ea6SVishwanathapura, Niranjana * 7d4829ea6SVishwanathapura, Niranjana * GPL LICENSE SUMMARY 8d4829ea6SVishwanathapura, Niranjana * 9d4829ea6SVishwanathapura, Niranjana * This program is free software; you can redistribute it and/or modify 10d4829ea6SVishwanathapura, Niranjana * it under the terms of version 2 of the GNU General Public License as 11d4829ea6SVishwanathapura, Niranjana * published by the Free Software Foundation. 12d4829ea6SVishwanathapura, Niranjana * 13d4829ea6SVishwanathapura, Niranjana * This program is distributed in the hope that it will be useful, but 14d4829ea6SVishwanathapura, Niranjana * WITHOUT ANY WARRANTY; without even the implied warranty of 15d4829ea6SVishwanathapura, Niranjana * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16d4829ea6SVishwanathapura, Niranjana * General Public License for more details. 17d4829ea6SVishwanathapura, Niranjana * 18d4829ea6SVishwanathapura, Niranjana * BSD LICENSE 19d4829ea6SVishwanathapura, Niranjana * 20d4829ea6SVishwanathapura, Niranjana * Redistribution and use in source and binary forms, with or without 21d4829ea6SVishwanathapura, Niranjana * modification, are permitted provided that the following conditions 22d4829ea6SVishwanathapura, Niranjana * are met: 23d4829ea6SVishwanathapura, Niranjana * 24d4829ea6SVishwanathapura, Niranjana * - Redistributions of source code must retain the above copyright 25d4829ea6SVishwanathapura, Niranjana * notice, this list of conditions and the following disclaimer. 26d4829ea6SVishwanathapura, Niranjana * - Redistributions in binary form must reproduce the above copyright 27d4829ea6SVishwanathapura, Niranjana * notice, this list of conditions and the following disclaimer in 28d4829ea6SVishwanathapura, Niranjana * the documentation and/or other materials provided with the 29d4829ea6SVishwanathapura, Niranjana * distribution. 30d4829ea6SVishwanathapura, Niranjana * - Neither the name of Intel Corporation nor the names of its 31d4829ea6SVishwanathapura, Niranjana * contributors may be used to endorse or promote products derived 32d4829ea6SVishwanathapura, Niranjana * from this software without specific prior written permission. 33d4829ea6SVishwanathapura, Niranjana * 34d4829ea6SVishwanathapura, Niranjana * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 35d4829ea6SVishwanathapura, Niranjana * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 36d4829ea6SVishwanathapura, Niranjana * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 37d4829ea6SVishwanathapura, Niranjana * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 38d4829ea6SVishwanathapura, Niranjana * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 39d4829ea6SVishwanathapura, Niranjana * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 40d4829ea6SVishwanathapura, Niranjana * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 41d4829ea6SVishwanathapura, Niranjana * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 42d4829ea6SVishwanathapura, Niranjana * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 43d4829ea6SVishwanathapura, Niranjana * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 44d4829ea6SVishwanathapura, Niranjana * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 45d4829ea6SVishwanathapura, Niranjana * 46d4829ea6SVishwanathapura, Niranjana */ 47d4829ea6SVishwanathapura, Niranjana 48d4829ea6SVishwanathapura, Niranjana /* 49d4829ea6SVishwanathapura, Niranjana * This file contains HFI1 support for VNIC functionality 50d4829ea6SVishwanathapura, Niranjana */ 51d4829ea6SVishwanathapura, Niranjana 52d4829ea6SVishwanathapura, Niranjana #include <linux/io.h> 53d4829ea6SVishwanathapura, Niranjana #include <linux/if_vlan.h> 54d4829ea6SVishwanathapura, Niranjana 55d4829ea6SVishwanathapura, Niranjana #include "vnic.h" 56d4829ea6SVishwanathapura, Niranjana 57d4829ea6SVishwanathapura, Niranjana #define HFI_TX_TIMEOUT_MS 1000 58d4829ea6SVishwanathapura, Niranjana 59d4829ea6SVishwanathapura, Niranjana #define HFI1_VNIC_RCV_Q_SIZE 1024 60d4829ea6SVishwanathapura, Niranjana 61d4829ea6SVishwanathapura, Niranjana #define HFI1_VNIC_UP 0 62d4829ea6SVishwanathapura, Niranjana 63d4829ea6SVishwanathapura, Niranjana static DEFINE_SPINLOCK(vport_cntr_lock); 64d4829ea6SVishwanathapura, Niranjana 652280740fSVishwanathapura, Niranjana static int setup_vnic_ctxt(struct hfi1_devdata *dd, struct hfi1_ctxtdata *uctxt) 662280740fSVishwanathapura, Niranjana { 672280740fSVishwanathapura, Niranjana unsigned int rcvctrl_ops = 0; 682280740fSVishwanathapura, Niranjana int ret; 692280740fSVishwanathapura, Niranjana 709b60d2cbSMichael J. Ruhl hfi1_init_ctxt(uctxt->sc); 712280740fSVishwanathapura, Niranjana 722280740fSVishwanathapura, Niranjana uctxt->do_interrupt = &handle_receive_interrupt; 732280740fSVishwanathapura, Niranjana 742280740fSVishwanathapura, Niranjana /* Now allocate the RcvHdr queue and eager buffers. */ 752280740fSVishwanathapura, Niranjana ret = hfi1_create_rcvhdrq(dd, uctxt); 762280740fSVishwanathapura, Niranjana if (ret) 772280740fSVishwanathapura, Niranjana goto done; 782280740fSVishwanathapura, Niranjana 792280740fSVishwanathapura, Niranjana ret = hfi1_setup_eagerbufs(uctxt); 802280740fSVishwanathapura, Niranjana if (ret) 812280740fSVishwanathapura, Niranjana goto done; 822280740fSVishwanathapura, Niranjana 832280740fSVishwanathapura, Niranjana if (uctxt->rcvhdrtail_kvaddr) 842280740fSVishwanathapura, Niranjana clear_rcvhdrtail(uctxt); 852280740fSVishwanathapura, Niranjana 862280740fSVishwanathapura, Niranjana rcvctrl_ops = HFI1_RCVCTRL_CTXT_ENB; 872280740fSVishwanathapura, Niranjana rcvctrl_ops |= HFI1_RCVCTRL_INTRAVAIL_ENB; 882280740fSVishwanathapura, Niranjana 892280740fSVishwanathapura, Niranjana if (!HFI1_CAP_KGET_MASK(uctxt->flags, MULTI_PKT_EGR)) 902280740fSVishwanathapura, Niranjana rcvctrl_ops |= HFI1_RCVCTRL_ONE_PKT_EGR_ENB; 912280740fSVishwanathapura, Niranjana if (HFI1_CAP_KGET_MASK(uctxt->flags, NODROP_EGR_FULL)) 922280740fSVishwanathapura, Niranjana rcvctrl_ops |= HFI1_RCVCTRL_NO_EGR_DROP_ENB; 932280740fSVishwanathapura, Niranjana if (HFI1_CAP_KGET_MASK(uctxt->flags, NODROP_RHQ_FULL)) 942280740fSVishwanathapura, Niranjana rcvctrl_ops |= HFI1_RCVCTRL_NO_RHQ_DROP_ENB; 952280740fSVishwanathapura, Niranjana if (HFI1_CAP_KGET_MASK(uctxt->flags, DMA_RTAIL)) 962280740fSVishwanathapura, Niranjana rcvctrl_ops |= HFI1_RCVCTRL_TAILUPD_ENB; 972280740fSVishwanathapura, Niranjana 982280740fSVishwanathapura, Niranjana hfi1_rcvctrl(uctxt->dd, rcvctrl_ops, uctxt->ctxt); 992280740fSVishwanathapura, Niranjana 1002280740fSVishwanathapura, Niranjana uctxt->is_vnic = true; 1012280740fSVishwanathapura, Niranjana done: 1022280740fSVishwanathapura, Niranjana return ret; 1032280740fSVishwanathapura, Niranjana } 1042280740fSVishwanathapura, Niranjana 1052280740fSVishwanathapura, Niranjana static int allocate_vnic_ctxt(struct hfi1_devdata *dd, 1062280740fSVishwanathapura, Niranjana struct hfi1_ctxtdata **vnic_ctxt) 1072280740fSVishwanathapura, Niranjana { 1082280740fSVishwanathapura, Niranjana struct hfi1_ctxtdata *uctxt; 1092280740fSVishwanathapura, Niranjana unsigned int ctxt; 1102280740fSVishwanathapura, Niranjana int ret; 1112280740fSVishwanathapura, Niranjana 1122280740fSVishwanathapura, Niranjana if (dd->flags & HFI1_FROZEN) 1132280740fSVishwanathapura, Niranjana return -EIO; 1142280740fSVishwanathapura, Niranjana 1152280740fSVishwanathapura, Niranjana for (ctxt = dd->first_dyn_alloc_ctxt; 1162280740fSVishwanathapura, Niranjana ctxt < dd->num_rcv_contexts; ctxt++) 1172280740fSVishwanathapura, Niranjana if (!dd->rcd[ctxt]) 1182280740fSVishwanathapura, Niranjana break; 1192280740fSVishwanathapura, Niranjana 1202280740fSVishwanathapura, Niranjana if (ctxt == dd->num_rcv_contexts) 1212280740fSVishwanathapura, Niranjana return -EBUSY; 1222280740fSVishwanathapura, Niranjana 1232280740fSVishwanathapura, Niranjana uctxt = hfi1_create_ctxtdata(dd->pport, ctxt, dd->node); 1242280740fSVishwanathapura, Niranjana if (!uctxt) { 1252280740fSVishwanathapura, Niranjana dd_dev_err(dd, "Unable to create ctxtdata, failing open\n"); 1262280740fSVishwanathapura, Niranjana return -ENOMEM; 1272280740fSVishwanathapura, Niranjana } 1282280740fSVishwanathapura, Niranjana 1292280740fSVishwanathapura, Niranjana uctxt->flags = HFI1_CAP_KGET(MULTI_PKT_EGR) | 1302280740fSVishwanathapura, Niranjana HFI1_CAP_KGET(NODROP_RHQ_FULL) | 1312280740fSVishwanathapura, Niranjana HFI1_CAP_KGET(NODROP_EGR_FULL) | 1322280740fSVishwanathapura, Niranjana HFI1_CAP_KGET(DMA_RTAIL); 1332280740fSVishwanathapura, Niranjana uctxt->seq_cnt = 1; 1342280740fSVishwanathapura, Niranjana 1352280740fSVishwanathapura, Niranjana /* Allocate and enable a PIO send context */ 1362280740fSVishwanathapura, Niranjana uctxt->sc = sc_alloc(dd, SC_VNIC, uctxt->rcvhdrqentsize, 1372280740fSVishwanathapura, Niranjana uctxt->numa_id); 1382280740fSVishwanathapura, Niranjana 1392280740fSVishwanathapura, Niranjana ret = uctxt->sc ? 0 : -ENOMEM; 1402280740fSVishwanathapura, Niranjana if (ret) 1412280740fSVishwanathapura, Niranjana goto bail; 1422280740fSVishwanathapura, Niranjana 1432280740fSVishwanathapura, Niranjana dd_dev_dbg(dd, "allocated vnic send context %u(%u)\n", 1442280740fSVishwanathapura, Niranjana uctxt->sc->sw_index, uctxt->sc->hw_context); 1452280740fSVishwanathapura, Niranjana ret = sc_enable(uctxt->sc); 1462280740fSVishwanathapura, Niranjana if (ret) 1472280740fSVishwanathapura, Niranjana goto bail; 1482280740fSVishwanathapura, Niranjana 1492280740fSVishwanathapura, Niranjana if (dd->num_msix_entries) 1502280740fSVishwanathapura, Niranjana hfi1_set_vnic_msix_info(uctxt); 1512280740fSVishwanathapura, Niranjana 1522280740fSVishwanathapura, Niranjana hfi1_stats.sps_ctxts++; 1532280740fSVishwanathapura, Niranjana dd_dev_dbg(dd, "created vnic context %d\n", uctxt->ctxt); 1542280740fSVishwanathapura, Niranjana *vnic_ctxt = uctxt; 1552280740fSVishwanathapura, Niranjana 1562280740fSVishwanathapura, Niranjana return ret; 1572280740fSVishwanathapura, Niranjana bail: 1582280740fSVishwanathapura, Niranjana /* 159f683c80cSMichael J. Ruhl * hfi1_rcd_put() will call hfi1_free_ctxtdata(), which will 160f683c80cSMichael J. Ruhl * release send_context structure if uctxt->sc is not null 1612280740fSVishwanathapura, Niranjana */ 1622280740fSVishwanathapura, Niranjana dd->rcd[uctxt->ctxt] = NULL; 163f683c80cSMichael J. Ruhl hfi1_rcd_put(uctxt); 1642280740fSVishwanathapura, Niranjana dd_dev_dbg(dd, "vnic allocation failed. rc %d\n", ret); 1652280740fSVishwanathapura, Niranjana return ret; 1662280740fSVishwanathapura, Niranjana } 1672280740fSVishwanathapura, Niranjana 1682280740fSVishwanathapura, Niranjana static void deallocate_vnic_ctxt(struct hfi1_devdata *dd, 1692280740fSVishwanathapura, Niranjana struct hfi1_ctxtdata *uctxt) 1702280740fSVishwanathapura, Niranjana { 1712280740fSVishwanathapura, Niranjana unsigned long flags; 1722280740fSVishwanathapura, Niranjana 1732280740fSVishwanathapura, Niranjana dd_dev_dbg(dd, "closing vnic context %d\n", uctxt->ctxt); 1742280740fSVishwanathapura, Niranjana flush_wc(); 1752280740fSVishwanathapura, Niranjana 1762280740fSVishwanathapura, Niranjana if (dd->num_msix_entries) 1772280740fSVishwanathapura, Niranjana hfi1_reset_vnic_msix_info(uctxt); 1782280740fSVishwanathapura, Niranjana 1792280740fSVishwanathapura, Niranjana spin_lock_irqsave(&dd->uctxt_lock, flags); 1802280740fSVishwanathapura, Niranjana /* 1812280740fSVishwanathapura, Niranjana * Disable receive context and interrupt available, reset all 1822280740fSVishwanathapura, Niranjana * RcvCtxtCtrl bits to default values. 1832280740fSVishwanathapura, Niranjana */ 1842280740fSVishwanathapura, Niranjana hfi1_rcvctrl(dd, HFI1_RCVCTRL_CTXT_DIS | 1852280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_TIDFLOW_DIS | 1862280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_INTRAVAIL_DIS | 1872280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_ONE_PKT_EGR_DIS | 1882280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_NO_RHQ_DROP_DIS | 1892280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_NO_EGR_DROP_DIS, uctxt->ctxt); 1902280740fSVishwanathapura, Niranjana /* 1912280740fSVishwanathapura, Niranjana * VNIC contexts are allocated from user context pool. 1922280740fSVishwanathapura, Niranjana * Release them back to user context pool. 1932280740fSVishwanathapura, Niranjana * 1942280740fSVishwanathapura, Niranjana * Reset context integrity checks to default. 1952280740fSVishwanathapura, Niranjana * (writes to CSRs probably belong in chip.c) 1962280740fSVishwanathapura, Niranjana */ 1972280740fSVishwanathapura, Niranjana write_kctxt_csr(dd, uctxt->sc->hw_context, SEND_CTXT_CHECK_ENABLE, 1982280740fSVishwanathapura, Niranjana hfi1_pkt_default_send_ctxt_mask(dd, SC_USER)); 1992280740fSVishwanathapura, Niranjana sc_disable(uctxt->sc); 2002280740fSVishwanathapura, Niranjana 2012280740fSVishwanathapura, Niranjana dd->send_contexts[uctxt->sc->sw_index].type = SC_USER; 2022280740fSVishwanathapura, Niranjana spin_unlock_irqrestore(&dd->uctxt_lock, flags); 2032280740fSVishwanathapura, Niranjana 2042280740fSVishwanathapura, Niranjana dd->rcd[uctxt->ctxt] = NULL; 2052280740fSVishwanathapura, Niranjana uctxt->event_flags = 0; 2062280740fSVishwanathapura, Niranjana 2072280740fSVishwanathapura, Niranjana hfi1_clear_tids(uctxt); 208637a9a7fSMichael J. Ruhl hfi1_clear_ctxt_pkey(dd, uctxt); 2092280740fSVishwanathapura, Niranjana 2102280740fSVishwanathapura, Niranjana hfi1_stats.sps_ctxts--; 211f683c80cSMichael J. Ruhl hfi1_rcd_put(uctxt); 2122280740fSVishwanathapura, Niranjana } 2132280740fSVishwanathapura, Niranjana 214d4829ea6SVishwanathapura, Niranjana void hfi1_vnic_setup(struct hfi1_devdata *dd) 215d4829ea6SVishwanathapura, Niranjana { 216d4829ea6SVishwanathapura, Niranjana idr_init(&dd->vnic.vesw_idr); 217d4829ea6SVishwanathapura, Niranjana } 218d4829ea6SVishwanathapura, Niranjana 219d4829ea6SVishwanathapura, Niranjana void hfi1_vnic_cleanup(struct hfi1_devdata *dd) 220d4829ea6SVishwanathapura, Niranjana { 221d4829ea6SVishwanathapura, Niranjana idr_destroy(&dd->vnic.vesw_idr); 222d4829ea6SVishwanathapura, Niranjana } 223d4829ea6SVishwanathapura, Niranjana 224d4829ea6SVishwanathapura, Niranjana #define SUM_GRP_COUNTERS(stats, qstats, x_grp) do { \ 225d4829ea6SVishwanathapura, Niranjana u64 *src64, *dst64; \ 226d4829ea6SVishwanathapura, Niranjana for (src64 = &qstats->x_grp.unicast, \ 227d4829ea6SVishwanathapura, Niranjana dst64 = &stats->x_grp.unicast; \ 228d4829ea6SVishwanathapura, Niranjana dst64 <= &stats->x_grp.s_1519_max;) { \ 229d4829ea6SVishwanathapura, Niranjana *dst64++ += *src64++; \ 230d4829ea6SVishwanathapura, Niranjana } \ 231d4829ea6SVishwanathapura, Niranjana } while (0) 232d4829ea6SVishwanathapura, Niranjana 233d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_update_stats - update statistics */ 234d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_update_stats(struct hfi1_vnic_vport_info *vinfo, 235d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *stats) 236d4829ea6SVishwanathapura, Niranjana { 237d4829ea6SVishwanathapura, Niranjana struct net_device *netdev = vinfo->netdev; 238d4829ea6SVishwanathapura, Niranjana u8 i; 239d4829ea6SVishwanathapura, Niranjana 240d4829ea6SVishwanathapura, Niranjana /* add tx counters on different queues */ 241d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_tx_q; i++) { 242d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *qstats = &vinfo->stats[i]; 243d4829ea6SVishwanathapura, Niranjana struct rtnl_link_stats64 *qnstats = &vinfo->stats[i].netstats; 244d4829ea6SVishwanathapura, Niranjana 245d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_fifo_errors += qnstats->tx_fifo_errors; 246d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_carrier_errors += qnstats->tx_carrier_errors; 247d4829ea6SVishwanathapura, Niranjana stats->tx_drop_state += qstats->tx_drop_state; 248d4829ea6SVishwanathapura, Niranjana stats->tx_dlid_zero += qstats->tx_dlid_zero; 249d4829ea6SVishwanathapura, Niranjana 250d4829ea6SVishwanathapura, Niranjana SUM_GRP_COUNTERS(stats, qstats, tx_grp); 251d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_packets += qnstats->tx_packets; 252d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_bytes += qnstats->tx_bytes; 253d4829ea6SVishwanathapura, Niranjana } 254d4829ea6SVishwanathapura, Niranjana 255d4829ea6SVishwanathapura, Niranjana /* add rx counters on different queues */ 256d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_rx_q; i++) { 257d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *qstats = &vinfo->stats[i]; 258d4829ea6SVishwanathapura, Niranjana struct rtnl_link_stats64 *qnstats = &vinfo->stats[i].netstats; 259d4829ea6SVishwanathapura, Niranjana 260d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_fifo_errors += qnstats->rx_fifo_errors; 261d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_nohandler += qnstats->rx_nohandler; 262d4829ea6SVishwanathapura, Niranjana stats->rx_drop_state += qstats->rx_drop_state; 263d4829ea6SVishwanathapura, Niranjana stats->rx_oversize += qstats->rx_oversize; 264d4829ea6SVishwanathapura, Niranjana stats->rx_runt += qstats->rx_runt; 265d4829ea6SVishwanathapura, Niranjana 266d4829ea6SVishwanathapura, Niranjana SUM_GRP_COUNTERS(stats, qstats, rx_grp); 267d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_packets += qnstats->rx_packets; 268d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_bytes += qnstats->rx_bytes; 269d4829ea6SVishwanathapura, Niranjana } 270d4829ea6SVishwanathapura, Niranjana 271d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_errors = stats->netstats.tx_fifo_errors + 272d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_carrier_errors + 273d4829ea6SVishwanathapura, Niranjana stats->tx_drop_state + stats->tx_dlid_zero; 274d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_dropped = stats->netstats.tx_errors; 275d4829ea6SVishwanathapura, Niranjana 276d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_errors = stats->netstats.rx_fifo_errors + 277d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_nohandler + 278d4829ea6SVishwanathapura, Niranjana stats->rx_drop_state + stats->rx_oversize + 279d4829ea6SVishwanathapura, Niranjana stats->rx_runt; 280d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_dropped = stats->netstats.rx_errors; 281d4829ea6SVishwanathapura, Niranjana 282d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_packets = stats->netstats.tx_packets; 283d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_bytes = stats->netstats.tx_bytes; 284d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_fifo_errors = stats->netstats.tx_fifo_errors; 285d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_carrier_errors = stats->netstats.tx_carrier_errors; 286d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_errors = stats->netstats.tx_errors; 287d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_dropped = stats->netstats.tx_dropped; 288d4829ea6SVishwanathapura, Niranjana 289d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_packets = stats->netstats.rx_packets; 290d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_bytes = stats->netstats.rx_bytes; 291d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_fifo_errors = stats->netstats.rx_fifo_errors; 292d4829ea6SVishwanathapura, Niranjana netdev->stats.multicast = stats->rx_grp.mcastbcast; 293d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_length_errors = stats->rx_oversize + stats->rx_runt; 294d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_errors = stats->netstats.rx_errors; 295d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_dropped = stats->netstats.rx_dropped; 296d4829ea6SVishwanathapura, Niranjana } 297d4829ea6SVishwanathapura, Niranjana 298d4829ea6SVishwanathapura, Niranjana /* update_len_counters - update pkt's len histogram counters */ 299d4829ea6SVishwanathapura, Niranjana static inline void update_len_counters(struct opa_vnic_grp_stats *grp, 300d4829ea6SVishwanathapura, Niranjana int len) 301d4829ea6SVishwanathapura, Niranjana { 302d4829ea6SVishwanathapura, Niranjana /* account for 4 byte FCS */ 303d4829ea6SVishwanathapura, Niranjana if (len >= 1515) 304d4829ea6SVishwanathapura, Niranjana grp->s_1519_max++; 305d4829ea6SVishwanathapura, Niranjana else if (len >= 1020) 306d4829ea6SVishwanathapura, Niranjana grp->s_1024_1518++; 307d4829ea6SVishwanathapura, Niranjana else if (len >= 508) 308d4829ea6SVishwanathapura, Niranjana grp->s_512_1023++; 309d4829ea6SVishwanathapura, Niranjana else if (len >= 252) 310d4829ea6SVishwanathapura, Niranjana grp->s_256_511++; 311d4829ea6SVishwanathapura, Niranjana else if (len >= 124) 312d4829ea6SVishwanathapura, Niranjana grp->s_128_255++; 313d4829ea6SVishwanathapura, Niranjana else if (len >= 61) 314d4829ea6SVishwanathapura, Niranjana grp->s_65_127++; 315d4829ea6SVishwanathapura, Niranjana else 316d4829ea6SVishwanathapura, Niranjana grp->s_64++; 317d4829ea6SVishwanathapura, Niranjana } 318d4829ea6SVishwanathapura, Niranjana 319d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_update_tx_counters - update transmit counters */ 320d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_update_tx_counters(struct hfi1_vnic_vport_info *vinfo, 321d4829ea6SVishwanathapura, Niranjana u8 q_idx, struct sk_buff *skb, int err) 322d4829ea6SVishwanathapura, Niranjana { 323d4829ea6SVishwanathapura, Niranjana struct ethhdr *mac_hdr = (struct ethhdr *)skb_mac_header(skb); 324d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *stats = &vinfo->stats[q_idx]; 325d4829ea6SVishwanathapura, Niranjana struct opa_vnic_grp_stats *tx_grp = &stats->tx_grp; 326d4829ea6SVishwanathapura, Niranjana u16 vlan_tci; 327d4829ea6SVishwanathapura, Niranjana 328d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_packets++; 329d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_bytes += skb->len + ETH_FCS_LEN; 330d4829ea6SVishwanathapura, Niranjana 331d4829ea6SVishwanathapura, Niranjana update_len_counters(tx_grp, skb->len); 332d4829ea6SVishwanathapura, Niranjana 333d4829ea6SVishwanathapura, Niranjana /* rest of the counts are for good packets only */ 334d4829ea6SVishwanathapura, Niranjana if (unlikely(err)) 335d4829ea6SVishwanathapura, Niranjana return; 336d4829ea6SVishwanathapura, Niranjana 337d4829ea6SVishwanathapura, Niranjana if (is_multicast_ether_addr(mac_hdr->h_dest)) 338d4829ea6SVishwanathapura, Niranjana tx_grp->mcastbcast++; 339d4829ea6SVishwanathapura, Niranjana else 340d4829ea6SVishwanathapura, Niranjana tx_grp->unicast++; 341d4829ea6SVishwanathapura, Niranjana 342d4829ea6SVishwanathapura, Niranjana if (!__vlan_get_tag(skb, &vlan_tci)) 343d4829ea6SVishwanathapura, Niranjana tx_grp->vlan++; 344d4829ea6SVishwanathapura, Niranjana else 345d4829ea6SVishwanathapura, Niranjana tx_grp->untagged++; 346d4829ea6SVishwanathapura, Niranjana } 347d4829ea6SVishwanathapura, Niranjana 348d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_update_rx_counters - update receive counters */ 349d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_update_rx_counters(struct hfi1_vnic_vport_info *vinfo, 350d4829ea6SVishwanathapura, Niranjana u8 q_idx, struct sk_buff *skb, int err) 351d4829ea6SVishwanathapura, Niranjana { 352d4829ea6SVishwanathapura, Niranjana struct ethhdr *mac_hdr = (struct ethhdr *)skb->data; 353d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *stats = &vinfo->stats[q_idx]; 354d4829ea6SVishwanathapura, Niranjana struct opa_vnic_grp_stats *rx_grp = &stats->rx_grp; 355d4829ea6SVishwanathapura, Niranjana u16 vlan_tci; 356d4829ea6SVishwanathapura, Niranjana 357d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_packets++; 358d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_bytes += skb->len + ETH_FCS_LEN; 359d4829ea6SVishwanathapura, Niranjana 360d4829ea6SVishwanathapura, Niranjana update_len_counters(rx_grp, skb->len); 361d4829ea6SVishwanathapura, Niranjana 362d4829ea6SVishwanathapura, Niranjana /* rest of the counts are for good packets only */ 363d4829ea6SVishwanathapura, Niranjana if (unlikely(err)) 364d4829ea6SVishwanathapura, Niranjana return; 365d4829ea6SVishwanathapura, Niranjana 366d4829ea6SVishwanathapura, Niranjana if (is_multicast_ether_addr(mac_hdr->h_dest)) 367d4829ea6SVishwanathapura, Niranjana rx_grp->mcastbcast++; 368d4829ea6SVishwanathapura, Niranjana else 369d4829ea6SVishwanathapura, Niranjana rx_grp->unicast++; 370d4829ea6SVishwanathapura, Niranjana 371d4829ea6SVishwanathapura, Niranjana if (!__vlan_get_tag(skb, &vlan_tci)) 372d4829ea6SVishwanathapura, Niranjana rx_grp->vlan++; 373d4829ea6SVishwanathapura, Niranjana else 374d4829ea6SVishwanathapura, Niranjana rx_grp->untagged++; 375d4829ea6SVishwanathapura, Niranjana } 376d4829ea6SVishwanathapura, Niranjana 377d4829ea6SVishwanathapura, Niranjana /* This function is overloaded for opa_vnic specific implementation */ 378d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_get_stats64(struct net_device *netdev, 379d4829ea6SVishwanathapura, Niranjana struct rtnl_link_stats64 *stats) 380d4829ea6SVishwanathapura, Niranjana { 381d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *vstats = (struct opa_vnic_stats *)stats; 382d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 383d4829ea6SVishwanathapura, Niranjana 384d4829ea6SVishwanathapura, Niranjana hfi1_vnic_update_stats(vinfo, vstats); 385d4829ea6SVishwanathapura, Niranjana } 386d4829ea6SVishwanathapura, Niranjana 387d4829ea6SVishwanathapura, Niranjana static u64 create_bypass_pbc(u32 vl, u32 dw_len) 388d4829ea6SVishwanathapura, Niranjana { 389d4829ea6SVishwanathapura, Niranjana u64 pbc; 390d4829ea6SVishwanathapura, Niranjana 391d4829ea6SVishwanathapura, Niranjana pbc = ((u64)PBC_IHCRC_NONE << PBC_INSERT_HCRC_SHIFT) 392d4829ea6SVishwanathapura, Niranjana | PBC_INSERT_BYPASS_ICRC | PBC_CREDIT_RETURN 393d4829ea6SVishwanathapura, Niranjana | PBC_PACKET_BYPASS 394d4829ea6SVishwanathapura, Niranjana | ((vl & PBC_VL_MASK) << PBC_VL_SHIFT) 395d4829ea6SVishwanathapura, Niranjana | (dw_len & PBC_LENGTH_DWS_MASK) << PBC_LENGTH_DWS_SHIFT; 396d4829ea6SVishwanathapura, Niranjana 397d4829ea6SVishwanathapura, Niranjana return pbc; 398d4829ea6SVishwanathapura, Niranjana } 399d4829ea6SVishwanathapura, Niranjana 400d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_maybe_stop_tx - stop tx queue if required */ 401d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_maybe_stop_tx(struct hfi1_vnic_vport_info *vinfo, 402d4829ea6SVishwanathapura, Niranjana u8 q_idx) 403d4829ea6SVishwanathapura, Niranjana { 404d4829ea6SVishwanathapura, Niranjana netif_stop_subqueue(vinfo->netdev, q_idx); 40564551edeSVishwanathapura, Niranjana if (!hfi1_vnic_sdma_write_avail(vinfo, q_idx)) 40664551edeSVishwanathapura, Niranjana return; 40764551edeSVishwanathapura, Niranjana 40864551edeSVishwanathapura, Niranjana netif_start_subqueue(vinfo->netdev, q_idx); 409d4829ea6SVishwanathapura, Niranjana } 410d4829ea6SVishwanathapura, Niranjana 411d4829ea6SVishwanathapura, Niranjana static netdev_tx_t hfi1_netdev_start_xmit(struct sk_buff *skb, 412d4829ea6SVishwanathapura, Niranjana struct net_device *netdev) 413d4829ea6SVishwanathapura, Niranjana { 414d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 415d4829ea6SVishwanathapura, Niranjana u8 pad_len, q_idx = skb->queue_mapping; 416d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 417d4829ea6SVishwanathapura, Niranjana struct opa_vnic_skb_mdata *mdata; 418d4829ea6SVishwanathapura, Niranjana u32 pkt_len, total_len; 419d4829ea6SVishwanathapura, Niranjana int err = -EINVAL; 420d4829ea6SVishwanathapura, Niranjana u64 pbc; 421d4829ea6SVishwanathapura, Niranjana 422d4829ea6SVishwanathapura, Niranjana v_dbg("xmit: queue %d skb len %d\n", q_idx, skb->len); 423d4829ea6SVishwanathapura, Niranjana if (unlikely(!netif_oper_up(netdev))) { 424d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].tx_drop_state++; 425d4829ea6SVishwanathapura, Niranjana goto tx_finish; 426d4829ea6SVishwanathapura, Niranjana } 427d4829ea6SVishwanathapura, Niranjana 428d4829ea6SVishwanathapura, Niranjana /* take out meta data */ 429d4829ea6SVishwanathapura, Niranjana mdata = (struct opa_vnic_skb_mdata *)skb->data; 430d4829ea6SVishwanathapura, Niranjana skb_pull(skb, sizeof(*mdata)); 431d4829ea6SVishwanathapura, Niranjana if (unlikely(mdata->flags & OPA_VNIC_SKB_MDATA_ENCAP_ERR)) { 432d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].tx_dlid_zero++; 433d4829ea6SVishwanathapura, Niranjana goto tx_finish; 434d4829ea6SVishwanathapura, Niranjana } 435d4829ea6SVishwanathapura, Niranjana 436d4829ea6SVishwanathapura, Niranjana /* add tail padding (for 8 bytes size alignment) and icrc */ 437d4829ea6SVishwanathapura, Niranjana pad_len = -(skb->len + OPA_VNIC_ICRC_TAIL_LEN) & 0x7; 438d4829ea6SVishwanathapura, Niranjana pad_len += OPA_VNIC_ICRC_TAIL_LEN; 439d4829ea6SVishwanathapura, Niranjana 440d4829ea6SVishwanathapura, Niranjana /* 441d4829ea6SVishwanathapura, Niranjana * pkt_len is how much data we have to write, includes header and data. 442d4829ea6SVishwanathapura, Niranjana * total_len is length of the packet in Dwords plus the PBC should not 443d4829ea6SVishwanathapura, Niranjana * include the CRC. 444d4829ea6SVishwanathapura, Niranjana */ 445d4829ea6SVishwanathapura, Niranjana pkt_len = (skb->len + pad_len) >> 2; 446d4829ea6SVishwanathapura, Niranjana total_len = pkt_len + 2; /* PBC + packet */ 447d4829ea6SVishwanathapura, Niranjana 448d4829ea6SVishwanathapura, Niranjana pbc = create_bypass_pbc(mdata->vl, total_len); 449d4829ea6SVishwanathapura, Niranjana 450d4829ea6SVishwanathapura, Niranjana skb_get(skb); 451d4829ea6SVishwanathapura, Niranjana v_dbg("pbc 0x%016llX len %d pad_len %d\n", pbc, skb->len, pad_len); 452d4829ea6SVishwanathapura, Niranjana err = dd->process_vnic_dma_send(dd, q_idx, vinfo, skb, pbc, pad_len); 453d4829ea6SVishwanathapura, Niranjana if (unlikely(err)) { 454d4829ea6SVishwanathapura, Niranjana if (err == -ENOMEM) 455d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].netstats.tx_fifo_errors++; 456d4829ea6SVishwanathapura, Niranjana else if (err != -EBUSY) 457d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].netstats.tx_carrier_errors++; 458d4829ea6SVishwanathapura, Niranjana } 459d4829ea6SVishwanathapura, Niranjana /* remove the header before updating tx counters */ 460d4829ea6SVishwanathapura, Niranjana skb_pull(skb, OPA_VNIC_HDR_LEN); 461d4829ea6SVishwanathapura, Niranjana 462d4829ea6SVishwanathapura, Niranjana if (unlikely(err == -EBUSY)) { 463d4829ea6SVishwanathapura, Niranjana hfi1_vnic_maybe_stop_tx(vinfo, q_idx); 464d4829ea6SVishwanathapura, Niranjana dev_kfree_skb_any(skb); 465d4829ea6SVishwanathapura, Niranjana return NETDEV_TX_BUSY; 466d4829ea6SVishwanathapura, Niranjana } 467d4829ea6SVishwanathapura, Niranjana 468d4829ea6SVishwanathapura, Niranjana tx_finish: 469d4829ea6SVishwanathapura, Niranjana /* update tx counters */ 470d4829ea6SVishwanathapura, Niranjana hfi1_vnic_update_tx_counters(vinfo, q_idx, skb, err); 471d4829ea6SVishwanathapura, Niranjana dev_kfree_skb_any(skb); 472d4829ea6SVishwanathapura, Niranjana return NETDEV_TX_OK; 473d4829ea6SVishwanathapura, Niranjana } 474d4829ea6SVishwanathapura, Niranjana 475d4829ea6SVishwanathapura, Niranjana static u16 hfi1_vnic_select_queue(struct net_device *netdev, 476d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb, 477d4829ea6SVishwanathapura, Niranjana void *accel_priv, 478d4829ea6SVishwanathapura, Niranjana select_queue_fallback_t fallback) 479d4829ea6SVishwanathapura, Niranjana { 48064551edeSVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 48164551edeSVishwanathapura, Niranjana struct opa_vnic_skb_mdata *mdata; 48264551edeSVishwanathapura, Niranjana struct sdma_engine *sde; 48364551edeSVishwanathapura, Niranjana 48464551edeSVishwanathapura, Niranjana mdata = (struct opa_vnic_skb_mdata *)skb->data; 48564551edeSVishwanathapura, Niranjana sde = sdma_select_engine_vl(vinfo->dd, mdata->entropy, mdata->vl); 48664551edeSVishwanathapura, Niranjana return sde->this_idx; 487d4829ea6SVishwanathapura, Niranjana } 488d4829ea6SVishwanathapura, Niranjana 489d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_decap_skb - strip OPA header from the skb (ethernet) packet */ 490d4829ea6SVishwanathapura, Niranjana static inline int hfi1_vnic_decap_skb(struct hfi1_vnic_rx_queue *rxq, 491d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb) 492d4829ea6SVishwanathapura, Niranjana { 493d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = rxq->vinfo; 494d4829ea6SVishwanathapura, Niranjana int max_len = vinfo->netdev->mtu + VLAN_ETH_HLEN; 495d4829ea6SVishwanathapura, Niranjana int rc = -EFAULT; 496d4829ea6SVishwanathapura, Niranjana 497d4829ea6SVishwanathapura, Niranjana skb_pull(skb, OPA_VNIC_HDR_LEN); 498d4829ea6SVishwanathapura, Niranjana 499d4829ea6SVishwanathapura, Niranjana /* Validate Packet length */ 500d4829ea6SVishwanathapura, Niranjana if (unlikely(skb->len > max_len)) 501d4829ea6SVishwanathapura, Niranjana vinfo->stats[rxq->idx].rx_oversize++; 502d4829ea6SVishwanathapura, Niranjana else if (unlikely(skb->len < ETH_ZLEN)) 503d4829ea6SVishwanathapura, Niranjana vinfo->stats[rxq->idx].rx_runt++; 504d4829ea6SVishwanathapura, Niranjana else 505d4829ea6SVishwanathapura, Niranjana rc = 0; 506d4829ea6SVishwanathapura, Niranjana return rc; 507d4829ea6SVishwanathapura, Niranjana } 508d4829ea6SVishwanathapura, Niranjana 509d4829ea6SVishwanathapura, Niranjana static inline struct sk_buff *hfi1_vnic_get_skb(struct hfi1_vnic_rx_queue *rxq) 510d4829ea6SVishwanathapura, Niranjana { 511d4829ea6SVishwanathapura, Niranjana unsigned char *pad_info; 512d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb; 513d4829ea6SVishwanathapura, Niranjana 514d4829ea6SVishwanathapura, Niranjana skb = skb_dequeue(&rxq->skbq); 515d4829ea6SVishwanathapura, Niranjana if (unlikely(!skb)) 516d4829ea6SVishwanathapura, Niranjana return NULL; 517d4829ea6SVishwanathapura, Niranjana 518d4829ea6SVishwanathapura, Niranjana /* remove tail padding and icrc */ 519d4829ea6SVishwanathapura, Niranjana pad_info = skb->data + skb->len - 1; 520d4829ea6SVishwanathapura, Niranjana skb_trim(skb, (skb->len - OPA_VNIC_ICRC_TAIL_LEN - 521d4829ea6SVishwanathapura, Niranjana ((*pad_info) & 0x7))); 522d4829ea6SVishwanathapura, Niranjana 523d4829ea6SVishwanathapura, Niranjana return skb; 524d4829ea6SVishwanathapura, Niranjana } 525d4829ea6SVishwanathapura, Niranjana 526d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_handle_rx - handle skb receive */ 527d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_handle_rx(struct hfi1_vnic_rx_queue *rxq, 528d4829ea6SVishwanathapura, Niranjana int *work_done, int work_to_do) 529d4829ea6SVishwanathapura, Niranjana { 530d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = rxq->vinfo; 531d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb; 532d4829ea6SVishwanathapura, Niranjana int rc; 533d4829ea6SVishwanathapura, Niranjana 534d4829ea6SVishwanathapura, Niranjana while (1) { 535d4829ea6SVishwanathapura, Niranjana if (*work_done >= work_to_do) 536d4829ea6SVishwanathapura, Niranjana break; 537d4829ea6SVishwanathapura, Niranjana 538d4829ea6SVishwanathapura, Niranjana skb = hfi1_vnic_get_skb(rxq); 539d4829ea6SVishwanathapura, Niranjana if (unlikely(!skb)) 540d4829ea6SVishwanathapura, Niranjana break; 541d4829ea6SVishwanathapura, Niranjana 542d4829ea6SVishwanathapura, Niranjana rc = hfi1_vnic_decap_skb(rxq, skb); 543d4829ea6SVishwanathapura, Niranjana /* update rx counters */ 544d4829ea6SVishwanathapura, Niranjana hfi1_vnic_update_rx_counters(vinfo, rxq->idx, skb, rc); 545d4829ea6SVishwanathapura, Niranjana if (unlikely(rc)) { 546d4829ea6SVishwanathapura, Niranjana dev_kfree_skb_any(skb); 547d4829ea6SVishwanathapura, Niranjana continue; 548d4829ea6SVishwanathapura, Niranjana } 549d4829ea6SVishwanathapura, Niranjana 550d4829ea6SVishwanathapura, Niranjana skb_checksum_none_assert(skb); 551d4829ea6SVishwanathapura, Niranjana skb->protocol = eth_type_trans(skb, rxq->netdev); 552d4829ea6SVishwanathapura, Niranjana 553d4829ea6SVishwanathapura, Niranjana napi_gro_receive(&rxq->napi, skb); 554d4829ea6SVishwanathapura, Niranjana (*work_done)++; 555d4829ea6SVishwanathapura, Niranjana } 556d4829ea6SVishwanathapura, Niranjana } 557d4829ea6SVishwanathapura, Niranjana 558d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_napi - napi receive polling callback function */ 559d4829ea6SVishwanathapura, Niranjana static int hfi1_vnic_napi(struct napi_struct *napi, int budget) 560d4829ea6SVishwanathapura, Niranjana { 561d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq = container_of(napi, 562d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue, napi); 563d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = rxq->vinfo; 564d4829ea6SVishwanathapura, Niranjana int work_done = 0; 565d4829ea6SVishwanathapura, Niranjana 566d4829ea6SVishwanathapura, Niranjana v_dbg("napi %d budget %d\n", rxq->idx, budget); 567d4829ea6SVishwanathapura, Niranjana hfi1_vnic_handle_rx(rxq, &work_done, budget); 568d4829ea6SVishwanathapura, Niranjana 569d4829ea6SVishwanathapura, Niranjana v_dbg("napi %d work_done %d\n", rxq->idx, work_done); 570d4829ea6SVishwanathapura, Niranjana if (work_done < budget) 571d4829ea6SVishwanathapura, Niranjana napi_complete(napi); 572d4829ea6SVishwanathapura, Niranjana 573d4829ea6SVishwanathapura, Niranjana return work_done; 574d4829ea6SVishwanathapura, Niranjana } 575d4829ea6SVishwanathapura, Niranjana 576d4829ea6SVishwanathapura, Niranjana void hfi1_vnic_bypass_rcv(struct hfi1_packet *packet) 577d4829ea6SVishwanathapura, Niranjana { 578d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = packet->rcd->dd; 579d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = NULL; 580d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq; 581d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb; 582d4829ea6SVishwanathapura, Niranjana int l4_type, vesw_id = -1; 583d4829ea6SVishwanathapura, Niranjana u8 q_idx; 584d4829ea6SVishwanathapura, Niranjana 585d4829ea6SVishwanathapura, Niranjana l4_type = HFI1_GET_L4_TYPE(packet->ebuf); 586d4829ea6SVishwanathapura, Niranjana if (likely(l4_type == OPA_VNIC_L4_ETHR)) { 587d4829ea6SVishwanathapura, Niranjana vesw_id = HFI1_VNIC_GET_VESWID(packet->ebuf); 588d4829ea6SVishwanathapura, Niranjana vinfo = idr_find(&dd->vnic.vesw_idr, vesw_id); 589d4829ea6SVishwanathapura, Niranjana 590d4829ea6SVishwanathapura, Niranjana /* 591d4829ea6SVishwanathapura, Niranjana * In case of invalid vesw id, count the error on 592d4829ea6SVishwanathapura, Niranjana * the first available vport. 593d4829ea6SVishwanathapura, Niranjana */ 594d4829ea6SVishwanathapura, Niranjana if (unlikely(!vinfo)) { 595d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo_tmp; 596d4829ea6SVishwanathapura, Niranjana int id_tmp = 0; 597d4829ea6SVishwanathapura, Niranjana 598d4829ea6SVishwanathapura, Niranjana vinfo_tmp = idr_get_next(&dd->vnic.vesw_idr, &id_tmp); 599d4829ea6SVishwanathapura, Niranjana if (vinfo_tmp) { 600d4829ea6SVishwanathapura, Niranjana spin_lock(&vport_cntr_lock); 601d4829ea6SVishwanathapura, Niranjana vinfo_tmp->stats[0].netstats.rx_nohandler++; 602d4829ea6SVishwanathapura, Niranjana spin_unlock(&vport_cntr_lock); 603d4829ea6SVishwanathapura, Niranjana } 604d4829ea6SVishwanathapura, Niranjana } 605d4829ea6SVishwanathapura, Niranjana } 606d4829ea6SVishwanathapura, Niranjana 607d4829ea6SVishwanathapura, Niranjana if (unlikely(!vinfo)) { 608d4829ea6SVishwanathapura, Niranjana dd_dev_warn(dd, "vnic rcv err: l4 %d vesw id %d ctx %d\n", 609d4829ea6SVishwanathapura, Niranjana l4_type, vesw_id, packet->rcd->ctxt); 610d4829ea6SVishwanathapura, Niranjana return; 611d4829ea6SVishwanathapura, Niranjana } 612d4829ea6SVishwanathapura, Niranjana 613d4829ea6SVishwanathapura, Niranjana q_idx = packet->rcd->vnic_q_idx; 614d4829ea6SVishwanathapura, Niranjana rxq = &vinfo->rxq[q_idx]; 615d4829ea6SVishwanathapura, Niranjana if (unlikely(!netif_oper_up(vinfo->netdev))) { 616d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].rx_drop_state++; 617d4829ea6SVishwanathapura, Niranjana skb_queue_purge(&rxq->skbq); 618d4829ea6SVishwanathapura, Niranjana return; 619d4829ea6SVishwanathapura, Niranjana } 620d4829ea6SVishwanathapura, Niranjana 621d4829ea6SVishwanathapura, Niranjana if (unlikely(skb_queue_len(&rxq->skbq) > HFI1_VNIC_RCV_Q_SIZE)) { 622d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].netstats.rx_fifo_errors++; 623d4829ea6SVishwanathapura, Niranjana return; 624d4829ea6SVishwanathapura, Niranjana } 625d4829ea6SVishwanathapura, Niranjana 626d4829ea6SVishwanathapura, Niranjana skb = netdev_alloc_skb(vinfo->netdev, packet->tlen); 627d4829ea6SVishwanathapura, Niranjana if (unlikely(!skb)) { 628d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].netstats.rx_fifo_errors++; 629d4829ea6SVishwanathapura, Niranjana return; 630d4829ea6SVishwanathapura, Niranjana } 631d4829ea6SVishwanathapura, Niranjana 632d4829ea6SVishwanathapura, Niranjana memcpy(skb->data, packet->ebuf, packet->tlen); 633d4829ea6SVishwanathapura, Niranjana skb_put(skb, packet->tlen); 634d4829ea6SVishwanathapura, Niranjana skb_queue_tail(&rxq->skbq, skb); 635d4829ea6SVishwanathapura, Niranjana 636d4829ea6SVishwanathapura, Niranjana if (napi_schedule_prep(&rxq->napi)) { 637d4829ea6SVishwanathapura, Niranjana v_dbg("napi %d scheduling\n", q_idx); 638d4829ea6SVishwanathapura, Niranjana __napi_schedule(&rxq->napi); 639d4829ea6SVishwanathapura, Niranjana } 640d4829ea6SVishwanathapura, Niranjana } 641d4829ea6SVishwanathapura, Niranjana 642d4829ea6SVishwanathapura, Niranjana static int hfi1_vnic_up(struct hfi1_vnic_vport_info *vinfo) 643d4829ea6SVishwanathapura, Niranjana { 644d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 645d4829ea6SVishwanathapura, Niranjana struct net_device *netdev = vinfo->netdev; 646d4829ea6SVishwanathapura, Niranjana int i, rc; 647d4829ea6SVishwanathapura, Niranjana 648d4829ea6SVishwanathapura, Niranjana /* ensure virtual eth switch id is valid */ 649d4829ea6SVishwanathapura, Niranjana if (!vinfo->vesw_id) 650d4829ea6SVishwanathapura, Niranjana return -EINVAL; 651d4829ea6SVishwanathapura, Niranjana 652d4829ea6SVishwanathapura, Niranjana rc = idr_alloc(&dd->vnic.vesw_idr, vinfo, vinfo->vesw_id, 653d4829ea6SVishwanathapura, Niranjana vinfo->vesw_id + 1, GFP_NOWAIT); 654d4829ea6SVishwanathapura, Niranjana if (rc < 0) 655d4829ea6SVishwanathapura, Niranjana return rc; 656d4829ea6SVishwanathapura, Niranjana 657d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_rx_q; i++) { 658d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq = &vinfo->rxq[i]; 659d4829ea6SVishwanathapura, Niranjana 660d4829ea6SVishwanathapura, Niranjana skb_queue_head_init(&rxq->skbq); 661d4829ea6SVishwanathapura, Niranjana napi_enable(&rxq->napi); 662d4829ea6SVishwanathapura, Niranjana } 663d4829ea6SVishwanathapura, Niranjana 664d4829ea6SVishwanathapura, Niranjana netif_carrier_on(netdev); 665d4829ea6SVishwanathapura, Niranjana netif_tx_start_all_queues(netdev); 666d4829ea6SVishwanathapura, Niranjana set_bit(HFI1_VNIC_UP, &vinfo->flags); 667d4829ea6SVishwanathapura, Niranjana 668d4829ea6SVishwanathapura, Niranjana return 0; 669d4829ea6SVishwanathapura, Niranjana } 670d4829ea6SVishwanathapura, Niranjana 671d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_down(struct hfi1_vnic_vport_info *vinfo) 672d4829ea6SVishwanathapura, Niranjana { 673d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 674d4829ea6SVishwanathapura, Niranjana u8 i; 675d4829ea6SVishwanathapura, Niranjana 676d4829ea6SVishwanathapura, Niranjana clear_bit(HFI1_VNIC_UP, &vinfo->flags); 677d4829ea6SVishwanathapura, Niranjana netif_carrier_off(vinfo->netdev); 678d4829ea6SVishwanathapura, Niranjana netif_tx_disable(vinfo->netdev); 679d4829ea6SVishwanathapura, Niranjana idr_remove(&dd->vnic.vesw_idr, vinfo->vesw_id); 680d4829ea6SVishwanathapura, Niranjana 6812280740fSVishwanathapura, Niranjana /* ensure irqs see the change */ 6822280740fSVishwanathapura, Niranjana hfi1_vnic_synchronize_irq(dd); 6832280740fSVishwanathapura, Niranjana 684d4829ea6SVishwanathapura, Niranjana /* remove unread skbs */ 685d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_rx_q; i++) { 686d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq = &vinfo->rxq[i]; 687d4829ea6SVishwanathapura, Niranjana 688d4829ea6SVishwanathapura, Niranjana napi_disable(&rxq->napi); 689d4829ea6SVishwanathapura, Niranjana skb_queue_purge(&rxq->skbq); 690d4829ea6SVishwanathapura, Niranjana } 691d4829ea6SVishwanathapura, Niranjana } 692d4829ea6SVishwanathapura, Niranjana 693d4829ea6SVishwanathapura, Niranjana static int hfi1_netdev_open(struct net_device *netdev) 694d4829ea6SVishwanathapura, Niranjana { 695d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 696d4829ea6SVishwanathapura, Niranjana int rc; 697d4829ea6SVishwanathapura, Niranjana 698d4829ea6SVishwanathapura, Niranjana mutex_lock(&vinfo->lock); 699d4829ea6SVishwanathapura, Niranjana rc = hfi1_vnic_up(vinfo); 700d4829ea6SVishwanathapura, Niranjana mutex_unlock(&vinfo->lock); 701d4829ea6SVishwanathapura, Niranjana return rc; 702d4829ea6SVishwanathapura, Niranjana } 703d4829ea6SVishwanathapura, Niranjana 704d4829ea6SVishwanathapura, Niranjana static int hfi1_netdev_close(struct net_device *netdev) 705d4829ea6SVishwanathapura, Niranjana { 706d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 707d4829ea6SVishwanathapura, Niranjana 708d4829ea6SVishwanathapura, Niranjana mutex_lock(&vinfo->lock); 709d4829ea6SVishwanathapura, Niranjana if (test_bit(HFI1_VNIC_UP, &vinfo->flags)) 710d4829ea6SVishwanathapura, Niranjana hfi1_vnic_down(vinfo); 711d4829ea6SVishwanathapura, Niranjana mutex_unlock(&vinfo->lock); 712d4829ea6SVishwanathapura, Niranjana return 0; 713d4829ea6SVishwanathapura, Niranjana } 714d4829ea6SVishwanathapura, Niranjana 7152280740fSVishwanathapura, Niranjana static int hfi1_vnic_allot_ctxt(struct hfi1_devdata *dd, 7162280740fSVishwanathapura, Niranjana struct hfi1_ctxtdata **vnic_ctxt) 7172280740fSVishwanathapura, Niranjana { 7182280740fSVishwanathapura, Niranjana int rc; 7192280740fSVishwanathapura, Niranjana 7202280740fSVishwanathapura, Niranjana rc = allocate_vnic_ctxt(dd, vnic_ctxt); 7212280740fSVishwanathapura, Niranjana if (rc) { 7222280740fSVishwanathapura, Niranjana dd_dev_err(dd, "vnic ctxt alloc failed %d\n", rc); 7232280740fSVishwanathapura, Niranjana return rc; 7242280740fSVishwanathapura, Niranjana } 7252280740fSVishwanathapura, Niranjana 7262280740fSVishwanathapura, Niranjana rc = setup_vnic_ctxt(dd, *vnic_ctxt); 7272280740fSVishwanathapura, Niranjana if (rc) { 7282280740fSVishwanathapura, Niranjana dd_dev_err(dd, "vnic ctxt setup failed %d\n", rc); 7292280740fSVishwanathapura, Niranjana deallocate_vnic_ctxt(dd, *vnic_ctxt); 7302280740fSVishwanathapura, Niranjana *vnic_ctxt = NULL; 7312280740fSVishwanathapura, Niranjana } 7322280740fSVishwanathapura, Niranjana 7332280740fSVishwanathapura, Niranjana return rc; 7342280740fSVishwanathapura, Niranjana } 7352280740fSVishwanathapura, Niranjana 7362280740fSVishwanathapura, Niranjana static int hfi1_vnic_init(struct hfi1_vnic_vport_info *vinfo) 7372280740fSVishwanathapura, Niranjana { 7382280740fSVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 7392280740fSVishwanathapura, Niranjana int i, rc = 0; 7402280740fSVishwanathapura, Niranjana 7412280740fSVishwanathapura, Niranjana mutex_lock(&hfi1_mutex); 74264551edeSVishwanathapura, Niranjana if (!dd->vnic.num_vports) { 74364551edeSVishwanathapura, Niranjana rc = hfi1_vnic_txreq_init(dd); 74464551edeSVishwanathapura, Niranjana if (rc) 74564551edeSVishwanathapura, Niranjana goto txreq_fail; 74664551edeSVishwanathapura, Niranjana 7472280740fSVishwanathapura, Niranjana dd->vnic.msix_idx = dd->first_dyn_msix_idx; 74864551edeSVishwanathapura, Niranjana } 7492280740fSVishwanathapura, Niranjana 7502280740fSVishwanathapura, Niranjana for (i = dd->vnic.num_ctxt; i < vinfo->num_rx_q; i++) { 7512280740fSVishwanathapura, Niranjana rc = hfi1_vnic_allot_ctxt(dd, &dd->vnic.ctxt[i]); 7522280740fSVishwanathapura, Niranjana if (rc) 7532280740fSVishwanathapura, Niranjana break; 754f683c80cSMichael J. Ruhl hfi1_rcd_get(dd->vnic.ctxt[i]); 7552280740fSVishwanathapura, Niranjana dd->vnic.ctxt[i]->vnic_q_idx = i; 7562280740fSVishwanathapura, Niranjana } 7572280740fSVishwanathapura, Niranjana 7582280740fSVishwanathapura, Niranjana if (i < vinfo->num_rx_q) { 7592280740fSVishwanathapura, Niranjana /* 7602280740fSVishwanathapura, Niranjana * If required amount of contexts is not 7612280740fSVishwanathapura, Niranjana * allocated successfully then remaining contexts 7622280740fSVishwanathapura, Niranjana * are released. 7632280740fSVishwanathapura, Niranjana */ 7642280740fSVishwanathapura, Niranjana while (i-- > dd->vnic.num_ctxt) { 7652280740fSVishwanathapura, Niranjana deallocate_vnic_ctxt(dd, dd->vnic.ctxt[i]); 766f683c80cSMichael J. Ruhl hfi1_rcd_put(dd->vnic.ctxt[i]); 7672280740fSVishwanathapura, Niranjana dd->vnic.ctxt[i] = NULL; 7682280740fSVishwanathapura, Niranjana } 7692280740fSVishwanathapura, Niranjana goto alloc_fail; 7702280740fSVishwanathapura, Niranjana } 7712280740fSVishwanathapura, Niranjana 7722280740fSVishwanathapura, Niranjana if (dd->vnic.num_ctxt != i) { 7732280740fSVishwanathapura, Niranjana dd->vnic.num_ctxt = i; 7742280740fSVishwanathapura, Niranjana hfi1_init_vnic_rsm(dd); 7752280740fSVishwanathapura, Niranjana } 7762280740fSVishwanathapura, Niranjana 7772280740fSVishwanathapura, Niranjana dd->vnic.num_vports++; 77864551edeSVishwanathapura, Niranjana hfi1_vnic_sdma_init(vinfo); 7792280740fSVishwanathapura, Niranjana alloc_fail: 78064551edeSVishwanathapura, Niranjana if (!dd->vnic.num_vports) 78164551edeSVishwanathapura, Niranjana hfi1_vnic_txreq_deinit(dd); 78264551edeSVishwanathapura, Niranjana txreq_fail: 7832280740fSVishwanathapura, Niranjana mutex_unlock(&hfi1_mutex); 7842280740fSVishwanathapura, Niranjana return rc; 7852280740fSVishwanathapura, Niranjana } 7862280740fSVishwanathapura, Niranjana 7872280740fSVishwanathapura, Niranjana static void hfi1_vnic_deinit(struct hfi1_vnic_vport_info *vinfo) 7882280740fSVishwanathapura, Niranjana { 7892280740fSVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 7902280740fSVishwanathapura, Niranjana int i; 7912280740fSVishwanathapura, Niranjana 7922280740fSVishwanathapura, Niranjana mutex_lock(&hfi1_mutex); 7932280740fSVishwanathapura, Niranjana if (--dd->vnic.num_vports == 0) { 7942280740fSVishwanathapura, Niranjana for (i = 0; i < dd->vnic.num_ctxt; i++) { 7952280740fSVishwanathapura, Niranjana deallocate_vnic_ctxt(dd, dd->vnic.ctxt[i]); 796f683c80cSMichael J. Ruhl hfi1_rcd_put(dd->vnic.ctxt[i]); 7972280740fSVishwanathapura, Niranjana dd->vnic.ctxt[i] = NULL; 7982280740fSVishwanathapura, Niranjana } 7992280740fSVishwanathapura, Niranjana hfi1_deinit_vnic_rsm(dd); 8002280740fSVishwanathapura, Niranjana dd->vnic.num_ctxt = 0; 80164551edeSVishwanathapura, Niranjana hfi1_vnic_txreq_deinit(dd); 8022280740fSVishwanathapura, Niranjana } 8032280740fSVishwanathapura, Niranjana mutex_unlock(&hfi1_mutex); 8042280740fSVishwanathapura, Niranjana } 8052280740fSVishwanathapura, Niranjana 806d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_set_vesw_id(struct net_device *netdev, int id) 807d4829ea6SVishwanathapura, Niranjana { 808d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 809d4829ea6SVishwanathapura, Niranjana bool reopen = false; 810d4829ea6SVishwanathapura, Niranjana 811d4829ea6SVishwanathapura, Niranjana /* 812d4829ea6SVishwanathapura, Niranjana * If vesw_id is being changed, and if the vnic port is up, 813d4829ea6SVishwanathapura, Niranjana * reset the vnic port to ensure new vesw_id gets picked up 814d4829ea6SVishwanathapura, Niranjana */ 815d4829ea6SVishwanathapura, Niranjana if (id != vinfo->vesw_id) { 816d4829ea6SVishwanathapura, Niranjana mutex_lock(&vinfo->lock); 817d4829ea6SVishwanathapura, Niranjana if (test_bit(HFI1_VNIC_UP, &vinfo->flags)) { 818d4829ea6SVishwanathapura, Niranjana hfi1_vnic_down(vinfo); 819d4829ea6SVishwanathapura, Niranjana reopen = true; 820d4829ea6SVishwanathapura, Niranjana } 821d4829ea6SVishwanathapura, Niranjana 822d4829ea6SVishwanathapura, Niranjana vinfo->vesw_id = id; 823d4829ea6SVishwanathapura, Niranjana if (reopen) 824d4829ea6SVishwanathapura, Niranjana hfi1_vnic_up(vinfo); 825d4829ea6SVishwanathapura, Niranjana 826d4829ea6SVishwanathapura, Niranjana mutex_unlock(&vinfo->lock); 827d4829ea6SVishwanathapura, Niranjana } 828d4829ea6SVishwanathapura, Niranjana } 829d4829ea6SVishwanathapura, Niranjana 830d4829ea6SVishwanathapura, Niranjana /* netdev ops */ 831d4829ea6SVishwanathapura, Niranjana static const struct net_device_ops hfi1_netdev_ops = { 832d4829ea6SVishwanathapura, Niranjana .ndo_open = hfi1_netdev_open, 833d4829ea6SVishwanathapura, Niranjana .ndo_stop = hfi1_netdev_close, 834d4829ea6SVishwanathapura, Niranjana .ndo_start_xmit = hfi1_netdev_start_xmit, 835d4829ea6SVishwanathapura, Niranjana .ndo_select_queue = hfi1_vnic_select_queue, 836d4829ea6SVishwanathapura, Niranjana .ndo_get_stats64 = hfi1_vnic_get_stats64, 837d4829ea6SVishwanathapura, Niranjana }; 838d4829ea6SVishwanathapura, Niranjana 839d4829ea6SVishwanathapura, Niranjana struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device, 840d4829ea6SVishwanathapura, Niranjana u8 port_num, 841d4829ea6SVishwanathapura, Niranjana enum rdma_netdev_t type, 842d4829ea6SVishwanathapura, Niranjana const char *name, 843d4829ea6SVishwanathapura, Niranjana unsigned char name_assign_type, 844d4829ea6SVishwanathapura, Niranjana void (*setup)(struct net_device *)) 845d4829ea6SVishwanathapura, Niranjana { 846d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = dd_from_ibdev(device); 847d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo; 848d4829ea6SVishwanathapura, Niranjana struct net_device *netdev; 849d4829ea6SVishwanathapura, Niranjana struct rdma_netdev *rn; 8502280740fSVishwanathapura, Niranjana int i, size, rc; 851d4829ea6SVishwanathapura, Niranjana 852d4829ea6SVishwanathapura, Niranjana if (!port_num || (port_num > dd->num_pports)) 853d4829ea6SVishwanathapura, Niranjana return ERR_PTR(-EINVAL); 854d4829ea6SVishwanathapura, Niranjana 855d4829ea6SVishwanathapura, Niranjana if (type != RDMA_NETDEV_OPA_VNIC) 856d4829ea6SVishwanathapura, Niranjana return ERR_PTR(-EOPNOTSUPP); 857d4829ea6SVishwanathapura, Niranjana 858d4829ea6SVishwanathapura, Niranjana size = sizeof(struct opa_vnic_rdma_netdev) + sizeof(*vinfo); 859d4829ea6SVishwanathapura, Niranjana netdev = alloc_netdev_mqs(size, name, name_assign_type, setup, 860d4829ea6SVishwanathapura, Niranjana dd->chip_sdma_engines, HFI1_NUM_VNIC_CTXT); 861d4829ea6SVishwanathapura, Niranjana if (!netdev) 862d4829ea6SVishwanathapura, Niranjana return ERR_PTR(-ENOMEM); 863d4829ea6SVishwanathapura, Niranjana 864d4829ea6SVishwanathapura, Niranjana rn = netdev_priv(netdev); 865d4829ea6SVishwanathapura, Niranjana vinfo = opa_vnic_dev_priv(netdev); 866d4829ea6SVishwanathapura, Niranjana vinfo->dd = dd; 867d4829ea6SVishwanathapura, Niranjana vinfo->num_tx_q = dd->chip_sdma_engines; 868d4829ea6SVishwanathapura, Niranjana vinfo->num_rx_q = HFI1_NUM_VNIC_CTXT; 869d4829ea6SVishwanathapura, Niranjana vinfo->netdev = netdev; 870d4829ea6SVishwanathapura, Niranjana rn->set_id = hfi1_vnic_set_vesw_id; 871d4829ea6SVishwanathapura, Niranjana 872d4829ea6SVishwanathapura, Niranjana netdev->features = NETIF_F_HIGHDMA | NETIF_F_SG; 873d4829ea6SVishwanathapura, Niranjana netdev->hw_features = netdev->features; 874d4829ea6SVishwanathapura, Niranjana netdev->vlan_features = netdev->features; 875d4829ea6SVishwanathapura, Niranjana netdev->watchdog_timeo = msecs_to_jiffies(HFI_TX_TIMEOUT_MS); 876d4829ea6SVishwanathapura, Niranjana netdev->netdev_ops = &hfi1_netdev_ops; 877d4829ea6SVishwanathapura, Niranjana mutex_init(&vinfo->lock); 878d4829ea6SVishwanathapura, Niranjana 879d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_rx_q; i++) { 880d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq = &vinfo->rxq[i]; 881d4829ea6SVishwanathapura, Niranjana 882d4829ea6SVishwanathapura, Niranjana rxq->idx = i; 883d4829ea6SVishwanathapura, Niranjana rxq->vinfo = vinfo; 884d4829ea6SVishwanathapura, Niranjana rxq->netdev = netdev; 885d4829ea6SVishwanathapura, Niranjana netif_napi_add(netdev, &rxq->napi, hfi1_vnic_napi, 64); 886d4829ea6SVishwanathapura, Niranjana } 887d4829ea6SVishwanathapura, Niranjana 8882280740fSVishwanathapura, Niranjana rc = hfi1_vnic_init(vinfo); 8892280740fSVishwanathapura, Niranjana if (rc) 8902280740fSVishwanathapura, Niranjana goto init_fail; 8912280740fSVishwanathapura, Niranjana 892d4829ea6SVishwanathapura, Niranjana return netdev; 8932280740fSVishwanathapura, Niranjana init_fail: 8942280740fSVishwanathapura, Niranjana mutex_destroy(&vinfo->lock); 8952280740fSVishwanathapura, Niranjana free_netdev(netdev); 8962280740fSVishwanathapura, Niranjana return ERR_PTR(rc); 897d4829ea6SVishwanathapura, Niranjana } 898d4829ea6SVishwanathapura, Niranjana 899d4829ea6SVishwanathapura, Niranjana void hfi1_vnic_free_rn(struct net_device *netdev) 900d4829ea6SVishwanathapura, Niranjana { 901d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 902d4829ea6SVishwanathapura, Niranjana 9032280740fSVishwanathapura, Niranjana hfi1_vnic_deinit(vinfo); 904d4829ea6SVishwanathapura, Niranjana mutex_destroy(&vinfo->lock); 905d4829ea6SVishwanathapura, Niranjana free_netdev(netdev); 906d4829ea6SVishwanathapura, Niranjana } 907