get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 745024,
    "url": "http://patchwork.ozlabs.org/api/patches/745024/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/1490833375-2788-6-git-send-email-sridhar.samudrala@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": "<1490833375-2788-6-git-send-email-sridhar.samudrala@intel.com>",
    "list_archive_url": null,
    "date": "2017-03-30T00:22:53",
    "name": "[next-queue,v6,5/7] i40e: Add TX and RX support over port netdev's in switchdev mode",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "9e6af1082fb923867d6580f69b8781b9eb52b8b4",
    "submitter": {
        "id": 65219,
        "url": "http://patchwork.ozlabs.org/api/people/65219/?format=api",
        "name": "Samudrala, Sridhar",
        "email": "sridhar.samudrala@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/1490833375-2788-6-git-send-email-sridhar.samudrala@intel.com/mbox/",
    "series": [],
    "comments": "http://patchwork.ozlabs.org/api/patches/745024/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/745024/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<intel-wired-lan-bounces@lists.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"
        ],
        "Received": [
            "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3vtljG2hFvz9rxm\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 30 Mar 2017 11:23:30 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id DE86C2E94D;\n\tThu, 30 Mar 2017 00:23:28 +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 KpdoVVF29rf4; Thu, 30 Mar 2017 00:23:17 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby silver.osuosl.org (Postfix) with ESMTP id 10F012FDEB;\n\tThu, 30 Mar 2017 00:23:06 +0000 (UTC)",
            "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id 22E461CE8BC\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 30 Mar 2017 00:23:05 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 1E99C89021\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 30 Mar 2017 00:23:05 +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 N1R1xRQbWOLC for <intel-wired-lan@lists.osuosl.org>;\n\tThu, 30 Mar 2017 00:22:57 +0000 (UTC)",
            "from mga07.intel.com (mga07.intel.com [134.134.136.100])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id 250E889038\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 30 Mar 2017 00:22:57 +0000 (UTC)",
            "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby orsmga105.jf.intel.com with ESMTP; 29 Mar 2017 17:22:56 -0700",
            "from arch-p28.jf.intel.com ([10.166.187.27])\n\tby orsmga003.jf.intel.com with ESMTP; 29 Mar 2017 17:22:56 -0700"
        ],
        "X-Virus-Scanned": [
            "amavisd-new at osuosl.org",
            "amavisd-new at osuosl.org"
        ],
        "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.36,244,1486454400\"; d=\"scan'208\";a=\"949601329\"",
        "From": "Sridhar Samudrala <sridhar.samudrala@intel.com>",
        "To": "intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org,\n\talexander.h.duyck@intel.com, anjali.singhai@intel.com,\n\tjakub.kicinski@netronome.com, gerlitz.or@gmail.com, jiri@resnulli.us, \n\tsridhar.samudrala@intel.com",
        "Date": "Wed, 29 Mar 2017 17:22:53 -0700",
        "Message-Id": "<1490833375-2788-6-git-send-email-sridhar.samudrala@intel.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1490833375-2788-1-git-send-email-sridhar.samudrala@intel.com>",
        "References": "<1490833375-2788-1-git-send-email-sridhar.samudrala@intel.com>",
        "Subject": "[Intel-wired-lan] [next-queue v6 PATCH 5/7] i40e: Add TX and RX\n\tsupport over port netdev's in switchdev mode",
        "X-BeenThere": "intel-wired-lan@lists.osuosl.org",
        "X-Mailman-Version": "2.1.18-1",
        "Precedence": "list",
        "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.lists.osuosl.org>",
        "List-Unsubscribe": "<http://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>",
        "List-Post": "<mailto:intel-wired-lan@lists.osuosl.org>",
        "List-Help": "<mailto:intel-wired-lan-request@lists.osuosl.org?subject=help>",
        "List-Subscribe": "<http://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=subscribe>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "intel-wired-lan-bounces@lists.osuosl.org",
        "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@lists.osuosl.org>"
    },
    "content": "In switchdev mode, broadcasts from VFs are received by the PF and passed\nto corresponding port representor netdev.\nAny frames sent via port netdevs are sent as directed transmits to the\ncorresponding VFs. To enable directed transmit, skb metadata dst is used\nto pass the port id and the frame is requeued to call the PFs transmit\nroutine. VF id is used as port id for VFs and PF port id is defined as\nI40_MAIN_VSI_PORT_ID.\n\nSmall script to demonstrate inter VF and PF to VF pings in switchdev mode.\nPF: p4p1, VFs: p4p1_0,p4p1_1 VF Port Reps:p4p1-vf0, p4p1-vf1\nPF Port rep: p4p1-pf\n\n# rmmod i40e; modprobe i40e\n# devlink dev eswitch set pci/0000:05:00.0 mode switchdev\n# echo 2 > /sys/class/net/p4p1/device/sriov_numvfs\n# ip link set p4p1 vf 0 mac 00:11:22:33:44:55\n# ip link set p4p1 vf 1 mac 00:11:22:33:44:56\n# rmmod i40evf; modprobe i40evf\n\n/* Create 2 namespaces and move the VFs to the corresponding ns */\n# ip netns add ns0\n# ip link set p4p1_0 netns ns0\n# ip netns exec ns0 ip addr add 192.168.1.10/24 dev p4p1_0\n# ip netns exec ns0 ip link set p4p1_0 up\n# ip netns add ns1\n# ip link set p4p1_1 netns ns1\n# ip netns exec ns1 ip addr add 192.168.1.11/24 dev p4p1_1\n# ip netns exec ns1 ip link set p4p1_1 up\n\n/* bring up pf and port netdevs */\n# ip addr add 192.168.1.1/24 dev p4p1\n# ip link set p4p1 up\n# ip link set p4p1-vf0 up\n# ip link set p4p1-vf1 up\n# ip link set p4p1-pf up\n\n# ip netns exec ns0 ping -c3 192.168.1.11  /* VF0 -> VF1 */\n# ip netns exec ns1 ping -c3 192.168.1.10  /* VF1 -> VF0 */\n# ping -c3 192.168.1.10   /* PF -> VF0 */\n# ping -c3 192.168.1.11   /* PF -> VF1 */\n\n/* VF0 -> IP in same subnet - broadcasts will be seen on p4p1-vf0 & p4p1 */\n# ip netns exec ns0 ping -c1 -W1 192.168.1.200\n/* VF1 -> IP in same subnet -  broadcasts will be seen on p4p1-vf1 & p4p1*/\n# ip netns exec ns0 ping -c1 -W1 192.168.1.200\n/* port rep VF0 -> IP in same subnet - broadcasts will be seen on p4p1_0 */\n# ping -I p4p1-vf0 -c1 -W1 192.168.1.200\n/* port rep VF1 -> IP in same subnet  - broadcasts will be seen on p4p1_1 */\n# ping -I p4p1-vf1 -c1 -W1 192.168.1.200\n\nSigned-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>\n---\n drivers/net/ethernet/intel/i40e/i40e.h             |   4 +\n drivers/net/ethernet/intel/i40e/i40e_main.c        |  27 +++-\n drivers/net/ethernet/intel/i40e/i40e_txrx.c        | 148 ++++++++++++++++++++-\n drivers/net/ethernet/intel/i40e/i40e_txrx.h        |   2 +\n drivers/net/ethernet/intel/i40e/i40e_type.h        |   3 +\n drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c |   8 +-\n 6 files changed, 184 insertions(+), 8 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h\nindex c865803..ac11005 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e.h\n@@ -55,6 +55,7 @@\n #include <linux/net_tstamp.h>\n #include <linux/ptp_clock_kernel.h>\n #include <net/devlink.h>\n+#include <net/dst_metadata.h>\n \n #include \"i40e_type.h\"\n #include \"i40e_prototype.h\"\n@@ -320,6 +321,8 @@ struct i40e_flex_pit {\n \tu8 pit_index;\n };\n \n+#define I40E_MAIN_VSI_PORT_ID\t(1 << 15)\n+\n enum i40e_port_netdev_type {\n \tI40E_PORT_NETDEV_PF,\n \tI40E_PORT_NETDEV_VF\n@@ -328,6 +331,7 @@ enum i40e_port_netdev_type {\n /* Port representor netdev private structure */\n struct i40e_port_netdev_priv {\n \tenum i40e_port_netdev_type type;\t/* type - PF or VF */\n+\tstruct metadata_dst *dst;\t\t/* port id */\n \tvoid *f;\t\t\t\t/* ptr to PF or VF struct */\n };\n \ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c\nindex 683aa20..e9c5c6b 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_main.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c\n@@ -5519,8 +5519,10 @@ int i40e_open(struct net_device *netdev)\n \n \tudp_tunnel_get_rx_info(netdev);\n \n-\tif (pf->port_netdev)\n+\tif (pf->port_netdev) {\n \t\tnetif_carrier_on(pf->port_netdev);\n+\t\tnetif_tx_start_all_queues(pf->port_netdev);\n+\t}\n \n \treturn 0;\n }\n@@ -5675,8 +5677,10 @@ int i40e_close(struct net_device *netdev)\n \n \ti40e_vsi_close(vsi);\n \n-\tif (pf->port_netdev)\n+\tif (pf->port_netdev) {\n \t\tnetif_carrier_off(pf->port_netdev);\n+\t\tnetif_tx_stop_all_queues(pf->port_netdev);\n+\t}\n \n \treturn 0;\n }\n@@ -10872,6 +10876,7 @@ static int i40e_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)\n static int i40e_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)\n {\n \tstruct i40e_pf *pf = devlink_priv(devlink);\n+\tstruct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];\n \tstruct i40e_vf *vf;\n \tint i, j, err = 0;\n \n@@ -10886,6 +10891,8 @@ static int i40e_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)\n \t\t}\n \t\ti40e_free_port_netdev(pf, I40E_PORT_NETDEV_PF);\n \t\tpf->eswitch_mode = mode;\n+\t\tvsi->netdev->priv_flags |=\n+\t\t\t(IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM);\n \t\tbreak;\n \tcase DEVLINK_ESWITCH_MODE_SWITCHDEV:\n \t\terr = i40e_alloc_port_netdev(pf, I40E_PORT_NETDEV_PF);\n@@ -10905,6 +10912,7 @@ static int i40e_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)\n \t\t\t}\n \t\t}\n \t\tpf->eswitch_mode = mode;\n+\t\tnetif_keep_dst(vsi->netdev);\n \t\tbreak;\n \tdefault:\n \t\terr = -EOPNOTSUPP;\n@@ -10996,6 +11004,7 @@ static int i40e_port_netdev_stop(struct net_device *dev)\n static const struct net_device_ops i40e_port_netdev_ops = {\n \t.ndo_open\t\t= i40e_port_netdev_open,\n \t.ndo_stop\t\t= i40e_port_netdev_stop,\n+\t.ndo_start_xmit\t\t= i40e_port_netdev_start_xmit,\n };\n \n /**\n@@ -11034,6 +11043,10 @@ int i40e_alloc_port_netdev(void *f, enum i40e_port_netdev_type type)\n \t\tpriv = netdev_priv(port_netdev);\n \t\tpriv->f = pf;\n \t\tpriv->type = I40E_PORT_NETDEV_PF;\n+\t\tpriv->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX,\n+\t\t\t\t\t       GFP_KERNEL);\n+\t\tpriv->dst->u.port_info.lower_dev = vsi->netdev;\n+\t\tpriv->dst->u.port_info.port_id = I40E_MAIN_VSI_PORT_ID;\n \t\tbreak;\n \tcase I40E_PORT_NETDEV_VF:\n \t\tvf = (struct i40e_vf *)f;\n@@ -11055,6 +11068,10 @@ int i40e_alloc_port_netdev(void *f, enum i40e_port_netdev_type type)\n \t\tpriv = netdev_priv(port_netdev);\n \t\tpriv->f = vf;\n \t\tpriv->type = I40E_PORT_NETDEV_VF;\n+\t\tpriv->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX,\n+\t\t\t\t\t       GFP_KERNEL);\n+\t\tpriv->dst->u.port_info.lower_dev = vsi->netdev;\n+\t\tpriv->dst->u.port_info.port_id = vf->vf_id;\n \t\tbreak;\n \tdefault:\n \t\treturn -EINVAL;\n@@ -11070,6 +11087,7 @@ int i40e_alloc_port_netdev(void *f, enum i40e_port_netdev_type type)\n \tif (err) {\n \t\tdev_err(&pf->pdev->dev, \"register_netdev failed for port netdev: %s\\n\",\n \t\t\tport_netdev->name);\n+\t\tdst_release((struct dst_entry *)priv->dst);\n \t\tfree_netdev(port_netdev);\n \t\treturn err;\n \t}\n@@ -11110,6 +11128,7 @@ int i40e_alloc_port_netdev(void *f, enum i40e_port_netdev_type type)\n  **/\n void i40e_free_port_netdev(void *f, enum i40e_port_netdev_type type)\n {\n+\tstruct i40e_port_netdev_priv *priv;\n \tstruct i40e_pf *pf;\n \tstruct i40e_vf *vf;\n \tstruct i40e_vsi *vsi;\n@@ -11123,6 +11142,8 @@ void i40e_free_port_netdev(void *f, enum i40e_port_netdev_type type)\n \t\t\treturn;\n \t\tdev_info(&pf->pdev->dev, \"Freeing PF Port representor %s\\n\",\n \t\t\t pf->port_netdev->name);\n+\t\tpriv = netdev_priv(pf->port_netdev);\n+\t\tdst_release((struct dst_entry *)priv->dst);\n \t\tunregister_netdev(pf->port_netdev);\n \t\tfree_netdev(pf->port_netdev);\n \t\tpf->port_netdev = NULL;\n@@ -11140,6 +11161,8 @@ void i40e_free_port_netdev(void *f, enum i40e_port_netdev_type type)\n \t\t\treturn;\n \t\tdev_info(&pf->pdev->dev, \"Freeing VF Port representor %s\\n\",\n \t\t\t vf->port_netdev->name);\n+\t\tpriv = netdev_priv(vf->port_netdev);\n+\t\tdst_release((struct dst_entry *)priv->dst);\n \t\tunregister_netdev(vf->port_netdev);\n \t\tfree_netdev(vf->port_netdev);\n \t\tvf->port_netdev = NULL;\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c\nindex ebffca0..86d2510 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c\n@@ -1302,20 +1302,64 @@ static bool i40e_alloc_mapped_page(struct i40e_ring *rx_ring,\n }\n \n /**\n+ * i40e_handle_lpbk_skb - Update skb->dev of a loopback frame\n+ * @rx_ring: rx ring in play\n+ * @skb: packet to send up\n+ **/\n+static void i40e_handle_lpbk_skb(struct i40e_ring *rx_ring, struct sk_buff *skb)\n+{\n+\tstruct i40e_q_vector *q_vector = rx_ring->q_vector;\n+\tstruct i40e_pf *pf = rx_ring->vsi->back;\n+\tstruct sk_buff *nskb;\n+\tstruct i40e_vf *vf;\n+\tstruct ethhdr *eth;\n+\tint vf_id;\n+\n+\tif ((skb->pkt_type != PACKET_BROADCAST) &&\n+\t    (skb->pkt_type != PACKET_MULTICAST) &&\n+\t    (skb->pkt_type != PACKET_OTHERHOST))\n+\t\treturn;\n+\n+\teth = (struct ethhdr *)skb_mac_header(skb);\n+\n+\t/* If a loopback packet is received in switchdev mode, clone the skb\n+\t * and pass it to the corresponding port netdev based on the source MAC.\n+\t */\n+\tfor (vf_id = 0; vf_id < pf->num_alloc_vfs; vf_id++) {\n+\t\tvf = &pf->vf[vf_id];\n+\t\tif (ether_addr_equal(eth->h_source,\n+\t\t\t\t     vf->default_lan_addr.addr)) {\n+\t\t\tnskb = skb_clone(skb, GFP_ATOMIC);\n+\t\t\tif (!nskb)\n+\t\t\t\tbreak;\n+\t\t\tnskb->offload_fwd_mark = 1;\n+\t\t\tnskb->dev = vf->port_netdev;\n+\t\t\tnapi_gro_receive(&q_vector->napi, nskb);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+}\n+\n+/**\n  * i40e_receive_skb - Send a completed packet up the stack\n  * @rx_ring:  rx ring in play\n  * @skb: packet to send up\n  * @vlan_tag: vlan tag for packet\n+ * @lpbk: is it a loopback frame?\n  **/\n static void i40e_receive_skb(struct i40e_ring *rx_ring,\n-\t\t\t     struct sk_buff *skb, u16 vlan_tag)\n+\t\t\t     struct sk_buff *skb, u16 vlan_tag, bool lpbk)\n {\n \tstruct i40e_q_vector *q_vector = rx_ring->q_vector;\n+\tstruct i40e_pf *pf = rx_ring->vsi->back;\n \n \tif ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&\n \t    (vlan_tag & VLAN_VID_MASK))\n \t\t__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);\n \n+\tif ((pf->eswitch_mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) && lpbk)\n+\t\ti40e_handle_lpbk_skb(rx_ring, skb);\n+\n \tnapi_gro_receive(&q_vector->napi, skb);\n }\n \n@@ -1528,6 +1572,7 @@ static inline void i40e_rx_hash(struct i40e_ring *ring,\n  * @rx_desc: pointer to the EOP Rx descriptor\n  * @skb: pointer to current skb being populated\n  * @rx_ptype: the packet type decoded by hardware\n+ * @lpbk: is it a loopback frame?\n  *\n  * This function checks the ring, descriptor, and packet information in\n  * order to populate the hash, checksum, VLAN, protocol, and\n@@ -1536,7 +1581,7 @@ static inline void i40e_rx_hash(struct i40e_ring *ring,\n static inline\n void i40e_process_skb_fields(struct i40e_ring *rx_ring,\n \t\t\t     union i40e_rx_desc *rx_desc, struct sk_buff *skb,\n-\t\t\t     u8 rx_ptype)\n+\t\t\t     u8 rx_ptype, bool *lpbk)\n {\n \tu64 qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);\n \tu32 rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>\n@@ -1545,6 +1590,9 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,\n \tu32 tsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>\n \t\t   I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT;\n \n+\t*lpbk = !!((rx_status & I40E_RXD_QW1_STATUS_LPBK_MASK) >>\n+\t\tI40E_RXD_QW1_STATUS_LPBK_SHIFT);\n+\n \tif (unlikely(tsynvalid))\n \t\ti40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, tsyn);\n \n@@ -1898,6 +1946,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)\n \t\tu16 vlan_tag;\n \t\tu8 rx_ptype;\n \t\tu64 qword;\n+\t\tbool lpbk;\n \n \t\t/* return some buffers to hardware, one at a time is too slow */\n \t\tif (cleaned_count >= I40E_RX_BUFFER_WRITE) {\n@@ -1970,12 +2019,12 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)\n \t\t\t   I40E_RXD_QW1_PTYPE_SHIFT;\n \n \t\t/* populate checksum, VLAN, and protocol */\n-\t\ti40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);\n+\t\ti40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype, &lpbk);\n \n \t\tvlan_tag = (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) ?\n \t\t\t   le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0;\n \n-\t\ti40e_receive_skb(rx_ring, skb, vlan_tag);\n+\t\ti40e_receive_skb(rx_ring, skb, vlan_tag, lpbk);\n \t\tskb = NULL;\n \n \t\t/* update budget accounting */\n@@ -3037,6 +3086,58 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,\n }\n \n /**\n+ * i40e_tvsi - set up the target vsi in TX context descriptor\n+ * @skb:     send buffer\n+ * @tx_ring:  ptr to the target vsi\n+ * @cd_type_cmd_tso_mss: Quad Word 1\n+ *\n+ * Returns 0 on success, -EINVAL on error\n+ **/\n+static int i40e_tvsi(struct sk_buff *skb, struct i40e_ring *tx_ring,\n+\t\t     u64 *cd_type_cmd_tso_mss)\n+{\n+\tstruct metadata_dst *md_dst = skb_metadata_dst(skb);\n+\tstruct i40e_pf *pf;\n+\tstruct i40e_vsi *t_vsi = NULL;\n+\tstruct i40e_vf *t_vf;\n+\tu64 cd_cmd, cd_tvsi;\n+\tu32 port_id;\n+\n+\t/* If skb metadata dst points to a port id, do a directed transmit to\n+\t * that VSI. TSO is mutually exclusive with this option. So TSO is not\n+\t * enabled when doing a directed transmit.\n+\t */\n+\tif (!md_dst || (md_dst->type != METADATA_HW_PORT_MUX))\n+\t\treturn 0;\n+\n+\tport_id = md_dst->u.port_info.port_id;\n+\n+\tpf = tx_ring->vsi->back;\n+\tif ((port_id >= pf->num_alloc_vfs) &&\n+\t    (port_id != I40E_MAIN_VSI_PORT_ID)) {\n+\t\tWARN_ONCE(1, \"Unexpected port_id: %d num_vfs:%d\\n\",\n+\t\t\t  md_dst->u.port_info.port_id, pf->num_alloc_vfs);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (port_id == I40E_MAIN_VSI_PORT_ID) {\n+\t\tt_vsi = pf->vsi[pf->lan_vsi];\n+\t} else {\n+\t\tt_vf = &pf->vf[port_id];\n+\t\tt_vsi = pf->vsi[t_vf->lan_vsi_idx];\n+\t}\n+\n+\tcd_cmd = I40E_TX_CTX_DESC_SWTCH_VSI;\n+\tcd_tvsi = t_vsi->id;\n+\tcd_tvsi = (cd_tvsi << I40E_TXD_CTX_QW1_VSI_SHIFT) &\n+\t\t  I40E_TXD_CTX_QW1_VSI_MASK;\n+\t*cd_type_cmd_tso_mss |= (cd_cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) |\n+\t\t\t\t cd_tvsi;\n+\n+\treturn 0;\n+}\n+\n+/**\n  * i40e_xmit_frame_ring - Sends buffer on Tx ring\n  * @skb:     send buffer\n  * @tx_ring: ring to send buffer on\n@@ -3101,6 +3202,8 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,\n \t\ttx_flags |= I40E_TX_FLAGS_IPV6;\n \n \ttso = i40e_tso(first, &hdr_len, &cd_type_cmd_tso_mss);\n+\tif (!tso)\n+\t\ttso = i40e_tvsi(skb, tx_ring, &cd_type_cmd_tso_mss);\n \n \tif (tso < 0)\n \t\tgoto out_drop;\n@@ -3164,3 +3267,40 @@ netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev)\n \n \treturn i40e_xmit_frame_ring(skb, tx_ring);\n }\n+\n+/**\n+ * i40e_port_netdev_start_xmit\n+ * @skb:    send buffer\n+ * @netdev: network interface device structure\n+ *\n+ * Sets skb->dev to PF netdev, and port id in the skb->dst and requeues\n+ * skb via dev_queue_xmit()\n+ **/\n+netdev_tx_t i40e_port_netdev_start_xmit(struct sk_buff *skb,\n+\t\t\t\t\tstruct net_device *netdev)\n+{\n+\tstruct i40e_port_netdev_priv *priv = netdev_priv(netdev);\n+\tstruct i40e_vsi *vsi;\n+\tstruct i40e_pf *pf;\n+\tstruct i40e_vf *vf;\n+\n+\tswitch (priv->type) {\n+\tcase I40E_PORT_NETDEV_VF:\n+\t\tvf = (struct i40e_vf *)priv->f;\n+\t\tpf = vf->pf;\n+\t\tbreak;\n+\tcase I40E_PORT_NETDEV_PF:\n+\t\tpf = (struct i40e_pf *)priv->f;\n+\t\tbreak;\n+\tdefault:\n+\t\tdev_kfree_skb_any(skb);\n+\t\treturn NETDEV_TX_OK;\n+\t}\n+\n+\tvsi = pf->vsi[pf->lan_vsi];\n+\tdst_hold(&priv->dst->dst);\n+\tskb_dst_set(skb, &priv->dst->dst);\n+\tskb->dev = vsi->netdev;\n+\n+\treturn dev_queue_xmit(skb);\n+}\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h\nindex d6609de..715de92 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h\n@@ -392,6 +392,8 @@ struct i40e_ring_container {\n \n bool i40e_alloc_rx_buffers(struct i40e_ring *rxr, u16 cleaned_count);\n netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev);\n+netdev_tx_t i40e_port_netdev_start_xmit(struct sk_buff *skb,\n+\t\t\t\t\tstruct net_device *netdev);\n void i40e_clean_tx_ring(struct i40e_ring *tx_ring);\n void i40e_clean_rx_ring(struct i40e_ring *rx_ring);\n int i40e_setup_tx_descriptors(struct i40e_ring *tx_ring);\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h\nindex 9200f2d..08364a4 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_type.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h\n@@ -729,6 +729,9 @@ enum i40e_rx_desc_status_bits {\n #define I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT  I40E_RX_DESC_STATUS_TSYNVALID_SHIFT\n #define I40E_RXD_QW1_STATUS_TSYNVALID_MASK \\\n \t\t\t\t    BIT_ULL(I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT)\n+#define I40E_RXD_QW1_STATUS_LPBK_SHIFT  I40E_RX_DESC_STATUS_LPBK_SHIFT\n+#define I40E_RXD_QW1_STATUS_LPBK_MASK \\\n+\t\t\t\tBIT_ULL(I40E_RXD_QW1_STATUS_LPBK_SHIFT)\n \n enum i40e_rx_desc_fltstat_values {\n \tI40E_RX_DESC_FLTSTAT_NO_DATA\t= 0,\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c\nindex 7c2e7b0..f8d25cb 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c\n@@ -1806,8 +1806,10 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)\n \tif (i40e_vsi_start_rings(pf->vsi[vf->lan_vsi_idx]))\n \t\taq_ret = I40E_ERR_TIMEOUT;\n \n-\tif ((aq_ret == 0) && vf->port_netdev)\n+\tif ((aq_ret == 0) && vf->port_netdev) {\n \t\tnetif_carrier_on(vf->port_netdev);\n+\t\tnetif_tx_start_all_queues(vf->port_netdev);\n+\t}\n \n error_param:\n \t/* send the response to the VF */\n@@ -1848,8 +1850,10 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)\n \n \ti40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);\n \n-\tif ((aq_ret == 0) && vf->port_netdev)\n+\tif ((aq_ret == 0) && vf->port_netdev) {\n+\t\tnetif_tx_stop_all_queues(vf->port_netdev);\n \t\tnetif_carrier_off(vf->port_netdev);\n+\t}\n \n error_param:\n \t/* send the response to the VF */\n",
    "prefixes": [
        "next-queue",
        "v6",
        "5/7"
    ]
}