From patchwork Thu Feb 4 21:59:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: George McCollister X-Patchwork-Id: 12068871 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9BB64C433E6 for ; Thu, 4 Feb 2021 22:00:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4DB7D64FA0 for ; Thu, 4 Feb 2021 22:00:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230051AbhBDWAq (ORCPT ); Thu, 4 Feb 2021 17:00:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38652 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229511AbhBDWAn (ORCPT ); Thu, 4 Feb 2021 17:00:43 -0500 Received: from mail-oi1-x22c.google.com (mail-oi1-x22c.google.com [IPv6:2607:f8b0:4864:20::22c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1CF9CC061788 for ; Thu, 4 Feb 2021 14:00:03 -0800 (PST) Received: by mail-oi1-x22c.google.com with SMTP id n7so5321874oic.11 for ; Thu, 04 Feb 2021 14:00:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=fdRfZFSaOXPBtGvI5pkTo8JDuSXxlPXCgYgl9rI+dP8=; b=XT16Z6zMmDD6Ljfys7j9OhEfJVMg5BYnokcTU7cSjluLOXyqFhoxYvv3aEMd5jFCpO Ojrlmmp8dIkoFmyB2wSgjPbCnbpcTlV8XoQtmmfFF1GeeDsQUImFticvFLq95wkOuGO3 KCXyjE+of1aMfz8YuVVeC4HPGoyo2POevZfRU1GZfeQq1xrlThn2JCQEY/iu2l1H1sev VM4Yu/1OpQJCMh9lmPIthU8lfex1Q/hkRJ9QjL0UaH469M1tGX+Ak3OtptPt67vIUraw kz2BlENIlfe2RdJjFCUxrHOjUKchkdI92VzMObe5zef22VCizyl4PPnTDjvqXc5pqZgA HtOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=fdRfZFSaOXPBtGvI5pkTo8JDuSXxlPXCgYgl9rI+dP8=; b=CwEnBWs+CVUJIxGktGf+7RI5B2miYDSnqPFPxl77YHgK8mC+IzAUG6Js5LFo13uFDv XxRaMubQ3w/lyau18IVzGxvkDpXdW2mbZieGeIm0VtKTTo2aWpDJ91uEqRyJ9FRA/ejs JvNbDnjkI8NqmQj8PFmjCurGfP6bUz61KX459qQqDB1xXBTszu9/rt3y/9oK8JnUtjMR SiVt7emlkktObkWKAfxAyjRlKtqyz07W+BfJLwQ5BJvRXgImJ8xF5q8moSs5p1ynT9Kc k3du2FvGZ1b5qhD8l9B006NWOjhkweUlz66M3SMmsNTw674T3NeUcBsoamldVy/x8RWb zy5g== X-Gm-Message-State: AOAM530kTxpxOOk4/fVavN2VOkI0hviqnhGdSRR9/SV87bv1OklALyS3 HytvR/8RLltCiFKsnAwKKA== X-Google-Smtp-Source: ABdhPJw9rzgLOF3qmqhd3/NQzrljBa+QL4BMwFgH/ePp72Us7/mV/1k2hPySLUvTDQwmLz9JoxAXmg== X-Received: by 2002:a05:6808:f09:: with SMTP id m9mr1103023oiw.92.1612476002573; Thu, 04 Feb 2021 14:00:02 -0800 (PST) Received: from threadripper.novatech-llc.local ([216.21.169.52]) by smtp.gmail.com with ESMTPSA id y10sm1361395ooy.11.2021.02.04.14.00.00 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 04 Feb 2021 14:00:01 -0800 (PST) From: George McCollister To: Jakub Kicinski Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jonathan Corbet , netdev@vger.kernel.org, George McCollister Subject: [PATCH net-next v2 1/4] net: hsr: generate supervision frame without HSR/PRP tag Date: Thu, 4 Feb 2021 15:59:23 -0600 Message-Id: <20210204215926.64377-2-george.mccollister@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20210204215926.64377-1-george.mccollister@gmail.com> References: <20210204215926.64377-1-george.mccollister@gmail.com> Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org For a switch to offload insertion of HSR/PRP tags, frames must not be sent to the CPU facing switch port with a tag. Generate supervision frames (eth type ETH_P_PRP) without HSR v1 (ETH_P_HSR)/PRP tag and rely on create_tagged_frame which inserts it later. This will allow skipping the tag insertion for all outgoing frames in the future which is required for HSR v1/PRP tag insertions to be offloaded. HSR v0 supervision frames always contain tag information so insertion of the tag can't be offloaded. IEC 62439-3 Ed.2.0 (HSR v1) specifically notes that this was changed since v0 to allow offloading. Signed-off-by: George McCollister --- net/hsr/hsr_device.c | 32 ++++---------------------------- net/hsr/hsr_forward.c | 6 +++++- 2 files changed, 9 insertions(+), 29 deletions(-) diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index ab953a1a0d6c..161b8da6a21d 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c @@ -242,8 +242,7 @@ static struct sk_buff *hsr_init_skb(struct hsr_port *master, u16 proto) * being, for PRP it is a trailer and for HSR it is a * header */ - skb = dev_alloc_skb(sizeof(struct hsr_tag) + - sizeof(struct hsr_sup_tag) + + skb = dev_alloc_skb(sizeof(struct hsr_sup_tag) + sizeof(struct hsr_sup_payload) + hlen + tlen); if (!skb) @@ -275,12 +274,10 @@ static void send_hsr_supervision_frame(struct hsr_port *master, { struct hsr_priv *hsr = master->hsr; __u8 type = HSR_TLV_LIFE_CHECK; - struct hsr_tag *hsr_tag = NULL; struct hsr_sup_payload *hsr_sp; struct hsr_sup_tag *hsr_stag; unsigned long irqflags; struct sk_buff *skb; - u16 proto; *interval = msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL); if (hsr->announce_count < 3 && hsr->prot_version == 0) { @@ -289,23 +286,12 @@ static void send_hsr_supervision_frame(struct hsr_port *master, hsr->announce_count++; } - if (!hsr->prot_version) - proto = ETH_P_PRP; - else - proto = ETH_P_HSR; - - skb = hsr_init_skb(master, proto); + skb = hsr_init_skb(master, ETH_P_PRP); if (!skb) { WARN_ONCE(1, "HSR: Could not send supervision frame\n"); return; } - if (hsr->prot_version > 0) { - hsr_tag = skb_put(skb, sizeof(struct hsr_tag)); - hsr_tag->encap_proto = htons(ETH_P_PRP); - set_hsr_tag_LSDU_size(hsr_tag, HSR_V1_SUP_LSDUSIZE); - } - hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag)); set_hsr_stag_path(hsr_stag, (hsr->prot_version ? 0x0 : 0xf)); set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version); @@ -315,8 +301,6 @@ static void send_hsr_supervision_frame(struct hsr_port *master, if (hsr->prot_version > 0) { hsr_stag->sequence_nr = htons(hsr->sup_sequence_nr); hsr->sup_sequence_nr++; - hsr_tag->sequence_nr = htons(hsr->sequence_nr); - hsr->sequence_nr++; } else { hsr_stag->sequence_nr = htons(hsr->sequence_nr); hsr->sequence_nr++; @@ -332,7 +316,7 @@ static void send_hsr_supervision_frame(struct hsr_port *master, hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload)); ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr); - if (skb_put_padto(skb, ETH_ZLEN + HSR_HLEN)) + if (skb_put_padto(skb, ETH_ZLEN)) return; hsr_forward_skb(skb, master); @@ -348,8 +332,6 @@ static void send_prp_supervision_frame(struct hsr_port *master, struct hsr_sup_tag *hsr_stag; unsigned long irqflags; struct sk_buff *skb; - struct prp_rct *rct; - u8 *tail; skb = hsr_init_skb(master, ETH_P_PRP); if (!skb) { @@ -373,17 +355,11 @@ static void send_prp_supervision_frame(struct hsr_port *master, hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload)); ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr); - if (skb_put_padto(skb, ETH_ZLEN + HSR_HLEN)) { + if (skb_put_padto(skb, ETH_ZLEN)) { spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); return; } - tail = skb_tail_pointer(skb) - HSR_HLEN; - rct = (struct prp_rct *)tail; - rct->PRP_suffix = htons(ETH_P_PRP); - set_prp_LSDU_size(rct, HSR_V1_SUP_LSDUSIZE); - rct->sequence_nr = htons(hsr->sequence_nr); - hsr->sequence_nr++; spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); hsr_forward_skb(skb, master); diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c index cadfccd7876e..c11be87daa8f 100644 --- a/net/hsr/hsr_forward.c +++ b/net/hsr/hsr_forward.c @@ -454,7 +454,11 @@ static void handle_std_frame(struct sk_buff *skb, void hsr_fill_frame_info(__be16 proto, struct sk_buff *skb, struct hsr_frame_info *frame) { - if (proto == htons(ETH_P_PRP) || + struct hsr_port *port = frame->port_rcv; + struct hsr_priv *hsr = port->hsr; + + /* HSRv0 supervisory frames double as a tag so treat them as tagged. */ + if ((!hsr->prot_version && proto == htons(ETH_P_PRP)) || proto == htons(ETH_P_HSR)) { /* HSR tagged frame :- Data or Supervision */ frame->skb_std = NULL; From patchwork Thu Feb 4 21:59:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: George McCollister X-Patchwork-Id: 12068873 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF84AC433DB for ; Thu, 4 Feb 2021 22:00:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7258C64F4D for ; Thu, 4 Feb 2021 22:00:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230123AbhBDWAr (ORCPT ); Thu, 4 Feb 2021 17:00:47 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38662 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229996AbhBDWAp (ORCPT ); Thu, 4 Feb 2021 17:00:45 -0500 Received: from mail-ot1-x336.google.com (mail-ot1-x336.google.com [IPv6:2607:f8b0:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C2650C06178A for ; Thu, 4 Feb 2021 14:00:04 -0800 (PST) Received: by mail-ot1-x336.google.com with SMTP id d7so4979837otf.3 for ; Thu, 04 Feb 2021 14:00:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=qqU53tgBg2nv83amFXPsQJ1KgpCCHS4E3smZEotoTAs=; b=fBa6Lkb1imoLWso/BdduesDLAfXVWX2XG1WazJlXcweVbmI05qsbU7nGG8Brl/nk/a XJrm7zyiVMd25HXJJHJr8FSUpkKX4ONfPMGfAXBI2MYT/f6bDCUZuaL+/tb3rgGzbVPl tD8MzVGlKzizeFyZULAEeybGfdHs0WJuPGnZgOJ+f7l+7GqFDQdYTds0bhBpXWR7XRJy qmXgX+khMUAeZatu8NgLa3R95BDcQeZBoLcY7m4ic319MfzXIsWqLnomriFdRbyt0ox5 qQgPEX+rt1rCozs/aCn1ZQkJKhvLjnvagBmCgxfHsaG10tJxtZI06DW0nmFA/NYkkpN0 Br8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=qqU53tgBg2nv83amFXPsQJ1KgpCCHS4E3smZEotoTAs=; b=pIVqN2l9/kpPidj3CpPbh2+d642g36KAiUDabphpsGtglqOBRchYWX+XYTYciVa68M 0FlSXyzVIvpvk9ylbp5ALVsBwWnPqit+Fa8VPjbsfpzKivMbGMvTqf/A/q/uN+2tqznz iI19ayanU1GUNs0+3W942bNx0Z3sX8UTq4eVDVM7j3pZSp4VTwHrijKLnztuhry3Gs7w GvLTmkiEC5/3L6PK+5zLAHwO5US5sYzsNynMhSMJhdgH+LOD4yymcW+FVKoN/Wu6n9ky nv43hob+cmoMiI+oDFRAbE2eR2qUQSAWXv8Wd0h/OwtEbWUcN0Lv+6ZLJGKyXUPMYOAi eJsg== X-Gm-Message-State: AOAM531SNWaXhajgQ5KSthkvPtlAxOl9I07BaTwrE/TLsicNWWZz4S+6 c0ELFWQRrc+lCTW/YGfEjA== X-Google-Smtp-Source: ABdhPJx319lXQkQXfxSBEPhqELNzvGE0xnB2sBMQGnyPuI2ufHpGxpDxTsQ7GoaTpt+bNTcsgPsokg== X-Received: by 2002:a9d:7b4d:: with SMTP id f13mr1110867oto.257.1612476004108; Thu, 04 Feb 2021 14:00:04 -0800 (PST) Received: from threadripper.novatech-llc.local ([216.21.169.52]) by smtp.gmail.com with ESMTPSA id y10sm1361395ooy.11.2021.02.04.14.00.02 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 04 Feb 2021 14:00:03 -0800 (PST) From: George McCollister To: Jakub Kicinski Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jonathan Corbet , netdev@vger.kernel.org, George McCollister Subject: [PATCH net-next v2 2/4] net: hsr: add offloading support Date: Thu, 4 Feb 2021 15:59:24 -0600 Message-Id: <20210204215926.64377-3-george.mccollister@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20210204215926.64377-1-george.mccollister@gmail.com> References: <20210204215926.64377-1-george.mccollister@gmail.com> Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Add support for offloading of HSR/PRP (IEC 62439-3) tag insertion tag removal, duplicate generation and forwarding. For HSR, insertion involves the switch adding a 6 byte HSR header after the 14 byte Ethernet header. For PRP it adds a 6 byte trailer. Tag removal involves automatically stripping the HSR/PRP header/trailer in the switch. This is possible when the switch also performs auto deduplication using the HSR/PRP header/trailer (making it no longer required). Forwarding involves automatically forwarding between redundant ports in an HSR. This is crucial because delay is accumulated as a frame passes through each node in the ring. Duplication involves the switch automatically sending a single frame from the CPU port to both redundant ports. This is required because the inserted HSR/PRP header/trailer must contain the same sequence number on the frames sent out both redundant ports. Export is_hsr_master so DSA can tell them apart from other devices in dsa_slave_changeupper. Signed-off-by: George McCollister --- Documentation/networking/netdev-features.rst | 21 +++++++++++++++++++++ include/linux/if_hsr.h | 27 +++++++++++++++++++++++++++ include/linux/netdev_features.h | 9 +++++++++ net/ethtool/common.c | 4 ++++ net/hsr/hsr_device.c | 14 +++----------- net/hsr/hsr_device.h | 1 - net/hsr/hsr_forward.c | 27 ++++++++++++++++++++++++--- net/hsr/hsr_forward.h | 1 + net/hsr/hsr_framereg.c | 2 ++ net/hsr/hsr_main.c | 11 +++++++++++ net/hsr/hsr_main.h | 8 +------- net/hsr/hsr_slave.c | 10 ++++++---- 12 files changed, 109 insertions(+), 26 deletions(-) create mode 100644 include/linux/if_hsr.h diff --git a/Documentation/networking/netdev-features.rst b/Documentation/networking/netdev-features.rst index a2d7d7160e39..d7b15bb64deb 100644 --- a/Documentation/networking/netdev-features.rst +++ b/Documentation/networking/netdev-features.rst @@ -182,3 +182,24 @@ stricter than Hardware LRO. A packet stream merged by Hardware GRO must be re-segmentable by GSO or TSO back to the exact original packet stream. Hardware GRO is dependent on RXCSUM since every packet successfully merged by hardware must also have the checksum verified by hardware. + +* hsr-tag-ins-offload + +This should be set for devices which insert an HSR (High-availability Seamless +Redundancy) or PRP (Parallel Redundancy Protocol) tag automatically. + +* hsr-tag-rm-offload + +This should be set for devices which remove HSR (High-availability Seamless +Redundancy) or PRP (Parallel Redundancy Protocol) tags automatically. + +* hsr-fwd-offload + +This should be set for devices which forward HSR (High-availability Seamless +Redundancy) frames from one port to another in hardware. + +* hsr-dup-offload + +This should be set for devices which duplicate outgoing HSR (High-availability +Seamless Redundancy) or PRP (Parallel Redundancy Protocol) tags automatically +frames in hardware. diff --git a/include/linux/if_hsr.h b/include/linux/if_hsr.h new file mode 100644 index 000000000000..38bbc537d4e4 --- /dev/null +++ b/include/linux/if_hsr.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_IF_HSR_H_ +#define _LINUX_IF_HSR_H_ + +/* used to differentiate various protocols */ +enum hsr_version { + HSR_V0 = 0, + HSR_V1, + PRP_V1, +}; + +#if IS_ENABLED(CONFIG_HSR) +extern bool is_hsr_master(struct net_device *dev); +extern int hsr_get_version(struct net_device *dev, enum hsr_version *ver); +#else +static inline bool is_hsr_master(struct net_device *dev) +{ + return false; +} +static inline int hsr_get_version(struct net_device *dev, + enum hsr_version *ver) +{ + return -EINVAL; +} +#endif /* CONFIG_HSR */ + +#endif /*_LINUX_IF_HSR_H_*/ diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index c06d6aaba9df..3de38d6a0aea 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -86,6 +86,11 @@ enum { NETIF_F_HW_MACSEC_BIT, /* Offload MACsec operations */ NETIF_F_GRO_UDP_FWD_BIT, /* Allow UDP GRO for forwarding */ + NETIF_F_HW_HSR_TAG_INS_BIT, /* Offload HSR tag insertion */ + NETIF_F_HW_HSR_TAG_RM_BIT, /* Offload HSR tag removal */ + NETIF_F_HW_HSR_FWD_BIT, /* Offload HSR forwarding */ + NETIF_F_HW_HSR_DUP_BIT, /* Offload HSR duplication */ + /* * Add your fresh new feature above and remember to update * netdev_features_strings[] in net/core/ethtool.c and maybe @@ -159,6 +164,10 @@ enum { #define NETIF_F_GSO_FRAGLIST __NETIF_F(GSO_FRAGLIST) #define NETIF_F_HW_MACSEC __NETIF_F(HW_MACSEC) #define NETIF_F_GRO_UDP_FWD __NETIF_F(GRO_UDP_FWD) +#define NETIF_F_HW_HSR_TAG_INS __NETIF_F(HW_HSR_TAG_INS) +#define NETIF_F_HW_HSR_TAG_RM __NETIF_F(HW_HSR_TAG_RM) +#define NETIF_F_HW_HSR_FWD __NETIF_F(HW_HSR_FWD) +#define NETIF_F_HW_HSR_DUP __NETIF_F(HW_HSR_DUP) /* Finds the next feature with the highest number of the range of start till 0. */ diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 835b9bba3e7e..c6a383dfd6c2 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -69,6 +69,10 @@ const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = { [NETIF_F_GRO_FRAGLIST_BIT] = "rx-gro-list", [NETIF_F_HW_MACSEC_BIT] = "macsec-hw-offload", [NETIF_F_GRO_UDP_FWD_BIT] = "rx-udp-gro-forwarding", + [NETIF_F_HW_HSR_TAG_INS_BIT] = "hsr-tag-ins-offload", + [NETIF_F_HW_HSR_TAG_RM_BIT] = "hsr-tag-rm-offload", + [NETIF_F_HW_HSR_FWD_BIT] = "hsr-fwd-offload", + [NETIF_F_HW_HSR_DUP_BIT] = "hsr-dup-offload", }; const char diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index 161b8da6a21d..1ff4fa3b383f 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c @@ -418,6 +418,7 @@ static struct hsr_proto_ops hsr_ops = { .send_sv_frame = send_hsr_supervision_frame, .create_tagged_frame = hsr_create_tagged_frame, .get_untagged_frame = hsr_get_untagged_frame, + .drop_frame = hsr_drop_frame, .fill_frame_info = hsr_fill_frame_info, .invalid_dan_ingress_frame = hsr_invalid_dan_ingress_frame, }; @@ -465,10 +466,11 @@ void hsr_dev_setup(struct net_device *dev) /* Return true if dev is a HSR master; return false otherwise. */ -inline bool is_hsr_master(struct net_device *dev) +bool is_hsr_master(struct net_device *dev) { return (dev->netdev_ops->ndo_start_xmit == hsr_dev_xmit); } +EXPORT_SYMBOL(is_hsr_master); /* Default multicast address for HSR Supervision frames */ static const unsigned char def_multicast_addr[ETH_ALEN] __aligned(2) = { @@ -521,16 +523,6 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], hsr->prot_version = protocol_version; - /* FIXME: should I modify the value of these? - * - * - hsr_dev->flags - i.e. - * IFF_MASTER/SLAVE? - * - hsr_dev->priv_flags - i.e. - * IFF_EBRIDGE? - * IFF_TX_SKB_SHARING? - * IFF_HSR_MASTER/SLAVE? - */ - /* Make sure the 1st call to netif_carrier_on() gets through */ netif_carrier_off(hsr_dev); diff --git a/net/hsr/hsr_device.h b/net/hsr/hsr_device.h index 868373822ee4..9060c92168f9 100644 --- a/net/hsr/hsr_device.h +++ b/net/hsr/hsr_device.h @@ -19,6 +19,5 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], unsigned char multicast_spec, u8 protocol_version, struct netlink_ext_ack *extack); void hsr_check_carrier_and_operstate(struct hsr_priv *hsr); -bool is_hsr_master(struct net_device *dev); int hsr_get_max_mtu(struct hsr_priv *hsr); #endif /* __HSR_DEVICE_H */ diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c index c11be87daa8f..76c650fa7345 100644 --- a/net/hsr/hsr_forward.c +++ b/net/hsr/hsr_forward.c @@ -247,6 +247,8 @@ struct sk_buff *hsr_create_tagged_frame(struct hsr_frame_info *frame, /* set the lane id properly */ hsr_set_path_id(hsr_ethhdr, port); return skb_clone(frame->skb_hsr, GFP_ATOMIC); + } else if (port->dev->features & NETIF_F_HW_HSR_TAG_INS) { + return skb_clone(frame->skb_std, GFP_ATOMIC); } /* Create the new skb with enough headroom to fit the HSR tag */ @@ -289,6 +291,8 @@ struct sk_buff *prp_create_tagged_frame(struct hsr_frame_info *frame, return NULL; } return skb_clone(frame->skb_prp, GFP_ATOMIC); + } else if (port->dev->features & NETIF_F_HW_HSR_TAG_INS) { + return skb_clone(frame->skb_std, GFP_ATOMIC); } skb = skb_copy_expand(frame->skb_std, 0, @@ -341,6 +345,14 @@ bool prp_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port) port->type == HSR_PT_SLAVE_A)); } +bool hsr_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port) +{ + if (port->dev->features & NETIF_F_HW_HSR_FWD) + return prp_drop_frame(frame, port); + + return false; +} + /* Forward the frame through all devices except: * - Back through the receiving device * - If it's a HSR frame: through a device where it has passed before @@ -357,6 +369,7 @@ static void hsr_forward_do(struct hsr_frame_info *frame) { struct hsr_port *port; struct sk_buff *skb; + bool sent = false; hsr_for_each_port(frame->port_rcv->hsr, port) { struct hsr_priv *hsr = port->hsr; @@ -372,6 +385,12 @@ static void hsr_forward_do(struct hsr_frame_info *frame) if (port->type != HSR_PT_MASTER && frame->is_local_exclusive) continue; + /* If hardware duplicate generation is enabled, only send out + * one port. + */ + if ((port->dev->features & NETIF_F_HW_HSR_DUP) && sent) + continue; + /* Don't send frame over port where it has been sent before. * Also fro SAN, this shouldn't be done. */ @@ -403,10 +422,12 @@ static void hsr_forward_do(struct hsr_frame_info *frame) } skb->dev = port->dev; - if (port->type == HSR_PT_MASTER) + if (port->type == HSR_PT_MASTER) { hsr_deliver_master(skb, port->dev, frame->node_src); - else - hsr_xmit(skb, port, frame); + } else { + if (!hsr_xmit(skb, port, frame)) + sent = true; + } } } diff --git a/net/hsr/hsr_forward.h b/net/hsr/hsr_forward.h index 618140d484ad..b6acaafa83fc 100644 --- a/net/hsr/hsr_forward.h +++ b/net/hsr/hsr_forward.h @@ -23,6 +23,7 @@ struct sk_buff *hsr_get_untagged_frame(struct hsr_frame_info *frame, struct sk_buff *prp_get_untagged_frame(struct hsr_frame_info *frame, struct hsr_port *port); bool prp_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port); +bool hsr_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port); void prp_fill_frame_info(__be16 proto, struct sk_buff *skb, struct hsr_frame_info *frame); void hsr_fill_frame_info(__be16 proto, struct sk_buff *skb, diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index 5c97de459905..f9a8cc82ae2e 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c @@ -277,6 +277,8 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) skb = frame->skb_hsr; else if (frame->skb_prp) skb = frame->skb_prp; + else if (frame->skb_std) + skb = frame->skb_std; if (!skb) return; diff --git a/net/hsr/hsr_main.c b/net/hsr/hsr_main.c index 2fd1976e5b1c..f7e284f23b1f 100644 --- a/net/hsr/hsr_main.c +++ b/net/hsr/hsr_main.c @@ -131,6 +131,17 @@ struct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt) return NULL; } +int hsr_get_version(struct net_device *dev, enum hsr_version *ver) +{ + struct hsr_priv *hsr; + + hsr = netdev_priv(dev); + *ver = hsr->prot_version; + + return 0; +} +EXPORT_SYMBOL(hsr_get_version); + static struct notifier_block hsr_nb = { .notifier_call = hsr_netdev_notify, /* Slave event notifications */ }; diff --git a/net/hsr/hsr_main.h b/net/hsr/hsr_main.h index a9c30a608e35..a169808ee78a 100644 --- a/net/hsr/hsr_main.h +++ b/net/hsr/hsr_main.h @@ -13,6 +13,7 @@ #include #include #include +#include /* Time constants as specified in the HSR specification (IEC-62439-3 2010) * Table 8. @@ -171,13 +172,6 @@ struct hsr_port { enum hsr_port_type type; }; -/* used by driver internally to differentiate various protocols */ -enum hsr_version { - HSR_V0 = 0, - HSR_V1, - PRP_V1, -}; - struct hsr_frame_info; struct hsr_node; diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c index 36d5fcf09c61..c5227d42faf5 100644 --- a/net/hsr/hsr_slave.c +++ b/net/hsr/hsr_slave.c @@ -48,12 +48,14 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb) goto finish_consume; } - /* For HSR, only tagged frames are expected, but for PRP - * there could be non tagged frames as well from Single - * attached nodes (SANs). + /* For HSR, only tagged frames are expected (unless the device offloads + * HSR tag removal), but for PRP there could be non tagged frames as + * well from Single attached nodes (SANs). */ protocol = eth_hdr(skb)->h_proto; - if (hsr->proto_ops->invalid_dan_ingress_frame && + + if (!(port->dev->features & NETIF_F_HW_HSR_TAG_RM) && + hsr->proto_ops->invalid_dan_ingress_frame && hsr->proto_ops->invalid_dan_ingress_frame(protocol)) goto finish_pass; From patchwork Thu Feb 4 21:59:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: George McCollister X-Patchwork-Id: 12068875 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ADEF3C433DB for ; Thu, 4 Feb 2021 22:01:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 69C6664FA0 for ; Thu, 4 Feb 2021 22:01:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229974AbhBDWBD (ORCPT ); Thu, 4 Feb 2021 17:01:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38672 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230118AbhBDWAr (ORCPT ); Thu, 4 Feb 2021 17:00:47 -0500 Received: from mail-ot1-x334.google.com (mail-ot1-x334.google.com [IPv6:2607:f8b0:4864:20::334]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B473CC06178B for ; Thu, 4 Feb 2021 14:00:06 -0800 (PST) Received: by mail-ot1-x334.google.com with SMTP id d1so4924845otl.13 for ; Thu, 04 Feb 2021 14:00:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=1ZySffUUeDJM726FBySm8qOwO5Z0SZpmWssweHDns38=; b=IwIZmx2aSwowtizqwJZhPX3ZqiQWzalWhYVlxq3vqI9cxtZPd9gWLXVUor3n7d98D/ IwSTlnldcWn4WZaPyPSuuEs7gWZqIMk7gLlyjO07O3FFcFXf4RmEvC+/upC+D9pqCMvf No1jcKVs51tH5d5Pj7ZxvZduNnheiwrOyh/UO0mIjO5VZsNfghts8I/O2yIUGBKljwJz WwwrsVy6Vp0hfj7KUEVonIRO1u1w2+ztVbYH7/KZhYoEmda9tT+MWQ+Sh/LTA5golxBO O5grZE2dyYTgC+/bQY1mTpUliXSTlZXqHhs1GRKIFhjfwpagXRtuqKOC2Fhelf4A8iQt 7H2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=1ZySffUUeDJM726FBySm8qOwO5Z0SZpmWssweHDns38=; b=X6wRn78UJDAgFddgIA83XEZCO5o2arHrmoElDTuQ/k8IGMzsq9/lJYyHu7kYJSQie+ 9nPns8xYtczk4tzrNe0MLq1G6ge7+sp0SRXhW3l4hwvYla6XAhNTtgBfgaTlvem6C08W gZ3ZTMaJwrYNtVDhbG4prYlt04n4rxgS/3DPPwtpqXCnomRkNRr7jErFkHddRw73y6je DhToV1G9nNSC2FlBSdO5zw+fBMa0bRju3emaAZZ6XvQ+Yu/XAoxgAsnuPKRQ2JkGrv5O sIf2K1pRskzspB1R+S6tt4ShZCQO8gDh2G4gbWjwLwWMrXyh1grDou00CTYVff41IKpc HJ+A== X-Gm-Message-State: AOAM533kQdPAWDfzT+KBg8bvmuuSBJUXqdOlbzeNtl+lg+N5g4YJt6Qc C8Aug+ify1di9XChlCnKRA== X-Google-Smtp-Source: ABdhPJzud+cV6ZnfR6BkLcF3pVyM+QFtSPmLq2x74kEgECZgWRbXQ5HgNOTVps+YzHCc1w4tkS+tew== X-Received: by 2002:a05:6830:1318:: with SMTP id p24mr1099497otq.302.1612476006095; Thu, 04 Feb 2021 14:00:06 -0800 (PST) Received: from threadripper.novatech-llc.local ([216.21.169.52]) by smtp.gmail.com with ESMTPSA id y10sm1361395ooy.11.2021.02.04.14.00.04 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 04 Feb 2021 14:00:04 -0800 (PST) From: George McCollister To: Jakub Kicinski Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jonathan Corbet , netdev@vger.kernel.org, George McCollister Subject: [PATCH net-next v2 3/4] net: dsa: add support for offloading HSR Date: Thu, 4 Feb 2021 15:59:25 -0600 Message-Id: <20210204215926.64377-4-george.mccollister@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20210204215926.64377-1-george.mccollister@gmail.com> References: <20210204215926.64377-1-george.mccollister@gmail.com> Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Add support for offloading of HSR/PRP (IEC 62439-3) tag insertion tag removal, duplicate generation and forwarding on DSA switches. Add DSA_NOTIFIER_HSR_JOIN and DSA_NOTIFIER_HSR_LEAVE which trigger calls to .port_hsr_join and .port_hsr_leave in the DSA driver for the switch. The DSA switch driver should then set netdev feature flags for the HSR/PRP operation that it offloads. NETIF_F_HW_HSR_TAG_INS NETIF_F_HW_HSR_TAG_RM NETIF_F_HW_HSR_FWD NETIF_F_HW_HSR_DUP Signed-off-by: George McCollister --- include/net/dsa.h | 13 +++++++++++++ net/dsa/dsa_priv.h | 11 +++++++++++ net/dsa/port.c | 34 ++++++++++++++++++++++++++++++++++ net/dsa/slave.c | 14 ++++++++++++++ net/dsa/switch.c | 24 ++++++++++++++++++++++++ 5 files changed, 96 insertions(+) diff --git a/include/net/dsa.h b/include/net/dsa.h index 60acb9fca124..84875960b706 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -172,6 +172,10 @@ struct dsa_switch_tree { list_for_each_entry((_dp), &(_dst)->ports, list) \ if ((_dp)->lag_dev == (_lag)) +#define dsa_hsr_foreach_port(_dp, _ds, _hsr) \ + list_for_each_entry((_dp), &(_ds)->dst->ports, list) \ + if ((_dp)->ds == (_ds) && (_dp)->hsr_dev == (_hsr)) + static inline struct net_device *dsa_lag_dev(struct dsa_switch_tree *dst, unsigned int id) { @@ -264,6 +268,7 @@ struct dsa_port { struct phylink_config pl_config; struct net_device *lag_dev; bool lag_tx_enabled; + struct net_device *hsr_dev; struct list_head list; @@ -769,6 +774,14 @@ struct dsa_switch_ops { struct netdev_lag_upper_info *info); int (*port_lag_leave)(struct dsa_switch *ds, int port, struct net_device *lag); + + /* + * HSR integration + */ + int (*port_hsr_join)(struct dsa_switch *ds, int port, + struct net_device *hsr); + void (*port_hsr_leave)(struct dsa_switch *ds, int port, + struct net_device *hsr); }; #define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes) \ diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 263593ce94a8..bb41f8bf4f6e 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -20,6 +20,8 @@ enum { DSA_NOTIFIER_BRIDGE_LEAVE, DSA_NOTIFIER_FDB_ADD, DSA_NOTIFIER_FDB_DEL, + DSA_NOTIFIER_HSR_JOIN, + DSA_NOTIFIER_HSR_LEAVE, DSA_NOTIFIER_LAG_CHANGE, DSA_NOTIFIER_LAG_JOIN, DSA_NOTIFIER_LAG_LEAVE, @@ -100,6 +102,13 @@ struct dsa_switchdev_event_work { u16 vid; }; +/* DSA_NOTIFIER_HSR_* */ +struct dsa_notifier_hsr_info { + struct net_device *hsr; + int sw_index; + int port; +}; + struct dsa_slave_priv { /* Copy of CPU port xmit for faster access in slave transmit hot path */ struct sk_buff * (*xmit)(struct sk_buff *skb, @@ -183,6 +192,8 @@ int dsa_port_vlan_del(struct dsa_port *dp, const struct switchdev_obj_port_vlan *vlan); int dsa_port_link_register_of(struct dsa_port *dp); void dsa_port_link_unregister_of(struct dsa_port *dp); +int dsa_port_hsr_join(struct dsa_port *dp, struct net_device *hsr); +void dsa_port_hsr_leave(struct dsa_port *dp, struct net_device *hsr); extern const struct phylink_mac_ops dsa_port_phylink_mac_ops; static inline bool dsa_port_offloads_netdev(struct dsa_port *dp, diff --git a/net/dsa/port.c b/net/dsa/port.c index 5e079a61528e..b93bda463026 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -868,3 +868,37 @@ int dsa_port_get_phy_sset_count(struct dsa_port *dp) return ret; } EXPORT_SYMBOL_GPL(dsa_port_get_phy_sset_count); + +int dsa_port_hsr_join(struct dsa_port *dp, struct net_device *hsr) +{ + struct dsa_notifier_hsr_info info = { + .sw_index = dp->ds->index, + .port = dp->index, + .hsr = hsr, + }; + int err; + + dp->hsr_dev = hsr; + + err = dsa_port_notify(dp, DSA_NOTIFIER_HSR_JOIN, &info); + if (err) + dp->hsr_dev = NULL; + + return err; +} + +void dsa_port_hsr_leave(struct dsa_port *dp, struct net_device *hsr) +{ + struct dsa_notifier_hsr_info info = { + .sw_index = dp->ds->index, + .port = dp->index, + .hsr = hsr, + }; + int err; + + dp->hsr_dev = NULL; + + err = dsa_port_notify(dp, DSA_NOTIFIER_HSR_LEAVE, &info); + if (err) + pr_err("DSA: failed to notify DSA_NOTIFIER_HSR_LEAVE\n"); +} diff --git a/net/dsa/slave.c b/net/dsa/slave.c index b0571ab4e5a7..11d01276f11d 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -1935,6 +1936,19 @@ static int dsa_slave_changeupper(struct net_device *dev, dsa_port_lag_leave(dp, info->upper_dev); err = NOTIFY_OK; } + } else if (is_hsr_master(info->upper_dev)) { + if (info->linking) { + err = dsa_port_hsr_join(dp, info->upper_dev); + if (err == -EOPNOTSUPP) { + NL_SET_ERR_MSG_MOD(info->info.extack, + "Offloading not supported"); + err = 0; + } + err = notifier_from_errno(err); + } else { + dsa_port_hsr_leave(dp, info->upper_dev); + err = NOTIFY_OK; + } } return err; diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 5026e4143663..1e0a65b307de 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -166,6 +166,24 @@ static int dsa_switch_fdb_del(struct dsa_switch *ds, return ds->ops->port_fdb_del(ds, port, info->addr, info->vid); } +static int dsa_switch_hsr_join(struct dsa_switch *ds, + struct dsa_notifier_hsr_info *info) +{ + if (ds->index == info->sw_index && ds->ops->port_hsr_join) + return ds->ops->port_hsr_join(ds, info->port, info->hsr); + + return 0; +} + +static int dsa_switch_hsr_leave(struct dsa_switch *ds, + struct dsa_notifier_hsr_info *info) +{ + if (ds->index == info->sw_index && ds->ops->port_hsr_leave) + ds->ops->port_hsr_leave(ds, info->port, info->hsr); + + return 0; +} + static int dsa_switch_lag_change(struct dsa_switch *ds, struct dsa_notifier_lag_info *info) { @@ -371,6 +389,12 @@ static int dsa_switch_event(struct notifier_block *nb, case DSA_NOTIFIER_FDB_DEL: err = dsa_switch_fdb_del(ds, info); break; + case DSA_NOTIFIER_HSR_JOIN: + err = dsa_switch_hsr_join(ds, info); + break; + case DSA_NOTIFIER_HSR_LEAVE: + err = dsa_switch_hsr_leave(ds, info); + break; case DSA_NOTIFIER_LAG_CHANGE: err = dsa_switch_lag_change(ds, info); break; From patchwork Thu Feb 4 21:59:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: George McCollister X-Patchwork-Id: 12068877 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 562C7C433E6 for ; Thu, 4 Feb 2021 22:01:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 18EDA64FA0 for ; Thu, 4 Feb 2021 22:01:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230165AbhBDWBI (ORCPT ); Thu, 4 Feb 2021 17:01:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38680 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229996AbhBDWAs (ORCPT ); Thu, 4 Feb 2021 17:00:48 -0500 Received: from mail-ot1-x331.google.com (mail-ot1-x331.google.com [IPv6:2607:f8b0:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A1EB3C06178C for ; Thu, 4 Feb 2021 14:00:08 -0800 (PST) Received: by mail-ot1-x331.google.com with SMTP id o12so4927693ote.12 for ; Thu, 04 Feb 2021 14:00:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=mFLtE3g0EjsOTeRVCEtooiFyBxJeQBA83vZYyjzIIkU=; b=BQPDdKU4fGNsfnO0LawkOfv4Hmk1DT1d4dstoCRsRpWYbyAV1pslqWfl/2F8oEXS3Y IC3xE4MRjM5u2an0LnXYZbp0lyZ78ETSnmEHxX8wRjRrolpau5sknlkfnWINqfJmo6Hn 7dy3ueDUW5Z4zyOcOti+YvXwvttFPMm9R2RQkoHfujSDM7YzBro98l2yuqNvOMuHo+Zb EF24uexDKiwJ9obNJibS4WuU5wSxfJFt8HN2Nue/8JdosnEqWy7a9mA6kTpp6hFoOe0V EQqTCBVDCVDSPuYK4Ui83hWoc9HCiTPBIYjFwr8HBns/kTn0eKbxIduBSvW6hIh9Rd1E 72BA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=mFLtE3g0EjsOTeRVCEtooiFyBxJeQBA83vZYyjzIIkU=; b=HKf8MAjW/X3/h38v9+8MRIEALi9fWMXB+QfO0yVHSIiFaQP1q/OD/M8GSG+/16RLac EHPYe5yL3zH9zvRRqaauJppZ1HW6s0cqZKJpQsj/bFl56vlMNTeuYG5gmEyf+i/PHJ99 XgXdWtjWfM69SMGuirpiaOYRHYR9etSf6hgqtjQfaSfllxSjrA2h6/hKDFeEKpWvjbcd XmgHl4Bimu037DBI96kC2Hpg1yPR1SJfJIwoaT0aW/SxwXrmFfBhvzX1JI5AMrr7XO0/ 3qF4sb16CYKcoEHqFxrjOzUyHysiCgLOqCrPuL482iJSjE8fbE4nQE3asWygC1Zv3f5k kL2w== X-Gm-Message-State: AOAM530vOv+i9xIo1k694o7AV+V/cL56wr3uE7AOsLCUbBs9kKY/uWwd jQXOYIaXP2fKodLuYJ1pPw== X-Google-Smtp-Source: ABdhPJzNlxoEC3IAzukplyJGkApg6c/PR1NK0FMK2O2YMyuZTZHXYuJXMI3r5nn60j+hd9BwWy3vOA== X-Received: by 2002:a05:6830:24a2:: with SMTP id v2mr1086186ots.298.1612476008094; Thu, 04 Feb 2021 14:00:08 -0800 (PST) Received: from threadripper.novatech-llc.local ([216.21.169.52]) by smtp.gmail.com with ESMTPSA id y10sm1361395ooy.11.2021.02.04.14.00.06 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 04 Feb 2021 14:00:06 -0800 (PST) From: George McCollister To: Jakub Kicinski Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jonathan Corbet , netdev@vger.kernel.org, George McCollister Subject: [PATCH net-next v2 4/4] net: dsa: xrs700x: add HSR offloading support Date: Thu, 4 Feb 2021 15:59:26 -0600 Message-Id: <20210204215926.64377-5-george.mccollister@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20210204215926.64377-1-george.mccollister@gmail.com> References: <20210204215926.64377-1-george.mccollister@gmail.com> Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Add offloading for HSR/PRP (IEC 62439-3) tag insertion, tag removal forwarding and duplication supported by the xrs7000 series switches. Only HSR v1 and PRP v1 are supported by the xrs7000 series switches (HSR v0 is not). Signed-off-by: George McCollister --- drivers/net/dsa/xrs700x/xrs700x.c | 106 ++++++++++++++++++++++++++++++++++ drivers/net/dsa/xrs700x/xrs700x_reg.h | 5 ++ net/dsa/tag_xrs700x.c | 7 ++- 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/xrs700x/xrs700x.c b/drivers/net/dsa/xrs700x/xrs700x.c index 259f5e657c46..566ce9330903 100644 --- a/drivers/net/dsa/xrs700x/xrs700x.c +++ b/drivers/net/dsa/xrs700x/xrs700x.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include "xrs700x.h" #include "xrs700x_reg.h" @@ -496,6 +498,108 @@ static void xrs700x_bridge_leave(struct dsa_switch *ds, int port, xrs700x_bridge_common(ds, port, bridge, false); } +static int xrs700x_hsr_join(struct dsa_switch *ds, int port, + struct net_device *hsr) +{ + unsigned int val = XRS_HSR_CFG_HSR_PRP; + struct dsa_port *partner = NULL, *dp; + struct xrs700x *priv = ds->priv; + struct net_device *slave; + enum hsr_version ver; + int ret; + + ret = hsr_get_version(hsr, &ver); + if (ret) + return ret; + + if (ver == HSR_V1) + val |= XRS_HSR_CFG_HSR; + else if (ver == PRP_V1) + val |= XRS_HSR_CFG_PRP; + else + return -EOPNOTSUPP; + + dsa_hsr_foreach_port(dp, ds, hsr) { + partner = dp; + } + + /* We can't enable redundancy on the switch until both + * redundant ports have signed up. + */ + if (!partner) + return 0; + + regmap_fields_write(priv->ps_forward, partner->index, + XRS_PORT_DISABLED); + regmap_fields_write(priv->ps_forward, port, XRS_PORT_DISABLED); + + regmap_write(priv->regmap, XRS_HSR_CFG(partner->index), + val | XRS_HSR_CFG_LANID_A); + regmap_write(priv->regmap, XRS_HSR_CFG(port), + val | XRS_HSR_CFG_LANID_B); + + /* Clear bits for both redundant ports (HSR only) and the CPU port to + * enable forwarding. + */ + val = GENMASK(ds->num_ports - 1, 0); + if (ver == HSR_V1) { + val &= ~BIT(partner->index); + val &= ~BIT(port); + } + val &= ~BIT(dsa_upstream_port(ds, port)); + regmap_write(priv->regmap, XRS_PORT_FWD_MASK(partner->index), val); + regmap_write(priv->regmap, XRS_PORT_FWD_MASK(port), val); + + regmap_fields_write(priv->ps_forward, partner->index, + XRS_PORT_FORWARDING); + regmap_fields_write(priv->ps_forward, port, XRS_PORT_FORWARDING); + + slave = dsa_to_port(ds, port)->slave; + + slave->features |= NETIF_F_HW_HSR_TAG_INS | NETIF_F_HW_HSR_TAG_RM | + NETIF_F_HW_HSR_FWD | NETIF_F_HW_HSR_DUP; + + return 0; +} + +static void xrs700x_hsr_leave(struct dsa_switch *ds, int port, + struct net_device *hsr) +{ + struct dsa_port *partner = NULL, *dp; + struct xrs700x *priv = ds->priv; + struct net_device *slave; + unsigned int val; + + dsa_hsr_foreach_port(dp, ds, hsr) { + partner = dp; + } + + if (!partner) + return; + + regmap_fields_write(priv->ps_forward, partner->index, + XRS_PORT_DISABLED); + regmap_fields_write(priv->ps_forward, port, XRS_PORT_DISABLED); + + regmap_write(priv->regmap, XRS_HSR_CFG(partner->index), 0); + regmap_write(priv->regmap, XRS_HSR_CFG(port), 0); + + /* Clear bit for the CPU port to enable forwarding. */ + val = GENMASK(ds->num_ports - 1, 0); + val &= ~BIT(dsa_upstream_port(ds, port)); + regmap_write(priv->regmap, XRS_PORT_FWD_MASK(partner->index), val); + regmap_write(priv->regmap, XRS_PORT_FWD_MASK(port), val); + + regmap_fields_write(priv->ps_forward, partner->index, + XRS_PORT_FORWARDING); + regmap_fields_write(priv->ps_forward, port, XRS_PORT_FORWARDING); + + slave = dsa_to_port(ds, port)->slave; + + slave->features &= ~(NETIF_F_HW_HSR_TAG_INS | NETIF_F_HW_HSR_TAG_RM | + NETIF_F_HW_HSR_FWD | NETIF_F_HW_HSR_DUP); +} + static const struct dsa_switch_ops xrs700x_ops = { .get_tag_protocol = xrs700x_get_tag_protocol, .setup = xrs700x_setup, @@ -509,6 +613,8 @@ static const struct dsa_switch_ops xrs700x_ops = { .get_stats64 = xrs700x_get_stats64, .port_bridge_join = xrs700x_bridge_join, .port_bridge_leave = xrs700x_bridge_leave, + .port_hsr_join = xrs700x_hsr_join, + .port_hsr_leave = xrs700x_hsr_leave, }; static int xrs700x_detect(struct xrs700x *priv) diff --git a/drivers/net/dsa/xrs700x/xrs700x_reg.h b/drivers/net/dsa/xrs700x/xrs700x_reg.h index a135d4d92b6d..470d00e07f15 100644 --- a/drivers/net/dsa/xrs700x/xrs700x_reg.h +++ b/drivers/net/dsa/xrs700x/xrs700x_reg.h @@ -49,6 +49,11 @@ /* Port Configuration Registers - HSR/PRP */ #define XRS_HSR_CFG(x) (XRS_PORT_HSR_BASE(x) + 0x0) +#define XRS_HSR_CFG_HSR_PRP BIT(0) +#define XRS_HSR_CFG_HSR 0 +#define XRS_HSR_CFG_PRP BIT(8) +#define XRS_HSR_CFG_LANID_A 0 +#define XRS_HSR_CFG_LANID_B BIT(10) /* Port Configuration Registers - PTP */ #define XRS_PTP_RX_SYNC_DELAY_NS_LO(x) (XRS_PORT_PTP_BASE(x) + 0x2) diff --git a/net/dsa/tag_xrs700x.c b/net/dsa/tag_xrs700x.c index db0ed1a5fcb7..858cdf9d2913 100644 --- a/net/dsa/tag_xrs700x.c +++ b/net/dsa/tag_xrs700x.c @@ -11,12 +11,17 @@ static struct sk_buff *xrs700x_xmit(struct sk_buff *skb, struct net_device *dev) { - struct dsa_port *dp = dsa_slave_to_port(dev); + struct dsa_port *partner, *dp = dsa_slave_to_port(dev); u8 *trailer; trailer = skb_put(skb, 1); trailer[0] = BIT(dp->index); + if (dp->hsr_dev) + dsa_hsr_foreach_port(partner, dp->ds, dp->hsr_dev) + if (partner != dp) + trailer[0] |= BIT(partner->index); + return skb; }