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 982250563eSMichael J. Ruhl hfi1_rcvctrl(uctxt->dd, rcvctrl_ops, uctxt); 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 int ret; 1102280740fSVishwanathapura, Niranjana 1112280740fSVishwanathapura, Niranjana if (dd->flags & HFI1_FROZEN) 1122280740fSVishwanathapura, Niranjana return -EIO; 1132280740fSVishwanathapura, Niranjana 114f2a3bc00SMichael J. Ruhl ret = hfi1_create_ctxtdata(dd->pport, dd->node, &uctxt); 115f2a3bc00SMichael J. Ruhl if (ret < 0) { 1162280740fSVishwanathapura, Niranjana dd_dev_err(dd, "Unable to create ctxtdata, failing open\n"); 1172280740fSVishwanathapura, Niranjana return -ENOMEM; 1182280740fSVishwanathapura, Niranjana } 1192280740fSVishwanathapura, Niranjana 1202280740fSVishwanathapura, Niranjana uctxt->flags = HFI1_CAP_KGET(MULTI_PKT_EGR) | 1212280740fSVishwanathapura, Niranjana HFI1_CAP_KGET(NODROP_RHQ_FULL) | 1222280740fSVishwanathapura, Niranjana HFI1_CAP_KGET(NODROP_EGR_FULL) | 1232280740fSVishwanathapura, Niranjana HFI1_CAP_KGET(DMA_RTAIL); 1242280740fSVishwanathapura, Niranjana uctxt->seq_cnt = 1; 1252280740fSVishwanathapura, Niranjana 1262280740fSVishwanathapura, Niranjana /* Allocate and enable a PIO send context */ 1272280740fSVishwanathapura, Niranjana uctxt->sc = sc_alloc(dd, SC_VNIC, uctxt->rcvhdrqentsize, 1282280740fSVishwanathapura, Niranjana uctxt->numa_id); 1292280740fSVishwanathapura, Niranjana 1302280740fSVishwanathapura, Niranjana ret = uctxt->sc ? 0 : -ENOMEM; 1312280740fSVishwanathapura, Niranjana if (ret) 1322280740fSVishwanathapura, Niranjana goto bail; 1332280740fSVishwanathapura, Niranjana 1342280740fSVishwanathapura, Niranjana dd_dev_dbg(dd, "allocated vnic send context %u(%u)\n", 1352280740fSVishwanathapura, Niranjana uctxt->sc->sw_index, uctxt->sc->hw_context); 1362280740fSVishwanathapura, Niranjana ret = sc_enable(uctxt->sc); 1372280740fSVishwanathapura, Niranjana if (ret) 1382280740fSVishwanathapura, Niranjana goto bail; 1392280740fSVishwanathapura, Niranjana 1402280740fSVishwanathapura, Niranjana if (dd->num_msix_entries) 1412280740fSVishwanathapura, Niranjana hfi1_set_vnic_msix_info(uctxt); 1422280740fSVishwanathapura, Niranjana 1432280740fSVishwanathapura, Niranjana hfi1_stats.sps_ctxts++; 1442280740fSVishwanathapura, Niranjana dd_dev_dbg(dd, "created vnic context %d\n", uctxt->ctxt); 1452280740fSVishwanathapura, Niranjana *vnic_ctxt = uctxt; 1462280740fSVishwanathapura, Niranjana 1472280740fSVishwanathapura, Niranjana return ret; 1482280740fSVishwanathapura, Niranjana bail: 149d295dbebSMichael J. Ruhl hfi1_free_ctxt(uctxt); 1502280740fSVishwanathapura, Niranjana dd_dev_dbg(dd, "vnic allocation failed. rc %d\n", ret); 1512280740fSVishwanathapura, Niranjana return ret; 1522280740fSVishwanathapura, Niranjana } 1532280740fSVishwanathapura, Niranjana 1542280740fSVishwanathapura, Niranjana static void deallocate_vnic_ctxt(struct hfi1_devdata *dd, 1552280740fSVishwanathapura, Niranjana struct hfi1_ctxtdata *uctxt) 1562280740fSVishwanathapura, Niranjana { 1572280740fSVishwanathapura, Niranjana dd_dev_dbg(dd, "closing vnic context %d\n", uctxt->ctxt); 1582280740fSVishwanathapura, Niranjana flush_wc(); 1592280740fSVishwanathapura, Niranjana 1602280740fSVishwanathapura, Niranjana if (dd->num_msix_entries) 1612280740fSVishwanathapura, Niranjana hfi1_reset_vnic_msix_info(uctxt); 1622280740fSVishwanathapura, Niranjana 1632280740fSVishwanathapura, Niranjana /* 1642280740fSVishwanathapura, Niranjana * Disable receive context and interrupt available, reset all 1652280740fSVishwanathapura, Niranjana * RcvCtxtCtrl bits to default values. 1662280740fSVishwanathapura, Niranjana */ 1672280740fSVishwanathapura, Niranjana hfi1_rcvctrl(dd, HFI1_RCVCTRL_CTXT_DIS | 1682280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_TIDFLOW_DIS | 1692280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_INTRAVAIL_DIS | 1702280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_ONE_PKT_EGR_DIS | 1712280740fSVishwanathapura, Niranjana HFI1_RCVCTRL_NO_RHQ_DROP_DIS | 1722250563eSMichael J. Ruhl HFI1_RCVCTRL_NO_EGR_DROP_DIS, uctxt); 1732280740fSVishwanathapura, Niranjana /* 1742280740fSVishwanathapura, Niranjana * VNIC contexts are allocated from user context pool. 1752280740fSVishwanathapura, Niranjana * Release them back to user context pool. 1762280740fSVishwanathapura, Niranjana * 1772280740fSVishwanathapura, Niranjana * Reset context integrity checks to default. 1782280740fSVishwanathapura, Niranjana * (writes to CSRs probably belong in chip.c) 1792280740fSVishwanathapura, Niranjana */ 1802280740fSVishwanathapura, Niranjana write_kctxt_csr(dd, uctxt->sc->hw_context, SEND_CTXT_CHECK_ENABLE, 1812280740fSVishwanathapura, Niranjana hfi1_pkt_default_send_ctxt_mask(dd, SC_USER)); 1822280740fSVishwanathapura, Niranjana sc_disable(uctxt->sc); 1832280740fSVishwanathapura, Niranjana 1842280740fSVishwanathapura, Niranjana dd->send_contexts[uctxt->sc->sw_index].type = SC_USER; 1852280740fSVishwanathapura, Niranjana 1862280740fSVishwanathapura, Niranjana uctxt->event_flags = 0; 1872280740fSVishwanathapura, Niranjana 1882280740fSVishwanathapura, Niranjana hfi1_clear_tids(uctxt); 189637a9a7fSMichael J. Ruhl hfi1_clear_ctxt_pkey(dd, uctxt); 1902280740fSVishwanathapura, Niranjana 1912280740fSVishwanathapura, Niranjana hfi1_stats.sps_ctxts--; 192f2a3bc00SMichael J. Ruhl 193d295dbebSMichael J. Ruhl hfi1_free_ctxt(uctxt); 1942280740fSVishwanathapura, Niranjana } 1952280740fSVishwanathapura, Niranjana 196d4829ea6SVishwanathapura, Niranjana void hfi1_vnic_setup(struct hfi1_devdata *dd) 197d4829ea6SVishwanathapura, Niranjana { 198d4829ea6SVishwanathapura, Niranjana idr_init(&dd->vnic.vesw_idr); 199d4829ea6SVishwanathapura, Niranjana } 200d4829ea6SVishwanathapura, Niranjana 201d4829ea6SVishwanathapura, Niranjana void hfi1_vnic_cleanup(struct hfi1_devdata *dd) 202d4829ea6SVishwanathapura, Niranjana { 203d4829ea6SVishwanathapura, Niranjana idr_destroy(&dd->vnic.vesw_idr); 204d4829ea6SVishwanathapura, Niranjana } 205d4829ea6SVishwanathapura, Niranjana 206d4829ea6SVishwanathapura, Niranjana #define SUM_GRP_COUNTERS(stats, qstats, x_grp) do { \ 207d4829ea6SVishwanathapura, Niranjana u64 *src64, *dst64; \ 208d4829ea6SVishwanathapura, Niranjana for (src64 = &qstats->x_grp.unicast, \ 209d4829ea6SVishwanathapura, Niranjana dst64 = &stats->x_grp.unicast; \ 210d4829ea6SVishwanathapura, Niranjana dst64 <= &stats->x_grp.s_1519_max;) { \ 211d4829ea6SVishwanathapura, Niranjana *dst64++ += *src64++; \ 212d4829ea6SVishwanathapura, Niranjana } \ 213d4829ea6SVishwanathapura, Niranjana } while (0) 214d4829ea6SVishwanathapura, Niranjana 215d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_update_stats - update statistics */ 216d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_update_stats(struct hfi1_vnic_vport_info *vinfo, 217d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *stats) 218d4829ea6SVishwanathapura, Niranjana { 219d4829ea6SVishwanathapura, Niranjana struct net_device *netdev = vinfo->netdev; 220d4829ea6SVishwanathapura, Niranjana u8 i; 221d4829ea6SVishwanathapura, Niranjana 222d4829ea6SVishwanathapura, Niranjana /* add tx counters on different queues */ 223d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_tx_q; i++) { 224d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *qstats = &vinfo->stats[i]; 225d4829ea6SVishwanathapura, Niranjana struct rtnl_link_stats64 *qnstats = &vinfo->stats[i].netstats; 226d4829ea6SVishwanathapura, Niranjana 227d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_fifo_errors += qnstats->tx_fifo_errors; 228d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_carrier_errors += qnstats->tx_carrier_errors; 229d4829ea6SVishwanathapura, Niranjana stats->tx_drop_state += qstats->tx_drop_state; 230d4829ea6SVishwanathapura, Niranjana stats->tx_dlid_zero += qstats->tx_dlid_zero; 231d4829ea6SVishwanathapura, Niranjana 232d4829ea6SVishwanathapura, Niranjana SUM_GRP_COUNTERS(stats, qstats, tx_grp); 233d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_packets += qnstats->tx_packets; 234d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_bytes += qnstats->tx_bytes; 235d4829ea6SVishwanathapura, Niranjana } 236d4829ea6SVishwanathapura, Niranjana 237d4829ea6SVishwanathapura, Niranjana /* add rx counters on different queues */ 238d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_rx_q; i++) { 239d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *qstats = &vinfo->stats[i]; 240d4829ea6SVishwanathapura, Niranjana struct rtnl_link_stats64 *qnstats = &vinfo->stats[i].netstats; 241d4829ea6SVishwanathapura, Niranjana 242d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_fifo_errors += qnstats->rx_fifo_errors; 243d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_nohandler += qnstats->rx_nohandler; 244d4829ea6SVishwanathapura, Niranjana stats->rx_drop_state += qstats->rx_drop_state; 245d4829ea6SVishwanathapura, Niranjana stats->rx_oversize += qstats->rx_oversize; 246d4829ea6SVishwanathapura, Niranjana stats->rx_runt += qstats->rx_runt; 247d4829ea6SVishwanathapura, Niranjana 248d4829ea6SVishwanathapura, Niranjana SUM_GRP_COUNTERS(stats, qstats, rx_grp); 249d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_packets += qnstats->rx_packets; 250d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_bytes += qnstats->rx_bytes; 251d4829ea6SVishwanathapura, Niranjana } 252d4829ea6SVishwanathapura, Niranjana 253d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_errors = stats->netstats.tx_fifo_errors + 254d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_carrier_errors + 255d4829ea6SVishwanathapura, Niranjana stats->tx_drop_state + stats->tx_dlid_zero; 256d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_dropped = stats->netstats.tx_errors; 257d4829ea6SVishwanathapura, Niranjana 258d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_errors = stats->netstats.rx_fifo_errors + 259d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_nohandler + 260d4829ea6SVishwanathapura, Niranjana stats->rx_drop_state + stats->rx_oversize + 261d4829ea6SVishwanathapura, Niranjana stats->rx_runt; 262d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_dropped = stats->netstats.rx_errors; 263d4829ea6SVishwanathapura, Niranjana 264d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_packets = stats->netstats.tx_packets; 265d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_bytes = stats->netstats.tx_bytes; 266d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_fifo_errors = stats->netstats.tx_fifo_errors; 267d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_carrier_errors = stats->netstats.tx_carrier_errors; 268d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_errors = stats->netstats.tx_errors; 269d4829ea6SVishwanathapura, Niranjana netdev->stats.tx_dropped = stats->netstats.tx_dropped; 270d4829ea6SVishwanathapura, Niranjana 271d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_packets = stats->netstats.rx_packets; 272d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_bytes = stats->netstats.rx_bytes; 273d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_fifo_errors = stats->netstats.rx_fifo_errors; 274d4829ea6SVishwanathapura, Niranjana netdev->stats.multicast = stats->rx_grp.mcastbcast; 275d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_length_errors = stats->rx_oversize + stats->rx_runt; 276d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_errors = stats->netstats.rx_errors; 277d4829ea6SVishwanathapura, Niranjana netdev->stats.rx_dropped = stats->netstats.rx_dropped; 278d4829ea6SVishwanathapura, Niranjana } 279d4829ea6SVishwanathapura, Niranjana 280d4829ea6SVishwanathapura, Niranjana /* update_len_counters - update pkt's len histogram counters */ 281d4829ea6SVishwanathapura, Niranjana static inline void update_len_counters(struct opa_vnic_grp_stats *grp, 282d4829ea6SVishwanathapura, Niranjana int len) 283d4829ea6SVishwanathapura, Niranjana { 284d4829ea6SVishwanathapura, Niranjana /* account for 4 byte FCS */ 285d4829ea6SVishwanathapura, Niranjana if (len >= 1515) 286d4829ea6SVishwanathapura, Niranjana grp->s_1519_max++; 287d4829ea6SVishwanathapura, Niranjana else if (len >= 1020) 288d4829ea6SVishwanathapura, Niranjana grp->s_1024_1518++; 289d4829ea6SVishwanathapura, Niranjana else if (len >= 508) 290d4829ea6SVishwanathapura, Niranjana grp->s_512_1023++; 291d4829ea6SVishwanathapura, Niranjana else if (len >= 252) 292d4829ea6SVishwanathapura, Niranjana grp->s_256_511++; 293d4829ea6SVishwanathapura, Niranjana else if (len >= 124) 294d4829ea6SVishwanathapura, Niranjana grp->s_128_255++; 295d4829ea6SVishwanathapura, Niranjana else if (len >= 61) 296d4829ea6SVishwanathapura, Niranjana grp->s_65_127++; 297d4829ea6SVishwanathapura, Niranjana else 298d4829ea6SVishwanathapura, Niranjana grp->s_64++; 299d4829ea6SVishwanathapura, Niranjana } 300d4829ea6SVishwanathapura, Niranjana 301d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_update_tx_counters - update transmit counters */ 302d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_update_tx_counters(struct hfi1_vnic_vport_info *vinfo, 303d4829ea6SVishwanathapura, Niranjana u8 q_idx, struct sk_buff *skb, int err) 304d4829ea6SVishwanathapura, Niranjana { 305d4829ea6SVishwanathapura, Niranjana struct ethhdr *mac_hdr = (struct ethhdr *)skb_mac_header(skb); 306d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *stats = &vinfo->stats[q_idx]; 307d4829ea6SVishwanathapura, Niranjana struct opa_vnic_grp_stats *tx_grp = &stats->tx_grp; 308d4829ea6SVishwanathapura, Niranjana u16 vlan_tci; 309d4829ea6SVishwanathapura, Niranjana 310d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_packets++; 311d4829ea6SVishwanathapura, Niranjana stats->netstats.tx_bytes += skb->len + ETH_FCS_LEN; 312d4829ea6SVishwanathapura, Niranjana 313d4829ea6SVishwanathapura, Niranjana update_len_counters(tx_grp, skb->len); 314d4829ea6SVishwanathapura, Niranjana 315d4829ea6SVishwanathapura, Niranjana /* rest of the counts are for good packets only */ 316d4829ea6SVishwanathapura, Niranjana if (unlikely(err)) 317d4829ea6SVishwanathapura, Niranjana return; 318d4829ea6SVishwanathapura, Niranjana 319d4829ea6SVishwanathapura, Niranjana if (is_multicast_ether_addr(mac_hdr->h_dest)) 320d4829ea6SVishwanathapura, Niranjana tx_grp->mcastbcast++; 321d4829ea6SVishwanathapura, Niranjana else 322d4829ea6SVishwanathapura, Niranjana tx_grp->unicast++; 323d4829ea6SVishwanathapura, Niranjana 324d4829ea6SVishwanathapura, Niranjana if (!__vlan_get_tag(skb, &vlan_tci)) 325d4829ea6SVishwanathapura, Niranjana tx_grp->vlan++; 326d4829ea6SVishwanathapura, Niranjana else 327d4829ea6SVishwanathapura, Niranjana tx_grp->untagged++; 328d4829ea6SVishwanathapura, Niranjana } 329d4829ea6SVishwanathapura, Niranjana 330d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_update_rx_counters - update receive counters */ 331d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_update_rx_counters(struct hfi1_vnic_vport_info *vinfo, 332d4829ea6SVishwanathapura, Niranjana u8 q_idx, struct sk_buff *skb, int err) 333d4829ea6SVishwanathapura, Niranjana { 334d4829ea6SVishwanathapura, Niranjana struct ethhdr *mac_hdr = (struct ethhdr *)skb->data; 335d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *stats = &vinfo->stats[q_idx]; 336d4829ea6SVishwanathapura, Niranjana struct opa_vnic_grp_stats *rx_grp = &stats->rx_grp; 337d4829ea6SVishwanathapura, Niranjana u16 vlan_tci; 338d4829ea6SVishwanathapura, Niranjana 339d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_packets++; 340d4829ea6SVishwanathapura, Niranjana stats->netstats.rx_bytes += skb->len + ETH_FCS_LEN; 341d4829ea6SVishwanathapura, Niranjana 342d4829ea6SVishwanathapura, Niranjana update_len_counters(rx_grp, skb->len); 343d4829ea6SVishwanathapura, Niranjana 344d4829ea6SVishwanathapura, Niranjana /* rest of the counts are for good packets only */ 345d4829ea6SVishwanathapura, Niranjana if (unlikely(err)) 346d4829ea6SVishwanathapura, Niranjana return; 347d4829ea6SVishwanathapura, Niranjana 348d4829ea6SVishwanathapura, Niranjana if (is_multicast_ether_addr(mac_hdr->h_dest)) 349d4829ea6SVishwanathapura, Niranjana rx_grp->mcastbcast++; 350d4829ea6SVishwanathapura, Niranjana else 351d4829ea6SVishwanathapura, Niranjana rx_grp->unicast++; 352d4829ea6SVishwanathapura, Niranjana 353d4829ea6SVishwanathapura, Niranjana if (!__vlan_get_tag(skb, &vlan_tci)) 354d4829ea6SVishwanathapura, Niranjana rx_grp->vlan++; 355d4829ea6SVishwanathapura, Niranjana else 356d4829ea6SVishwanathapura, Niranjana rx_grp->untagged++; 357d4829ea6SVishwanathapura, Niranjana } 358d4829ea6SVishwanathapura, Niranjana 359d4829ea6SVishwanathapura, Niranjana /* This function is overloaded for opa_vnic specific implementation */ 360d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_get_stats64(struct net_device *netdev, 361d4829ea6SVishwanathapura, Niranjana struct rtnl_link_stats64 *stats) 362d4829ea6SVishwanathapura, Niranjana { 363d4829ea6SVishwanathapura, Niranjana struct opa_vnic_stats *vstats = (struct opa_vnic_stats *)stats; 364d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 365d4829ea6SVishwanathapura, Niranjana 366d4829ea6SVishwanathapura, Niranjana hfi1_vnic_update_stats(vinfo, vstats); 367d4829ea6SVishwanathapura, Niranjana } 368d4829ea6SVishwanathapura, Niranjana 369d4829ea6SVishwanathapura, Niranjana static u64 create_bypass_pbc(u32 vl, u32 dw_len) 370d4829ea6SVishwanathapura, Niranjana { 371d4829ea6SVishwanathapura, Niranjana u64 pbc; 372d4829ea6SVishwanathapura, Niranjana 373d4829ea6SVishwanathapura, Niranjana pbc = ((u64)PBC_IHCRC_NONE << PBC_INSERT_HCRC_SHIFT) 374d4829ea6SVishwanathapura, Niranjana | PBC_INSERT_BYPASS_ICRC | PBC_CREDIT_RETURN 375d4829ea6SVishwanathapura, Niranjana | PBC_PACKET_BYPASS 376d4829ea6SVishwanathapura, Niranjana | ((vl & PBC_VL_MASK) << PBC_VL_SHIFT) 377d4829ea6SVishwanathapura, Niranjana | (dw_len & PBC_LENGTH_DWS_MASK) << PBC_LENGTH_DWS_SHIFT; 378d4829ea6SVishwanathapura, Niranjana 379d4829ea6SVishwanathapura, Niranjana return pbc; 380d4829ea6SVishwanathapura, Niranjana } 381d4829ea6SVishwanathapura, Niranjana 382d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_maybe_stop_tx - stop tx queue if required */ 383d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_maybe_stop_tx(struct hfi1_vnic_vport_info *vinfo, 384d4829ea6SVishwanathapura, Niranjana u8 q_idx) 385d4829ea6SVishwanathapura, Niranjana { 386d4829ea6SVishwanathapura, Niranjana netif_stop_subqueue(vinfo->netdev, q_idx); 38764551edeSVishwanathapura, Niranjana if (!hfi1_vnic_sdma_write_avail(vinfo, q_idx)) 38864551edeSVishwanathapura, Niranjana return; 38964551edeSVishwanathapura, Niranjana 39064551edeSVishwanathapura, Niranjana netif_start_subqueue(vinfo->netdev, q_idx); 391d4829ea6SVishwanathapura, Niranjana } 392d4829ea6SVishwanathapura, Niranjana 393d4829ea6SVishwanathapura, Niranjana static netdev_tx_t hfi1_netdev_start_xmit(struct sk_buff *skb, 394d4829ea6SVishwanathapura, Niranjana struct net_device *netdev) 395d4829ea6SVishwanathapura, Niranjana { 396d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 397d4829ea6SVishwanathapura, Niranjana u8 pad_len, q_idx = skb->queue_mapping; 398d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 399d4829ea6SVishwanathapura, Niranjana struct opa_vnic_skb_mdata *mdata; 400d4829ea6SVishwanathapura, Niranjana u32 pkt_len, total_len; 401d4829ea6SVishwanathapura, Niranjana int err = -EINVAL; 402d4829ea6SVishwanathapura, Niranjana u64 pbc; 403d4829ea6SVishwanathapura, Niranjana 404d4829ea6SVishwanathapura, Niranjana v_dbg("xmit: queue %d skb len %d\n", q_idx, skb->len); 405d4829ea6SVishwanathapura, Niranjana if (unlikely(!netif_oper_up(netdev))) { 406d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].tx_drop_state++; 407d4829ea6SVishwanathapura, Niranjana goto tx_finish; 408d4829ea6SVishwanathapura, Niranjana } 409d4829ea6SVishwanathapura, Niranjana 410d4829ea6SVishwanathapura, Niranjana /* take out meta data */ 411d4829ea6SVishwanathapura, Niranjana mdata = (struct opa_vnic_skb_mdata *)skb->data; 412d4829ea6SVishwanathapura, Niranjana skb_pull(skb, sizeof(*mdata)); 413d4829ea6SVishwanathapura, Niranjana if (unlikely(mdata->flags & OPA_VNIC_SKB_MDATA_ENCAP_ERR)) { 414d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].tx_dlid_zero++; 415d4829ea6SVishwanathapura, Niranjana goto tx_finish; 416d4829ea6SVishwanathapura, Niranjana } 417d4829ea6SVishwanathapura, Niranjana 418d4829ea6SVishwanathapura, Niranjana /* add tail padding (for 8 bytes size alignment) and icrc */ 419d4829ea6SVishwanathapura, Niranjana pad_len = -(skb->len + OPA_VNIC_ICRC_TAIL_LEN) & 0x7; 420d4829ea6SVishwanathapura, Niranjana pad_len += OPA_VNIC_ICRC_TAIL_LEN; 421d4829ea6SVishwanathapura, Niranjana 422d4829ea6SVishwanathapura, Niranjana /* 423d4829ea6SVishwanathapura, Niranjana * pkt_len is how much data we have to write, includes header and data. 424d4829ea6SVishwanathapura, Niranjana * total_len is length of the packet in Dwords plus the PBC should not 425d4829ea6SVishwanathapura, Niranjana * include the CRC. 426d4829ea6SVishwanathapura, Niranjana */ 427d4829ea6SVishwanathapura, Niranjana pkt_len = (skb->len + pad_len) >> 2; 428d4829ea6SVishwanathapura, Niranjana total_len = pkt_len + 2; /* PBC + packet */ 429d4829ea6SVishwanathapura, Niranjana 430d4829ea6SVishwanathapura, Niranjana pbc = create_bypass_pbc(mdata->vl, total_len); 431d4829ea6SVishwanathapura, Niranjana 432d4829ea6SVishwanathapura, Niranjana skb_get(skb); 433d4829ea6SVishwanathapura, Niranjana v_dbg("pbc 0x%016llX len %d pad_len %d\n", pbc, skb->len, pad_len); 434d4829ea6SVishwanathapura, Niranjana err = dd->process_vnic_dma_send(dd, q_idx, vinfo, skb, pbc, pad_len); 435d4829ea6SVishwanathapura, Niranjana if (unlikely(err)) { 436d4829ea6SVishwanathapura, Niranjana if (err == -ENOMEM) 437d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].netstats.tx_fifo_errors++; 438d4829ea6SVishwanathapura, Niranjana else if (err != -EBUSY) 439d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].netstats.tx_carrier_errors++; 440d4829ea6SVishwanathapura, Niranjana } 441d4829ea6SVishwanathapura, Niranjana /* remove the header before updating tx counters */ 442d4829ea6SVishwanathapura, Niranjana skb_pull(skb, OPA_VNIC_HDR_LEN); 443d4829ea6SVishwanathapura, Niranjana 444d4829ea6SVishwanathapura, Niranjana if (unlikely(err == -EBUSY)) { 445d4829ea6SVishwanathapura, Niranjana hfi1_vnic_maybe_stop_tx(vinfo, q_idx); 446d4829ea6SVishwanathapura, Niranjana dev_kfree_skb_any(skb); 447d4829ea6SVishwanathapura, Niranjana return NETDEV_TX_BUSY; 448d4829ea6SVishwanathapura, Niranjana } 449d4829ea6SVishwanathapura, Niranjana 450d4829ea6SVishwanathapura, Niranjana tx_finish: 451d4829ea6SVishwanathapura, Niranjana /* update tx counters */ 452d4829ea6SVishwanathapura, Niranjana hfi1_vnic_update_tx_counters(vinfo, q_idx, skb, err); 453d4829ea6SVishwanathapura, Niranjana dev_kfree_skb_any(skb); 454d4829ea6SVishwanathapura, Niranjana return NETDEV_TX_OK; 455d4829ea6SVishwanathapura, Niranjana } 456d4829ea6SVishwanathapura, Niranjana 457d4829ea6SVishwanathapura, Niranjana static u16 hfi1_vnic_select_queue(struct net_device *netdev, 458d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb, 459d4829ea6SVishwanathapura, Niranjana void *accel_priv, 460d4829ea6SVishwanathapura, Niranjana select_queue_fallback_t fallback) 461d4829ea6SVishwanathapura, Niranjana { 46264551edeSVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 46364551edeSVishwanathapura, Niranjana struct opa_vnic_skb_mdata *mdata; 46464551edeSVishwanathapura, Niranjana struct sdma_engine *sde; 46564551edeSVishwanathapura, Niranjana 46664551edeSVishwanathapura, Niranjana mdata = (struct opa_vnic_skb_mdata *)skb->data; 46764551edeSVishwanathapura, Niranjana sde = sdma_select_engine_vl(vinfo->dd, mdata->entropy, mdata->vl); 46864551edeSVishwanathapura, Niranjana return sde->this_idx; 469d4829ea6SVishwanathapura, Niranjana } 470d4829ea6SVishwanathapura, Niranjana 471d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_decap_skb - strip OPA header from the skb (ethernet) packet */ 472d4829ea6SVishwanathapura, Niranjana static inline int hfi1_vnic_decap_skb(struct hfi1_vnic_rx_queue *rxq, 473d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb) 474d4829ea6SVishwanathapura, Niranjana { 475d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = rxq->vinfo; 476d4829ea6SVishwanathapura, Niranjana int max_len = vinfo->netdev->mtu + VLAN_ETH_HLEN; 477d4829ea6SVishwanathapura, Niranjana int rc = -EFAULT; 478d4829ea6SVishwanathapura, Niranjana 479d4829ea6SVishwanathapura, Niranjana skb_pull(skb, OPA_VNIC_HDR_LEN); 480d4829ea6SVishwanathapura, Niranjana 481d4829ea6SVishwanathapura, Niranjana /* Validate Packet length */ 482d4829ea6SVishwanathapura, Niranjana if (unlikely(skb->len > max_len)) 483d4829ea6SVishwanathapura, Niranjana vinfo->stats[rxq->idx].rx_oversize++; 484d4829ea6SVishwanathapura, Niranjana else if (unlikely(skb->len < ETH_ZLEN)) 485d4829ea6SVishwanathapura, Niranjana vinfo->stats[rxq->idx].rx_runt++; 486d4829ea6SVishwanathapura, Niranjana else 487d4829ea6SVishwanathapura, Niranjana rc = 0; 488d4829ea6SVishwanathapura, Niranjana return rc; 489d4829ea6SVishwanathapura, Niranjana } 490d4829ea6SVishwanathapura, Niranjana 491d4829ea6SVishwanathapura, Niranjana static inline struct sk_buff *hfi1_vnic_get_skb(struct hfi1_vnic_rx_queue *rxq) 492d4829ea6SVishwanathapura, Niranjana { 493d4829ea6SVishwanathapura, Niranjana unsigned char *pad_info; 494d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb; 495d4829ea6SVishwanathapura, Niranjana 496d4829ea6SVishwanathapura, Niranjana skb = skb_dequeue(&rxq->skbq); 497d4829ea6SVishwanathapura, Niranjana if (unlikely(!skb)) 498d4829ea6SVishwanathapura, Niranjana return NULL; 499d4829ea6SVishwanathapura, Niranjana 500d4829ea6SVishwanathapura, Niranjana /* remove tail padding and icrc */ 501d4829ea6SVishwanathapura, Niranjana pad_info = skb->data + skb->len - 1; 502d4829ea6SVishwanathapura, Niranjana skb_trim(skb, (skb->len - OPA_VNIC_ICRC_TAIL_LEN - 503d4829ea6SVishwanathapura, Niranjana ((*pad_info) & 0x7))); 504d4829ea6SVishwanathapura, Niranjana 505d4829ea6SVishwanathapura, Niranjana return skb; 506d4829ea6SVishwanathapura, Niranjana } 507d4829ea6SVishwanathapura, Niranjana 508d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_handle_rx - handle skb receive */ 509d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_handle_rx(struct hfi1_vnic_rx_queue *rxq, 510d4829ea6SVishwanathapura, Niranjana int *work_done, int work_to_do) 511d4829ea6SVishwanathapura, Niranjana { 512d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = rxq->vinfo; 513d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb; 514d4829ea6SVishwanathapura, Niranjana int rc; 515d4829ea6SVishwanathapura, Niranjana 516d4829ea6SVishwanathapura, Niranjana while (1) { 517d4829ea6SVishwanathapura, Niranjana if (*work_done >= work_to_do) 518d4829ea6SVishwanathapura, Niranjana break; 519d4829ea6SVishwanathapura, Niranjana 520d4829ea6SVishwanathapura, Niranjana skb = hfi1_vnic_get_skb(rxq); 521d4829ea6SVishwanathapura, Niranjana if (unlikely(!skb)) 522d4829ea6SVishwanathapura, Niranjana break; 523d4829ea6SVishwanathapura, Niranjana 524d4829ea6SVishwanathapura, Niranjana rc = hfi1_vnic_decap_skb(rxq, skb); 525d4829ea6SVishwanathapura, Niranjana /* update rx counters */ 526d4829ea6SVishwanathapura, Niranjana hfi1_vnic_update_rx_counters(vinfo, rxq->idx, skb, rc); 527d4829ea6SVishwanathapura, Niranjana if (unlikely(rc)) { 528d4829ea6SVishwanathapura, Niranjana dev_kfree_skb_any(skb); 529d4829ea6SVishwanathapura, Niranjana continue; 530d4829ea6SVishwanathapura, Niranjana } 531d4829ea6SVishwanathapura, Niranjana 532d4829ea6SVishwanathapura, Niranjana skb_checksum_none_assert(skb); 533d4829ea6SVishwanathapura, Niranjana skb->protocol = eth_type_trans(skb, rxq->netdev); 534d4829ea6SVishwanathapura, Niranjana 535d4829ea6SVishwanathapura, Niranjana napi_gro_receive(&rxq->napi, skb); 536d4829ea6SVishwanathapura, Niranjana (*work_done)++; 537d4829ea6SVishwanathapura, Niranjana } 538d4829ea6SVishwanathapura, Niranjana } 539d4829ea6SVishwanathapura, Niranjana 540d4829ea6SVishwanathapura, Niranjana /* hfi1_vnic_napi - napi receive polling callback function */ 541d4829ea6SVishwanathapura, Niranjana static int hfi1_vnic_napi(struct napi_struct *napi, int budget) 542d4829ea6SVishwanathapura, Niranjana { 543d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq = container_of(napi, 544d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue, napi); 545d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = rxq->vinfo; 546d4829ea6SVishwanathapura, Niranjana int work_done = 0; 547d4829ea6SVishwanathapura, Niranjana 548d4829ea6SVishwanathapura, Niranjana v_dbg("napi %d budget %d\n", rxq->idx, budget); 549d4829ea6SVishwanathapura, Niranjana hfi1_vnic_handle_rx(rxq, &work_done, budget); 550d4829ea6SVishwanathapura, Niranjana 551d4829ea6SVishwanathapura, Niranjana v_dbg("napi %d work_done %d\n", rxq->idx, work_done); 552d4829ea6SVishwanathapura, Niranjana if (work_done < budget) 553d4829ea6SVishwanathapura, Niranjana napi_complete(napi); 554d4829ea6SVishwanathapura, Niranjana 555d4829ea6SVishwanathapura, Niranjana return work_done; 556d4829ea6SVishwanathapura, Niranjana } 557d4829ea6SVishwanathapura, Niranjana 558d4829ea6SVishwanathapura, Niranjana void hfi1_vnic_bypass_rcv(struct hfi1_packet *packet) 559d4829ea6SVishwanathapura, Niranjana { 560d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = packet->rcd->dd; 561d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = NULL; 562d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq; 563d4829ea6SVishwanathapura, Niranjana struct sk_buff *skb; 564d4829ea6SVishwanathapura, Niranjana int l4_type, vesw_id = -1; 565d4829ea6SVishwanathapura, Niranjana u8 q_idx; 566d4829ea6SVishwanathapura, Niranjana 56772c07e2bSDon Hiatt l4_type = hfi1_16B_get_l4(packet->ebuf); 56872c07e2bSDon Hiatt if (likely(l4_type == OPA_16B_L4_ETHR)) { 569d4829ea6SVishwanathapura, Niranjana vesw_id = HFI1_VNIC_GET_VESWID(packet->ebuf); 570d4829ea6SVishwanathapura, Niranjana vinfo = idr_find(&dd->vnic.vesw_idr, vesw_id); 571d4829ea6SVishwanathapura, Niranjana 572d4829ea6SVishwanathapura, Niranjana /* 573d4829ea6SVishwanathapura, Niranjana * In case of invalid vesw id, count the error on 574d4829ea6SVishwanathapura, Niranjana * the first available vport. 575d4829ea6SVishwanathapura, Niranjana */ 576d4829ea6SVishwanathapura, Niranjana if (unlikely(!vinfo)) { 577d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo_tmp; 578d4829ea6SVishwanathapura, Niranjana int id_tmp = 0; 579d4829ea6SVishwanathapura, Niranjana 580d4829ea6SVishwanathapura, Niranjana vinfo_tmp = idr_get_next(&dd->vnic.vesw_idr, &id_tmp); 581d4829ea6SVishwanathapura, Niranjana if (vinfo_tmp) { 582d4829ea6SVishwanathapura, Niranjana spin_lock(&vport_cntr_lock); 583d4829ea6SVishwanathapura, Niranjana vinfo_tmp->stats[0].netstats.rx_nohandler++; 584d4829ea6SVishwanathapura, Niranjana spin_unlock(&vport_cntr_lock); 585d4829ea6SVishwanathapura, Niranjana } 586d4829ea6SVishwanathapura, Niranjana } 587d4829ea6SVishwanathapura, Niranjana } 588d4829ea6SVishwanathapura, Niranjana 589d4829ea6SVishwanathapura, Niranjana if (unlikely(!vinfo)) { 590d4829ea6SVishwanathapura, Niranjana dd_dev_warn(dd, "vnic rcv err: l4 %d vesw id %d ctx %d\n", 591d4829ea6SVishwanathapura, Niranjana l4_type, vesw_id, packet->rcd->ctxt); 592d4829ea6SVishwanathapura, Niranjana return; 593d4829ea6SVishwanathapura, Niranjana } 594d4829ea6SVishwanathapura, Niranjana 595d4829ea6SVishwanathapura, Niranjana q_idx = packet->rcd->vnic_q_idx; 596d4829ea6SVishwanathapura, Niranjana rxq = &vinfo->rxq[q_idx]; 597d4829ea6SVishwanathapura, Niranjana if (unlikely(!netif_oper_up(vinfo->netdev))) { 598d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].rx_drop_state++; 599d4829ea6SVishwanathapura, Niranjana skb_queue_purge(&rxq->skbq); 600d4829ea6SVishwanathapura, Niranjana return; 601d4829ea6SVishwanathapura, Niranjana } 602d4829ea6SVishwanathapura, Niranjana 603d4829ea6SVishwanathapura, Niranjana if (unlikely(skb_queue_len(&rxq->skbq) > HFI1_VNIC_RCV_Q_SIZE)) { 604d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].netstats.rx_fifo_errors++; 605d4829ea6SVishwanathapura, Niranjana return; 606d4829ea6SVishwanathapura, Niranjana } 607d4829ea6SVishwanathapura, Niranjana 608d4829ea6SVishwanathapura, Niranjana skb = netdev_alloc_skb(vinfo->netdev, packet->tlen); 609d4829ea6SVishwanathapura, Niranjana if (unlikely(!skb)) { 610d4829ea6SVishwanathapura, Niranjana vinfo->stats[q_idx].netstats.rx_fifo_errors++; 611d4829ea6SVishwanathapura, Niranjana return; 612d4829ea6SVishwanathapura, Niranjana } 613d4829ea6SVishwanathapura, Niranjana 614d4829ea6SVishwanathapura, Niranjana memcpy(skb->data, packet->ebuf, packet->tlen); 615d4829ea6SVishwanathapura, Niranjana skb_put(skb, packet->tlen); 616d4829ea6SVishwanathapura, Niranjana skb_queue_tail(&rxq->skbq, skb); 617d4829ea6SVishwanathapura, Niranjana 618d4829ea6SVishwanathapura, Niranjana if (napi_schedule_prep(&rxq->napi)) { 619d4829ea6SVishwanathapura, Niranjana v_dbg("napi %d scheduling\n", q_idx); 620d4829ea6SVishwanathapura, Niranjana __napi_schedule(&rxq->napi); 621d4829ea6SVishwanathapura, Niranjana } 622d4829ea6SVishwanathapura, Niranjana } 623d4829ea6SVishwanathapura, Niranjana 624d4829ea6SVishwanathapura, Niranjana static int hfi1_vnic_up(struct hfi1_vnic_vport_info *vinfo) 625d4829ea6SVishwanathapura, Niranjana { 626d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 627d4829ea6SVishwanathapura, Niranjana struct net_device *netdev = vinfo->netdev; 628d4829ea6SVishwanathapura, Niranjana int i, rc; 629d4829ea6SVishwanathapura, Niranjana 630d4829ea6SVishwanathapura, Niranjana /* ensure virtual eth switch id is valid */ 631d4829ea6SVishwanathapura, Niranjana if (!vinfo->vesw_id) 632d4829ea6SVishwanathapura, Niranjana return -EINVAL; 633d4829ea6SVishwanathapura, Niranjana 634d4829ea6SVishwanathapura, Niranjana rc = idr_alloc(&dd->vnic.vesw_idr, vinfo, vinfo->vesw_id, 635d4829ea6SVishwanathapura, Niranjana vinfo->vesw_id + 1, GFP_NOWAIT); 636d4829ea6SVishwanathapura, Niranjana if (rc < 0) 637d4829ea6SVishwanathapura, Niranjana return rc; 638d4829ea6SVishwanathapura, Niranjana 639d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_rx_q; i++) { 640d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq = &vinfo->rxq[i]; 641d4829ea6SVishwanathapura, Niranjana 642d4829ea6SVishwanathapura, Niranjana skb_queue_head_init(&rxq->skbq); 643d4829ea6SVishwanathapura, Niranjana napi_enable(&rxq->napi); 644d4829ea6SVishwanathapura, Niranjana } 645d4829ea6SVishwanathapura, Niranjana 646d4829ea6SVishwanathapura, Niranjana netif_carrier_on(netdev); 647d4829ea6SVishwanathapura, Niranjana netif_tx_start_all_queues(netdev); 648d4829ea6SVishwanathapura, Niranjana set_bit(HFI1_VNIC_UP, &vinfo->flags); 649d4829ea6SVishwanathapura, Niranjana 650d4829ea6SVishwanathapura, Niranjana return 0; 651d4829ea6SVishwanathapura, Niranjana } 652d4829ea6SVishwanathapura, Niranjana 653d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_down(struct hfi1_vnic_vport_info *vinfo) 654d4829ea6SVishwanathapura, Niranjana { 655d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 656d4829ea6SVishwanathapura, Niranjana u8 i; 657d4829ea6SVishwanathapura, Niranjana 658d4829ea6SVishwanathapura, Niranjana clear_bit(HFI1_VNIC_UP, &vinfo->flags); 659d4829ea6SVishwanathapura, Niranjana netif_carrier_off(vinfo->netdev); 660d4829ea6SVishwanathapura, Niranjana netif_tx_disable(vinfo->netdev); 661d4829ea6SVishwanathapura, Niranjana idr_remove(&dd->vnic.vesw_idr, vinfo->vesw_id); 662d4829ea6SVishwanathapura, Niranjana 6632280740fSVishwanathapura, Niranjana /* ensure irqs see the change */ 6642280740fSVishwanathapura, Niranjana hfi1_vnic_synchronize_irq(dd); 6652280740fSVishwanathapura, Niranjana 666d4829ea6SVishwanathapura, Niranjana /* remove unread skbs */ 667d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_rx_q; i++) { 668d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq = &vinfo->rxq[i]; 669d4829ea6SVishwanathapura, Niranjana 670d4829ea6SVishwanathapura, Niranjana napi_disable(&rxq->napi); 671d4829ea6SVishwanathapura, Niranjana skb_queue_purge(&rxq->skbq); 672d4829ea6SVishwanathapura, Niranjana } 673d4829ea6SVishwanathapura, Niranjana } 674d4829ea6SVishwanathapura, Niranjana 675d4829ea6SVishwanathapura, Niranjana static int hfi1_netdev_open(struct net_device *netdev) 676d4829ea6SVishwanathapura, Niranjana { 677d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 678d4829ea6SVishwanathapura, Niranjana int rc; 679d4829ea6SVishwanathapura, Niranjana 680d4829ea6SVishwanathapura, Niranjana mutex_lock(&vinfo->lock); 681d4829ea6SVishwanathapura, Niranjana rc = hfi1_vnic_up(vinfo); 682d4829ea6SVishwanathapura, Niranjana mutex_unlock(&vinfo->lock); 683d4829ea6SVishwanathapura, Niranjana return rc; 684d4829ea6SVishwanathapura, Niranjana } 685d4829ea6SVishwanathapura, Niranjana 686d4829ea6SVishwanathapura, Niranjana static int hfi1_netdev_close(struct net_device *netdev) 687d4829ea6SVishwanathapura, Niranjana { 688d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 689d4829ea6SVishwanathapura, Niranjana 690d4829ea6SVishwanathapura, Niranjana mutex_lock(&vinfo->lock); 691d4829ea6SVishwanathapura, Niranjana if (test_bit(HFI1_VNIC_UP, &vinfo->flags)) 692d4829ea6SVishwanathapura, Niranjana hfi1_vnic_down(vinfo); 693d4829ea6SVishwanathapura, Niranjana mutex_unlock(&vinfo->lock); 694d4829ea6SVishwanathapura, Niranjana return 0; 695d4829ea6SVishwanathapura, Niranjana } 696d4829ea6SVishwanathapura, Niranjana 6972280740fSVishwanathapura, Niranjana static int hfi1_vnic_allot_ctxt(struct hfi1_devdata *dd, 6982280740fSVishwanathapura, Niranjana struct hfi1_ctxtdata **vnic_ctxt) 6992280740fSVishwanathapura, Niranjana { 7002280740fSVishwanathapura, Niranjana int rc; 7012280740fSVishwanathapura, Niranjana 7022280740fSVishwanathapura, Niranjana rc = allocate_vnic_ctxt(dd, vnic_ctxt); 7032280740fSVishwanathapura, Niranjana if (rc) { 7042280740fSVishwanathapura, Niranjana dd_dev_err(dd, "vnic ctxt alloc failed %d\n", rc); 7052280740fSVishwanathapura, Niranjana return rc; 7062280740fSVishwanathapura, Niranjana } 7072280740fSVishwanathapura, Niranjana 7082280740fSVishwanathapura, Niranjana rc = setup_vnic_ctxt(dd, *vnic_ctxt); 7092280740fSVishwanathapura, Niranjana if (rc) { 7102280740fSVishwanathapura, Niranjana dd_dev_err(dd, "vnic ctxt setup failed %d\n", rc); 7112280740fSVishwanathapura, Niranjana deallocate_vnic_ctxt(dd, *vnic_ctxt); 7122280740fSVishwanathapura, Niranjana *vnic_ctxt = NULL; 7132280740fSVishwanathapura, Niranjana } 7142280740fSVishwanathapura, Niranjana 7152280740fSVishwanathapura, Niranjana return rc; 7162280740fSVishwanathapura, Niranjana } 7172280740fSVishwanathapura, Niranjana 7182280740fSVishwanathapura, Niranjana static int hfi1_vnic_init(struct hfi1_vnic_vport_info *vinfo) 7192280740fSVishwanathapura, Niranjana { 7202280740fSVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 7212280740fSVishwanathapura, Niranjana int i, rc = 0; 7222280740fSVishwanathapura, Niranjana 7232280740fSVishwanathapura, Niranjana mutex_lock(&hfi1_mutex); 72464551edeSVishwanathapura, Niranjana if (!dd->vnic.num_vports) { 72564551edeSVishwanathapura, Niranjana rc = hfi1_vnic_txreq_init(dd); 72664551edeSVishwanathapura, Niranjana if (rc) 72764551edeSVishwanathapura, Niranjana goto txreq_fail; 72864551edeSVishwanathapura, Niranjana 7292280740fSVishwanathapura, Niranjana dd->vnic.msix_idx = dd->first_dyn_msix_idx; 73064551edeSVishwanathapura, Niranjana } 7312280740fSVishwanathapura, Niranjana 7322280740fSVishwanathapura, Niranjana for (i = dd->vnic.num_ctxt; i < vinfo->num_rx_q; i++) { 7332280740fSVishwanathapura, Niranjana rc = hfi1_vnic_allot_ctxt(dd, &dd->vnic.ctxt[i]); 7342280740fSVishwanathapura, Niranjana if (rc) 7352280740fSVishwanathapura, Niranjana break; 736f683c80cSMichael J. Ruhl hfi1_rcd_get(dd->vnic.ctxt[i]); 7372280740fSVishwanathapura, Niranjana dd->vnic.ctxt[i]->vnic_q_idx = i; 7382280740fSVishwanathapura, Niranjana } 7392280740fSVishwanathapura, Niranjana 7402280740fSVishwanathapura, Niranjana if (i < vinfo->num_rx_q) { 7412280740fSVishwanathapura, Niranjana /* 7422280740fSVishwanathapura, Niranjana * If required amount of contexts is not 7432280740fSVishwanathapura, Niranjana * allocated successfully then remaining contexts 7442280740fSVishwanathapura, Niranjana * are released. 7452280740fSVishwanathapura, Niranjana */ 7462280740fSVishwanathapura, Niranjana while (i-- > dd->vnic.num_ctxt) { 7472280740fSVishwanathapura, Niranjana deallocate_vnic_ctxt(dd, dd->vnic.ctxt[i]); 748f683c80cSMichael J. Ruhl hfi1_rcd_put(dd->vnic.ctxt[i]); 7492280740fSVishwanathapura, Niranjana dd->vnic.ctxt[i] = NULL; 7502280740fSVishwanathapura, Niranjana } 7512280740fSVishwanathapura, Niranjana goto alloc_fail; 7522280740fSVishwanathapura, Niranjana } 7532280740fSVishwanathapura, Niranjana 7542280740fSVishwanathapura, Niranjana if (dd->vnic.num_ctxt != i) { 7552280740fSVishwanathapura, Niranjana dd->vnic.num_ctxt = i; 7562280740fSVishwanathapura, Niranjana hfi1_init_vnic_rsm(dd); 7572280740fSVishwanathapura, Niranjana } 7582280740fSVishwanathapura, Niranjana 7592280740fSVishwanathapura, Niranjana dd->vnic.num_vports++; 76064551edeSVishwanathapura, Niranjana hfi1_vnic_sdma_init(vinfo); 7612280740fSVishwanathapura, Niranjana alloc_fail: 76264551edeSVishwanathapura, Niranjana if (!dd->vnic.num_vports) 76364551edeSVishwanathapura, Niranjana hfi1_vnic_txreq_deinit(dd); 76464551edeSVishwanathapura, Niranjana txreq_fail: 7652280740fSVishwanathapura, Niranjana mutex_unlock(&hfi1_mutex); 7662280740fSVishwanathapura, Niranjana return rc; 7672280740fSVishwanathapura, Niranjana } 7682280740fSVishwanathapura, Niranjana 7692280740fSVishwanathapura, Niranjana static void hfi1_vnic_deinit(struct hfi1_vnic_vport_info *vinfo) 7702280740fSVishwanathapura, Niranjana { 7712280740fSVishwanathapura, Niranjana struct hfi1_devdata *dd = vinfo->dd; 7722280740fSVishwanathapura, Niranjana int i; 7732280740fSVishwanathapura, Niranjana 7742280740fSVishwanathapura, Niranjana mutex_lock(&hfi1_mutex); 7752280740fSVishwanathapura, Niranjana if (--dd->vnic.num_vports == 0) { 7762280740fSVishwanathapura, Niranjana for (i = 0; i < dd->vnic.num_ctxt; i++) { 7772280740fSVishwanathapura, Niranjana deallocate_vnic_ctxt(dd, dd->vnic.ctxt[i]); 778f683c80cSMichael J. Ruhl hfi1_rcd_put(dd->vnic.ctxt[i]); 7792280740fSVishwanathapura, Niranjana dd->vnic.ctxt[i] = NULL; 7802280740fSVishwanathapura, Niranjana } 7812280740fSVishwanathapura, Niranjana hfi1_deinit_vnic_rsm(dd); 7822280740fSVishwanathapura, Niranjana dd->vnic.num_ctxt = 0; 78364551edeSVishwanathapura, Niranjana hfi1_vnic_txreq_deinit(dd); 7842280740fSVishwanathapura, Niranjana } 7852280740fSVishwanathapura, Niranjana mutex_unlock(&hfi1_mutex); 7862280740fSVishwanathapura, Niranjana } 7872280740fSVishwanathapura, Niranjana 788d4829ea6SVishwanathapura, Niranjana static void hfi1_vnic_set_vesw_id(struct net_device *netdev, int id) 789d4829ea6SVishwanathapura, Niranjana { 790d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 791d4829ea6SVishwanathapura, Niranjana bool reopen = false; 792d4829ea6SVishwanathapura, Niranjana 793d4829ea6SVishwanathapura, Niranjana /* 794d4829ea6SVishwanathapura, Niranjana * If vesw_id is being changed, and if the vnic port is up, 795d4829ea6SVishwanathapura, Niranjana * reset the vnic port to ensure new vesw_id gets picked up 796d4829ea6SVishwanathapura, Niranjana */ 797d4829ea6SVishwanathapura, Niranjana if (id != vinfo->vesw_id) { 798d4829ea6SVishwanathapura, Niranjana mutex_lock(&vinfo->lock); 799d4829ea6SVishwanathapura, Niranjana if (test_bit(HFI1_VNIC_UP, &vinfo->flags)) { 800d4829ea6SVishwanathapura, Niranjana hfi1_vnic_down(vinfo); 801d4829ea6SVishwanathapura, Niranjana reopen = true; 802d4829ea6SVishwanathapura, Niranjana } 803d4829ea6SVishwanathapura, Niranjana 804d4829ea6SVishwanathapura, Niranjana vinfo->vesw_id = id; 805d4829ea6SVishwanathapura, Niranjana if (reopen) 806d4829ea6SVishwanathapura, Niranjana hfi1_vnic_up(vinfo); 807d4829ea6SVishwanathapura, Niranjana 808d4829ea6SVishwanathapura, Niranjana mutex_unlock(&vinfo->lock); 809d4829ea6SVishwanathapura, Niranjana } 810d4829ea6SVishwanathapura, Niranjana } 811d4829ea6SVishwanathapura, Niranjana 812d4829ea6SVishwanathapura, Niranjana /* netdev ops */ 813d4829ea6SVishwanathapura, Niranjana static const struct net_device_ops hfi1_netdev_ops = { 814d4829ea6SVishwanathapura, Niranjana .ndo_open = hfi1_netdev_open, 815d4829ea6SVishwanathapura, Niranjana .ndo_stop = hfi1_netdev_close, 816d4829ea6SVishwanathapura, Niranjana .ndo_start_xmit = hfi1_netdev_start_xmit, 817d4829ea6SVishwanathapura, Niranjana .ndo_select_queue = hfi1_vnic_select_queue, 818d4829ea6SVishwanathapura, Niranjana .ndo_get_stats64 = hfi1_vnic_get_stats64, 819d4829ea6SVishwanathapura, Niranjana }; 820d4829ea6SVishwanathapura, Niranjana 8218e959601SNiranjana Vishwanathapura static void hfi1_vnic_free_rn(struct net_device *netdev) 8228e959601SNiranjana Vishwanathapura { 8238e959601SNiranjana Vishwanathapura struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev); 8248e959601SNiranjana Vishwanathapura 8258e959601SNiranjana Vishwanathapura hfi1_vnic_deinit(vinfo); 8268e959601SNiranjana Vishwanathapura mutex_destroy(&vinfo->lock); 8278e959601SNiranjana Vishwanathapura free_netdev(netdev); 8288e959601SNiranjana Vishwanathapura } 8298e959601SNiranjana Vishwanathapura 830d4829ea6SVishwanathapura, Niranjana struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device, 831d4829ea6SVishwanathapura, Niranjana u8 port_num, 832d4829ea6SVishwanathapura, Niranjana enum rdma_netdev_t type, 833d4829ea6SVishwanathapura, Niranjana const char *name, 834d4829ea6SVishwanathapura, Niranjana unsigned char name_assign_type, 835d4829ea6SVishwanathapura, Niranjana void (*setup)(struct net_device *)) 836d4829ea6SVishwanathapura, Niranjana { 837d4829ea6SVishwanathapura, Niranjana struct hfi1_devdata *dd = dd_from_ibdev(device); 838d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_vport_info *vinfo; 839d4829ea6SVishwanathapura, Niranjana struct net_device *netdev; 840d4829ea6SVishwanathapura, Niranjana struct rdma_netdev *rn; 8412280740fSVishwanathapura, Niranjana int i, size, rc; 842d4829ea6SVishwanathapura, Niranjana 843d4829ea6SVishwanathapura, Niranjana if (!port_num || (port_num > dd->num_pports)) 844d4829ea6SVishwanathapura, Niranjana return ERR_PTR(-EINVAL); 845d4829ea6SVishwanathapura, Niranjana 846d4829ea6SVishwanathapura, Niranjana if (type != RDMA_NETDEV_OPA_VNIC) 847d4829ea6SVishwanathapura, Niranjana return ERR_PTR(-EOPNOTSUPP); 848d4829ea6SVishwanathapura, Niranjana 849d4829ea6SVishwanathapura, Niranjana size = sizeof(struct opa_vnic_rdma_netdev) + sizeof(*vinfo); 850d4829ea6SVishwanathapura, Niranjana netdev = alloc_netdev_mqs(size, name, name_assign_type, setup, 851d4829ea6SVishwanathapura, Niranjana dd->chip_sdma_engines, HFI1_NUM_VNIC_CTXT); 852d4829ea6SVishwanathapura, Niranjana if (!netdev) 853d4829ea6SVishwanathapura, Niranjana return ERR_PTR(-ENOMEM); 854d4829ea6SVishwanathapura, Niranjana 855d4829ea6SVishwanathapura, Niranjana rn = netdev_priv(netdev); 856d4829ea6SVishwanathapura, Niranjana vinfo = opa_vnic_dev_priv(netdev); 857d4829ea6SVishwanathapura, Niranjana vinfo->dd = dd; 858d4829ea6SVishwanathapura, Niranjana vinfo->num_tx_q = dd->chip_sdma_engines; 859d4829ea6SVishwanathapura, Niranjana vinfo->num_rx_q = HFI1_NUM_VNIC_CTXT; 860d4829ea6SVishwanathapura, Niranjana vinfo->netdev = netdev; 8618e959601SNiranjana Vishwanathapura rn->free_rdma_netdev = hfi1_vnic_free_rn; 862d4829ea6SVishwanathapura, Niranjana rn->set_id = hfi1_vnic_set_vesw_id; 863d4829ea6SVishwanathapura, Niranjana 864d4829ea6SVishwanathapura, Niranjana netdev->features = NETIF_F_HIGHDMA | NETIF_F_SG; 865d4829ea6SVishwanathapura, Niranjana netdev->hw_features = netdev->features; 866d4829ea6SVishwanathapura, Niranjana netdev->vlan_features = netdev->features; 867d4829ea6SVishwanathapura, Niranjana netdev->watchdog_timeo = msecs_to_jiffies(HFI_TX_TIMEOUT_MS); 868d4829ea6SVishwanathapura, Niranjana netdev->netdev_ops = &hfi1_netdev_ops; 869d4829ea6SVishwanathapura, Niranjana mutex_init(&vinfo->lock); 870d4829ea6SVishwanathapura, Niranjana 871d4829ea6SVishwanathapura, Niranjana for (i = 0; i < vinfo->num_rx_q; i++) { 872d4829ea6SVishwanathapura, Niranjana struct hfi1_vnic_rx_queue *rxq = &vinfo->rxq[i]; 873d4829ea6SVishwanathapura, Niranjana 874d4829ea6SVishwanathapura, Niranjana rxq->idx = i; 875d4829ea6SVishwanathapura, Niranjana rxq->vinfo = vinfo; 876d4829ea6SVishwanathapura, Niranjana rxq->netdev = netdev; 877d4829ea6SVishwanathapura, Niranjana netif_napi_add(netdev, &rxq->napi, hfi1_vnic_napi, 64); 878d4829ea6SVishwanathapura, Niranjana } 879d4829ea6SVishwanathapura, Niranjana 8802280740fSVishwanathapura, Niranjana rc = hfi1_vnic_init(vinfo); 8812280740fSVishwanathapura, Niranjana if (rc) 8822280740fSVishwanathapura, Niranjana goto init_fail; 8832280740fSVishwanathapura, Niranjana 884d4829ea6SVishwanathapura, Niranjana return netdev; 8852280740fSVishwanathapura, Niranjana init_fail: 8862280740fSVishwanathapura, Niranjana mutex_destroy(&vinfo->lock); 8872280740fSVishwanathapura, Niranjana free_netdev(netdev); 8882280740fSVishwanathapura, Niranjana return ERR_PTR(rc); 889d4829ea6SVishwanathapura, Niranjana } 890