Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1026306/?format=api
{ "id": 1026306, "url": "http://patchwork.ozlabs.org/api/patches/1026306/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20190116235414.4946-1-harshitha.ramamurthy@intel.com/", "project": { "id": 46, "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api", "name": "Intel Wired Ethernet development", "link_name": "intel-wired-lan", "list_id": "intel-wired-lan.osuosl.org", "list_email": "intel-wired-lan@osuosl.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20190116235414.4946-1-harshitha.ramamurthy@intel.com>", "list_archive_url": null, "date": "2019-01-16T23:54:14", "name": "[v3] i40e: Add macvlan support on i40e", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": false, "hash": "bf4bd9898c113cc2117ec6a4da505316f547889f", "submitter": { "id": 68642, "url": "http://patchwork.ozlabs.org/api/people/68642/?format=api", "name": "Harshitha Ramamurthy", "email": "harshitha.ramamurthy@intel.com" }, "delegate": { "id": 68, "url": "http://patchwork.ozlabs.org/api/users/68/?format=api", "username": "jtkirshe", "first_name": "Jeff", "last_name": "Kirsher", "email": "jeffrey.t.kirsher@intel.com" }, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20190116235414.4946-1-harshitha.ramamurthy@intel.com/mbox/", "series": [ { "id": 86586, "url": "http://patchwork.ozlabs.org/api/series/86586/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=86586", "date": "2019-01-16T23:54:14", "name": "[v3] i40e: Add macvlan support on i40e", "version": 3, "mbox": "http://patchwork.ozlabs.org/series/86586/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1026306/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1026306/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@osuosl.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Authentication-Results": [ "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=osuosl.org\n\t(client-ip=140.211.166.136; helo=silver.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=intel.com" ], "Received": [ "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 43g3wH5XTlz9sBn\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 17 Jan 2019 10:54:38 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id 7718B24B3A;\n\tWed, 16 Jan 2019 23:54:37 +0000 (UTC)", "from silver.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id eHdRoqQn-pV7; Wed, 16 Jan 2019 23:54:35 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby silver.osuosl.org (Postfix) with ESMTP id 37D2C25D10;\n\tWed, 16 Jan 2019 23:54:35 +0000 (UTC)", "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ash.osuosl.org (Postfix) with ESMTP id B73501BF40F\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 16 Jan 2019 23:54:33 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id B3A5F25D10\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 16 Jan 2019 23:54:33 +0000 (UTC)", "from silver.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id MxdlJN-eENU4 for <intel-wired-lan@lists.osuosl.org>;\n\tWed, 16 Jan 2019 23:54:32 +0000 (UTC)", "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n\tby silver.osuosl.org (Postfix) with ESMTPS id 4055E24B3A\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 16 Jan 2019 23:54:32 +0000 (UTC)", "from fmsmga008.fm.intel.com ([10.253.24.58])\n\tby orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t16 Jan 2019 15:54:31 -0800", "from harshitha-linux4.jf.intel.com ([10.166.17.81])\n\tby fmsmga008.fm.intel.com with ESMTP; 16 Jan 2019 15:54:30 -0800" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6", "X-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos;i=\"5.56,488,1539673200\"; d=\"scan'208\";a=\"117300131\"", "From": "Harshitha Ramamurthy <harshitha.ramamurthy@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Wed, 16 Jan 2019 18:54:14 -0500", "Message-Id": "<20190116235414.4946-1-harshitha.ramamurthy@intel.com>", "X-Mailer": "git-send-email 2.17.1", "Subject": "[Intel-wired-lan] [PATCH v3] i40e: Add macvlan support on i40e", "X-BeenThere": "intel-wired-lan@osuosl.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>", "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>", "Cc": "alexander.h.duyck@intel.com", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "intel-wired-lan-bounces@osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>" }, "content": "This patch enables macvlan offloads for i40e. The idea is to use\nchannels as macvlan interfaces. The channels are VSIs of\ntype VMDQ. When the first macvlan is created, the maximum number of\nchannels possible are created. From then on, as a macvlan interface\nis created, a mac filter is added to these already created channels\n(VSIs).\n\nThis patch builds on top of the recent changes which move\naway from the select_queue implementation of picking the tx queue.\n\nSteps to configure macvlan offloads:\n1. sudo ethtool -K ens261f1 l2-fwd-offload on\n2. ip link add link ens261f1 name macvlan1 type macvlan\n3. sudo ip link add link ens261f1 name macvlan1 type macvlan\n4. sudo ip link set macvlan1 up\n\nSigned-off-by: Harshitha Ramamurthy <harshitha.ramamurthy@intel.com>\n---\nv3: Renamed i40e_remove_macvlan_channels() to i40e_free_macvlan_channels()\n Fixed an indentation issue and added some comments\n Removed a code name from the commit message\n Addressed some more of Shannon's comments \n\nv2: Addressed Shannon's comments\n Added a new function to remove all macvlan VSIs\n\n drivers/net/ethernet/intel/i40e/i40e.h | 26 ++\n drivers/net/ethernet/intel/i40e/i40e_main.c | 481 +++++++++++++++++++-\n 2 files changed, 505 insertions(+), 2 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h\nindex c06a4b5cdfae..107edcf2cf19 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e.h\n@@ -27,6 +27,7 @@\n #include <net/ip6_checksum.h>\n #include <linux/ethtool.h>\n #include <linux/if_vlan.h>\n+#include <linux/if_macvlan.h>\n #include <linux/if_bridge.h>\n #include <linux/clocksource.h>\n #include <linux/net_tstamp.h>\n@@ -391,6 +392,11 @@ struct i40e_flex_pit {\n \tu8 pit_index;\n };\n \n+struct i40e_fwd_adapter {\n+\tstruct net_device *netdev;\n+\tint bit_no;\n+};\n+\n struct i40e_channel {\n \tstruct list_head list;\n \tbool initialized;\n@@ -405,11 +411,25 @@ struct i40e_channel {\n \tstruct i40e_aqc_vsi_properties_data info;\n \n \tu64 max_tx_rate;\n+\tstruct i40e_fwd_adapter *fwd;\n \n \t/* track this channel belongs to which VSI */\n \tstruct i40e_vsi *parent_vsi;\n };\n \n+static inline bool i40e_is_channel_macvlan(struct i40e_channel *ch)\n+{\n+\treturn !!ch->fwd;\n+}\n+\n+static inline u8 *i40e_channel_mac(struct i40e_channel *ch)\n+{\n+\tif (i40e_is_channel_macvlan(ch))\n+\t\treturn ch->fwd->netdev->dev_addr;\n+\telse\n+\t\treturn NULL;\n+}\n+\n /* struct that defines the Ethernet device */\n struct i40e_pf {\n \tstruct pci_dev *pdev;\n@@ -787,6 +807,12 @@ struct i40e_vsi {\n \tstruct list_head ch_list;\n \tu16 tc_seid_map[I40E_MAX_TRAFFIC_CLASS];\n \n+\t/* macvlan fields */\n+#define I40E_MAX_MACVLANS\t128 /* Max HW capable vectors - 1 on FVL */\n+\tDECLARE_BITMAP(fwd_bitmask, I40E_MAX_MACVLANS);\n+\tstruct list_head macvlan_list;\n+\tint macvlan_cnt;\n+\n \tvoid *priv;\t/* client driver data reference. */\n \n \t/* VSI specific handlers */\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c\nindex 6675d1bb873c..6365064d8d3d 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_main.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c\n@@ -5818,8 +5818,10 @@ static int i40e_add_channel(struct i40e_pf *pf, u16 uplink_seid,\n \t\treturn -ENOENT;\n \t}\n \n-\t/* Success, update channel */\n-\tch->enabled_tc = enabled_tc;\n+\t/* Success, update channel, set enabled_tc only if the channel\n+\t * is not a macvlan\n+\t */\n+\tch->enabled_tc = !i40e_is_channel_macvlan(ch) && enabled_tc;\n \tch->seid = ctxt.seid;\n \tch->vsi_number = ctxt.vsi_number;\n \tch->stat_counter_idx = cpu_to_le16(ctxt.info.stat_counter_idx);\n@@ -6811,6 +6813,473 @@ static void i40e_vsi_set_default_tc_config(struct i40e_vsi *vsi)\n \t}\n }\n \n+/**\n+ * i40e_del_macvlan_filter\n+ * @hw: pointer to the HW structure\n+ * @seid: seid of the channel VSI\n+ * @macaddr: the mac address to apply as a filter\n+ * @aq_err: store the admin Q error\n+ *\n+ * This function deletes a mac filter on the channel VSI which serves as the\n+ * macvlan. Returns 0 on success.\n+ **/\n+static i40e_status i40e_del_macvlan_filter(struct i40e_hw *hw, u16 seid,\n+\t\t\t\t\t const u8 *macaddr, int *aq_err)\n+{\n+\tstruct i40e_aqc_remove_macvlan_element_data element;\n+\ti40e_status status;\n+\n+\tmemset(&element, 0, sizeof(element));\n+\tether_addr_copy(element.mac_addr, macaddr);\n+\telement.vlan_tag = 0;\n+\telement.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;\n+\tstatus = i40e_aq_remove_macvlan(hw, seid, &element, 1, NULL);\n+\t*aq_err = hw->aq.asq_last_status;\n+\treturn status;\n+}\n+\n+/**\n+ * i40e_add_macvlan_filter\n+ * @hw: pointer to the HW structure\n+ * @seid: seid of the channel VSI\n+ * @macaddr: the mac address to apply as a filter\n+ * @aq_err: store the admin Q error\n+ *\n+ * This function adds a mac filter on the channel VSI which serves as the\n+ * macvlan. Returns 0 on success.\n+ **/\n+static i40e_status i40e_add_macvlan_filter(struct i40e_hw *hw, u16 seid,\n+\t\t\t\t\t const u8 *macaddr, int *aq_err)\n+{\n+\tstruct i40e_aqc_add_macvlan_element_data element;\n+\ti40e_status status;\n+\tu16 cmd_flags = 0;\n+\n+\tether_addr_copy(element.mac_addr, macaddr);\n+\telement.vlan_tag = 0;\n+\telement.queue_number = 0;\n+\telement.match_method = I40E_AQC_MM_ERR_NO_RES;\n+\tcmd_flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;\n+\telement.flags = cpu_to_le16(cmd_flags);\n+\tstatus = i40e_aq_add_macvlan(hw, seid, &element, 1, NULL);\n+\t*aq_err = hw->aq.asq_last_status;\n+\treturn status;\n+}\n+\n+/**\n+ * i40e_reset_ch_rings - Reset the queue contexts in a channel\n+ * @vsi: the VSI we want to access\n+ * @ch: the channel we want to access\n+ */\n+static void i40e_reset_ch_rings(struct i40e_vsi *vsi, struct i40e_channel *ch)\n+{\n+\tstruct i40e_ring *tx_ring, *rx_ring;\n+\tu16 pf_q;\n+\tint i;\n+\n+\tfor (i = 0; i < ch->num_queue_pairs; i++) {\n+\t\tpf_q = ch->base_queue + i;\n+\t\ttx_ring = vsi->tx_rings[pf_q];\n+\t\ttx_ring->ch = NULL;\n+\t\trx_ring = vsi->rx_rings[pf_q];\n+\t\trx_ring->ch = NULL;\n+\t}\n+}\n+\n+/**\n+ * i40e_free_macvlan_channels\n+ * @vsi: the VSI we want to access\n+ *\n+ * This function frees the Qs of the channel VSI from\n+ * the stack and also deletes the channel VSIs which\n+ * serve as macvlans.\n+ */\n+static void i40e_free_macvlan_channels(struct i40e_vsi *vsi)\n+{\n+\tstruct i40e_channel *ch, *ch_tmp;\n+\tint ret;\n+\n+\tif (list_empty(&vsi->macvlan_list))\n+\t\treturn;\n+\n+\tlist_for_each_entry_safe(ch, ch_tmp, &vsi->macvlan_list, list) {\n+\t\tstruct i40e_vsi *parent_vsi;\n+\n+\t\tif (i40e_is_channel_macvlan(ch)) {\n+\t\t\ti40e_reset_ch_rings(vsi, ch);\n+\t\t\tclear_bit(ch->fwd->bit_no, vsi->fwd_bitmask);\n+\t\t\tnetdev_unbind_sb_channel(vsi->netdev, ch->fwd->netdev);\n+\t\t\tnetdev_set_sb_channel(ch->fwd->netdev, 0);\n+\t\t\tkfree(ch->fwd);\n+\t\t\tch->fwd = NULL;\n+\t\t}\n+\n+\t\tlist_del(&ch->list);\n+\t\tparent_vsi = ch->parent_vsi;\n+\t\tif (!parent_vsi || !ch->initialized) {\n+\t\t\tkfree(ch);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* remove the VSI */\n+\t\tret = i40e_aq_delete_element(&vsi->back->hw, ch->seid,\n+\t\t\t\t\t NULL);\n+\t\tif (ret)\n+\t\t\tdev_err(&vsi->back->pdev->dev,\n+\t\t\t\t\"unable to remove channel (%d) for parent VSI(%d)\\n\",\n+\t\t\t\tch->seid, parent_vsi->seid);\n+\t\tkfree(ch);\n+\t}\n+\tvsi->macvlan_cnt = 0;\n+}\n+\n+/**\n+ * i40e_fwd_ring_up - bring the macvlan device up\n+ * @vsi: the VSI we want to access\n+ * @vdev: macvlan netdevice\n+ * @fwd: the private fwd structure\n+ */\n+static int i40e_fwd_ring_up(struct i40e_vsi *vsi, struct net_device *vdev,\n+\t\t\t struct i40e_fwd_adapter *fwd)\n+{\n+\tint ret = 0, num_tc = 1, i, aq_err;\n+\tstruct i40e_channel *ch, *ch_tmp;\n+\tstruct i40e_pf *pf = vsi->back;\n+\tstruct i40e_hw *hw = &pf->hw;\n+\n+\tif (list_empty(&vsi->macvlan_list))\n+\t\treturn -EINVAL;\n+\n+\t/* Go through the list and find an available channel */\n+\tlist_for_each_entry_safe(ch, ch_tmp, &vsi->macvlan_list, list) {\n+\t\tif (!i40e_is_channel_macvlan(ch)) {\n+\t\t\tch->fwd = fwd;\n+\t\t\t/* record configuration for macvlan interface in vdev */\n+\t\t\tfor (i = 0; i < num_tc; i++)\n+\t\t\t\tnetdev_bind_sb_channel_queue(vsi->netdev, vdev,\n+\t\t\t\t\t\t\t i,\n+\t\t\t\t\t\t\t ch->num_queue_pairs,\n+\t\t\t\t\t\t\t ch->base_queue);\n+\t\t\tfor (i = 0; i < ch->num_queue_pairs; i++) {\n+\t\t\t\tstruct i40e_ring *tx_ring, *rx_ring;\n+\t\t\t\tu16 pf_q;\n+\n+\t\t\t\tpf_q = ch->base_queue + i;\n+\n+\t\t\t\t/* Get to TX ring ptr */\n+\t\t\t\ttx_ring = vsi->tx_rings[pf_q];\n+\t\t\t\ttx_ring->ch = ch;\n+\n+\t\t\t\t/* Get the RX ring ptr */\n+\t\t\t\trx_ring = vsi->rx_rings[pf_q];\n+\t\t\t\trx_ring->ch = ch;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\t/* Guarantee all rings are updated before we update the\n+\t * MAC address filter.\n+\t */\n+\twmb();\n+\n+\t/* Add a mac filter */\n+\tret = i40e_add_macvlan_filter(hw, ch->seid, vdev->dev_addr, &aq_err);\n+\tif (ret) {\n+\t\t/* if we cannot add the MAC rule then disable the offload */\n+\t\tmacvlan_release_l2fw_offload(vdev);\n+\t\tfor (i = 0; i < ch->num_queue_pairs; i++) {\n+\t\t\tstruct i40e_ring *rx_ring;\n+\t\t\tu16 pf_q;\n+\n+\t\t\tpf_q = ch->base_queue + i;\n+\t\t\trx_ring = vsi->rx_rings[pf_q];\n+\t\t\trx_ring->netdev = NULL;\n+\t\t}\n+\t\tdev_info(&pf->pdev->dev,\n+\t\t\t \"Error adding mac filter on macvlan err %s, aq_err %s\\n\",\n+\t\t\t i40e_stat_str(hw, ret),\n+\t\t\t i40e_aq_str(hw, aq_err));\n+\t\tnetdev_err(vdev, \"L2fwd offload disabled to L2 filter error\\n\");\n+\t}\n+\treturn ret;\n+}\n+\n+/**\n+ * i40e_setup_macvlans - create the channels which will be macvlans\n+ * @vsi: the VSI we want to access\n+ * @macvlan_cnt: no. of macvlans to be setup\n+ * @qcnt: no. of Qs per macvlan\n+ * @vdev: macvlan netdevice\n+ */\n+static int i40e_setup_macvlans(struct i40e_vsi *vsi, u16 macvlan_cnt, u16 qcnt,\n+\t\t\t struct net_device *vdev)\n+{\n+\tstruct i40e_pf *pf = vsi->back;\n+\tstruct i40e_hw *hw = &pf->hw;\n+\tstruct i40e_vsi_context ctxt;\n+\tu16 sections, qmap, num_qps;\n+\tstruct i40e_channel *ch;\n+\tint i, pow, ret = 0;\n+\tu8 offset = 0;\n+\n+\tif (vsi->type != I40E_VSI_MAIN)\n+\t\treturn -EINVAL;\n+\tif (!macvlan_cnt)\n+\t\treturn -EINVAL;\n+\n+\tnum_qps = vsi->num_queue_pairs - (macvlan_cnt * qcnt);\n+\n+\t/* find the next higher power-of-2 of num queue pairs */\n+\tpow = fls(roundup_pow_of_two(num_qps) - 1);\n+\n+\tqmap = (offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |\n+\t\t(pow << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT);\n+\n+\t/* Setup context bits for the main VSI */\n+\tsections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID;\n+\tsections |= I40E_AQ_VSI_PROP_SCHED_VALID;\n+\tmemset(&ctxt, 0, sizeof(ctxt));\n+\tctxt.seid = vsi->seid;\n+\tctxt.pf_num = vsi->back->hw.pf_id;\n+\tctxt.vf_num = 0;\n+\tctxt.uplink_seid = vsi->uplink_seid;\n+\tctxt.info = vsi->info;\n+\tctxt.info.tc_mapping[0] = cpu_to_le16(qmap);\n+\tctxt.info.mapping_flags |= cpu_to_le16(I40E_AQ_VSI_QUE_MAP_CONTIG);\n+\tctxt.info.queue_mapping[0] = cpu_to_le16(vsi->base_queue);\n+\tctxt.info.valid_sections |= cpu_to_le16(sections);\n+\n+\t/* Reconfigure RSS for main VSI with new max queue count */\n+\tvsi->rss_size = max_t(u16, num_qps, qcnt);\n+\tret = i40e_vsi_config_rss(vsi);\n+\tif (ret) {\n+\t\tdev_info(&pf->pdev->dev,\n+\t\t\t \"Failed to reconfig RSS for num_queues (%u)\\n\",\n+\t\t\t vsi->rss_size);\n+\t\treturn ret;\n+\t}\n+\tvsi->reconfig_rss = true;\n+\tdev_dbg(&vsi->back->pdev->dev,\n+\t\t\"Reconfigured RSS with num_queues (%u)\\n\", vsi->rss_size);\n+\tvsi->next_base_queue = num_qps;\n+\tvsi->cnt_q_avail = vsi->num_queue_pairs - num_qps;\n+\n+\t/* Update the VSI after updating the VSI queue-mapping\n+\t * information\n+\t */\n+\tret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);\n+\tif (ret) {\n+\t\tdev_info(&pf->pdev->dev,\n+\t\t\t \"Update vsi tc config failed, err %s aq_err %s\\n\",\n+\t\t\t i40e_stat_str(hw, ret),\n+\t\t\t i40e_aq_str(hw, hw->aq.asq_last_status));\n+\t\treturn ret;\n+\t}\n+\t/* update the local VSI info with updated queue map */\n+\ti40e_vsi_update_queue_map(vsi, &ctxt);\n+\tvsi->info.valid_sections = 0;\n+\n+\t/* Create channels for macvlans */\n+\tINIT_LIST_HEAD(&vsi->macvlan_list);\n+\tfor (i = 0; i < macvlan_cnt; i++) {\n+\t\tch = kzalloc(sizeof(*ch), GFP_KERNEL);\n+\t\tif (!ch) {\n+\t\t\tret = -ENOMEM;\n+\t\t\tgoto err_free;\n+\t\t}\n+\t\tINIT_LIST_HEAD(&ch->list);\n+\t\tch->num_queue_pairs = qcnt;\n+\t\tif (!i40e_setup_channel(pf, vsi, ch)) {\n+\t\t\tret = -EINVAL;\n+\t\t\tgoto err_free;\n+\t\t}\n+\t\tch->parent_vsi = vsi;\n+\t\tvsi->cnt_q_avail -= ch->num_queue_pairs;\n+\t\tvsi->macvlan_cnt++;\n+\t\tlist_add_tail(&ch->list, &vsi->macvlan_list);\n+\t}\n+\treturn ret;\n+\n+err_free:\n+\tdev_info(&pf->pdev->dev, \"Failed to setup macvlans\\n\");\n+\ti40e_free_macvlan_channels(vsi);\n+\treturn ret;\n+}\n+\n+/**\n+ * i40e_fwd_add - configure macvlans\n+ * @netdev: net device to configure\n+ * @vdev: macvlan netdevice\n+ **/\n+static void *i40e_fwd_add(struct net_device *netdev, struct net_device *vdev)\n+{\n+\tstruct i40e_netdev_priv *np = netdev_priv(netdev);\n+\tu16 q_per_macvlan = 0, macvlan_cnt = 0, vectors;\n+\tstruct i40e_vsi *vsi = np->vsi;\n+\tstruct i40e_pf *pf = vsi->back;\n+\tstruct i40e_fwd_adapter *fwd;\n+\tint avail_macvlan, ret;\n+\n+\tif ((pf->flags & I40E_FLAG_DCB_ENABLED)) {\n+\t\tnetdev_info(netdev, \"Macvlans are not supported when DCB is enabled\\n\");\n+\t\treturn ERR_PTR(-EINVAL);\n+\t}\n+\tif ((pf->flags & I40E_FLAG_TC_MQPRIO)) {\n+\t\tnetdev_info(netdev, \"Macvlans are not supported when HW TC offload is on\\n\");\n+\t\treturn ERR_PTR(-EINVAL);\n+\t}\n+\n+\t/* The macvlan device has to be a single Q device so that the\n+\t * tc_to_txq field can be reused to pick the tx queue.\n+\t */\n+\tif (netif_is_multiqueue(vdev))\n+\t\treturn ERR_PTR(-ERANGE);\n+\n+\tif (!vsi->macvlan_cnt) {\n+\t\t/* reserve bit 0 for the pf device */\n+\t\tset_bit(0, vsi->fwd_bitmask);\n+\n+\t\t/* Try to reserve as many queues for macvlans. First reserve\n+\t\t * 3/4th of max vectors, then half, then quarter and calculate\n+\t\t * Qs per macvlan as you go\n+\t\t */\n+\t\tvectors = pf->num_lan_msix;\n+\t\tif (vectors <= I40E_MAX_MACVLANS && vectors > 96) {\n+\t\t\t/* allocate 4 Qs per macvlan and 32 Qs to the PF*/\n+\t\t\tq_per_macvlan = 4;\n+\t\t\tmacvlan_cnt = (vectors - 32) / 4;\n+\t\t} else if (vectors <= 96 && vectors > 64) {\n+\t\t\t/* allocate 4 Qs per macvlan and 32 Qs to the PF*/\n+\t\t\tq_per_macvlan = 4;\n+\t\t\tmacvlan_cnt = (vectors - 32) / 4;\n+\t\t} else if (vectors <= 64 && vectors > 32) {\n+\t\t\t/* allocate 2 Qs per macvlan and 16 Qs to the PF*/\n+\t\t\tq_per_macvlan = 2;\n+\t\t\tmacvlan_cnt = (vectors - 16) / 2;\n+\t\t} else {\n+\t\t\t/* allocate 1 Q per macvlan 16 Qs to the PF*/\n+\t\t\tq_per_macvlan = 1;\n+\t\t\tmacvlan_cnt = (vectors - 16);\n+\t\t}\n+\t\tif (macvlan_cnt == 0)\n+\t\t\treturn ERR_PTR(-EBUSY);\n+\n+\t\t/* Quiesce VSI queues */\n+\t\ti40e_quiesce_vsi(vsi);\n+\n+\t\t/* sets up the macvlans but does not \"enable\" them */\n+\t\tret = i40e_setup_macvlans(vsi, macvlan_cnt, q_per_macvlan,\n+\t\t\t\t\t vdev);\n+\t\tif (ret)\n+\t\t\treturn ERR_PTR(ret);\n+\n+\t\t/* Unquiesce VSI */\n+\t\ti40e_unquiesce_vsi(vsi);\n+\t}\n+\tavail_macvlan = find_first_zero_bit(vsi->fwd_bitmask,\n+\t\t\t\t\t vsi->macvlan_cnt);\n+\tif (avail_macvlan >= I40E_MAX_MACVLANS)\n+\t\treturn ERR_PTR(-EBUSY);\n+\n+\t/* create the fwd struct */\n+\tfwd = kzalloc(sizeof(*fwd), GFP_KERNEL);\n+\tif (!fwd)\n+\t\treturn ERR_PTR(-ENOMEM);\n+\n+\tset_bit(avail_macvlan, vsi->fwd_bitmask);\n+\tfwd->bit_no = avail_macvlan;\n+\tnetdev_set_sb_channel(vdev, avail_macvlan);\n+\tfwd->netdev = vdev;\n+\n+\tif (!netif_running(netdev))\n+\t\treturn fwd;\n+\n+\t/* Set fwd ring up */\n+\tret = i40e_fwd_ring_up(vsi, vdev, fwd);\n+\tif (ret) {\n+\t\t/* unbind the queues and drop the subordinate channel config */\n+\t\tnetdev_unbind_sb_channel(netdev, vdev);\n+\t\tnetdev_set_sb_channel(vdev, 0);\n+\n+\t\tkfree(fwd);\n+\t\treturn ERR_PTR(-EINVAL);\n+\t}\n+\treturn fwd;\n+}\n+\n+/**\n+ * i40e_del_all_macvlans - Delete all the mac filters on the channels\n+ * @vsi: the VSI we want to access\n+ */\n+static void i40e_del_all_macvlans(struct i40e_vsi *vsi)\n+{\n+\tstruct i40e_channel *ch, *ch_tmp;\n+\tstruct i40e_pf *pf = vsi->back;\n+\tstruct i40e_hw *hw = &pf->hw;\n+\tint aq_err, ret = 0;\n+\n+\tlist_for_each_entry_safe(ch, ch_tmp, &vsi->macvlan_list, list) {\n+\t\tif (i40e_is_channel_macvlan(ch)) {\n+\t\t\tret = i40e_del_macvlan_filter(hw, ch->seid,\n+\t\t\t\t\t\t i40e_channel_mac(ch),\n+\t\t\t\t\t\t &aq_err);\n+\t\t\tif (!ret) {\n+\t\t\t\t/* Reset queue contexts */\n+\t\t\t\ti40e_reset_ch_rings(vsi, ch);\n+\t\t\t\tclear_bit(ch->fwd->bit_no, vsi->fwd_bitmask);\n+\t\t\t\tnetdev_unbind_sb_channel(vsi->netdev,\n+\t\t\t\t\t\t\t ch->fwd->netdev);\n+\t\t\t\tnetdev_set_sb_channel(ch->fwd->netdev, 0);\n+\t\t\t\tkfree(ch->fwd);\n+\t\t\t\tch->fwd = NULL;\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+/**\n+ * i40e_fwd_del - delete macvlan interfaces\n+ * @netdev: net device to configure\n+ * @vdev: macvlan netdevice\n+ */\n+static void i40e_fwd_del(struct net_device *netdev, void *vdev)\n+{\n+\tstruct i40e_netdev_priv *np = netdev_priv(netdev);\n+\tstruct i40e_fwd_adapter *fwd = vdev;\n+\tstruct i40e_channel *ch, *ch_tmp;\n+\tstruct i40e_vsi *vsi = np->vsi;\n+\tstruct i40e_pf *pf = vsi->back;\n+\tstruct i40e_hw *hw = &pf->hw;\n+\tint aq_err, ret = 0;\n+\n+\t/* Find the channel associated with the macvlan and del mac filter */\n+\tlist_for_each_entry_safe(ch, ch_tmp, &vsi->macvlan_list, list) {\n+\t\tif (i40e_is_channel_macvlan(ch) &&\n+\t\t ether_addr_equal(i40e_channel_mac(ch),\n+\t\t\t\t fwd->netdev->dev_addr)) {\n+\t\t\tret = i40e_del_macvlan_filter(hw, ch->seid,\n+\t\t\t\t\t\t i40e_channel_mac(ch),\n+\t\t\t\t\t\t &aq_err);\n+\t\t\tif (!ret) {\n+\t\t\t\t/* Reset queue contexts */\n+\t\t\t\ti40e_reset_ch_rings(vsi, ch);\n+\t\t\t\tclear_bit(ch->fwd->bit_no, vsi->fwd_bitmask);\n+\t\t\t\tnetdev_unbind_sb_channel(netdev, fwd->netdev);\n+\t\t\t\tnetdev_set_sb_channel(fwd->netdev, 0);\n+\t\t\t\tkfree(ch->fwd);\n+\t\t\t\tch->fwd = NULL;\n+\t\t\t} else {\n+\t\t\t\tdev_info(&pf->pdev->dev,\n+\t\t\t\t\t \"Error deleting mac filter on macvlan err %s, aq_err %s\\n\",\n+\t\t\t\t\t i40e_stat_str(hw, ret),\n+\t\t\t\t\t i40e_aq_str(hw, aq_err));\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+}\n+\n /**\n * i40e_setup_tc - configure multiple traffic classes\n * @netdev: net device to configure\n@@ -11581,6 +12050,9 @@ static int i40e_set_features(struct net_device *netdev,\n \t\treturn -EINVAL;\n \t}\n \n+\tif (!(features & NETIF_F_HW_L2FW_DOFFLOAD))\n+\t\ti40e_del_all_macvlans(vsi);\n+\n \tneed_reset = i40e_set_ntuple(pf, features);\n \n \tif (need_reset)\n@@ -12314,6 +12786,8 @@ static const struct net_device_ops i40e_netdev_ops = {\n \t.ndo_bpf\t\t= i40e_xdp,\n \t.ndo_xdp_xmit\t\t= i40e_xdp_xmit,\n \t.ndo_xsk_async_xmit\t= i40e_xsk_async_xmit,\n+\t.ndo_dfwd_add_station\t= i40e_fwd_add,\n+\t.ndo_dfwd_del_station\t= i40e_fwd_del,\n };\n \n /**\n@@ -12373,6 +12847,9 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)\n \t/* record features VLANs can make use of */\n \tnetdev->vlan_features |= hw_enc_features | NETIF_F_TSO_MANGLEID;\n \n+\t/* enable macvlan offloads */\n+\tnetdev->hw_features |= NETIF_F_HW_L2FW_DOFFLOAD;\n+\n \thw_features = hw_enc_features\t\t|\n \t\t NETIF_F_HW_VLAN_CTAG_TX\t|\n \t\t NETIF_F_HW_VLAN_CTAG_RX;\n", "prefixes": [ "v3" ] }