get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/1015667/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 1015667,
    "url": "http://patchwork.ozlabs.org/api/patches/1015667/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20181218215456.15494-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": "<20181218215456.15494-1-harshitha.ramamurthy@intel.com>",
    "list_archive_url": null,
    "date": "2018-12-18T21:54:56",
    "name": "i40e: Add macvlan support on i40e",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "6001f0ddb26f8aebf46ac8390f754b78d81665a7",
    "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/20181218215456.15494-1-harshitha.ramamurthy@intel.com/mbox/",
    "series": [
        {
            "id": 82724,
            "url": "http://patchwork.ozlabs.org/api/series/82724/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=82724",
            "date": "2018-12-18T21:54:56",
            "name": "i40e: Add macvlan support on i40e",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/82724/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/1015667/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/1015667/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.137; helo=fraxinus.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 fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\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 43KBdw17RVz9s6w\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 19 Dec 2018 08:55:15 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 4E99185087;\n\tTue, 18 Dec 2018 21:55:14 +0000 (UTC)",
            "from fraxinus.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id C26Met0GszhX; Tue, 18 Dec 2018 21:55:12 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id DDC5684D8C;\n\tTue, 18 Dec 2018 21:55:12 +0000 (UTC)",
            "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id 951771BF311\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 18 Dec 2018 21:55:11 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 90DF88666D\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 18 Dec 2018 21:55:11 +0000 (UTC)",
            "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id Wsn4x7iPOagU for <intel-wired-lan@lists.osuosl.org>;\n\tTue, 18 Dec 2018 21:55:08 +0000 (UTC)",
            "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id 7D5A5864EF\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 18 Dec 2018 21:55:08 +0000 (UTC)",
            "from fmsmga007.fm.intel.com ([10.253.24.52])\n\tby orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t18 Dec 2018 13:55:07 -0800",
            "from harshitha-linux4.jf.intel.com ([10.166.17.81])\n\tby fmsmga007.fm.intel.com with ESMTP; 18 Dec 2018 13:55:07 -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,370,1539673200\"; d=\"scan'208\";a=\"108409948\"",
        "From": "Harshitha Ramamurthy <harshitha.ramamurthy@intel.com>",
        "To": "intel-wired-lan@lists.osuosl.org",
        "Date": "Tue, 18 Dec 2018 16:54:56 -0500",
        "Message-Id": "<20181218215456.15494-1-harshitha.ramamurthy@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "Subject": "[Intel-wired-lan] [PATCH] 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 on Fortville devices. The idea\nis to use channels as macvlan interfaces. The channels are VSIs of\ntype VMDQ. When the first macvlan is created, the maximum no. 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 the macvlan:\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---\n drivers/net/ethernet/intel/i40e/i40e.h      |  26 ++\n drivers/net/ethernet/intel/i40e/i40e_main.c | 425 +++++++++++++++++++-\n 2 files changed, 449 insertions(+), 2 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h\nindex 4f4de85887a6..7416625e091e 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@@ -390,6 +391,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@@ -404,11 +410,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@@ -784,6 +804,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 1ab1f579343f..1e61c22c27f4 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,417 @@ 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_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 avaialble 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 -EBUSY;\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+\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 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(&vsi->back->pdev->dev,\n+\t\t\t \"Failed to reconfig rss for num_queues (%u)\\n\",\n+\t\t\t vsi->rss_size);\n+\t\tgoto err_free;\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\tgoto err_free;\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+\tvsi->macvlan_cnt = macvlan_cnt;\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\tdev_info(&pf->pdev->dev, \"Failed to setup macvlan\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tch->parent_vsi = vsi;\n+\t\tvsi->cnt_q_avail -= ch->num_queue_pairs;\n+\t\tlist_add_tail(&ch->list, &vsi->macvlan_list);\n+\t}\n+err_free:\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 can't be a multiqueue device */\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+\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_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_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\t} else {\n+\t\t\t\t\tdev_info(&pf->pdev->dev,\n+\t\t\t\t\t\t \"Error deleting mac filter on macvlan err %s, aq_err %s\\n\",\n+\t\t\t\t\t\t i40e_stat_str(hw, ret),\n+\t\t\t\t\t\t i40e_aq_str(hw, aq_err));\n+\t\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@@ -11580,6 +11993,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@@ -12313,6 +12729,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@@ -12372,6 +12790,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": []
}