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 702280740fSVishwanathapura, Niranjana ret = hfi1_init_ctxt(uctxt->sc); 712280740fSVishwanathapura, Niranjana if (ret) 722280740fSVishwanathapura, Niranjana goto done; 732280740fSVishwanathapura, Niranjana 742280740fSVishwanathapura, Niranjana uctxt->do_interrupt = &handle_receive_interrupt; 752280740fSVishwanathapura, Niranjana 762280740fSVishwanathapura, Niranjana /* Now allocate the RcvHdr queue and eager buffers. */ 772280740fSVishwanathapura, Niranjana ret = hfi1_create_rcvhdrq(dd, uctxt); 782280740fSVishwanathapura, Niranjana if (ret) 792280740fSVishwanathapura, Niranjana goto done; 802280740fSVishwanathapura, Niranjana 812280740fSVishwanathapura, Niranjana ret = hfi1_setup_eagerbufs(uctxt); 822280740fSVishwanathapura, Niranjana if (ret) 832280740fSVishwanathapura, Niranjana goto done; 842280740fSVishwanathapura, Niranjana 852280740fSVishwanathapura, Niranjana set_bit(HFI1_CTXT_SETUP_DONE, &uctxt->event_flags); 862280740fSVishwanathapura, Niranjana 872280740fSVishwanathapura, Niranjana if (uctxt->rcvhdrtail_kvaddr) 882280740fSVishwanathapura, Niranjana clear_rcvhdrtail(uctxt); 892280740fSVishwanathapura, Niranjana 902280740fSVishwanathapura, Niranjana rcvctrl_ops = HFI1_RCVCTRL_CTXT_ENB; 912280740fSVishwanathapura, Niranjana rcvctrl_ops |= HFI1_RCVCTRL_INTRAVAIL_ENB; 922280740fSVishwanathapura, Niranjana 932280740fSVishwanathapura, Niranjana if (!HFI1_CAP_KGET_MASK(uctxt->flags, MULTI_PKT_EGR)) 942280740fSVishwanathapura, Niranjana rcvctrl_ops |= HFI1_RCVCTRL_ONE_PKT_EGR_ENB; 952280740fSVishwanathapura, Niranjana if (HFI1_CAP_KGET_MASK(uctxt->flags, NODROP_EGR_FULL)) 962280740fSVishwanathapura, Niranjana rcvctrl_ops |= HFI1_RCVCTRL_NO_EGR_DROP_ENB; 972280740fSVishwanathapura, Niranjana if (HFI1_CAP_KGET_MASK(uctxt->flags, NODROP_RHQ_FULL)) 982280740fSVishwanathapura, Niranjana rcvctrl_ops |= HFI1_RCVCTRL_NO_RHQ_DROP_ENB; 992280740fSVishwanathapura, Niranjana if (HFI1_CAP_KGET_MASK(uctxt->flags, DMA_RTAIL)) 1002280740fSVishwanathapura, Niranjana rcvctrl_ops |= HFI1_RCVCTRL_TAILUPD_ENB; 1012280740fSVishwanathapura, Niranjana 1022280740fSVishwanathapura, Niranjana hfi1_rcvctrl(uctxt->dd, rcvctrl_ops, uctxt->ctxt); 1032280740fSVishwanathapura, Niranjana 1042280740fSVishwanathapura, Niranjana uctxt->is_vnic = true; 1052280740fSVishwanathapura, Niranjana done: 1062280740fSVishwanathapura, Niranjana return ret; 1072280740fSVishwanathapura, Niranjana } 1082280740fSVishwanathapura, Niranjana 1092280740fSVishwanathapura, Niranjana static int allocate_vnic_ctxt(struct hfi1_devdata *dd, 1102280740fSVishwanathapura, Niranjana struct hfi1_ctxtdata **vnic_ctxt) 1112280740fSVishwanathapura, Niranjana { 1122280740fSVishwanathapura, Niranjana struct hfi1_ctxtdata *uctxt; 1132280740fSVishwanathapura, Niranjana unsigned int ctxt; 1142280740fSVishwanathapura, Niranjana int ret; 1152280740fSVishwanathapura, Niranjana 1162280740fSVishwanathapura, Niranjana if (dd->flags & HFI1_FROZEN) 1172280740fSVishwanathapura, Niranjana return -EIO; 1182280740fSVishwanathapura, Niranjana 1192280740fSVishwanathapura, Niranjana for (ctxt = dd->first_dyn_alloc_ctxt; 1202280740fSVishwanathapura, Niranjana ctxt < dd->num_rcv_contexts; ctxt++) 1212280740fSVishwanathapura, Niranjana if (!dd->rcd[ctxt]) 1222280740fSVishwanathapura, Niranjana break; 1232280740fSVishwanathapura, Niranjana 1242280740fSVishwanathapura, Niranjana if (ctxt == dd->num_rcv_contexts) 1252280740fSVishwanathapura, Niranjana return -EBUSY; 1262280740fSVishwanathapura, Niranjana 1272280740fSVishwanathapura, Niranjana uctxt = hfi1_create_ctxtdata(dd->pport, ctxt, dd->node); 1282280740fSVishwanathapura, Niranjana if (!uctxt) { 1292280740fSVishwanathapura, Niranjana dd_dev_err(dd, "Unable to create ctxtdata, failing open\n"); 1302280740fSVishwanathapura, Niranjana return -ENOMEM; 1312280740fSVishwanathapura, Niranjana } 1322280740fSVishwanathapura, Niranjana 1332280740fSVishwanathapura, Niranjana uctxt->flags = HFI1_CAP_KGET(MULTI_PKT_EGR) | 1342280740fSVishwanathapura, Niranjana HFI1_CAP_KGET(NODROP_RHQ_FULL) | 1352280740fSVishwanathapura, Niranjana HFI1_CAP_KGET(NODROP_EGR_FULL) | 1362280740fSVishwanathapura, Niranjana HFI1_CAP_KGET(DMA_RTAIL); 1372280740fSVishwanathapura, Niranjana uctxt->seq_cnt = 1; 1382280740fSVishwanathapura, Niranjana 1392280740fSVishwanathapura, Niranjana /* Allocate and enable a PIO send context */ 1402280740fSVishwanathapura, Niranjana uctxt->sc = sc_alloc(dd, SC_VNIC, uctxt->rcvhdrqentsize, 1412280740fSVishwanathapura, Niranjana uctxt->numa_id); 1422280740fSVishwanathapura, Niranjana 1432280740fSVishwanathapura, Niranjana ret = uctxt->sc ? 0 : -ENOMEM; 1442280740fSVishwanathapura, Niranjana if (ret) 1452280740fSVishwanathapura, Niranjana goto bail; 1462280740fSVishwanathapura, Niranjana 1472280740fSVishwanathapura, Niranjana dd_dev_dbg(dd, "allocated vnic send context %u(%u)\n", 1482280740fSVishwanathapura, Niranjana uctxt->sc->sw_index, uctxt->sc->hw_context); 1492280740fSVishwanathapura, Niranjana ret = sc_enable(uctxt->sc); 1502280740fSVishwanathapura, Niranjana if (ret) 1512280740fSVishwanathapura, Niranjana goto bail; 1522280740fSVishwanathapura, Niranjana 1532280740fSVishwanathapura, Niranjana if (dd->num_msix_entries) 1542280740fSVishwanathapura, Niranjana hfi1_set_vnic_msix_info(uctxt); 1552280740fSVishwanathapura, Niranjana 1562280740fSVishwanathapura, Niranjana hfi1_stats.sps_ctxts++; 1572280740fSVishwanathapura, Niranjana dd_dev_dbg(dd, "created vnic context %d\n", uctxt->ctxt); 1582280740fSVishwanathapura, Niranjana *vnic_ctxt = uctxt; 1592280740fSVishwanathapura, Niranjana 1602280740fSVishwanathapura, Niranjana return ret; 1612280740fSVishwanathapura, Niranjana bail: 1622280740fSVishwanathapura, Niranjana /* 1632280740fSVishwanathapura, Niranjana * hfi1_free_ctxtdata() also releases send_context 1642280740fSVishwanathapura, Niranjana * structure if uctxt->sc is not null 1652280740fSVishwanathapura, Niranjana */ 1662280740fSVishwanathapura, Niranjana dd->rcd[uctxt->ctxt] = NULL; 1672280740fSVishwanathapura, Niranjana hfi1_free_ctxtdata(dd, uctxt); 1682280740fSVishwanathapura, Niranjana dd_dev_dbg(dd, "vnic allocation failed. rc %d\n", ret); 1692280740fSVishwanathapura, Niranjana return ret; 1702280740fSVishwanathapura, Niranjana } 1712280740fSVishwanathapura, Niranjana 1722280740fSVishwanathapura, Niranjana static void deallocate_vnic_ctxt(struct hfi1_devdata *dd, 1732280740fSVishwanathapura, Niranjana struct hfi1_ctxtdata *uctxt) 1742280740fSVishwanathapura, Niranjana { 1752280740fSVishwanathapura, Niranjana unsigned long flags; 1762280740fSVishwanathapura, Niranjana 1772280740fSVishwanathapura, Niranjana dd_dev_dbg(dd, "closing vnic context %d\n", uctxt->ctxt); 1782280740fSVishwanathapura, Niranjana flush_wc(); 1792280740fSVishwanathapura, Niranjana 1802280740fSVishwanathapura, Niranjana if (dd->num_msix_entries) 1812280740fSVishwanathapura, Niranjana hfi1_reset_vnic_msix_info(uctxt); 1822280740fSVishwanathapura, Niranjana 1832280740fSVishwanathapura, Niranjana spin_lock_irqsave(&dd->uctxt_lock, flags); 1842280740fSVishwanathapura, Niranjana /* 1852280740fSVishwanathapura, Niranjana * Disable receive context and interrupt available, reset all 1862280740fSVishwanathapura, Niranjana * RcvCtxtCtrl bits to default values. 1872280740fSVishwanathapura, Niranjana */ 1882280740fSVishwanathapura, Niranjana hfi1_rcvctrl(dd, HFI1_RCVCTRL_CTXT_DIS | 1892280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_TIDFLOW_DIS | 1902280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_INTRAVAIL_DIS | 1912280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_ONE_PKT_EGR_DIS | 1922280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_NO_RHQ_DROP_DIS | 1932280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_NO_EGR_DROP_DIS, uctxt->ctxt); 1942280740fSVishwanathapura, Niranjana /* 1952280740fSVishwanathapura, Niranjana * VNIC contexts are allocated from user context pool. 1962280740fSVishwanathapura, Niranjana * Release them back to user context pool. 1972280740fSVishwanathapura, Niranjana * 1982280740fSVishwanathapura, Niranjana * Reset context integrity checks to default. 1992280740fSVishwanathapura, Niranjana * (writes to CSRs probably belong in chip.c) 2002280740fSVishwanathapura, Niranjana */ 2012280740fSVishwanathapura, Niranjana write_kctxt_csr(dd, uctxt->sc->hw_context, SEND_CTXT_CHECK_ENABLE, 2022280740fSVishwanathapura, Niranjana hfi1_pkt_default_send_ctxt_mask(dd, SC_USER)); 2032280740fSVishwanathapura, Niranjana sc_disable(uctxt->sc); 2042280740fSVishwanathapura, Niranjana 2052280740fSVishwanathapura, Niranjana dd->send_contexts[uctxt->sc->sw_index].type = SC_USER; 2062280740fSVishwanathapura, Niranjana spin_unlock_irqrestore(&dd->uctxt_lock, flags); 2072280740fSVishwanathapura, Niranjana 2082280740fSVishwanathapura, Niranjana dd->rcd[uctxt->ctxt] = NULL; 2092280740fSVishwanathapura, Niranjana uctxt->event_flags = 0; 2102280740fSVishwanathapura, Niranjana 2112280740fSVishwanathapura, Niranjana hfi1_clear_tids(uctxt); 2122280740fSVishwanathapura, Niranjana hfi1_clear_ctxt_pkey(dd, uctxt->ctxt); 2132280740fSVishwanathapura, Niranjana 2142280740fSVishwanathapura, Niranjana hfi1_stats.sps_ctxts--; 2152280740fSVishwanathapura, Niranjana hfi1_free_ctxtdata(dd, uctxt); 2162280740fSVishwanathapura, Niranjana } 2172280740fSVishwanathapura, Niranjana 218d4829ea6SVishwanathapura, Niranjana void hfi1_vnic_setup(struct hfi1_devdata *dd) 219d4829ea6SVishwanathapura, Niranjana { 220d4829ea6SVishwanathapura, Niranjana idr_init(&dd->vnic.vesw_idr); 221d4829ea6SVishwanathapura, Niranjana } 222d4829ea6SVishwanathapura, Niranjana 223d4829ea6SVishwanathapura, Niranjana void hfi1_vnic_cleanup(struct hfi1_devdata *dd) 224d4829ea6SVishwanathapura, Niranjana { 225d4829ea6SVishwanathapura, Niranjana idr_destroy(&dd->vnic.vesw_idr); 226d4829ea6SVishwanathapura, Niranjana } 227d4829ea6SVishwanathapura, Niranjana 228d4829ea6SVishwanathapura, Niranjana #define SUM_GRP_COUNTERS(stats, qstats, x_grp) do { \ 229d4829ea6SVishwanathapura, Niranjana u64 *src64, *dst64; \ 230d4829ea6SVishwanathapura, Niranjana for (src64 = &qstats->x_grp.unicast, \ 231d4829ea6SVishwanathapura, Niranjana dst64 = &stats->x_grp.unicast; \ 232d4829ea6SVishwanathapura, Niranjana dst64 <= &stats->x_grp.s_1519_max;) { \ 233d4829ea6SVishwanathapura, Niranjana *dst64++ += *src64++; \ 234d4829ea6SVishwanathapura, Niranjana } \ 235d4829ea6SVishwanathapura, Niranjana } while (0) 236d4829ea6SVishwanathapura, Niranjana 237d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_update_stats - update statistics */ 238d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_update_stats(struct hfi1_vnic_vport_info *vinfo, 239d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *stats) 240d4829ea6SVishwanathapura, Niranjana { 241d4829ea6SVishwanathapura, Niranjana struct net_device *netdev = vinfo->netdev; 242d4829ea6SVishwanathapura, Niranjana u8 i; 243d4829ea6SVishwanathapura, Niranjana 244d4829ea6SVishwanathapura, Niranjana /* add tx counters on different queues */ 245d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_tx_q; i++) { 246d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *qstats = &vinfo->stats[i]; 247d4829ea6SVishwanathapura, Niranjana struct rtnl_link_stats64 *qnstats = &vinfo->stats[i].netstats; 248d4829ea6SVishwanathapura, Niranjana 249d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_fifo_errors += qnstats->tx_fifo_errors; 250d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_carrier_errors += qnstats->tx_carrier_errors; 251d4829ea6SVishwanathapura, Niranjana stats->tx_drop_state += qstats->tx_drop_state; 252d4829ea6SVishwanathapura, Niranjana stats->tx_dlid_zero += qstats->tx_dlid_zero; 253d4829ea6SVishwanathapura, Niranjana 254d4829ea6SVishwanathapura, Niranjana SUM_GRP_COUNTERS(stats, qstats, tx_grp); 255d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_packets += qnstats->tx_packets; 256d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_bytes += qnstats->tx_bytes; 257d4829ea6SVishwanathapura, Niranjana } 258d4829ea6SVishwanathapura, Niranjana 259d4829ea6SVishwanathapura, Niranjana /* add rx counters on different queues */ 260d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_rx_q; i++) { 261d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *qstats = &vinfo->stats[i]; 262d4829ea6SVishwanathapura, Niranjana struct rtnl_link_stats64 *qnstats = &vinfo->stats[i].netstats; 263d4829ea6SVishwanathapura, Niranjana 264d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_fifo_errors += qnstats->rx_fifo_errors; 265d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_nohandler += qnstats->rx_nohandler; 266d4829ea6SVishwanathapura, Niranjana stats->rx_drop_state += qstats->rx_drop_state; 267d4829ea6SVishwanathapura, Niranjana stats->rx_oversize += qstats->rx_oversize; 268d4829ea6SVishwanathapura, Niranjana stats->rx_runt += qstats->rx_runt; 269d4829ea6SVishwanathapura, Niranjana 270d4829ea6SVishwanathapura, Niranjana SUM_GRP_COUNTERS(stats, qstats, rx_grp); 271d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_packets += qnstats->rx_packets; 272d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_bytes += qnstats->rx_bytes; 273d4829ea6SVishwanathapura, Niranjana } 274d4829ea6SVishwanathapura, Niranjana 275d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_errors = stats->netstats.tx_fifo_errors + 276d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_carrier_errors + 277d4829ea6SVishwanathapura, Niranjana stats->tx_drop_state + stats->tx_dlid_zero; 278d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_dropped = stats->netstats.tx_errors; 279d4829ea6SVishwanathapura, Niranjana 280d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_errors = stats->netstats.rx_fifo_errors + 281d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_nohandler + 282d4829ea6SVishwanathapura, Niranjana stats->rx_drop_state + stats->rx_oversize + 283d4829ea6SVishwanathapura, Niranjana stats->rx_runt; 284d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_dropped = stats->netstats.rx_errors; 285d4829ea6SVishwanathapura, Niranjana 286d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_packets = stats->netstats.tx_packets; 287d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_bytes = stats->netstats.tx_bytes; 288d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_fifo_errors = stats->netstats.tx_fifo_errors; 289d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_carrier_errors = stats->netstats.tx_carrier_errors; 290d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_errors = stats->netstats.tx_errors; 291d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_dropped = stats->netstats.tx_dropped; 292d4829ea6SVishwanathapura, Niranjana 293d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_packets = stats->netstats.rx_packets; 294d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_bytes = stats->netstats.rx_bytes; 295d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_fifo_errors = stats->netstats.rx_fifo_errors; 296d4829ea6SVishwanathapura, Niranjana netdev->stats.multicast = stats->rx_grp.mcastbcast; 297d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_length_errors = stats->rx_oversize + stats->rx_runt; 298d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_errors = stats->netstats.rx_errors; 299d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_dropped = stats->netstats.rx_dropped; 300d4829ea6SVishwanathapura, Niranjana } 301d4829ea6SVishwanathapura, Niranjana 302d4829ea6SVishwanathapura, Niranjana /* update_len_counters - update pkt's len histogram counters */ 303d4829ea6SVishwanathapura, Niranjana static inline void update_len_counters(struct opa_vnic_grp_stats *grp, 304d4829ea6SVishwanathapura, Niranjana int len) 305d4829ea6SVishwanathapura, Niranjana { 306d4829ea6SVishwanathapura, Niranjana /* account for 4 byte FCS */ 307d4829ea6SVishwanathapura, Niranjana if (len >= 1515) 308d4829ea6SVishwanathapura, Niranjana grp->s_1519_max++; 309d4829ea6SVishwanathapura, Niranjana else if (len >= 1020) 310d4829ea6SVishwanathapura, Niranjana grp->s_1024_1518++; 311d4829ea6SVishwanathapura, Niranjana else if (len >= 508) 312d4829ea6SVishwanathapura, Niranjana grp->s_512_1023++; 313d4829ea6SVishwanathapura, Niranjana else if (len >= 252) 314d4829ea6SVishwanathapura, Niranjana grp->s_256_511++; 315d4829ea6SVishwanathapura, Niranjana else if (len >= 124) 316d4829ea6SVishwanathapura, Niranjana grp->s_128_255++; 317d4829ea6SVishwanathapura, Niranjana else if (len >= 61) 318d4829ea6SVishwanathapura, Niranjana grp->s_65_127++; 319d4829ea6SVishwanathapura, Niranjana else 320d4829ea6SVishwanathapura, Niranjana grp->s_64++; 321d4829ea6SVishwanathapura, Niranjana } 322d4829ea6SVishwanathapura, Niranjana 323d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_update_tx_counters - update transmit counters */ 324d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_update_tx_counters(struct hfi1_vnic_vport_info *vinfo, 325d4829ea6SVishwanathapura, Niranjana u8 q_idx, struct sk_buff *skb, int err) 326d4829ea6SVishwanathapura, Niranjana { 327d4829ea6SVishwanathapura, Niranjana struct ethhdr *mac_hdr = (struct ethhdr *)skb_mac_header(skb); 328d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *stats = &vinfo->stats[q_idx]; 329d4829ea6SVishwanathapura, Niranjana struct opa_vnic_grp_stats *tx_grp = &stats->tx_grp; 330d4829ea6SVishwanathapura, Niranjana u16 vlan_tci; 331d4829ea6SVishwanathapura, Niranjana 332d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_packets++; 333d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_bytes += skb->len + ETH_FCS_LEN; 334d4829ea6SVishwanathapura, Niranjana 335d4829ea6SVishwanathapura, Niranjana update_len_counters(tx_grp, skb->len); 336d4829ea6SVishwanathapura, Niranjana 337d4829ea6SVishwanathapura, Niranjana /* rest of the counts are for good packets only */ 338d4829ea6SVishwanathapura, Niranjana if (unlikely(err)) 339d4829ea6SVishwanathapura, Niranjana return; 340d4829ea6SVishwanathapura, Niranjana 341d4829ea6SVishwanathapura, Niranjana if (is_multicast_ether_addr(mac_hdr->h_dest)) 342d4829ea6SVishwanathapura, Niranjana tx_grp->mcastbcast++; 343d4829ea6SVishwanathapura, Niranjana else 344d4829ea6SVishwanathapura, Niranjana tx_grp->unicast++; 345d4829ea6SVishwanathapura, Niranjana 346d4829ea6SVishwanathapura, Niranjana if (!__vlan_get_tag(skb, &vlan_tci)) 347d4829ea6SVishwanathapura, Niranjana tx_grp->vlan++; 348d4829ea6SVishwanathapura, Niranjana else 349d4829ea6SVishwanathapura, Niranjana tx_grp->untagged++; 350d4829ea6SVishwanathapura, Niranjana } 351d4829ea6SVishwanathapura, Niranjana 352d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_update_rx_counters - update receive counters */ 353d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_update_rx_counters(struct hfi1_vnic_vport_info *vinfo, 354d4829ea6SVishwanathapura, Niranjana u8 q_idx, struct sk_buff *skb, int err) 355d4829ea6SVishwanathapura, Niranjana { 356d4829ea6SVishwanathapura, Niranjana struct ethhdr *mac_hdr = (struct ethhdr *)skb->data; 357d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *stats = &vinfo->stats[q_idx]; 358d4829ea6SVishwanathapura, Niranjana struct opa_vnic_grp_stats *rx_grp = &stats->rx_grp; 359d4829ea6SVishwanathapura, Niranjana u16 vlan_tci; 360d4829ea6SVishwanathapura, Niranjana 361d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_packets++; 362d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_bytes += skb->len + ETH_FCS_LEN; 363d4829ea6SVishwanathapura, Niranjana 364d4829ea6SVishwanathapura, Niranjana update_len_counters(rx_grp, skb->len); 365d4829ea6SVishwanathapura, Niranjana 366d4829ea6SVishwanathapura, Niranjana /* rest of the counts are for good packets only */ 367d4829ea6SVishwanathapura, Niranjana if (unlikely(err)) 368d4829ea6SVishwanathapura, Niranjana return; 369d4829ea6SVishwanathapura, Niranjana 370d4829ea6SVishwanathapura, Niranjana if (is_multicast_ether_addr(mac_hdr->h_dest)) 371d4829ea6SVishwanathapura, Niranjana rx_grp->mcastbcast++; 372d4829ea6SVishwanathapura, Niranjana else 373d4829ea6SVishwanathapura, Niranjana rx_grp->unicast++; 374d4829ea6SVishwanathapura, Niranjana 375d4829ea6SVishwanathapura, Niranjana if (!__vlan_get_tag(skb, &vlan_tci)) 376d4829ea6SVishwanathapura, Niranjana rx_grp->vlan++; 377d4829ea6SVishwanathapura, Niranjana else 378d4829ea6SVishwanathapura, Niranjana rx_grp->untagged++; 379d4829ea6SVishwanathapura, Niranjana } 380d4829ea6SVishwanathapura, Niranjana 381d4829ea6SVishwanathapura, Niranjana /* This function is overloaded for opa_vnic specific implementation */ 382d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_get_stats64(struct net_device *netdev, 383d4829ea6SVishwanathapura, Niranjana struct rtnl_link_stats64 *stats) 384d4829ea6SVishwanathapura, Niranjana { 385d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *vstats = (struct opa_vnic_stats *)stats; 386d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 387d4829ea6SVishwanathapura, Niranjana 388d4829ea6SVishwanathapura, Niranjana hfi1_vnic_update_stats(vinfo, vstats); 389d4829ea6SVishwanathapura, Niranjana } 390d4829ea6SVishwanathapura, Niranjana 391d4829ea6SVishwanathapura, Niranjana static u64 create_bypass_pbc(u32 vl, u32 dw_len) 392d4829ea6SVishwanathapura, Niranjana { 393d4829ea6SVishwanathapura, Niranjana u64 pbc; 394d4829ea6SVishwanathapura, Niranjana 395d4829ea6SVishwanathapura, Niranjana pbc = ((u64)PBC_IHCRC_NONE << PBC_INSERT_HCRC_SHIFT) 396d4829ea6SVishwanathapura, Niranjana | PBC_INSERT_BYPASS_ICRC | PBC_CREDIT_RETURN 397d4829ea6SVishwanathapura, Niranjana | PBC_PACKET_BYPASS 398d4829ea6SVishwanathapura, Niranjana | ((vl & PBC_VL_MASK) << PBC_VL_SHIFT) 399d4829ea6SVishwanathapura, Niranjana | (dw_len & PBC_LENGTH_DWS_MASK) << PBC_LENGTH_DWS_SHIFT; 400d4829ea6SVishwanathapura, Niranjana 401d4829ea6SVishwanathapura, Niranjana return pbc; 402d4829ea6SVishwanathapura, Niranjana } 403d4829ea6SVishwanathapura, Niranjana 404d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_maybe_stop_tx - stop tx queue if required */ 405d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_maybe_stop_tx(struct hfi1_vnic_vport_info *vinfo, 406d4829ea6SVishwanathapura, Niranjana u8 q_idx) 407d4829ea6SVishwanathapura, Niranjana { 408d4829ea6SVishwanathapura, Niranjana netif_stop_subqueue(vinfo->netdev, q_idx); 40964551edeSVishwanathapura, Niranjana if (!hfi1_vnic_sdma_write_avail(vinfo, q_idx)) 41064551edeSVishwanathapura, Niranjana return; 41164551edeSVishwanathapura, Niranjana 41264551edeSVishwanathapura, Niranjana netif_start_subqueue(vinfo->netdev, q_idx); 413d4829ea6SVishwanathapura, Niranjana } 414d4829ea6SVishwanathapura, Niranjana 415d4829ea6SVishwanathapura, Niranjana static netdev_tx_t hfi1_netdev_start_xmit(struct sk_buff *skb, 416d4829ea6SVishwanathapura, Niranjana struct net_device *netdev) 417d4829ea6SVishwanathapura, Niranjana { 418d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 419d4829ea6SVishwanathapura, Niranjana u8 pad_len, q_idx = skb->queue_mapping; 420d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 421d4829ea6SVishwanathapura, Niranjana struct opa_vnic_skb_mdata *mdata; 422d4829ea6SVishwanathapura, Niranjana u32 pkt_len, total_len; 423d4829ea6SVishwanathapura, Niranjana int err = -EINVAL; 424d4829ea6SVishwanathapura, Niranjana u64 pbc; 425d4829ea6SVishwanathapura, Niranjana 426d4829ea6SVishwanathapura, Niranjana v_dbg("xmit: queue %d skb len %d\n", q_idx, skb->len); 427d4829ea6SVishwanathapura, Niranjana if (unlikely(!netif_oper_up(netdev))) { 428d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].tx_drop_state++; 429d4829ea6SVishwanathapura, Niranjana goto tx_finish; 430d4829ea6SVishwanathapura, Niranjana } 431d4829ea6SVishwanathapura, Niranjana 432d4829ea6SVishwanathapura, Niranjana /* take out meta data */ 433d4829ea6SVishwanathapura, Niranjana mdata = (struct opa_vnic_skb_mdata *)skb->data; 434d4829ea6SVishwanathapura, Niranjana skb_pull(skb, sizeof(*mdata)); 435d4829ea6SVishwanathapura, Niranjana if (unlikely(mdata->flags & OPA_VNIC_SKB_MDATA_ENCAP_ERR)) { 436d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].tx_dlid_zero++; 437d4829ea6SVishwanathapura, Niranjana goto tx_finish; 438d4829ea6SVishwanathapura, Niranjana } 439d4829ea6SVishwanathapura, Niranjana 440d4829ea6SVishwanathapura, Niranjana /* add tail padding (for 8 bytes size alignment) and icrc */ 441d4829ea6SVishwanathapura, Niranjana pad_len = -(skb->len + OPA_VNIC_ICRC_TAIL_LEN) & 0x7; 442d4829ea6SVishwanathapura, Niranjana pad_len += OPA_VNIC_ICRC_TAIL_LEN; 443d4829ea6SVishwanathapura, Niranjana 444d4829ea6SVishwanathapura, Niranjana /* 445d4829ea6SVishwanathapura, Niranjana * pkt_len is how much data we have to write, includes header and data. 446d4829ea6SVishwanathapura, Niranjana * total_len is length of the packet in Dwords plus the PBC should not 447d4829ea6SVishwanathapura, Niranjana * include the CRC. 448d4829ea6SVishwanathapura, Niranjana */ 449d4829ea6SVishwanathapura, Niranjana pkt_len = (skb->len + pad_len) >> 2; 450d4829ea6SVishwanathapura, Niranjana total_len = pkt_len + 2; /* PBC + packet */ 451d4829ea6SVishwanathapura, Niranjana 452d4829ea6SVishwanathapura, Niranjana pbc = create_bypass_pbc(mdata->vl, total_len); 453d4829ea6SVishwanathapura, Niranjana 454d4829ea6SVishwanathapura, Niranjana skb_get(skb); 455d4829ea6SVishwanathapura, Niranjana v_dbg("pbc 0x%016llX len %d pad_len %d\n", pbc, skb->len, pad_len); 456d4829ea6SVishwanathapura, Niranjana err = dd->process_vnic_dma_send(dd, q_idx, vinfo, skb, pbc, pad_len); 457d4829ea6SVishwanathapura, Niranjana if (unlikely(err)) { 458d4829ea6SVishwanathapura, Niranjana if (err == -ENOMEM) 459d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].netstats.tx_fifo_errors++; 460d4829ea6SVishwanathapura, Niranjana else if (err != -EBUSY) 461d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].netstats.tx_carrier_errors++; 462d4829ea6SVishwanathapura, Niranjana } 463d4829ea6SVishwanathapura, Niranjana /* remove the header before updating tx counters */ 464d4829ea6SVishwanathapura, Niranjana skb_pull(skb, OPA_VNIC_HDR_LEN); 465d4829ea6SVishwanathapura, Niranjana 466d4829ea6SVishwanathapura, Niranjana if (unlikely(err == -EBUSY)) { 467d4829ea6SVishwanathapura, Niranjana hfi1_vnic_maybe_stop_tx(vinfo, q_idx); 468d4829ea6SVishwanathapura, Niranjana dev_kfree_skb_any(skb); 469d4829ea6SVishwanathapura, Niranjana return NETDEV_TX_BUSY; 470d4829ea6SVishwanathapura, Niranjana } 471d4829ea6SVishwanathapura, Niranjana 472d4829ea6SVishwanathapura, Niranjana tx_finish: 473d4829ea6SVishwanathapura, Niranjana /* update tx counters */ 474d4829ea6SVishwanathapura, Niranjana hfi1_vnic_update_tx_counters(vinfo, q_idx, skb, err); 475d4829ea6SVishwanathapura, Niranjana dev_kfree_skb_any(skb); 476d4829ea6SVishwanathapura, Niranjana return NETDEV_TX_OK; 477d4829ea6SVishwanathapura, Niranjana } 478d4829ea6SVishwanathapura, Niranjana 479d4829ea6SVishwanathapura, Niranjana static u16 hfi1_vnic_select_queue(struct net_device *netdev, 480d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb, 481d4829ea6SVishwanathapura, Niranjana void *accel_priv, 482d4829ea6SVishwanathapura, Niranjana select_queue_fallback_t fallback) 483d4829ea6SVishwanathapura, Niranjana { 48464551edeSVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 48564551edeSVishwanathapura, Niranjana struct opa_vnic_skb_mdata *mdata; 48664551edeSVishwanathapura, Niranjana struct sdma_engine *sde; 48764551edeSVishwanathapura, Niranjana 48864551edeSVishwanathapura, Niranjana mdata = (struct opa_vnic_skb_mdata *)skb->data; 48964551edeSVishwanathapura, Niranjana sde = sdma_select_engine_vl(vinfo->dd, mdata->entropy, mdata->vl); 49064551edeSVishwanathapura, Niranjana return sde->this_idx; 491d4829ea6SVishwanathapura, Niranjana } 492d4829ea6SVishwanathapura, Niranjana 493d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_decap_skb - strip OPA header from the skb (ethernet) packet */ 494d4829ea6SVishwanathapura, Niranjana static inline int hfi1_vnic_decap_skb(struct hfi1_vnic_rx_queue *rxq, 495d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb) 496d4829ea6SVishwanathapura, Niranjana { 497d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = rxq->vinfo; 498d4829ea6SVishwanathapura, Niranjana int max_len = vinfo->netdev->mtu + VLAN_ETH_HLEN; 499d4829ea6SVishwanathapura, Niranjana int rc = -EFAULT; 500d4829ea6SVishwanathapura, Niranjana 501d4829ea6SVishwanathapura, Niranjana skb_pull(skb, OPA_VNIC_HDR_LEN); 502d4829ea6SVishwanathapura, Niranjana 503d4829ea6SVishwanathapura, Niranjana /* Validate Packet length */ 504d4829ea6SVishwanathapura, Niranjana if (unlikely(skb->len > max_len)) 505d4829ea6SVishwanathapura, Niranjana vinfo->stats[rxq->idx].rx_oversize++; 506d4829ea6SVishwanathapura, Niranjana else if (unlikely(skb->len < ETH_ZLEN)) 507d4829ea6SVishwanathapura, Niranjana vinfo->stats[rxq->idx].rx_runt++; 508d4829ea6SVishwanathapura, Niranjana else 509d4829ea6SVishwanathapura, Niranjana rc = 0; 510d4829ea6SVishwanathapura, Niranjana return rc; 511d4829ea6SVishwanathapura, Niranjana } 512d4829ea6SVishwanathapura, Niranjana 513d4829ea6SVishwanathapura, Niranjana static inline struct sk_buff *hfi1_vnic_get_skb(struct hfi1_vnic_rx_queue *rxq) 514d4829ea6SVishwanathapura, Niranjana { 515d4829ea6SVishwanathapura, Niranjana unsigned char *pad_info; 516d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb; 517d4829ea6SVishwanathapura, Niranjana 518d4829ea6SVishwanathapura, Niranjana skb = skb_dequeue(&rxq->skbq); 519d4829ea6SVishwanathapura, Niranjana if (unlikely(!skb)) 520d4829ea6SVishwanathapura, Niranjana return NULL; 521d4829ea6SVishwanathapura, Niranjana 522d4829ea6SVishwanathapura, Niranjana /* remove tail padding and icrc */ 523d4829ea6SVishwanathapura, Niranjana pad_info = skb->data + skb->len - 1; 524d4829ea6SVishwanathapura, Niranjana skb_trim(skb, (skb->len - OPA_VNIC_ICRC_TAIL_LEN - 525d4829ea6SVishwanathapura, Niranjana ((*pad_info) & 0x7))); 526d4829ea6SVishwanathapura, Niranjana 527d4829ea6SVishwanathapura, Niranjana return skb; 528d4829ea6SVishwanathapura, Niranjana } 529d4829ea6SVishwanathapura, Niranjana 530d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_handle_rx - handle skb receive */ 531d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_handle_rx(struct hfi1_vnic_rx_queue *rxq, 532d4829ea6SVishwanathapura, Niranjana int *work_done, int work_to_do) 533d4829ea6SVishwanathapura, Niranjana { 534d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = rxq->vinfo; 535d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb; 536d4829ea6SVishwanathapura, Niranjana int rc; 537d4829ea6SVishwanathapura, Niranjana 538d4829ea6SVishwanathapura, Niranjana while (1) { 539d4829ea6SVishwanathapura, Niranjana if (*work_done >= work_to_do) 540d4829ea6SVishwanathapura, Niranjana break; 541d4829ea6SVishwanathapura, Niranjana 542d4829ea6SVishwanathapura, Niranjana skb = hfi1_vnic_get_skb(rxq); 543d4829ea6SVishwanathapura, Niranjana if (unlikely(!skb)) 544d4829ea6SVishwanathapura, Niranjana break; 545d4829ea6SVishwanathapura, Niranjana 546d4829ea6SVishwanathapura, Niranjana rc = hfi1_vnic_decap_skb(rxq, skb); 547d4829ea6SVishwanathapura, Niranjana /* update rx counters */ 548d4829ea6SVishwanathapura, Niranjana hfi1_vnic_update_rx_counters(vinfo, rxq->idx, skb, rc); 549d4829ea6SVishwanathapura, Niranjana if (unlikely(rc)) { 550d4829ea6SVishwanathapura, Niranjana dev_kfree_skb_any(skb); 551d4829ea6SVishwanathapura, Niranjana continue; 552d4829ea6SVishwanathapura, Niranjana } 553d4829ea6SVishwanathapura, Niranjana 554d4829ea6SVishwanathapura, Niranjana skb_checksum_none_assert(skb); 555d4829ea6SVishwanathapura, Niranjana skb->protocol = eth_type_trans(skb, rxq->netdev); 556d4829ea6SVishwanathapura, Niranjana 557d4829ea6SVishwanathapura, Niranjana napi_gro_receive(&rxq->napi, skb); 558d4829ea6SVishwanathapura, Niranjana (*work_done)++; 559d4829ea6SVishwanathapura, Niranjana } 560d4829ea6SVishwanathapura, Niranjana } 561d4829ea6SVishwanathapura, Niranjana 562d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_napi - napi receive polling callback function */ 563d4829ea6SVishwanathapura, Niranjana static int hfi1_vnic_napi(struct napi_struct *napi, int budget) 564d4829ea6SVishwanathapura, Niranjana { 565d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq = container_of(napi, 566d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue, napi); 567d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = rxq->vinfo; 568d4829ea6SVishwanathapura, Niranjana int work_done = 0; 569d4829ea6SVishwanathapura, Niranjana 570d4829ea6SVishwanathapura, Niranjana v_dbg("napi %d budget %d\n", rxq->idx, budget); 571d4829ea6SVishwanathapura, Niranjana hfi1_vnic_handle_rx(rxq, &work_done, budget); 572d4829ea6SVishwanathapura, Niranjana 573d4829ea6SVishwanathapura, Niranjana v_dbg("napi %d work_done %d\n", rxq->idx, work_done); 574d4829ea6SVishwanathapura, Niranjana if (work_done < budget) 575d4829ea6SVishwanathapura, Niranjana napi_complete(napi); 576d4829ea6SVishwanathapura, Niranjana 577d4829ea6SVishwanathapura, Niranjana return work_done; 578d4829ea6SVishwanathapura, Niranjana } 579d4829ea6SVishwanathapura, Niranjana 580d4829ea6SVishwanathapura, Niranjana void hfi1_vnic_bypass_rcv(struct hfi1_packet *packet) 581d4829ea6SVishwanathapura, Niranjana { 582d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = packet->rcd->dd; 583d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = NULL; 584d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq; 585d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb; 586d4829ea6SVishwanathapura, Niranjana int l4_type, vesw_id = -1; 587d4829ea6SVishwanathapura, Niranjana u8 q_idx; 588d4829ea6SVishwanathapura, Niranjana 589d4829ea6SVishwanathapura, Niranjana l4_type = HFI1_GET_L4_TYPE(packet->ebuf); 590d4829ea6SVishwanathapura, Niranjana if (likely(l4_type == OPA_VNIC_L4_ETHR)) { 591d4829ea6SVishwanathapura, Niranjana vesw_id = HFI1_VNIC_GET_VESWID(packet->ebuf); 592d4829ea6SVishwanathapura, Niranjana vinfo = idr_find(&dd->vnic.vesw_idr, vesw_id); 593d4829ea6SVishwanathapura, Niranjana 594d4829ea6SVishwanathapura, Niranjana /* 595d4829ea6SVishwanathapura, Niranjana * In case of invalid vesw id, count the error on 596d4829ea6SVishwanathapura, Niranjana * the first available vport. 597d4829ea6SVishwanathapura, Niranjana */ 598d4829ea6SVishwanathapura, Niranjana if (unlikely(!vinfo)) { 599d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo_tmp; 600d4829ea6SVishwanathapura, Niranjana int id_tmp = 0; 601d4829ea6SVishwanathapura, Niranjana 602d4829ea6SVishwanathapura, Niranjana vinfo_tmp = idr_get_next(&dd->vnic.vesw_idr, &id_tmp); 603d4829ea6SVishwanathapura, Niranjana if (vinfo_tmp) { 604d4829ea6SVishwanathapura, Niranjana spin_lock(&vport_cntr_lock); 605d4829ea6SVishwanathapura, Niranjana vinfo_tmp->stats[0].netstats.rx_nohandler++; 606d4829ea6SVishwanathapura, Niranjana spin_unlock(&vport_cntr_lock); 607d4829ea6SVishwanathapura, Niranjana } 608d4829ea6SVishwanathapura, Niranjana } 609d4829ea6SVishwanathapura, Niranjana } 610d4829ea6SVishwanathapura, Niranjana 611d4829ea6SVishwanathapura, Niranjana if (unlikely(!vinfo)) { 612d4829ea6SVishwanathapura, Niranjana dd_dev_warn(dd, "vnic rcv err: l4 %d vesw id %d ctx %d\n", 613d4829ea6SVishwanathapura, Niranjana l4_type, vesw_id, packet->rcd->ctxt); 614d4829ea6SVishwanathapura, Niranjana return; 615d4829ea6SVishwanathapura, Niranjana } 616d4829ea6SVishwanathapura, Niranjana 617d4829ea6SVishwanathapura, Niranjana q_idx = packet->rcd->vnic_q_idx; 618d4829ea6SVishwanathapura, Niranjana rxq = &vinfo->rxq[q_idx]; 619d4829ea6SVishwanathapura, Niranjana if (unlikely(!netif_oper_up(vinfo->netdev))) { 620d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].rx_drop_state++; 621d4829ea6SVishwanathapura, Niranjana skb_queue_purge(&rxq->skbq); 622d4829ea6SVishwanathapura, Niranjana return; 623d4829ea6SVishwanathapura, Niranjana } 624d4829ea6SVishwanathapura, Niranjana 625d4829ea6SVishwanathapura, Niranjana if (unlikely(skb_queue_len(&rxq->skbq) > HFI1_VNIC_RCV_Q_SIZE)) { 626d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].netstats.rx_fifo_errors++; 627d4829ea6SVishwanathapura, Niranjana return; 628d4829ea6SVishwanathapura, Niranjana } 629d4829ea6SVishwanathapura, Niranjana 630d4829ea6SVishwanathapura, Niranjana skb = netdev_alloc_skb(vinfo->netdev, packet->tlen); 631d4829ea6SVishwanathapura, Niranjana if (unlikely(!skb)) { 632d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].netstats.rx_fifo_errors++; 633d4829ea6SVishwanathapura, Niranjana return; 634d4829ea6SVishwanathapura, Niranjana } 635d4829ea6SVishwanathapura, Niranjana 636d4829ea6SVishwanathapura, Niranjana memcpy(skb->data, packet->ebuf, packet->tlen); 637d4829ea6SVishwanathapura, Niranjana skb_put(skb, packet->tlen); 638d4829ea6SVishwanathapura, Niranjana skb_queue_tail(&rxq->skbq, skb); 639d4829ea6SVishwanathapura, Niranjana 640d4829ea6SVishwanathapura, Niranjana if (napi_schedule_prep(&rxq->napi)) { 641d4829ea6SVishwanathapura, Niranjana v_dbg("napi %d scheduling\n", q_idx); 642d4829ea6SVishwanathapura, Niranjana __napi_schedule(&rxq->napi); 643d4829ea6SVishwanathapura, Niranjana } 644d4829ea6SVishwanathapura, Niranjana } 645d4829ea6SVishwanathapura, Niranjana 646d4829ea6SVishwanathapura, Niranjana static int hfi1_vnic_up(struct hfi1_vnic_vport_info *vinfo) 647d4829ea6SVishwanathapura, Niranjana { 648d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 649d4829ea6SVishwanathapura, Niranjana struct net_device *netdev = vinfo->netdev; 650d4829ea6SVishwanathapura, Niranjana int i, rc; 651d4829ea6SVishwanathapura, Niranjana 652d4829ea6SVishwanathapura, Niranjana /* ensure virtual eth switch id is valid */ 653d4829ea6SVishwanathapura, Niranjana if (!vinfo->vesw_id) 654d4829ea6SVishwanathapura, Niranjana return -EINVAL; 655d4829ea6SVishwanathapura, Niranjana 656d4829ea6SVishwanathapura, Niranjana rc = idr_alloc(&dd->vnic.vesw_idr, vinfo, vinfo->vesw_id, 657d4829ea6SVishwanathapura, Niranjana vinfo->vesw_id + 1, GFP_NOWAIT); 658d4829ea6SVishwanathapura, Niranjana if (rc < 0) 659d4829ea6SVishwanathapura, Niranjana return rc; 660d4829ea6SVishwanathapura, Niranjana 661d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_rx_q; i++) { 662d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq = &vinfo->rxq[i]; 663d4829ea6SVishwanathapura, Niranjana 664d4829ea6SVishwanathapura, Niranjana skb_queue_head_init(&rxq->skbq); 665d4829ea6SVishwanathapura, Niranjana napi_enable(&rxq->napi); 666d4829ea6SVishwanathapura, Niranjana } 667d4829ea6SVishwanathapura, Niranjana 668d4829ea6SVishwanathapura, Niranjana netif_carrier_on(netdev); 669d4829ea6SVishwanathapura, Niranjana netif_tx_start_all_queues(netdev); 670d4829ea6SVishwanathapura, Niranjana set_bit(HFI1_VNIC_UP, &vinfo->flags); 671d4829ea6SVishwanathapura, Niranjana 672d4829ea6SVishwanathapura, Niranjana return 0; 673d4829ea6SVishwanathapura, Niranjana } 674d4829ea6SVishwanathapura, Niranjana 675d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_down(struct hfi1_vnic_vport_info *vinfo) 676d4829ea6SVishwanathapura, Niranjana { 677d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 678d4829ea6SVishwanathapura, Niranjana u8 i; 679d4829ea6SVishwanathapura, Niranjana 680d4829ea6SVishwanathapura, Niranjana clear_bit(HFI1_VNIC_UP, &vinfo->flags); 681d4829ea6SVishwanathapura, Niranjana netif_carrier_off(vinfo->netdev); 682d4829ea6SVishwanathapura, Niranjana netif_tx_disable(vinfo->netdev); 683d4829ea6SVishwanathapura, Niranjana idr_remove(&dd->vnic.vesw_idr, vinfo->vesw_id); 684d4829ea6SVishwanathapura, Niranjana 6852280740fSVishwanathapura, Niranjana /* ensure irqs see the change */ 6862280740fSVishwanathapura, Niranjana hfi1_vnic_synchronize_irq(dd); 6872280740fSVishwanathapura, Niranjana 688d4829ea6SVishwanathapura, Niranjana /* remove unread skbs */ 689d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_rx_q; i++) { 690d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq = &vinfo->rxq[i]; 691d4829ea6SVishwanathapura, Niranjana 692d4829ea6SVishwanathapura, Niranjana napi_disable(&rxq->napi); 693d4829ea6SVishwanathapura, Niranjana skb_queue_purge(&rxq->skbq); 694d4829ea6SVishwanathapura, Niranjana } 695d4829ea6SVishwanathapura, Niranjana } 696d4829ea6SVishwanathapura, Niranjana 697d4829ea6SVishwanathapura, Niranjana static int hfi1_netdev_open(struct net_device *netdev) 698d4829ea6SVishwanathapura, Niranjana { 699d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 700d4829ea6SVishwanathapura, Niranjana int rc; 701d4829ea6SVishwanathapura, Niranjana 702d4829ea6SVishwanathapura, Niranjana mutex_lock(&vinfo->lock); 703d4829ea6SVishwanathapura, Niranjana rc = hfi1_vnic_up(vinfo); 704d4829ea6SVishwanathapura, Niranjana mutex_unlock(&vinfo->lock); 705d4829ea6SVishwanathapura, Niranjana return rc; 706d4829ea6SVishwanathapura, Niranjana } 707d4829ea6SVishwanathapura, Niranjana 708d4829ea6SVishwanathapura, Niranjana static int hfi1_netdev_close(struct net_device *netdev) 709d4829ea6SVishwanathapura, Niranjana { 710d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 711d4829ea6SVishwanathapura, Niranjana 712d4829ea6SVishwanathapura, Niranjana mutex_lock(&vinfo->lock); 713d4829ea6SVishwanathapura, Niranjana if (test_bit(HFI1_VNIC_UP, &vinfo->flags)) 714d4829ea6SVishwanathapura, Niranjana hfi1_vnic_down(vinfo); 715d4829ea6SVishwanathapura, Niranjana mutex_unlock(&vinfo->lock); 716d4829ea6SVishwanathapura, Niranjana return 0; 717d4829ea6SVishwanathapura, Niranjana } 718d4829ea6SVishwanathapura, Niranjana 7192280740fSVishwanathapura, Niranjana static int hfi1_vnic_allot_ctxt(struct hfi1_devdata *dd, 7202280740fSVishwanathapura, Niranjana struct hfi1_ctxtdata **vnic_ctxt) 7212280740fSVishwanathapura, Niranjana { 7222280740fSVishwanathapura, Niranjana int rc; 7232280740fSVishwanathapura, Niranjana 7242280740fSVishwanathapura, Niranjana rc = allocate_vnic_ctxt(dd, vnic_ctxt); 7252280740fSVishwanathapura, Niranjana if (rc) { 7262280740fSVishwanathapura, Niranjana dd_dev_err(dd, "vnic ctxt alloc failed %d\n", rc); 7272280740fSVishwanathapura, Niranjana return rc; 7282280740fSVishwanathapura, Niranjana } 7292280740fSVishwanathapura, Niranjana 7302280740fSVishwanathapura, Niranjana rc = setup_vnic_ctxt(dd, *vnic_ctxt); 7312280740fSVishwanathapura, Niranjana if (rc) { 7322280740fSVishwanathapura, Niranjana dd_dev_err(dd, "vnic ctxt setup failed %d\n", rc); 7332280740fSVishwanathapura, Niranjana deallocate_vnic_ctxt(dd, *vnic_ctxt); 7342280740fSVishwanathapura, Niranjana *vnic_ctxt = NULL; 7352280740fSVishwanathapura, Niranjana } 7362280740fSVishwanathapura, Niranjana 7372280740fSVishwanathapura, Niranjana return rc; 7382280740fSVishwanathapura, Niranjana } 7392280740fSVishwanathapura, Niranjana 7402280740fSVishwanathapura, Niranjana static int hfi1_vnic_init(struct hfi1_vnic_vport_info *vinfo) 7412280740fSVishwanathapura, Niranjana { 7422280740fSVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 7432280740fSVishwanathapura, Niranjana int i, rc = 0; 7442280740fSVishwanathapura, Niranjana 7452280740fSVishwanathapura, Niranjana mutex_lock(&hfi1_mutex); 74664551edeSVishwanathapura, Niranjana if (!dd->vnic.num_vports) { 74764551edeSVishwanathapura, Niranjana rc = hfi1_vnic_txreq_init(dd); 74864551edeSVishwanathapura, Niranjana if (rc) 74964551edeSVishwanathapura, Niranjana goto txreq_fail; 75064551edeSVishwanathapura, Niranjana 7512280740fSVishwanathapura, Niranjana dd->vnic.msix_idx = dd->first_dyn_msix_idx; 75264551edeSVishwanathapura, Niranjana } 7532280740fSVishwanathapura, Niranjana 7542280740fSVishwanathapura, Niranjana for (i = dd->vnic.num_ctxt; i < vinfo->num_rx_q; i++) { 7552280740fSVishwanathapura, Niranjana rc = hfi1_vnic_allot_ctxt(dd, &dd->vnic.ctxt[i]); 7562280740fSVishwanathapura, Niranjana if (rc) 7572280740fSVishwanathapura, Niranjana break; 7582280740fSVishwanathapura, Niranjana dd->vnic.ctxt[i]->vnic_q_idx = i; 7592280740fSVishwanathapura, Niranjana } 7602280740fSVishwanathapura, Niranjana 7612280740fSVishwanathapura, Niranjana if (i < vinfo->num_rx_q) { 7622280740fSVishwanathapura, Niranjana /* 7632280740fSVishwanathapura, Niranjana * If required amount of contexts is not 7642280740fSVishwanathapura, Niranjana * allocated successfully then remaining contexts 7652280740fSVishwanathapura, Niranjana * are released. 7662280740fSVishwanathapura, Niranjana */ 7672280740fSVishwanathapura, Niranjana while (i-- > dd->vnic.num_ctxt) { 7682280740fSVishwanathapura, Niranjana deallocate_vnic_ctxt(dd, dd->vnic.ctxt[i]); 7692280740fSVishwanathapura, Niranjana dd->vnic.ctxt[i] = NULL; 7702280740fSVishwanathapura, Niranjana } 7712280740fSVishwanathapura, Niranjana goto alloc_fail; 7722280740fSVishwanathapura, Niranjana } 7732280740fSVishwanathapura, Niranjana 7742280740fSVishwanathapura, Niranjana if (dd->vnic.num_ctxt != i) { 7752280740fSVishwanathapura, Niranjana dd->vnic.num_ctxt = i; 7762280740fSVishwanathapura, Niranjana hfi1_init_vnic_rsm(dd); 7772280740fSVishwanathapura, Niranjana } 7782280740fSVishwanathapura, Niranjana 7792280740fSVishwanathapura, Niranjana dd->vnic.num_vports++; 78064551edeSVishwanathapura, Niranjana hfi1_vnic_sdma_init(vinfo); 7812280740fSVishwanathapura, Niranjana alloc_fail: 78264551edeSVishwanathapura, Niranjana if (!dd->vnic.num_vports) 78364551edeSVishwanathapura, Niranjana hfi1_vnic_txreq_deinit(dd); 78464551edeSVishwanathapura, Niranjana txreq_fail: 7852280740fSVishwanathapura, Niranjana mutex_unlock(&hfi1_mutex); 7862280740fSVishwanathapura, Niranjana return rc; 7872280740fSVishwanathapura, Niranjana } 7882280740fSVishwanathapura, Niranjana 7892280740fSVishwanathapura, Niranjana static void hfi1_vnic_deinit(struct hfi1_vnic_vport_info *vinfo) 7902280740fSVishwanathapura, Niranjana { 7912280740fSVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 7922280740fSVishwanathapura, Niranjana int i; 7932280740fSVishwanathapura, Niranjana 7942280740fSVishwanathapura, Niranjana mutex_lock(&hfi1_mutex); 7952280740fSVishwanathapura, Niranjana if (--dd->vnic.num_vports == 0) { 7962280740fSVishwanathapura, Niranjana for (i = 0; i < dd->vnic.num_ctxt; i++) { 7972280740fSVishwanathapura, Niranjana deallocate_vnic_ctxt(dd, dd->vnic.ctxt[i]); 7982280740fSVishwanathapura, Niranjana dd->vnic.ctxt[i] = NULL; 7992280740fSVishwanathapura, Niranjana } 8002280740fSVishwanathapura, Niranjana hfi1_deinit_vnic_rsm(dd); 8012280740fSVishwanathapura, Niranjana dd->vnic.num_ctxt = 0; 80264551edeSVishwanathapura, Niranjana hfi1_vnic_txreq_deinit(dd); 8032280740fSVishwanathapura, Niranjana } 8042280740fSVishwanathapura, Niranjana mutex_unlock(&hfi1_mutex); 8052280740fSVishwanathapura, Niranjana } 8062280740fSVishwanathapura, Niranjana 807d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_set_vesw_id(struct net_device *netdev, int id) 808d4829ea6SVishwanathapura, Niranjana { 809d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 810d4829ea6SVishwanathapura, Niranjana bool reopen = false; 811d4829ea6SVishwanathapura, Niranjana 812d4829ea6SVishwanathapura, Niranjana /* 813d4829ea6SVishwanathapura, Niranjana * If vesw_id is being changed, and if the vnic port is up, 814d4829ea6SVishwanathapura, Niranjana * reset the vnic port to ensure new vesw_id gets picked up 815d4829ea6SVishwanathapura, Niranjana */ 816d4829ea6SVishwanathapura, Niranjana if (id != vinfo->vesw_id) { 817d4829ea6SVishwanathapura, Niranjana mutex_lock(&vinfo->lock); 818d4829ea6SVishwanathapura, Niranjana if (test_bit(HFI1_VNIC_UP, &vinfo->flags)) { 819d4829ea6SVishwanathapura, Niranjana hfi1_vnic_down(vinfo); 820d4829ea6SVishwanathapura, Niranjana reopen = true; 821d4829ea6SVishwanathapura, Niranjana } 822d4829ea6SVishwanathapura, Niranjana 823d4829ea6SVishwanathapura, Niranjana vinfo->vesw_id = id; 824d4829ea6SVishwanathapura, Niranjana if (reopen) 825d4829ea6SVishwanathapura, Niranjana hfi1_vnic_up(vinfo); 826d4829ea6SVishwanathapura, Niranjana 827d4829ea6SVishwanathapura, Niranjana mutex_unlock(&vinfo->lock); 828d4829ea6SVishwanathapura, Niranjana } 829d4829ea6SVishwanathapura, Niranjana } 830d4829ea6SVishwanathapura, Niranjana 831d4829ea6SVishwanathapura, Niranjana /* netdev ops */ 832d4829ea6SVishwanathapura, Niranjana static const struct net_device_ops hfi1_netdev_ops = { 833d4829ea6SVishwanathapura, Niranjana .ndo_open = hfi1_netdev_open, 834d4829ea6SVishwanathapura, Niranjana .ndo_stop = hfi1_netdev_close, 835d4829ea6SVishwanathapura, Niranjana .ndo_start_xmit = hfi1_netdev_start_xmit, 836d4829ea6SVishwanathapura, Niranjana .ndo_select_queue = hfi1_vnic_select_queue, 837d4829ea6SVishwanathapura, Niranjana .ndo_get_stats64 = hfi1_vnic_get_stats64, 838d4829ea6SVishwanathapura, Niranjana }; 839d4829ea6SVishwanathapura, Niranjana 840d4829ea6SVishwanathapura, Niranjana struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device, 841d4829ea6SVishwanathapura, Niranjana u8 port_num, 842d4829ea6SVishwanathapura, Niranjana enum rdma_netdev_t type, 843d4829ea6SVishwanathapura, Niranjana const char *name, 844d4829ea6SVishwanathapura, Niranjana unsigned char name_assign_type, 845d4829ea6SVishwanathapura, Niranjana void (*setup)(struct net_device *)) 846d4829ea6SVishwanathapura, Niranjana { 847d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = dd_from_ibdev(device); 848d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo; 849d4829ea6SVishwanathapura, Niranjana struct net_device *netdev; 850d4829ea6SVishwanathapura, Niranjana struct rdma_netdev *rn; 8512280740fSVishwanathapura, Niranjana int i, size, rc; 852d4829ea6SVishwanathapura, Niranjana 853d4829ea6SVishwanathapura, Niranjana if (!port_num || (port_num > dd->num_pports)) 854d4829ea6SVishwanathapura, Niranjana return ERR_PTR(-EINVAL); 855d4829ea6SVishwanathapura, Niranjana 856d4829ea6SVishwanathapura, Niranjana if (type != RDMA_NETDEV_OPA_VNIC) 857d4829ea6SVishwanathapura, Niranjana return ERR_PTR(-EOPNOTSUPP); 858d4829ea6SVishwanathapura, Niranjana 859d4829ea6SVishwanathapura, Niranjana size = sizeof(struct opa_vnic_rdma_netdev) + sizeof(*vinfo); 860d4829ea6SVishwanathapura, Niranjana netdev = alloc_netdev_mqs(size, name, name_assign_type, setup, 861d4829ea6SVishwanathapura, Niranjana dd->chip_sdma_engines, HFI1_NUM_VNIC_CTXT); 862d4829ea6SVishwanathapura, Niranjana if (!netdev) 863d4829ea6SVishwanathapura, Niranjana return ERR_PTR(-ENOMEM); 864d4829ea6SVishwanathapura, Niranjana 865d4829ea6SVishwanathapura, Niranjana rn = netdev_priv(netdev); 866d4829ea6SVishwanathapura, Niranjana vinfo = opa_vnic_dev_priv(netdev); 867d4829ea6SVishwanathapura, Niranjana vinfo->dd = dd; 868d4829ea6SVishwanathapura, Niranjana vinfo->num_tx_q = dd->chip_sdma_engines; 869d4829ea6SVishwanathapura, Niranjana vinfo->num_rx_q = HFI1_NUM_VNIC_CTXT; 870d4829ea6SVishwanathapura, Niranjana vinfo->netdev = netdev; 871d4829ea6SVishwanathapura, Niranjana rn->set_id = hfi1_vnic_set_vesw_id; 872d4829ea6SVishwanathapura, Niranjana 873d4829ea6SVishwanathapura, Niranjana netdev->features = NETIF_F_HIGHDMA | NETIF_F_SG; 874d4829ea6SVishwanathapura, Niranjana netdev->hw_features = netdev->features; 875d4829ea6SVishwanathapura, Niranjana netdev->vlan_features = netdev->features; 876d4829ea6SVishwanathapura, Niranjana netdev->watchdog_timeo = msecs_to_jiffies(HFI_TX_TIMEOUT_MS); 877d4829ea6SVishwanathapura, Niranjana netdev->netdev_ops = &hfi1_netdev_ops; 878d4829ea6SVishwanathapura, Niranjana mutex_init(&vinfo->lock); 879d4829ea6SVishwanathapura, Niranjana 880d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_rx_q; i++) { 881d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq = &vinfo->rxq[i]; 882d4829ea6SVishwanathapura, Niranjana 883d4829ea6SVishwanathapura, Niranjana rxq->idx = i; 884d4829ea6SVishwanathapura, Niranjana rxq->vinfo = vinfo; 885d4829ea6SVishwanathapura, Niranjana rxq->netdev = netdev; 886d4829ea6SVishwanathapura, Niranjana netif_napi_add(netdev, &rxq->napi, hfi1_vnic_napi, 64); 887d4829ea6SVishwanathapura, Niranjana } 888d4829ea6SVishwanathapura, Niranjana 8892280740fSVishwanathapura, Niranjana rc = hfi1_vnic_init(vinfo); 8902280740fSVishwanathapura, Niranjana if (rc) 8912280740fSVishwanathapura, Niranjana goto init_fail; 8922280740fSVishwanathapura, Niranjana 893d4829ea6SVishwanathapura, Niranjana return netdev; 8942280740fSVishwanathapura, Niranjana init_fail: 8952280740fSVishwanathapura, Niranjana mutex_destroy(&vinfo->lock); 8962280740fSVishwanathapura, Niranjana free_netdev(netdev); 8972280740fSVishwanathapura, Niranjana return ERR_PTR(rc); 898d4829ea6SVishwanathapura, Niranjana } 899d4829ea6SVishwanathapura, Niranjana 900d4829ea6SVishwanathapura, Niranjana void hfi1_vnic_free_rn(struct net_device *netdev) 901d4829ea6SVishwanathapura, Niranjana { 902d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 903d4829ea6SVishwanathapura, Niranjana 9042280740fSVishwanathapura, Niranjana hfi1_vnic_deinit(vinfo); 905d4829ea6SVishwanathapura, Niranjana mutex_destroy(&vinfo->lock); 906d4829ea6SVishwanathapura, Niranjana free_netdev(netdev); 907d4829ea6SVishwanathapura, Niranjana } 908