From patchwork Mon Jan 25 22:03:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12044513 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,URIBL_BLOCKED,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 92812C433E0 for ; Mon, 25 Jan 2021 22:05:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5CA042100A for ; Mon, 25 Jan 2021 22:05:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732358AbhAYWF2 (ORCPT ); Mon, 25 Jan 2021 17:05:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59338 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733144AbhAYWFI (ORCPT ); Mon, 25 Jan 2021 17:05:08 -0500 Received: from mail-ed1-x52e.google.com (mail-ed1-x52e.google.com [IPv6:2a00:1450:4864:20::52e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D6191C061574 for ; Mon, 25 Jan 2021 14:04:25 -0800 (PST) Received: by mail-ed1-x52e.google.com with SMTP id d22so17427025edy.1 for ; Mon, 25 Jan 2021 14:04:25 -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 :mime-version:content-transfer-encoding; bh=TBSx4XIJtMGHAQY0/1r1qqjVrggCv03U4scN9BHN/Sg=; b=A7Gclv56ePABg8JE7w2AxfsSFCHWG4e2gfjj8XXyro2xPy/9Dut7NJU45CcB00Tp5x bq7w2sgUT1JGKncMEjJERyWpoXQ2bBWhFtkodtX2CMtY19SBZMMS5u3dYz8AUM7VJ9y9 3RyOjevHcVbGRoKZDndFBa6W768ar2lIG9KkG+uMMMAWK9k1jHwgU/kK+msly8omYQYr G2pcOR4cj/h3bBKMcqq56IqlMCDqj9Q/dmEW853bvfZ6w24VDSgGE1tFViFEP68Yx7Yu LLH0onFhWau/xvLp3YPqsi276OrTpISDzr27EpwD1aVoa3HmwrwJHKPeDHhoWfW3HIEH GprQ== 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:mime-version:content-transfer-encoding; bh=TBSx4XIJtMGHAQY0/1r1qqjVrggCv03U4scN9BHN/Sg=; b=I9J346HQR5Yat5hVh+owXMI5LfK0fSEP1zf2or0lKKw6qIpUsFCw8ARaCx6vwlyFBN G6KWPkVuFxXmYDpxZo4ODA3LAEddGBhFXsIGLMgPa/eLnj0le2NjBYuCxWO9Qca9wkT1 KW58qHM63GLZhYWhojksQQlnkjrn+rrETk44b+ijsG6/js2Mv3wT3ECkWIsjwG4yc8Eo LtBqX0Nab5RUy5K25GlVJJ5jSA3bMSpqldVmDcInpEB2d4xYUNh06DpzNtk891cpOxA3 47cilJ7KglnFRSe3Wptg7RdZ8brtd3o53ciZcFvfsy5/kl3RpgIGl9uKY81Gn/PvkiRY hk0g== X-Gm-Message-State: AOAM5311oYyWELdVnRR7o3hx1UWrUi63lz4ZfaX+Q3J3cIHp0Dn0lxxa HY0yZr5IZ9sKpjxpk+zbW+dwqHB2RmQ= X-Google-Smtp-Source: ABdhPJxSx9Vp+p8KZvIZFb85sicPHbApqItm0996uaNE0ttjlsJEet/hlFyD2Y5QTmzccA7tsroq0g== X-Received: by 2002:a05:6402:1249:: with SMTP id l9mr2052198edw.375.1611612264538; Mon, 25 Jan 2021 14:04:24 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id s13sm1760555edi.92.2021.01.25.14.04.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 14:04:23 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Claudiu Manoil , Alexandre Belloni , Vladimir Oltean , UNGLinuxDriver@microchip.com Subject: [PATCH v7 net-next 01/11] net: dsa: tag_8021q: add helpers to deduce whether a VLAN ID is RX or TX VLAN Date: Tue, 26 Jan 2021 00:03:23 +0200 Message-Id: <20210125220333.1004365-2-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210125220333.1004365-1-olteanv@gmail.com> References: <20210125220333.1004365-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Vladimir Oltean The sja1105 implementation can be blind about this, but the felix driver doesn't do exactly what it's being told, so it needs to know whether it is a TX or an RX VLAN, so it can install the appropriate type of TCAM rule. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- Changes in v7: None. Changes in v6: None. Changes in v5: None. Changes in v4: None. Changes in v3: None. Changes in v2: None. include/linux/dsa/8021q.h | 14 ++++++++++++++ net/dsa/tag_8021q.c | 15 +++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/include/linux/dsa/8021q.h b/include/linux/dsa/8021q.h index 88cd72dfa4e0..b12b05f1c8b4 100644 --- a/include/linux/dsa/8021q.h +++ b/include/linux/dsa/8021q.h @@ -64,6 +64,10 @@ int dsa_8021q_rx_source_port(u16 vid); u16 dsa_8021q_rx_subvlan(u16 vid); +bool vid_is_dsa_8021q_rxvlan(u16 vid); + +bool vid_is_dsa_8021q_txvlan(u16 vid); + bool vid_is_dsa_8021q(u16 vid); #else @@ -123,6 +127,16 @@ u16 dsa_8021q_rx_subvlan(u16 vid) return 0; } +bool vid_is_dsa_8021q_rxvlan(u16 vid) +{ + return false; +} + +bool vid_is_dsa_8021q_txvlan(u16 vid) +{ + return false; +} + bool vid_is_dsa_8021q(u16 vid) { return false; diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c index 8e3e8a5b8559..008c1ec6e20c 100644 --- a/net/dsa/tag_8021q.c +++ b/net/dsa/tag_8021q.c @@ -133,10 +133,21 @@ u16 dsa_8021q_rx_subvlan(u16 vid) } EXPORT_SYMBOL_GPL(dsa_8021q_rx_subvlan); +bool vid_is_dsa_8021q_rxvlan(u16 vid) +{ + return (vid & DSA_8021Q_DIR_MASK) == DSA_8021Q_DIR_RX; +} +EXPORT_SYMBOL_GPL(vid_is_dsa_8021q_rxvlan); + +bool vid_is_dsa_8021q_txvlan(u16 vid) +{ + return (vid & DSA_8021Q_DIR_MASK) == DSA_8021Q_DIR_TX; +} +EXPORT_SYMBOL_GPL(vid_is_dsa_8021q_txvlan); + bool vid_is_dsa_8021q(u16 vid) { - return ((vid & DSA_8021Q_DIR_MASK) == DSA_8021Q_DIR_RX || - (vid & DSA_8021Q_DIR_MASK) == DSA_8021Q_DIR_TX); + return vid_is_dsa_8021q_rxvlan(vid) || vid_is_dsa_8021q_txvlan(vid); } EXPORT_SYMBOL_GPL(vid_is_dsa_8021q); From patchwork Mon Jan 25 22:03:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12044519 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,URIBL_BLOCKED,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 CA93CC433E0 for ; Mon, 25 Jan 2021 22:06:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 99811216FD for ; Mon, 25 Jan 2021 22:06:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733193AbhAYWGv (ORCPT ); Mon, 25 Jan 2021 17:06:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59348 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733148AbhAYWFI (ORCPT ); Mon, 25 Jan 2021 17:05:08 -0500 Received: from mail-ej1-x629.google.com (mail-ej1-x629.google.com [IPv6:2a00:1450:4864:20::629]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A6D13C06174A for ; Mon, 25 Jan 2021 14:04:27 -0800 (PST) Received: by mail-ej1-x629.google.com with SMTP id g12so20264629ejf.8 for ; Mon, 25 Jan 2021 14:04:27 -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 :mime-version:content-transfer-encoding; bh=TXHkSQfYP+HcG+tZ7hnVepbi7ZCRYkZi1Hu/yGOuK5g=; b=bP1k8TfQjlbg++gDEosba6u9orhQN1b0pVRVmHzHpUuE0qg+u0avNjo7+6BWq5KGrQ NuFKpngH+vGTapX8PVT02p2IkL/UeF2oI4sfsDFDctnPcrlJLMTnLXvdCmIG1RcgRO6P 0O2B59hr+xuuKLokLXdWLvMn44ymSPc8LnRgh2mcwo19W+3KebXquxUO+Zb42i7KOww2 P4EdeEDp1JJnulHJ2FQLtKgb8R0i4YZhh0YvG5VOZZiiZj8gwRl6vN1OYLl9rEFS0eWY ozX1FfA49VhPpxfLr8mw5v52uCTPYgXl7Vi+lnaYcNc6wyO1rVd9gnG3P3sM85wur7hh Gpvw== 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:mime-version:content-transfer-encoding; bh=TXHkSQfYP+HcG+tZ7hnVepbi7ZCRYkZi1Hu/yGOuK5g=; b=NZKx4rH3O6Olz0AmvPigPAVQIqRLf/d3J5PQb6gZOo3lZ5djUS2QhUu/szazVy137o 9XBeVrfSF3s8dOUxoI7F9h+RJl/RXYFT4HXoywLcoBc46HBokyuER06P9KIG3r6YNVeQ esQCPImAVz976xOV4DuiJ1WG1Zyd3wJfmtgnqAi+IgyfI4r85tAAZc+cpRGJYOiigqSq fYeRATaprfPBBJ406dLC7qYFmGQLX6n6lgh3YPmNQpJvze9UGnX+UExhGs51eoZgPH1T yYoyC8Ypz1wbTDqhSOp6fsft71zkeBrdz4l2VQTmcFs55oIuMA+Usvb0ga+CnCREbkBd 6P1Q== X-Gm-Message-State: AOAM5328gwQyC1/0buUkIeD0UQLeLemTPNxwTYif/pHXlU/fGiicqgtM RrbXP1LKN4vJOxfHUkpDITQ= X-Google-Smtp-Source: ABdhPJyWNq8Lkq1HY3NjmQ3RLuBOUx6PRVtZvG76hvw7hiM7m4G5AjUWogI0siYJJh86FUR0pnfKrw== X-Received: by 2002:a17:906:d103:: with SMTP id b3mr1699634ejz.60.1611612266370; Mon, 25 Jan 2021 14:04:26 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id s13sm1760555edi.92.2021.01.25.14.04.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 14:04:25 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Claudiu Manoil , Alexandre Belloni , Vladimir Oltean , UNGLinuxDriver@microchip.com Subject: [PATCH v7 net-next 02/11] net: mscc: ocelot: export VCAP structures to include/soc/mscc Date: Tue, 26 Jan 2021 00:03:24 +0200 Message-Id: <20210125220333.1004365-3-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210125220333.1004365-1-olteanv@gmail.com> References: <20210125220333.1004365-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Vladimir Oltean The Felix driver will need to preinstall some VCAP filters for its tag_8021q implementation (outside of the tc-flower offload logic), so these need to be exported to the common includes. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- changes in v7: none. changes in v6: none. Changes in v5: None. Changes in v3: None. Changes in v2: Patch is new. Changes in v4: Use EXPORT_SYMBOL for ocelot_vcap_filter_add and ocelot_vcap_filter_del so that building as module does not fail. Changes in v3: None. Changes in v2: Patch is new. drivers/net/ethernet/mscc/ocelot_net.c | 1 + drivers/net/ethernet/mscc/ocelot_vcap.c | 2 + drivers/net/ethernet/mscc/ocelot_vcap.h | 293 +----------------------- include/soc/mscc/ocelot_vcap.h | 289 +++++++++++++++++++++++ 4 files changed, 294 insertions(+), 291 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 9553eb3e441c..05142803a463 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -9,6 +9,7 @@ */ #include +#include #include "ocelot.h" #include "ocelot_vcap.h" diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c index d8c778ee6f1b..489bf16362a7 100644 --- a/drivers/net/ethernet/mscc/ocelot_vcap.c +++ b/drivers/net/ethernet/mscc/ocelot_vcap.c @@ -1150,6 +1150,7 @@ int ocelot_vcap_filter_add(struct ocelot *ocelot, vcap_entry_set(ocelot, index, filter); return 0; } +EXPORT_SYMBOL(ocelot_vcap_filter_add); static void ocelot_vcap_block_remove_filter(struct ocelot *ocelot, struct ocelot_vcap_block *block, @@ -1204,6 +1205,7 @@ int ocelot_vcap_filter_del(struct ocelot *ocelot, return 0; } +EXPORT_SYMBOL(ocelot_vcap_filter_del); int ocelot_vcap_filter_stats_update(struct ocelot *ocelot, struct ocelot_vcap_filter *filter) diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.h b/drivers/net/ethernet/mscc/ocelot_vcap.h index 82fd10581a14..cfc8b976d1de 100644 --- a/drivers/net/ethernet/mscc/ocelot_vcap.h +++ b/drivers/net/ethernet/mscc/ocelot_vcap.h @@ -7,300 +7,11 @@ #define _MSCC_OCELOT_VCAP_H_ #include "ocelot.h" -#include "ocelot_police.h" -#include -#include +#include +#include #define OCELOT_POLICER_DISCARD 0x17f -struct ocelot_ipv4 { - u8 addr[4]; -}; - -enum ocelot_vcap_bit { - OCELOT_VCAP_BIT_ANY, - OCELOT_VCAP_BIT_0, - OCELOT_VCAP_BIT_1 -}; - -struct ocelot_vcap_u8 { - u8 value[1]; - u8 mask[1]; -}; - -struct ocelot_vcap_u16 { - u8 value[2]; - u8 mask[2]; -}; - -struct ocelot_vcap_u24 { - u8 value[3]; - u8 mask[3]; -}; - -struct ocelot_vcap_u32 { - u8 value[4]; - u8 mask[4]; -}; - -struct ocelot_vcap_u40 { - u8 value[5]; - u8 mask[5]; -}; - -struct ocelot_vcap_u48 { - u8 value[6]; - u8 mask[6]; -}; - -struct ocelot_vcap_u64 { - u8 value[8]; - u8 mask[8]; -}; - -struct ocelot_vcap_u128 { - u8 value[16]; - u8 mask[16]; -}; - -struct ocelot_vcap_vid { - u16 value; - u16 mask; -}; - -struct ocelot_vcap_ipv4 { - struct ocelot_ipv4 value; - struct ocelot_ipv4 mask; -}; - -struct ocelot_vcap_udp_tcp { - u16 value; - u16 mask; -}; - -struct ocelot_vcap_port { - u8 value; - u8 mask; -}; - -enum ocelot_vcap_key_type { - OCELOT_VCAP_KEY_ANY, - OCELOT_VCAP_KEY_ETYPE, - OCELOT_VCAP_KEY_LLC, - OCELOT_VCAP_KEY_SNAP, - OCELOT_VCAP_KEY_ARP, - OCELOT_VCAP_KEY_IPV4, - OCELOT_VCAP_KEY_IPV6 -}; - -struct ocelot_vcap_key_vlan { - struct ocelot_vcap_vid vid; /* VLAN ID (12 bit) */ - struct ocelot_vcap_u8 pcp; /* PCP (3 bit) */ - enum ocelot_vcap_bit dei; /* DEI */ - enum ocelot_vcap_bit tagged; /* Tagged/untagged frame */ -}; - -struct ocelot_vcap_key_etype { - struct ocelot_vcap_u48 dmac; - struct ocelot_vcap_u48 smac; - struct ocelot_vcap_u16 etype; - struct ocelot_vcap_u16 data; /* MAC data */ -}; - -struct ocelot_vcap_key_llc { - struct ocelot_vcap_u48 dmac; - struct ocelot_vcap_u48 smac; - - /* LLC header: DSAP at byte 0, SSAP at byte 1, Control at byte 2 */ - struct ocelot_vcap_u32 llc; -}; - -struct ocelot_vcap_key_snap { - struct ocelot_vcap_u48 dmac; - struct ocelot_vcap_u48 smac; - - /* SNAP header: Organization Code at byte 0, Type at byte 3 */ - struct ocelot_vcap_u40 snap; -}; - -struct ocelot_vcap_key_arp { - struct ocelot_vcap_u48 smac; - enum ocelot_vcap_bit arp; /* Opcode ARP/RARP */ - enum ocelot_vcap_bit req; /* Opcode request/reply */ - enum ocelot_vcap_bit unknown; /* Opcode unknown */ - enum ocelot_vcap_bit smac_match; /* Sender MAC matches SMAC */ - enum ocelot_vcap_bit dmac_match; /* Target MAC matches DMAC */ - - /**< Protocol addr. length 4, hardware length 6 */ - enum ocelot_vcap_bit length; - - enum ocelot_vcap_bit ip; /* Protocol address type IP */ - enum ocelot_vcap_bit ethernet; /* Hardware address type Ethernet */ - struct ocelot_vcap_ipv4 sip; /* Sender IP address */ - struct ocelot_vcap_ipv4 dip; /* Target IP address */ -}; - -struct ocelot_vcap_key_ipv4 { - enum ocelot_vcap_bit ttl; /* TTL zero */ - enum ocelot_vcap_bit fragment; /* Fragment */ - enum ocelot_vcap_bit options; /* Header options */ - struct ocelot_vcap_u8 ds; - struct ocelot_vcap_u8 proto; /* Protocol */ - struct ocelot_vcap_ipv4 sip; /* Source IP address */ - struct ocelot_vcap_ipv4 dip; /* Destination IP address */ - struct ocelot_vcap_u48 data; /* Not UDP/TCP: IP data */ - struct ocelot_vcap_udp_tcp sport; /* UDP/TCP: Source port */ - struct ocelot_vcap_udp_tcp dport; /* UDP/TCP: Destination port */ - enum ocelot_vcap_bit tcp_fin; - enum ocelot_vcap_bit tcp_syn; - enum ocelot_vcap_bit tcp_rst; - enum ocelot_vcap_bit tcp_psh; - enum ocelot_vcap_bit tcp_ack; - enum ocelot_vcap_bit tcp_urg; - enum ocelot_vcap_bit sip_eq_dip; /* SIP equals DIP */ - enum ocelot_vcap_bit sport_eq_dport; /* SPORT equals DPORT */ - enum ocelot_vcap_bit seq_zero; /* TCP sequence number is zero */ -}; - -struct ocelot_vcap_key_ipv6 { - struct ocelot_vcap_u8 proto; /* IPv6 protocol */ - struct ocelot_vcap_u128 sip; /* IPv6 source (byte 0-7 ignored) */ - struct ocelot_vcap_u128 dip; /* IPv6 destination (byte 0-7 ignored) */ - enum ocelot_vcap_bit ttl; /* TTL zero */ - struct ocelot_vcap_u8 ds; - struct ocelot_vcap_u48 data; /* Not UDP/TCP: IP data */ - struct ocelot_vcap_udp_tcp sport; - struct ocelot_vcap_udp_tcp dport; - enum ocelot_vcap_bit tcp_fin; - enum ocelot_vcap_bit tcp_syn; - enum ocelot_vcap_bit tcp_rst; - enum ocelot_vcap_bit tcp_psh; - enum ocelot_vcap_bit tcp_ack; - enum ocelot_vcap_bit tcp_urg; - enum ocelot_vcap_bit sip_eq_dip; /* SIP equals DIP */ - enum ocelot_vcap_bit sport_eq_dport; /* SPORT equals DPORT */ - enum ocelot_vcap_bit seq_zero; /* TCP sequence number is zero */ -}; - -enum ocelot_mask_mode { - OCELOT_MASK_MODE_NONE, - OCELOT_MASK_MODE_PERMIT_DENY, - OCELOT_MASK_MODE_POLICY, - OCELOT_MASK_MODE_REDIRECT, -}; - -enum ocelot_es0_tag { - OCELOT_NO_ES0_TAG, - OCELOT_ES0_TAG, - OCELOT_FORCE_PORT_TAG, - OCELOT_FORCE_UNTAG, -}; - -enum ocelot_tag_tpid_sel { - OCELOT_TAG_TPID_SEL_8021Q, - OCELOT_TAG_TPID_SEL_8021AD, -}; - -struct ocelot_vcap_action { - union { - /* VCAP ES0 */ - struct { - enum ocelot_es0_tag push_outer_tag; - enum ocelot_es0_tag push_inner_tag; - enum ocelot_tag_tpid_sel tag_a_tpid_sel; - int tag_a_vid_sel; - int tag_a_pcp_sel; - u16 vid_a_val; - u8 pcp_a_val; - u8 dei_a_val; - enum ocelot_tag_tpid_sel tag_b_tpid_sel; - int tag_b_vid_sel; - int tag_b_pcp_sel; - u16 vid_b_val; - u8 pcp_b_val; - u8 dei_b_val; - }; - - /* VCAP IS1 */ - struct { - bool vid_replace_ena; - u16 vid; - bool vlan_pop_cnt_ena; - int vlan_pop_cnt; - bool pcp_dei_ena; - u8 pcp; - u8 dei; - bool qos_ena; - u8 qos_val; - u8 pag_override_mask; - u8 pag_val; - }; - - /* VCAP IS2 */ - struct { - bool cpu_copy_ena; - u8 cpu_qu_num; - enum ocelot_mask_mode mask_mode; - unsigned long port_mask; - bool police_ena; - struct ocelot_policer pol; - u32 pol_ix; - }; - }; -}; - -struct ocelot_vcap_stats { - u64 bytes; - u64 pkts; - u64 used; -}; - -enum ocelot_vcap_filter_type { - OCELOT_VCAP_FILTER_DUMMY, - OCELOT_VCAP_FILTER_PAG, - OCELOT_VCAP_FILTER_OFFLOAD, -}; - -struct ocelot_vcap_filter { - struct list_head list; - - enum ocelot_vcap_filter_type type; - int block_id; - int goto_target; - int lookup; - u8 pag; - u16 prio; - u32 id; - - struct ocelot_vcap_action action; - struct ocelot_vcap_stats stats; - /* For VCAP IS1 and IS2 */ - unsigned long ingress_port_mask; - /* For VCAP ES0 */ - struct ocelot_vcap_port ingress_port; - struct ocelot_vcap_port egress_port; - - enum ocelot_vcap_bit dmac_mc; - enum ocelot_vcap_bit dmac_bc; - struct ocelot_vcap_key_vlan vlan; - - enum ocelot_vcap_key_type key_type; - union { - /* OCELOT_VCAP_KEY_ANY: No specific fields */ - struct ocelot_vcap_key_etype etype; - struct ocelot_vcap_key_llc llc; - struct ocelot_vcap_key_snap snap; - struct ocelot_vcap_key_arp arp; - struct ocelot_vcap_key_ipv4 ipv4; - struct ocelot_vcap_key_ipv6 ipv6; - } key; -}; - -int ocelot_vcap_filter_add(struct ocelot *ocelot, - struct ocelot_vcap_filter *rule, - struct netlink_ext_ack *extack); -int ocelot_vcap_filter_del(struct ocelot *ocelot, - struct ocelot_vcap_filter *rule); int ocelot_vcap_filter_stats_update(struct ocelot *ocelot, struct ocelot_vcap_filter *rule); struct ocelot_vcap_filter * diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h index 96300adf3648..7f1b82fba63c 100644 --- a/include/soc/mscc/ocelot_vcap.h +++ b/include/soc/mscc/ocelot_vcap.h @@ -400,4 +400,293 @@ enum vcap_es0_action_field { VCAP_ES0_ACT_HIT_STICKY, }; +struct ocelot_ipv4 { + u8 addr[4]; +}; + +enum ocelot_vcap_bit { + OCELOT_VCAP_BIT_ANY, + OCELOT_VCAP_BIT_0, + OCELOT_VCAP_BIT_1 +}; + +struct ocelot_vcap_u8 { + u8 value[1]; + u8 mask[1]; +}; + +struct ocelot_vcap_u16 { + u8 value[2]; + u8 mask[2]; +}; + +struct ocelot_vcap_u24 { + u8 value[3]; + u8 mask[3]; +}; + +struct ocelot_vcap_u32 { + u8 value[4]; + u8 mask[4]; +}; + +struct ocelot_vcap_u40 { + u8 value[5]; + u8 mask[5]; +}; + +struct ocelot_vcap_u48 { + u8 value[6]; + u8 mask[6]; +}; + +struct ocelot_vcap_u64 { + u8 value[8]; + u8 mask[8]; +}; + +struct ocelot_vcap_u128 { + u8 value[16]; + u8 mask[16]; +}; + +struct ocelot_vcap_vid { + u16 value; + u16 mask; +}; + +struct ocelot_vcap_ipv4 { + struct ocelot_ipv4 value; + struct ocelot_ipv4 mask; +}; + +struct ocelot_vcap_udp_tcp { + u16 value; + u16 mask; +}; + +struct ocelot_vcap_port { + u8 value; + u8 mask; +}; + +enum ocelot_vcap_key_type { + OCELOT_VCAP_KEY_ANY, + OCELOT_VCAP_KEY_ETYPE, + OCELOT_VCAP_KEY_LLC, + OCELOT_VCAP_KEY_SNAP, + OCELOT_VCAP_KEY_ARP, + OCELOT_VCAP_KEY_IPV4, + OCELOT_VCAP_KEY_IPV6 +}; + +struct ocelot_vcap_key_vlan { + struct ocelot_vcap_vid vid; /* VLAN ID (12 bit) */ + struct ocelot_vcap_u8 pcp; /* PCP (3 bit) */ + enum ocelot_vcap_bit dei; /* DEI */ + enum ocelot_vcap_bit tagged; /* Tagged/untagged frame */ +}; + +struct ocelot_vcap_key_etype { + struct ocelot_vcap_u48 dmac; + struct ocelot_vcap_u48 smac; + struct ocelot_vcap_u16 etype; + struct ocelot_vcap_u16 data; /* MAC data */ +}; + +struct ocelot_vcap_key_llc { + struct ocelot_vcap_u48 dmac; + struct ocelot_vcap_u48 smac; + + /* LLC header: DSAP at byte 0, SSAP at byte 1, Control at byte 2 */ + struct ocelot_vcap_u32 llc; +}; + +struct ocelot_vcap_key_snap { + struct ocelot_vcap_u48 dmac; + struct ocelot_vcap_u48 smac; + + /* SNAP header: Organization Code at byte 0, Type at byte 3 */ + struct ocelot_vcap_u40 snap; +}; + +struct ocelot_vcap_key_arp { + struct ocelot_vcap_u48 smac; + enum ocelot_vcap_bit arp; /* Opcode ARP/RARP */ + enum ocelot_vcap_bit req; /* Opcode request/reply */ + enum ocelot_vcap_bit unknown; /* Opcode unknown */ + enum ocelot_vcap_bit smac_match; /* Sender MAC matches SMAC */ + enum ocelot_vcap_bit dmac_match; /* Target MAC matches DMAC */ + + /**< Protocol addr. length 4, hardware length 6 */ + enum ocelot_vcap_bit length; + + enum ocelot_vcap_bit ip; /* Protocol address type IP */ + enum ocelot_vcap_bit ethernet; /* Hardware address type Ethernet */ + struct ocelot_vcap_ipv4 sip; /* Sender IP address */ + struct ocelot_vcap_ipv4 dip; /* Target IP address */ +}; + +struct ocelot_vcap_key_ipv4 { + enum ocelot_vcap_bit ttl; /* TTL zero */ + enum ocelot_vcap_bit fragment; /* Fragment */ + enum ocelot_vcap_bit options; /* Header options */ + struct ocelot_vcap_u8 ds; + struct ocelot_vcap_u8 proto; /* Protocol */ + struct ocelot_vcap_ipv4 sip; /* Source IP address */ + struct ocelot_vcap_ipv4 dip; /* Destination IP address */ + struct ocelot_vcap_u48 data; /* Not UDP/TCP: IP data */ + struct ocelot_vcap_udp_tcp sport; /* UDP/TCP: Source port */ + struct ocelot_vcap_udp_tcp dport; /* UDP/TCP: Destination port */ + enum ocelot_vcap_bit tcp_fin; + enum ocelot_vcap_bit tcp_syn; + enum ocelot_vcap_bit tcp_rst; + enum ocelot_vcap_bit tcp_psh; + enum ocelot_vcap_bit tcp_ack; + enum ocelot_vcap_bit tcp_urg; + enum ocelot_vcap_bit sip_eq_dip; /* SIP equals DIP */ + enum ocelot_vcap_bit sport_eq_dport; /* SPORT equals DPORT */ + enum ocelot_vcap_bit seq_zero; /* TCP sequence number is zero */ +}; + +struct ocelot_vcap_key_ipv6 { + struct ocelot_vcap_u8 proto; /* IPv6 protocol */ + struct ocelot_vcap_u128 sip; /* IPv6 source (byte 0-7 ignored) */ + struct ocelot_vcap_u128 dip; /* IPv6 destination (byte 0-7 ignored) */ + enum ocelot_vcap_bit ttl; /* TTL zero */ + struct ocelot_vcap_u8 ds; + struct ocelot_vcap_u48 data; /* Not UDP/TCP: IP data */ + struct ocelot_vcap_udp_tcp sport; + struct ocelot_vcap_udp_tcp dport; + enum ocelot_vcap_bit tcp_fin; + enum ocelot_vcap_bit tcp_syn; + enum ocelot_vcap_bit tcp_rst; + enum ocelot_vcap_bit tcp_psh; + enum ocelot_vcap_bit tcp_ack; + enum ocelot_vcap_bit tcp_urg; + enum ocelot_vcap_bit sip_eq_dip; /* SIP equals DIP */ + enum ocelot_vcap_bit sport_eq_dport; /* SPORT equals DPORT */ + enum ocelot_vcap_bit seq_zero; /* TCP sequence number is zero */ +}; + +enum ocelot_mask_mode { + OCELOT_MASK_MODE_NONE, + OCELOT_MASK_MODE_PERMIT_DENY, + OCELOT_MASK_MODE_POLICY, + OCELOT_MASK_MODE_REDIRECT, +}; + +enum ocelot_es0_tag { + OCELOT_NO_ES0_TAG, + OCELOT_ES0_TAG, + OCELOT_FORCE_PORT_TAG, + OCELOT_FORCE_UNTAG, +}; + +enum ocelot_tag_tpid_sel { + OCELOT_TAG_TPID_SEL_8021Q, + OCELOT_TAG_TPID_SEL_8021AD, +}; + +struct ocelot_vcap_action { + union { + /* VCAP ES0 */ + struct { + enum ocelot_es0_tag push_outer_tag; + enum ocelot_es0_tag push_inner_tag; + enum ocelot_tag_tpid_sel tag_a_tpid_sel; + int tag_a_vid_sel; + int tag_a_pcp_sel; + u16 vid_a_val; + u8 pcp_a_val; + u8 dei_a_val; + enum ocelot_tag_tpid_sel tag_b_tpid_sel; + int tag_b_vid_sel; + int tag_b_pcp_sel; + u16 vid_b_val; + u8 pcp_b_val; + u8 dei_b_val; + }; + + /* VCAP IS1 */ + struct { + bool vid_replace_ena; + u16 vid; + bool vlan_pop_cnt_ena; + int vlan_pop_cnt; + bool pcp_dei_ena; + u8 pcp; + u8 dei; + bool qos_ena; + u8 qos_val; + u8 pag_override_mask; + u8 pag_val; + }; + + /* VCAP IS2 */ + struct { + bool cpu_copy_ena; + u8 cpu_qu_num; + enum ocelot_mask_mode mask_mode; + unsigned long port_mask; + bool police_ena; + struct ocelot_policer pol; + u32 pol_ix; + }; + }; +}; + +struct ocelot_vcap_stats { + u64 bytes; + u64 pkts; + u64 used; +}; + +enum ocelot_vcap_filter_type { + OCELOT_VCAP_FILTER_DUMMY, + OCELOT_VCAP_FILTER_PAG, + OCELOT_VCAP_FILTER_OFFLOAD, +}; + +struct ocelot_vcap_filter { + struct list_head list; + + enum ocelot_vcap_filter_type type; + int block_id; + int goto_target; + int lookup; + u8 pag; + u16 prio; + u32 id; + + struct ocelot_vcap_action action; + struct ocelot_vcap_stats stats; + /* For VCAP IS1 and IS2 */ + unsigned long ingress_port_mask; + /* For VCAP ES0 */ + struct ocelot_vcap_port ingress_port; + struct ocelot_vcap_port egress_port; + + enum ocelot_vcap_bit dmac_mc; + enum ocelot_vcap_bit dmac_bc; + struct ocelot_vcap_key_vlan vlan; + + enum ocelot_vcap_key_type key_type; + union { + /* OCELOT_VCAP_KEY_ANY: No specific fields */ + struct ocelot_vcap_key_etype etype; + struct ocelot_vcap_key_llc llc; + struct ocelot_vcap_key_snap snap; + struct ocelot_vcap_key_arp arp; + struct ocelot_vcap_key_ipv4 ipv4; + struct ocelot_vcap_key_ipv6 ipv6; + } key; +}; + +int ocelot_vcap_filter_add(struct ocelot *ocelot, + struct ocelot_vcap_filter *rule, + struct netlink_ext_ack *extack); +int ocelot_vcap_filter_del(struct ocelot *ocelot, + struct ocelot_vcap_filter *rule); + #endif /* _OCELOT_VCAP_H_ */ From patchwork Mon Jan 25 22:03:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12044517 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,URIBL_BLOCKED,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 5C361C433E0 for ; Mon, 25 Jan 2021 22:06:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 23C3E216FD for ; Mon, 25 Jan 2021 22:06:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733181AbhAYWGq (ORCPT ); Mon, 25 Jan 2021 17:06:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59352 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733155AbhAYWFJ (ORCPT ); Mon, 25 Jan 2021 17:05:09 -0500 Received: from mail-ed1-x533.google.com (mail-ed1-x533.google.com [IPv6:2a00:1450:4864:20::533]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 132B0C061756 for ; Mon, 25 Jan 2021 14:04:29 -0800 (PST) Received: by mail-ed1-x533.google.com with SMTP id f1so17361169edr.12 for ; Mon, 25 Jan 2021 14:04:29 -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 :mime-version:content-transfer-encoding; bh=qg/4up8Zvai8vksH4rAIXOtpatM8jVNOUkUD0I41kNQ=; b=SapSEvqQi0uIgaf6HOiwkYBeT1oQUgf9iFXwYawmLNLVjSibUUu5c5IdkPi8Q07YgF Gqj5VH9e+MmeCaWUfyWicgIYf0bcoan7IV1nEmNF/ABc3Ez8PHe84xFBLTaOjZZWRB9+ wlhWkj8eqRwlJfMvsDghUi8iSjFMDIo/lWhRUhsU+TORra29Sc07WWEqRJ4TjFCNodmu XA6mX1NFq6x72x44a0l4GUJPwYU1E/5aooPoD4qCehmxN8HkGW+EJMpjZ9BmSzvupDcv h0pDRVwPrcwj0/ptoV/x9wQ0ETbOf6s09lVpDDyAyqzJmLcqL8F7NurZYL2KpcIQPuJE fT1Q== 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:mime-version:content-transfer-encoding; bh=qg/4up8Zvai8vksH4rAIXOtpatM8jVNOUkUD0I41kNQ=; b=SVhraflzOa8R4cpUEYgDtdppaz1Hpi4OOa0LYaxgvJusfKYWETZT+8eHo3E6zwEFRk 8hz2tECP7T/syIBRQAhfz9XpT74LmiJhcR8YpNssZMe9gs3xjcuDheci8XhrMAFXINgR NWVTnG9xFInDG2o3GkuBfNm17fveXLHcwwrGybQW9aOYFK6L+QAVbwlgM1vFGfTC43SJ NNc8UVizN9hJZpskkvN7C8ks1B1WJMsJccjJjkNkI+NSC2J+7afZvNmMflXuN3kCRorl iruQMY3WzvOA07k576giabgw4DYl9CNuzdYlf2n31kOwgX0PN3SE13KQI2EMwKSIHKd/ Cc+A== X-Gm-Message-State: AOAM532E6PhAnod4cGh64G0ZPR7x2kIV8U/ArFYHoMSFVXw/emAqPYkF 2mnsjTzxsacrSgyck5vHQqU= X-Google-Smtp-Source: ABdhPJwQui3PCKX/AfYm07tB3q3IZiCStM4LDhYCVBsv9OAOaKuskZmoFwpFPvJo4m+4muYbd4D/pA== X-Received: by 2002:aa7:ca51:: with SMTP id j17mr2274339edt.124.1611612267842; Mon, 25 Jan 2021 14:04:27 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id s13sm1760555edi.92.2021.01.25.14.04.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 14:04:27 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Claudiu Manoil , Alexandre Belloni , Vladimir Oltean , UNGLinuxDriver@microchip.com Subject: [PATCH v7 net-next 03/11] net: mscc: ocelot: store a namespaced VCAP filter ID Date: Tue, 26 Jan 2021 00:03:25 +0200 Message-Id: <20210125220333.1004365-4-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210125220333.1004365-1-olteanv@gmail.com> References: <20210125220333.1004365-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Vladimir Oltean We will be adding some private VCAP filters that should not interfere in any way with the filters added using tc-flower. So we need to allocate some IDs which will not be used by tc. Currently ocelot uses an u32 id derived from the flow cookie, which in itself is an unsigned long. This is a problem in itself, since on 64 bit systems, sizeof(unsigned long)=8, so the driver is already truncating these. Create a struct ocelot_vcap_id which contains the full unsigned long cookie from tc, as well as a boolean that is supposed to namespace the filters added by tc with the ones that aren't. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- Changes in v7: None. Changes in v6: None. Changes in v5: None. Changes in v4: None. Changes in v3: None. Changes in v2: Patch is new. drivers/net/ethernet/mscc/ocelot_flower.c | 7 ++++--- drivers/net/ethernet/mscc/ocelot_vcap.c | 16 ++++++++++++---- drivers/net/ethernet/mscc/ocelot_vcap.h | 3 ++- include/soc/mscc/ocelot_vcap.h | 7 ++++++- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c index 729495a1a77e..c3ac026f6aea 100644 --- a/drivers/net/ethernet/mscc/ocelot_flower.c +++ b/drivers/net/ethernet/mscc/ocelot_flower.c @@ -622,7 +622,8 @@ static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress, int ret; filter->prio = f->common.prio; - filter->id = f->cookie; + filter->id.cookie = f->cookie; + filter->id.tc_offload = true; ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter); if (ret) @@ -717,7 +718,7 @@ int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, block = &ocelot->block[block_id]; - filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie); + filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true); if (!filter) return 0; @@ -741,7 +742,7 @@ int ocelot_cls_flower_stats(struct ocelot *ocelot, int port, block = &ocelot->block[block_id]; - filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie); + filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true); if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY) return 0; diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c index 489bf16362a7..b82fd4103a68 100644 --- a/drivers/net/ethernet/mscc/ocelot_vcap.c +++ b/drivers/net/ethernet/mscc/ocelot_vcap.c @@ -959,6 +959,12 @@ static void ocelot_vcap_filter_add_to_block(struct ocelot *ocelot, list_add(&filter->list, pos->prev); } +static bool ocelot_vcap_filter_equal(const struct ocelot_vcap_filter *a, + const struct ocelot_vcap_filter *b) +{ + return !memcmp(&a->id, &b->id, sizeof(struct ocelot_vcap_id)); +} + static int ocelot_vcap_block_get_filter_index(struct ocelot_vcap_block *block, struct ocelot_vcap_filter *filter) { @@ -966,7 +972,7 @@ static int ocelot_vcap_block_get_filter_index(struct ocelot_vcap_block *block, int index = 0; list_for_each_entry(tmp, &block->rules, list) { - if (filter->id == tmp->id) + if (ocelot_vcap_filter_equal(filter, tmp)) return index; index++; } @@ -991,12 +997,14 @@ ocelot_vcap_block_find_filter_by_index(struct ocelot_vcap_block *block, } struct ocelot_vcap_filter * -ocelot_vcap_block_find_filter_by_id(struct ocelot_vcap_block *block, int id) +ocelot_vcap_block_find_filter_by_id(struct ocelot_vcap_block *block, int cookie, + bool tc_offload) { struct ocelot_vcap_filter *filter; list_for_each_entry(filter, &block->rules, list) - if (filter->id == id) + if (filter->id.tc_offload == tc_offload && + filter->id.cookie == cookie) return filter; return NULL; @@ -1161,7 +1169,7 @@ static void ocelot_vcap_block_remove_filter(struct ocelot *ocelot, list_for_each_safe(pos, q, &block->rules) { tmp = list_entry(pos, struct ocelot_vcap_filter, list); - if (tmp->id == filter->id) { + if (ocelot_vcap_filter_equal(filter, tmp)) { if (tmp->block_id == VCAP_IS2 && tmp->action.police_ena) ocelot_vcap_policer_del(ocelot, block, diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.h b/drivers/net/ethernet/mscc/ocelot_vcap.h index cfc8b976d1de..3b0c7916056e 100644 --- a/drivers/net/ethernet/mscc/ocelot_vcap.h +++ b/drivers/net/ethernet/mscc/ocelot_vcap.h @@ -15,7 +15,8 @@ int ocelot_vcap_filter_stats_update(struct ocelot *ocelot, struct ocelot_vcap_filter *rule); struct ocelot_vcap_filter * -ocelot_vcap_block_find_filter_by_id(struct ocelot_vcap_block *block, int id); +ocelot_vcap_block_find_filter_by_id(struct ocelot_vcap_block *block, int id, + bool tc_offload); void ocelot_detect_vcap_constants(struct ocelot *ocelot); int ocelot_vcap_init(struct ocelot *ocelot); diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h index 7f1b82fba63c..76e01c927e17 100644 --- a/include/soc/mscc/ocelot_vcap.h +++ b/include/soc/mscc/ocelot_vcap.h @@ -648,6 +648,11 @@ enum ocelot_vcap_filter_type { OCELOT_VCAP_FILTER_OFFLOAD, }; +struct ocelot_vcap_id { + unsigned long cookie; + bool tc_offload; +}; + struct ocelot_vcap_filter { struct list_head list; @@ -657,7 +662,7 @@ struct ocelot_vcap_filter { int lookup; u8 pag; u16 prio; - u32 id; + struct ocelot_vcap_id id; struct ocelot_vcap_action action; struct ocelot_vcap_stats stats; From patchwork Mon Jan 25 22:03:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12044515 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,URIBL_BLOCKED,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 BE8FCC433E6 for ; Mon, 25 Jan 2021 22:06:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 89EC4216FD for ; Mon, 25 Jan 2021 22:06:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733180AbhAYWGR (ORCPT ); Mon, 25 Jan 2021 17:06:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59358 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732134AbhAYWFK (ORCPT ); Mon, 25 Jan 2021 17:05:10 -0500 Received: from mail-ej1-x630.google.com (mail-ej1-x630.google.com [IPv6:2a00:1450:4864:20::630]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 75756C0613D6 for ; Mon, 25 Jan 2021 14:04:30 -0800 (PST) Received: by mail-ej1-x630.google.com with SMTP id w1so20201442ejf.11 for ; Mon, 25 Jan 2021 14:04:30 -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 :mime-version:content-transfer-encoding; bh=YCg9KlHjU+4+nj9DXghx0cPGR0Hm3/1sRcbbBPFiAX4=; b=mryobeBgPMPvHF02VOYwHB5ngSBENb5dXj+Sk/ilyFBe5AdHQvfCND7HOp9NcYEIIp wBZrQcifcS4sdX8BaYVcmWuljGe/421sux1+SzUBl2/MGTX5YDsNKCcPV+VkOq1CJtEA zWtNmi7qxqoiZcwrF+oZCV8WYaXOI++rO04lu0vl8FQCQLog31HEz9zsFQJzn1G3+MhX FkD40AlsL2YZeLwIPH2UfMz0ZC1XmnmeI9KbP5CksYI+2bQREYscyG2p1tQkh9d81TPo 9n9+vbDn71El5sdYWq5l0kt4PmY1vjGx8faQAjvXDFx9V9AfgpDe6mS6YuA41F+84mtF 8pNw== 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:mime-version:content-transfer-encoding; bh=YCg9KlHjU+4+nj9DXghx0cPGR0Hm3/1sRcbbBPFiAX4=; b=eacNnY4jwCv2Jm4z6JrQE8ngYTs0fmCWryyqCWuBBc1mvYQcKugR+2JOzwpcCTltsJ aEAq6M3mnYSMfPxi6t1HjxNkX8VJzat52ZpKQyTau+uNZPe35xQnS47D4tH6Tno0PP/U T0wFiDVwGCcmJFV0XNWaPmdJ4AU2ctvdFzks1zFrUkoaSX1u522X8qeATxpLLrPNK1kW yMiCNGGkI2L6Q+efe6ars07z4ZIbhlXwsDibCt/ldXSd7bbsr/988kXEJ2NpGRyUoRBL wFBUmim4BryFsYvodMFm27+lP6CgVq9WnpgrL3mZdu00xeNtmPpk6pa+sNOjzmPQhIj7 l9vw== X-Gm-Message-State: AOAM5334bbrKY3hzmuAP5AhNGbPl2fz3XsU5EAjS5X57fiE8VKjbXbT8 CctI/Z6ANR2GakAPcvcyQrE= X-Google-Smtp-Source: ABdhPJwGmhf3bIax6TwYrxe2jMNx3w2/QbrZhW6vyu3io3s3RPC7CqYoxNCmcsBPzSJF0lj+DT1eCw== X-Received: by 2002:a17:906:358f:: with SMTP id o15mr1645769ejb.369.1611612269202; Mon, 25 Jan 2021 14:04:29 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id s13sm1760555edi.92.2021.01.25.14.04.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 14:04:28 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Claudiu Manoil , Alexandre Belloni , Vladimir Oltean , UNGLinuxDriver@microchip.com Subject: [PATCH v7 net-next 04/11] net: mscc: ocelot: reapply bridge forwarding mask on bonding join/leave Date: Tue, 26 Jan 2021 00:03:26 +0200 Message-Id: <20210125220333.1004365-5-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210125220333.1004365-1-olteanv@gmail.com> References: <20210125220333.1004365-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Vladimir Oltean Applying the bridge forwarding mask currently is done only on the STP state changes for any port. But it depends on both STP state changes, and bonding interface state changes. Export the bit that recalculates the forwarding mask so that it could be reused, and call it when a port starts and stops offloading a bonding interface. Now that the logic is split into a separate function, we can rename "p" into "port", since the "port" variable was already taken in ocelot_bridge_stp_state_set. Also, we can rename "i" into "lag", to make it more clear what is it that we're iterating through. Signed-off-by: Vladimir Oltean Reviewed-by: Alexandre Belloni Reviewed-by: Florian Fainelli --- Changes in v7: None. Changes in v6: None. Jakub, just FYI: ./scripts/get_maintainer.pl parses the "bpf" string from the patchwork instance name, and wants me to CC the BPF maintainers because of that. Changes in v5: None. Changes in v4: Patch is carried over from the "LAG offload for Ocelot DSA switches" series: https://patchwork.kernel.org/project/netdevbpf/patch/20210116005943.219479-10-olteanv@gmail.com/ I need it here because it refactors ocelot_apply_bridge_fwd_mask into a separate function which I also need to call from felix now. drivers/net/ethernet/mscc/ocelot.c | 63 +++++++++++++++++------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 5b2c0cea49ea..7352f58f9bc2 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -889,10 +889,42 @@ int ocelot_get_ts_info(struct ocelot *ocelot, int port, } EXPORT_SYMBOL(ocelot_get_ts_info); +static void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot) +{ + int port; + + /* Apply FWD mask. The loop is needed to add/remove the current port as + * a source for the other ports. + */ + for (port = 0; port < ocelot->num_phys_ports; port++) { + if (ocelot->bridge_fwd_mask & BIT(port)) { + unsigned long mask = ocelot->bridge_fwd_mask & ~BIT(port); + int lag; + + for (lag = 0; lag < ocelot->num_phys_ports; lag++) { + unsigned long bond_mask = ocelot->lags[lag]; + + if (!bond_mask) + continue; + + if (bond_mask & BIT(port)) { + mask &= ~bond_mask; + break; + } + } + + ocelot_write_rix(ocelot, mask, + ANA_PGID_PGID, PGID_SRC + port); + } else { + ocelot_write_rix(ocelot, 0, + ANA_PGID_PGID, PGID_SRC + port); + } + } +} + void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state) { u32 port_cfg; - int p, i; if (!(BIT(port) & ocelot->bridge_mask)) return; @@ -915,32 +947,7 @@ void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state) ocelot_write_gix(ocelot, port_cfg, ANA_PORT_PORT_CFG, port); - /* Apply FWD mask. The loop is needed to add/remove the current port as - * a source for the other ports. - */ - for (p = 0; p < ocelot->num_phys_ports; p++) { - if (ocelot->bridge_fwd_mask & BIT(p)) { - unsigned long mask = ocelot->bridge_fwd_mask & ~BIT(p); - - for (i = 0; i < ocelot->num_phys_ports; i++) { - unsigned long bond_mask = ocelot->lags[i]; - - if (!bond_mask) - continue; - - if (bond_mask & BIT(p)) { - mask &= ~bond_mask; - break; - } - } - - ocelot_write_rix(ocelot, mask, - ANA_PGID_PGID, PGID_SRC + p); - } else { - ocelot_write_rix(ocelot, 0, - ANA_PGID_PGID, PGID_SRC + p); - } - } + ocelot_apply_bridge_fwd_mask(ocelot); } EXPORT_SYMBOL(ocelot_bridge_stp_state_set); @@ -1297,6 +1304,7 @@ int ocelot_port_lag_join(struct ocelot *ocelot, int port, } ocelot_setup_lag(ocelot, lag); + ocelot_apply_bridge_fwd_mask(ocelot); ocelot_set_aggr_pgids(ocelot); return 0; @@ -1330,6 +1338,7 @@ void ocelot_port_lag_leave(struct ocelot *ocelot, int port, ocelot_write_gix(ocelot, port_cfg | ANA_PORT_PORT_CFG_PORTID_VAL(port), ANA_PORT_PORT_CFG, port); + ocelot_apply_bridge_fwd_mask(ocelot); ocelot_set_aggr_pgids(ocelot); } EXPORT_SYMBOL(ocelot_port_lag_leave); From patchwork Mon Jan 25 22:03:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12044523 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,URIBL_BLOCKED,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 C44A0C433DB for ; Mon, 25 Jan 2021 22:07:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 96FD72100A for ; Mon, 25 Jan 2021 22:07:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732134AbhAYWHW (ORCPT ); Mon, 25 Jan 2021 17:07:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59532 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733151AbhAYWGM (ORCPT ); Mon, 25 Jan 2021 17:06:12 -0500 Received: from mail-ed1-x536.google.com (mail-ed1-x536.google.com [IPv6:2a00:1450:4864:20::536]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C970EC0613ED for ; Mon, 25 Jan 2021 14:04:31 -0800 (PST) Received: by mail-ed1-x536.google.com with SMTP id n6so17383803edt.10 for ; Mon, 25 Jan 2021 14:04:31 -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 :mime-version:content-transfer-encoding; bh=R80rKR8xhGvkhvxNcFZ5Dztn+Dx4q1giZJEP37pLBOc=; b=WniA88n4xprxNsLmUHlLmDiLKAYWv3Wfn54uhAQmu9E8urPlw+IHsCrssCthec+H1z ZqcPevzRq84qhSAibx+YfwdfE/giiokbS3YtCZ2znxM6Chybjg+1bapdRymL1GjP/V6Q SxLGYKfvvW8dDR6zpyy8/VoaU/O4EItZ9naENizKFYAHd+THTsnbrhcQqJ30SxXs6FLE dpstFvw2Rwi47SWNwnEaiq9g9a+4tY3IaXWt3XTpsRwnFzdmL9hjQVFhDBF+EUXRx+N8 Xf969cMyj+NR8u0Ftd2Rs0FlE/HrRVxF/TUJXKbSW4vHlfvD29Ha/Loc69qv4i9GuAWZ iVJA== 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:mime-version:content-transfer-encoding; bh=R80rKR8xhGvkhvxNcFZ5Dztn+Dx4q1giZJEP37pLBOc=; b=JgEUlltX1RpjTmXs4rJFenfusk6B3GHELK8K+P15nvjIhtoBJixe25gp5u1QSkwTsv 4j/ryTHU9L1MGx+1i8sLX9ldzFn4SbouT1PPkJ2Rq+ki5k+an0rybjPRUh8md5gOnL34 WsLmRnC40ZRfT7+ryQXwP2Kuk6P2CoK19D57Cif6B8t6nLja2H0qVYHqhVS3quB4Hf83 aMUWWuwYg9zMRhROsIhRG8DqjjFV5l3wvKp6sfPRlFVUBXV+FK4vkF3811wZtfLmstcy 4YGIjErlu/I7BKknDZtT5WCFNcP9V1LstgHDSP+0coN6S/OyUwqxoKOlDXvSpvbjcEW3 zi1A== X-Gm-Message-State: AOAM530sCIVkGR0kDr3hz1rXSB5c+mR0K9D+LQdDQ1PZS1AfBH2ZiRUR RDNU1Po7fzz8nquESJUbBrU= X-Google-Smtp-Source: ABdhPJxM7M98224JoBI90LsYR+MXRdNjAp9VxktFNLQlqgBg34ApRm1A5Z2E5Km4LUh4oA9LO6h7hQ== X-Received: by 2002:a05:6402:524a:: with SMTP id t10mr2235068edd.270.1611612270529; Mon, 25 Jan 2021 14:04:30 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id s13sm1760555edi.92.2021.01.25.14.04.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 14:04:29 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Claudiu Manoil , Alexandre Belloni , Vladimir Oltean , UNGLinuxDriver@microchip.com Subject: [PATCH v7 net-next 05/11] net: mscc: ocelot: don't use NPI tag prefix for the CPU port module Date: Tue, 26 Jan 2021 00:03:27 +0200 Message-Id: <20210125220333.1004365-6-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210125220333.1004365-1-olteanv@gmail.com> References: <20210125220333.1004365-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Vladimir Oltean Context: Ocelot switches put the injection/extraction frame header in front of the Ethernet header. When used in NPI mode, a DSA master would see junk instead of the destination MAC address, and it would most likely drop the packets. So the Ocelot frame header can have an optional prefix, which is just "ff:ff:ff:ff:ff:fe > ff:ff:ff:ff:ff:ff" padding put before the actual tag (still before the real Ethernet header) such that the DSA master thinks it's looking at a broadcast frame with a strange EtherType. Unfortunately, a lesson learned in commit 69df578c5f4b ("net: mscc: ocelot: eliminate confusion between CPU and NPI port") seems to have been forgotten in the meanwhile. The CPU port module and the NPI port have independent settings for the length of the tag prefix. However, the driver is using the same variable to program both of them. There is no reason really to use any tag prefix with the CPU port module, since that is not connected to any Ethernet port. So this patch makes the inj_prefix and xtr_prefix variables apply only to the NPI port (which the switchdev ocelot_vsc7514 driver does not use). Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- Changes in v7: None. Changes in v6: None. Changes in v5: None. Changes in v4: Patch is new. drivers/net/dsa/ocelot/felix.c | 8 ++++---- drivers/net/ethernet/mscc/ocelot.c | 12 ++++++------ drivers/net/ethernet/mscc/ocelot_vsc7514.c | 2 -- include/soc/mscc/ocelot.h | 4 ++-- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 767cbdccdb3e..054e57dd4383 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -425,8 +425,8 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) ocelot->num_mact_rows = felix->info->num_mact_rows; ocelot->vcap = felix->info->vcap; ocelot->ops = felix->info->ops; - ocelot->inj_prefix = OCELOT_TAG_PREFIX_SHORT; - ocelot->xtr_prefix = OCELOT_TAG_PREFIX_SHORT; + ocelot->npi_inj_prefix = OCELOT_TAG_PREFIX_SHORT; + ocelot->npi_xtr_prefix = OCELOT_TAG_PREFIX_SHORT; ocelot->devlink = felix->ds->devlink; port_phy_modes = kcalloc(num_phys_ports, sizeof(phy_interface_t), @@ -541,9 +541,9 @@ static void felix_npi_port_init(struct ocelot *ocelot, int port) /* NPI port Injection/Extraction configuration */ ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_XTR_HDR, - ocelot->xtr_prefix); + ocelot->npi_xtr_prefix); ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_INJ_HDR, - ocelot->inj_prefix); + ocelot->npi_inj_prefix); /* Disable transmission of pause frames */ ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 0); diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 7352f58f9bc2..714165c2f85a 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1359,9 +1359,9 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu) if (port == ocelot->npi) { maxlen += OCELOT_TAG_LEN; - if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_SHORT) + if (ocelot->npi_inj_prefix == OCELOT_TAG_PREFIX_SHORT) maxlen += OCELOT_SHORT_PREFIX_LEN; - else if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_LONG) + else if (ocelot->npi_inj_prefix == OCELOT_TAG_PREFIX_LONG) maxlen += OCELOT_LONG_PREFIX_LEN; } @@ -1391,9 +1391,9 @@ int ocelot_get_max_mtu(struct ocelot *ocelot, int port) if (port == ocelot->npi) { max_mtu -= OCELOT_TAG_LEN; - if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_SHORT) + if (ocelot->npi_inj_prefix == OCELOT_TAG_PREFIX_SHORT) max_mtu -= OCELOT_SHORT_PREFIX_LEN; - else if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_LONG) + else if (ocelot->npi_inj_prefix == OCELOT_TAG_PREFIX_LONG) max_mtu -= OCELOT_LONG_PREFIX_LEN; } @@ -1478,9 +1478,9 @@ static void ocelot_cpu_port_init(struct ocelot *ocelot) ocelot_fields_write(ocelot, cpu, QSYS_SWITCH_PORT_MODE_PORT_ENA, 1); /* CPU port Injection/Extraction configuration */ ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_XTR_HDR, - ocelot->xtr_prefix); + OCELOT_TAG_PREFIX_NONE); ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_INJ_HDR, - ocelot->inj_prefix); + OCELOT_TAG_PREFIX_NONE); /* Configure the CPU port to be VLAN aware */ ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) | diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 30a38df08a21..407244fe5b17 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -1347,8 +1347,6 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ocelot->num_flooding_pgids = 1; ocelot->vcap = vsc7514_vcap_props; - ocelot->inj_prefix = OCELOT_TAG_PREFIX_NONE; - ocelot->xtr_prefix = OCELOT_TAG_PREFIX_NONE; ocelot->npi = -1; err = ocelot_init(ocelot); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index cdc33fa05660..93c22627dedd 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -651,8 +651,8 @@ struct ocelot { int npi; - enum ocelot_tag_prefix inj_prefix; - enum ocelot_tag_prefix xtr_prefix; + enum ocelot_tag_prefix npi_inj_prefix; + enum ocelot_tag_prefix npi_xtr_prefix; u32 *lags; From patchwork Mon Jan 25 22:03:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12044525 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,URIBL_BLOCKED,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 07000C433E0 for ; Mon, 25 Jan 2021 22:09:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C428B2100A for ; Mon, 25 Jan 2021 22:09:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732237AbhAYWJB (ORCPT ); Mon, 25 Jan 2021 17:09:01 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59534 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733145AbhAYWGM (ORCPT ); Mon, 25 Jan 2021 17:06:12 -0500 Received: from mail-ed1-x52f.google.com (mail-ed1-x52f.google.com [IPv6:2a00:1450:4864:20::52f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 620FDC061786 for ; Mon, 25 Jan 2021 14:04:33 -0800 (PST) Received: by mail-ed1-x52f.google.com with SMTP id d22so17427402edy.1 for ; Mon, 25 Jan 2021 14:04:33 -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 :mime-version:content-transfer-encoding; bh=LnAfhs0pCnZlnrIHuWTEBYlC8Wv/rXHwldl6wPaIqx8=; b=ZU/pXtm1ssf9cs/pi4bt/qUkLujdXwwb7EEShwVq0nvok4yZ/i8U7eIuZOceKSiiit mKCtP2BE/GlJMaBJe8CM+E6x1vXg6kLPsvHg1yQgHrZPsgZXTKPgxD6nsPd9m3OhvZyV o6408wt94aXnSYEo3r0JkTAhHMCW7GnJPVRJxed9VISHfJzwCHe7iuAVCbVbIZFnAjPu hAzyeOfQ2aCSxaZ0p2ALSeAjspGLtjnbVS07B63vtRpE/STOYOEuOUS0lT6TNLkL6WNN sShpSDsd9qzW0lRuFMb223UoDQn93zmD4TJysYcHkZHkjzFNRw5+GsOFbXrG8xXQBdEk PIbQ== 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:mime-version:content-transfer-encoding; bh=LnAfhs0pCnZlnrIHuWTEBYlC8Wv/rXHwldl6wPaIqx8=; b=qVBlAGv8xQlcF3vRORcmL2LwhzE3DOoZNmCfckdKcgS4Oc1aFEbZj70DKP6PkNRPgU /Gs6xZffE8geWPpHTrxzSYBzWpqc9aG0sjQ0v8Bxgz815OHoHin5ExOcztGp6oYpl/G1 HyHwyW19l40rM6EdTjel5mG9yNJIMo4AURiKU5w/uaQbc75KRGkmKeNj+4kQ6eHo5Xz6 klXF9EdkLjKmTlrLk6rANCzs4vwHIbpZRYNV4eRgbOnQo68FTXjaBDYNyMtBIilwHvk0 /vteQak9QHFOgl7QdGaAEkH2jMlYdrkBurhHCz6d7BhQSxpcEgHiGaDiGzaSQrgOcFDX FnGA== X-Gm-Message-State: AOAM531pedsi9iMxOm+pfCvTUxJ+purBFBEQhfSwaOOj5rulMWAzMqy1 z2548mBm6RS1pRGh4y4j7Ag= X-Google-Smtp-Source: ABdhPJz6uQARPu5qYAFUujHmMLQc4xLelfl3jUv99fFqQ6UFF8h99ys6IWFqOdx060qPtYoqS4Ws1A== X-Received: by 2002:aa7:dd49:: with SMTP id o9mr2207242edw.14.1611612272123; Mon, 25 Jan 2021 14:04:32 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id s13sm1760555edi.92.2021.01.25.14.04.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 14:04:31 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Claudiu Manoil , Alexandre Belloni , Vladimir Oltean , UNGLinuxDriver@microchip.com Subject: [PATCH v7 net-next 06/11] net: dsa: document the existing switch tree notifiers and add a new one Date: Tue, 26 Jan 2021 00:03:28 +0200 Message-Id: <20210125220333.1004365-7-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210125220333.1004365-1-olteanv@gmail.com> References: <20210125220333.1004365-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Vladimir Oltean The existence of dsa_broadcast has generated some confusion in the past: https://www.mail-archive.com/netdev@vger.kernel.org/msg365042.html So let's document the existing dsa_port_notify and dsa_broadcast functions and explain when each of them should be used. Also, in fact, the in-between function has always been there but was lacking a name, and is the main reason for this patch: dsa_tree_notify. Refactor dsa_broadcast to use it. This patch also moves dsa_broadcast (a top-level function) to dsa2.c, where it really belonged in the first place, but had no companion so it stood with dsa_port_notify. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- Changes in v7: None. Changes in v6: None. Changes in v5: Patch is new. net/dsa/dsa2.c | 43 +++++++++++++++++++++++++++++++++++++++++++ net/dsa/dsa_priv.h | 2 ++ net/dsa/port.c | 36 +++++++++++++----------------------- 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index cc13549120e5..2953d0c1c7bc 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -21,6 +21,49 @@ static DEFINE_MUTEX(dsa2_mutex); LIST_HEAD(dsa_tree_list); +/** + * dsa_tree_notify - Execute code for all switches in a DSA switch tree. + * @dst: collection of struct dsa_switch devices to notify. + * @e: event, must be of type DSA_NOTIFIER_* + * @v: event-specific value. + * + * Given a struct dsa_switch_tree, this can be used to run a function once for + * each member DSA switch. The other alternative of traversing the tree is only + * through its ports list, which does not uniquely list the switches. + */ +int dsa_tree_notify(struct dsa_switch_tree *dst, unsigned long e, void *v) +{ + struct raw_notifier_head *nh = &dst->nh; + int err; + + err = raw_notifier_call_chain(nh, e, v); + + return notifier_to_errno(err); +} + +/** + * dsa_broadcast - Notify all DSA trees in the system. + * @e: event, must be of type DSA_NOTIFIER_* + * @v: event-specific value. + * + * Can be used to notify the switching fabric of events such as cross-chip + * bridging between disjoint trees (such as islands of tagger-compatible + * switches bridged by an incompatible middle switch). + */ +int dsa_broadcast(unsigned long e, void *v) +{ + struct dsa_switch_tree *dst; + int err = 0; + + list_for_each_entry(dst, &dsa_tree_list, list) { + err = dsa_tree_notify(dst, e, v); + if (err) + break; + } + + return err; +} + /** * dsa_lag_map() - Map LAG netdev to a linear LAG ID * @dst: Tree in which to record the mapping. diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 2ce46bb87703..3cc1e6d76e3a 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -283,6 +283,8 @@ void dsa_switch_unregister_notifier(struct dsa_switch *ds); /* dsa2.c */ void dsa_lag_map(struct dsa_switch_tree *dst, struct net_device *lag); void dsa_lag_unmap(struct dsa_switch_tree *dst, struct net_device *lag); +int dsa_tree_notify(struct dsa_switch_tree *dst, unsigned long e, void *v); +int dsa_broadcast(unsigned long e, void *v); extern struct list_head dsa_tree_list; diff --git a/net/dsa/port.c b/net/dsa/port.c index f5b0f72ee7cd..a8886cf40160 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -13,31 +13,21 @@ #include "dsa_priv.h" -static int dsa_broadcast(unsigned long e, void *v) -{ - struct dsa_switch_tree *dst; - int err = 0; - - list_for_each_entry(dst, &dsa_tree_list, list) { - struct raw_notifier_head *nh = &dst->nh; - - err = raw_notifier_call_chain(nh, e, v); - err = notifier_to_errno(err); - if (err) - break; - } - - return err; -} - +/** + * dsa_port_notify - Notify the switching fabric of changes to a port + * @dp: port on which change occurred + * @e: event, must be of type DSA_NOTIFIER_* + * @v: event-specific value. + * + * Notify all switches in the DSA tree that this port's switch belongs to, + * including this switch itself, of an event. Allows the other switches to + * reconfigure themselves for cross-chip operations. Can also be used to + * reconfigure ports without net_devices (CPU ports, DSA links) whenever + * a user port's state changes. + */ static int dsa_port_notify(const struct dsa_port *dp, unsigned long e, void *v) { - struct raw_notifier_head *nh = &dp->ds->dst->nh; - int err; - - err = raw_notifier_call_chain(nh, e, v); - - return notifier_to_errno(err); + return dsa_tree_notify(dp->ds->dst, e, v); } int dsa_port_set_state(struct dsa_port *dp, u8 state) From patchwork Mon Jan 25 22:03:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12044535 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,URIBL_BLOCKED,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 28178C433DB for ; Mon, 25 Jan 2021 22:10:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EBFD42068D for ; Mon, 25 Jan 2021 22:10:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732165AbhAYWKu (ORCPT ); Mon, 25 Jan 2021 17:10:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59540 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733156AbhAYWGM (ORCPT ); Mon, 25 Jan 2021 17:06:12 -0500 Received: from mail-ed1-x534.google.com (mail-ed1-x534.google.com [IPv6:2a00:1450:4864:20::534]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DC9BBC061788 for ; Mon, 25 Jan 2021 14:04:34 -0800 (PST) Received: by mail-ed1-x534.google.com with SMTP id b21so17393190edy.6 for ; Mon, 25 Jan 2021 14:04:34 -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 :mime-version:content-transfer-encoding; bh=6LIw+XeErXv4IwY9a83U6YsuOtVgf/8xg9msZXrfbXU=; b=f7USBCEHf9K+asWgPDc8ivruWlifp44cZ1Pwa5nmwXIcCi8ZJYv1plHXN0JM35sT4l Yp2xFxR68W9nS5wGh4nkctdxy7rLMntlX7JIfq2oWuAGcs3ahSvXW3ETxA9nqE6mUmr4 SWKRyVAmyntEkzlNLAxQWsW/UE/sZF8/B/XukkK3N4UfPm+nOjYecAQls35Jw6fUdswD 1d0jbKMIsnkfp/ODEZDksZXw53wxI+65MgCrzIiAyvUQnhl0O7jp59OHhTpXIGS8oSgj 4LhgRH5k1kT8MQzE2gGGV53lEJsIIj058qCFCIt+3ow7iIodCT00+nTxml5QHksGMs8m hc3w== 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:mime-version:content-transfer-encoding; bh=6LIw+XeErXv4IwY9a83U6YsuOtVgf/8xg9msZXrfbXU=; b=UB7vXL84lmVO840vDmvSfw3DDIz9D10MZJPIZ8PbSrRzuCdmPocqRn6v04w4xewBA5 VstuBUlcrRrlC+geCEMqy0s9rvRcXVOb8X6v0HHNrw0dyEk81RxFF2i0OFfAeqqg0m8i Npurjx2eCZe/rUX2zh7++6vBQ4dW3YiGipMRMWLHsL+ns8czOZ0ucoQJGlza5bDb49Tt z4jxtDTU8f5NYpnFww95CGhZKuvyWNCEBJRbkjNmGz1vy3MnAC6l1ylERK95CAYxQz7Y 0ERcWAFse7N1m0olCkn7P/yn1JvB6YmeEX21iltZHxg56Y0qZ/V7buOfoIFaOY6QMH0D ZmTg== X-Gm-Message-State: AOAM531KkxToIAXfUNbkQlXjrQVeSmb/uiI0W2CPVO61Ab1Lu5UzE+cc tMBx5TsTMbr0SEJvPBwyNeU= X-Google-Smtp-Source: ABdhPJwfrQuTJb/VfNppk2RYQaVGr+tXTY3YL5MzgN6r5sm0K527KmSU8Vrl+YGqng9IAWanFkWHWg== X-Received: by 2002:a05:6402:c9c:: with SMTP id cm28mr2247246edb.281.1611612273550; Mon, 25 Jan 2021 14:04:33 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id s13sm1760555edi.92.2021.01.25.14.04.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 14:04:32 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Claudiu Manoil , Alexandre Belloni , Vladimir Oltean , UNGLinuxDriver@microchip.com Subject: [PATCH v7 net-next 07/11] net: dsa: keep a copy of the tagging protocol in the DSA switch tree Date: Tue, 26 Jan 2021 00:03:29 +0200 Message-Id: <20210125220333.1004365-8-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210125220333.1004365-1-olteanv@gmail.com> References: <20210125220333.1004365-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Vladimir Oltean Cascading DSA switches can be done multiple ways. There is the brute force approach / tag stacking, where one upstream switch, located between leaf switches and the host Ethernet controller, will just happily transport the DSA header of those leaf switches as payload. For this kind of setups, DSA works without any special kind of treatment compared to a single switch - they just aren't aware of each other. Then there's the approach where the upstream switch understands the tags it transports from its leaves below, as it doesn't push a tag of its own, but it routes based on the source port & switch id information present in that tag (as opposed to DMAC & VID) and it strips the tag when egressing a front-facing port. Currently only Marvell implements the latter, and Marvell DSA trees contain only Marvell switches. So it is safe to say that DSA trees already have a single tag protocol shared by all switches, and in fact this is what makes the switches able to understand each other. It's time to make this official and enforce it (yes, this also means we won't have any "switch understands tag to some extent but is not able to speak it" hardware oddities that we'll support in the future). This is needed due to the imminent introduction of the dsa_switch_ops:: {set,del}_tag_protocol driver API. When that is introduced, we'll have to notify switches of the tagging protocol that they're configured to use, even at probe and remove time. Currently the tag_ops structure pointer is held only for CPU ports. But there are switches which don't have CPU ports and nonetheless still need to be configured. These would be Marvell leaf switches whose upstream port is just a DSA link. How do we inform these of their tagging protocol setup/deletion? One answer to the above would be: iterate through the DSA switch tree's ports once, list the CPU ports, get their tag_ops, then iterate again now that we have it, and notify everybody of that tag_ops. But what to do if conflicts appear between one cpu_dp->tag_ops and another? There's no escaping the fact that it makes no sense to have multiple tag_ops in the same dst. Ease our work and just keep the master copy of the tag_ops inside the struct dsa_switch_tree. Note that reference counting the tagger module driver still happens for each CPU port that uses that tagging protocol. There are many places in the data path that access master->dsa_ptr->tag_ops and we would introduce unnecessary performance penalty going through yet another indirection, so keep those right where they are. Signed-off-by: Vladimir Oltean --- Changes in v7: Patch is new. include/net/dsa.h | 7 ++++++- net/dsa/dsa2.c | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 2f5435d3d1db..b8af1d6c879a 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -140,6 +140,9 @@ struct dsa_switch_tree { /* Has this tree been applied to the hardware? */ bool setup; + /* Tagging protocol operations */ + const struct dsa_device_ops *tag_ops; + /* * Configuration data for the platform device that owns * this dsa switch tree instance. @@ -225,7 +228,9 @@ struct dsa_port { struct net_device *slave; }; - /* CPU port tagging operations used by master or slave devices */ + /* Copy of the tagging protocol operations, for quicker access + * in the data path. Valid only for the CPU ports. + */ const struct dsa_device_ops *tag_ops; /* Copies for faster access in master receive hot path */ diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 2953d0c1c7bc..42f22955e111 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -1026,6 +1026,12 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master) dp->master = master; dp->type = DSA_PORT_TYPE_CPU; + if (dst->tag_ops && dst->tag_ops != tag_ops) { + dev_err(ds->dev, + "A DSA switch tree can have only one tagging protocol\n"); + return -EINVAL; + } + dst->tag_ops = tag_ops; dp->filter = tag_ops->filter; dp->rcv = tag_ops->rcv; dp->tag_ops = tag_ops; From patchwork Mon Jan 25 22:03:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12044529 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,URIBL_BLOCKED,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 860F8C433E0 for ; Mon, 25 Jan 2021 22:09:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 414122100A for ; Mon, 25 Jan 2021 22:09:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732581AbhAYWI6 (ORCPT ); Mon, 25 Jan 2021 17:08:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59542 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733167AbhAYWGM (ORCPT ); Mon, 25 Jan 2021 17:06:12 -0500 Received: from mail-ed1-x52e.google.com (mail-ed1-x52e.google.com [IPv6:2a00:1450:4864:20::52e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3E387C06178A for ; Mon, 25 Jan 2021 14:04:36 -0800 (PST) Received: by mail-ed1-x52e.google.com with SMTP id g1so17424329edu.4 for ; Mon, 25 Jan 2021 14:04:36 -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 :mime-version:content-transfer-encoding; bh=wkV08S57GvvCzTx5Fnpz+cxQKWVR7Zpw/qGH9NAjvF8=; b=s/zMIfZIDIWekP7fDaw59hCmdqTkMsTK+kinMAplWTcx5x1Nsc5nYCkR7hfMzKcvMO Wmwa7cSta55YrlNL7yvYdEk8T0dZSrdrT2wXCM5QOOpy3caiQVK4K4xJKRnmqMaEhtfN CfT/J75LEWJQsSI7h6PpS3GK1yJd4YVZA9yIq9hxJLtZqFxuGhSiDZnSfyr2cm1Pk5o+ fnBV9mH8hWQ4lyIU6DsCib8jm7naaOcr9F83ymT42kN2MO2Ahp2dULuA66nI5/9OCPAB ZOR15ZoLRmO7ElonnYkyK0WsqMnm1uMczYqSxeYzQa6KQ2JVw8nEzieKo0q3gfrgzetZ JuNw== 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:mime-version:content-transfer-encoding; bh=wkV08S57GvvCzTx5Fnpz+cxQKWVR7Zpw/qGH9NAjvF8=; b=b/5ZQOE9SDCe6l8k7XiYvkcwOyHt7xOkCOYpy8N8CbRc64+FPCi0rDt1TRb6A/55gR K/RUVht6DVnNXyecI39BXwnBbN5zn53rL6maLT/ptMCgQWp1ykAUrpfZ+dEVWJ7+elpC vp2twpm+HQ7AIqEyVzP/B0sIpiqQNEpXu2Y4OAretYzLGg10eyVjgBbZSZkFO1syJQAz qdqoGxsLWCKmD4hFVAXXGVAY4dEMg73GalUTodqHdLwc3QfPRpgyLv0JvicCX6nUbID4 0UxMj8BE0Uc4R5jtucBxbZmN5vi0zoguc6Fx0MpkboYEuOOnepN65MIEHAQKfqWc78Gr JITg== X-Gm-Message-State: AOAM531/Ur4268WNTE0daUgP14UGpaxaCRgj9XFScWp35Q1BBm7vLmU2 eOo0r53n+3M6ao5aOMceSXk= X-Google-Smtp-Source: ABdhPJxCKBcRaLVIM+85wOv9Uy9gUqva0CBjDPAUoJg4E4E8N/8fHaTn2h2/xb3Jam5eCIJqxq/NPg== X-Received: by 2002:a05:6402:22b7:: with SMTP id cx23mr2191897edb.313.1611612274913; Mon, 25 Jan 2021 14:04:34 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id s13sm1760555edi.92.2021.01.25.14.04.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 14:04:34 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Claudiu Manoil , Alexandre Belloni , Vladimir Oltean , UNGLinuxDriver@microchip.com Subject: [PATCH v7 net-next 08/11] net: dsa: allow changing the tag protocol via the "tagging" device attribute Date: Tue, 26 Jan 2021 00:03:30 +0200 Message-Id: <20210125220333.1004365-9-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210125220333.1004365-1-olteanv@gmail.com> References: <20210125220333.1004365-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Vladimir Oltean Currently DSA exposes the following sysfs: $ cat /sys/class/net/eno2/dsa/tagging ocelot which is a read-only device attribute, introduced in the kernel as commit 98cdb4807123 ("net: dsa: Expose tagging protocol to user-space"), and used by libpcap since its commit 993db3800d7d ("Add support for DSA link-layer types"). It would be nice if we could extend this device attribute by making it writable: $ echo ocelot-8021q > /sys/class/net/eno2/dsa/tagging This is useful with DSA switches that can make use of more than one tagging protocol. It may be useful in dsa_loop in the future too, to perform offline testing of various taggers, or for changing between dsa and edsa on Marvell switches, if that is desirable. In terms of implementation, drivers can now move their tagging protocol configuration outside of .setup/.teardown, and into .set_tag_protocol and .del_tag_protocol. The calling order is: .setup -> [.set_tag_protocol -> .del_tag_protocol]+ -> .teardown There was one more contract between the DSA framework and drivers, which is that if a CPU port needs to account for the tagger overhead in its MTU configuration, it must do that privately. Which means it needs the information about what tagger it uses before we call its MTU configuration function. That promise is still held. Writing to the tagging sysfs will first tear down the tagging protocol for all switches in the tree attached to that DSA master, then will attempt setup with the new tagger. Writing will fail quickly with -EOPNOTSUPP for drivers that don't support .set_tag_protocol, since that is checked during the deletion phase. It is assumed that all switches within the same DSA tree use the same driver, and therefore either all have .set_tag_protocol implemented, or none do. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- Changes in v7: - Hold the rtnl_mutex in dsa_tree_change_tag_proto and change the calling convention such that drivers now expect rtnl_mutex to be held. - Call {set,del}_tag_protocol for DSA links with the tag_ops of the DSA tree and not of their own dp, since the latter is an invalid pointer never set up by anybody. - Wrap the calls done at probe and remove time into some helper functions called dsa_switch_inform_initial_tag_proto and dsa_switch_inform_tag_proto_gone. Call dsa_switch_inform_tag_proto_gone more vigorously during the probe error path. Changes in v6: - Removed redundant tree_index from dsa_notifier_tag_proto_info. - Call .{set,del}_tag_protocol for the DSA links too. - Check for ops::set_tag_protocol only once instead of in a loop. - Check for ops::set_tag_protocol in dsa_switch_tag_proto_set too. Changes in v5: - Update the sysfs documentation - Make the tagger_lock per DSA switch tree instead of per DSA switch, and hold it across the entire delete -> set procedure. - Use dsa_tree_notify instead of dsa_broadcast. Changes in v4: Patch is new. Documentation/ABI/testing/sysfs-class-net-dsa | 11 +- include/net/dsa.h | 15 +++ net/dsa/dsa.c | 20 +++ net/dsa/dsa2.c | 119 +++++++++++++++++- net/dsa/dsa_priv.h | 16 +++ net/dsa/master.c | 26 +++- net/dsa/port.c | 8 ++ net/dsa/slave.c | 35 ++++-- net/dsa/switch.c | 84 +++++++++++++ 9 files changed, 314 insertions(+), 20 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-class-net-dsa b/Documentation/ABI/testing/sysfs-class-net-dsa index 985d84c585c6..e2da26b44dd0 100644 --- a/Documentation/ABI/testing/sysfs-class-net-dsa +++ b/Documentation/ABI/testing/sysfs-class-net-dsa @@ -3,5 +3,12 @@ Date: August 2018 KernelVersion: 4.20 Contact: netdev@vger.kernel.org Description: - String indicating the type of tagging protocol used by the - DSA slave network device. + On read, this file returns a string indicating the type of + tagging protocol used by the DSA network devices that are + attached to this master interface. + On write, this file changes the tagging protocol of the + attached DSA switches, if this operation is supported by the + driver. Changing the tagging protocol must be done with the DSA + interfaces and the master interface all administratively down. + See the "name" field of each registered struct dsa_device_ops + for a list of valid values. diff --git a/include/net/dsa.h b/include/net/dsa.h index b8af1d6c879a..0d8251de520f 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -485,9 +485,24 @@ static inline bool dsa_port_is_vlan_filtering(const struct dsa_port *dp) typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid, bool is_static, void *data); struct dsa_switch_ops { + /* + * Tagging protocol helpers. + * Switches that support a single tagging protocol should implement + * only @get_tag_protocol and hardcode the protocol that they support. + * Switches which can operate using multiple tagging protocols should + * report in @get_tag_protocol the tagger in current use. They can + * optionally set up the tagging protocol in @set_tag_protocol and + * perform teardown (memory deallocation, etc) in @del_tag_protocol. + * The framework guarantees paired calls to the last two functions. + * These helpers are called with @port as the CPU ports and DSA links. + */ enum dsa_tag_protocol (*get_tag_protocol)(struct dsa_switch *ds, int port, enum dsa_tag_protocol mprot); + int (*set_tag_protocol)(struct dsa_switch *ds, int port, + enum dsa_tag_protocol proto); + void (*del_tag_protocol)(struct dsa_switch *ds, int port, + enum dsa_tag_protocol proto); int (*setup)(struct dsa_switch *ds); void (*teardown)(struct dsa_switch *ds); diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index f4ce3c5826a0..aa23736685ba 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -84,6 +84,26 @@ const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops) return ops->name; }; +const struct dsa_device_ops *dsa_find_tagger_by_name(const char *buf) +{ + const struct dsa_device_ops *ops = NULL; + struct dsa_tag_driver *dsa_tag_driver; + + mutex_lock(&dsa_tag_drivers_lock); + list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) { + const struct dsa_device_ops *tmp = dsa_tag_driver->ops; + + if (!sysfs_streq(buf, tmp->name)) + continue; + + ops = tmp; + break; + } + mutex_unlock(&dsa_tag_drivers_lock); + + return ops; +} + const struct dsa_device_ops *dsa_tag_driver_get(int tag_protocol) { struct dsa_tag_driver *dsa_tag_driver; diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 42f22955e111..a7253f3586a1 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -667,6 +667,47 @@ static const struct devlink_ops dsa_devlink_ops = { .sb_occ_tc_port_bind_get = dsa_devlink_sb_occ_tc_port_bind_get, }; +static int dsa_switch_inform_initial_tag_proto(struct dsa_switch *ds) +{ + enum dsa_tag_protocol proto = ds->dst->tag_ops->proto; + struct dsa_port *dp; + int err; + + if (!ds->ops->set_tag_protocol) + return 0; + + list_for_each_entry(dp, &ds->dst->ports, list) { + if ((dsa_is_cpu_port(ds, dp->index) || + dsa_is_dsa_port(ds, dp->index)) && dp->ds == ds) { + rtnl_lock(); + err = ds->ops->set_tag_protocol(ds, dp->index, proto); + rtnl_unlock(); + if (err) + return err; + } + } + + return 0; +} + +static void dsa_switch_inform_tag_proto_gone(struct dsa_switch *ds) +{ + enum dsa_tag_protocol proto = ds->dst->tag_ops->proto; + struct dsa_port *dp; + + if (!ds->ops->del_tag_protocol) + return; + + list_for_each_entry(dp, &ds->dst->ports, list) { + if ((dsa_is_cpu_port(ds, dp->index) || + dsa_is_dsa_port(ds, dp->index)) && dp->ds == ds) { + rtnl_lock(); + ds->ops->del_tag_protocol(ds, dp->index, proto); + rtnl_unlock(); + } + } +} + static int dsa_switch_setup(struct dsa_switch *ds) { struct dsa_devlink_priv *dl_priv; @@ -717,26 +758,39 @@ static int dsa_switch_setup(struct dsa_switch *ds) if (err < 0) goto unregister_notifier; + /* Notify the switches of their tagging protocol after the .setup() + * method, but before we start registering the user ports, whose MTU + * configuration on the CPU port might depend upon the tagger. + */ + err = dsa_switch_inform_initial_tag_proto(ds); + if (err) + goto teardown; + devlink_params_publish(ds->devlink); if (!ds->slave_mii_bus && ds->ops->phy_read) { ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev); if (!ds->slave_mii_bus) { err = -ENOMEM; - goto unregister_notifier; + goto teardown_tag_proto; } dsa_slave_mii_bus_init(ds); err = mdiobus_register(ds->slave_mii_bus); if (err < 0) - goto unregister_notifier; + goto teardown_tag_proto; } ds->setup = true; return 0; +teardown_tag_proto: + dsa_switch_inform_tag_proto_gone(ds); +teardown: + if (ds->ops->teardown) + ds->ops->teardown(ds); unregister_notifier: dsa_switch_unregister_notifier(ds); unregister_devlink_ports: @@ -761,6 +815,7 @@ static void dsa_switch_teardown(struct dsa_switch *ds) if (ds->slave_mii_bus && ds->ops->phy_read) mdiobus_unregister(ds->slave_mii_bus); + dsa_switch_inform_tag_proto_gone(ds); dsa_switch_unregister_notifier(ds); if (ds->ops->teardown) @@ -941,6 +996,62 @@ static void dsa_tree_teardown(struct dsa_switch_tree *dst) dst->setup = false; } +/* Since the dsa/tagging sysfs device attribute is per master, the assumption + * is that all DSA switches within a tree share the same tagger, otherwise + * they would have formed disjoint trees (different "dsa,member" values). + */ +int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, + struct net_device *master, + const struct dsa_device_ops *tag_ops, + const struct dsa_device_ops *old_tag_ops) +{ + struct dsa_notifier_tag_proto_info info; + struct dsa_port *dp; + int err = -EBUSY; + + if (!rtnl_trylock()) + return restart_syscall(); + + /* At the moment we don't allow changing the tag protocol under + * traffic. The rtnl_mutex also happens to serialize concurrent + * attempts to change the tagging protocol. If we ever lift the IFF_UP + * restriction, there needs to be another mutex which serializes this. + */ + if (master->flags & IFF_UP) + goto out_unlock; + + list_for_each_entry(dp, &dst->ports, list) { + if (!dsa_is_user_port(dp->ds, dp->index)) + continue; + + if (dp->slave->flags & IFF_UP) + goto out_unlock; + } + + info.tag_ops = old_tag_ops; + err = dsa_tree_notify(dst, DSA_NOTIFIER_TAG_PROTO_DEL, &info); + if (err) + goto out_unlock; + + info.tag_ops = tag_ops; + err = dsa_tree_notify(dst, DSA_NOTIFIER_TAG_PROTO_SET, &info); + if (err) + goto out_unwind_tagger; + + dst->tag_ops = tag_ops; + + rtnl_unlock(); + + return 0; + +out_unwind_tagger: + info.tag_ops = old_tag_ops; + dsa_tree_notify(dst, DSA_NOTIFIER_TAG_PROTO_SET, &info); +out_unlock: + rtnl_unlock(); + return err; +} + static struct dsa_port *dsa_port_touch(struct dsa_switch *ds, int index) { struct dsa_switch_tree *dst = ds->dst; @@ -1032,9 +1143,7 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master) return -EINVAL; } dst->tag_ops = tag_ops; - dp->filter = tag_ops->filter; - dp->rcv = tag_ops->rcv; - dp->tag_ops = tag_ops; + dsa_port_set_tag_protocol(dp, tag_ops); dp->dst = dst; return 0; diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 3cc1e6d76e3a..bf6f1d4c2fee 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -28,6 +28,8 @@ enum { DSA_NOTIFIER_VLAN_ADD, DSA_NOTIFIER_VLAN_DEL, DSA_NOTIFIER_MTU, + DSA_NOTIFIER_TAG_PROTO_SET, + DSA_NOTIFIER_TAG_PROTO_DEL, }; /* DSA_NOTIFIER_AGEING_TIME */ @@ -82,6 +84,11 @@ struct dsa_notifier_mtu_info { int mtu; }; +/* DSA_NOTIFIER_TAG_PROTO_* */ +struct dsa_notifier_tag_proto_info { + const struct dsa_device_ops *tag_ops; +}; + struct dsa_switchdev_event_work { struct dsa_switch *ds; int port; @@ -115,6 +122,7 @@ struct dsa_slave_priv { /* dsa.c */ const struct dsa_device_ops *dsa_tag_driver_get(int tag_protocol); void dsa_tag_driver_put(const struct dsa_device_ops *ops); +const struct dsa_device_ops *dsa_find_tagger_by_name(const char *buf); bool dsa_schedule_work(struct work_struct *work); const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops); @@ -139,6 +147,8 @@ static inline struct net_device *dsa_master_find_slave(struct net_device *dev, } /* port.c */ +void dsa_port_set_tag_protocol(struct dsa_port *cpu_dp, + const struct dsa_device_ops *tag_ops); int dsa_port_set_state(struct dsa_port *dp, u8 state); int dsa_port_enable_rt(struct dsa_port *dp, struct phy_device *phy); int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy); @@ -201,6 +211,8 @@ int dsa_slave_suspend(struct net_device *slave_dev); int dsa_slave_resume(struct net_device *slave_dev); int dsa_slave_register_notifier(void); void dsa_slave_unregister_notifier(void); +void dsa_slave_setup_tagger(struct net_device *slave); +int dsa_slave_change_mtu(struct net_device *dev, int new_mtu); static inline struct dsa_port *dsa_slave_to_port(const struct net_device *dev) { @@ -285,6 +297,10 @@ void dsa_lag_map(struct dsa_switch_tree *dst, struct net_device *lag); void dsa_lag_unmap(struct dsa_switch_tree *dst, struct net_device *lag); int dsa_tree_notify(struct dsa_switch_tree *dst, unsigned long e, void *v); int dsa_broadcast(unsigned long e, void *v); +int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, + struct net_device *master, + const struct dsa_device_ops *tag_ops, + const struct dsa_device_ops *old_tag_ops); extern struct list_head dsa_tree_list; diff --git a/net/dsa/master.c b/net/dsa/master.c index cb3a5cf99b25..6c0068fbecda 100644 --- a/net/dsa/master.c +++ b/net/dsa/master.c @@ -280,7 +280,31 @@ static ssize_t tagging_show(struct device *d, struct device_attribute *attr, return sprintf(buf, "%s\n", dsa_tag_protocol_to_str(cpu_dp->tag_ops)); } -static DEVICE_ATTR_RO(tagging); + +static ssize_t tagging_store(struct device *d, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct net_device *dev = to_net_dev(d); + struct dsa_port *cpu_dp = dev->dsa_ptr; + const struct dsa_device_ops *ops; + int err; + + ops = dsa_find_tagger_by_name(buf); + /* Bad tagger name, or module is not loaded? */ + if (!ops) + return -ENOENT; + + if (ops == cpu_dp->tag_ops) + goto out; + + err = dsa_tree_change_tag_proto(cpu_dp->ds->dst, dev, ops, + cpu_dp->tag_ops); + if (err) + return err; +out: + return count; +} +static DEVICE_ATTR_RW(tagging); static struct attribute *dsa_slave_attrs[] = { &dev_attr_tagging.attr, diff --git a/net/dsa/port.c b/net/dsa/port.c index a8886cf40160..5e079a61528e 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -526,6 +526,14 @@ int dsa_port_vlan_del(struct dsa_port *dp, return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info); } +void dsa_port_set_tag_protocol(struct dsa_port *cpu_dp, + const struct dsa_device_ops *tag_ops) +{ + cpu_dp->filter = tag_ops->filter; + cpu_dp->rcv = tag_ops->rcv; + cpu_dp->tag_ops = tag_ops; +} + static struct phy_device *dsa_port_get_phy_device(struct dsa_port *dp) { struct device_node *phy_dn; diff --git a/net/dsa/slave.c b/net/dsa/slave.c index f2fb433f3828..b0571ab4e5a7 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1430,7 +1430,7 @@ static void dsa_bridge_mtu_normalization(struct dsa_port *dp) dsa_hw_port_list_free(&hw_port_list); } -static int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) +int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) { struct net_device *master = dsa_slave_to_master(dev); struct dsa_port *dp = dsa_slave_to_port(dev); @@ -1708,6 +1708,27 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev) return ret; } +void dsa_slave_setup_tagger(struct net_device *slave) +{ + struct dsa_port *dp = dsa_slave_to_port(slave); + struct dsa_slave_priv *p = netdev_priv(slave); + const struct dsa_port *cpu_dp = dp->cpu_dp; + struct net_device *master = cpu_dp->master; + + if (cpu_dp->tag_ops->tail_tag) + slave->needed_tailroom = cpu_dp->tag_ops->overhead; + else + slave->needed_headroom = cpu_dp->tag_ops->overhead; + /* Try to save one extra realloc later in the TX path (in the master) + * by also inheriting the master's needed headroom and tailroom. + * The 8021q driver also does this. + */ + slave->needed_headroom += master->needed_headroom; + slave->needed_tailroom += master->needed_tailroom; + + p->xmit = cpu_dp->tag_ops->xmit; +} + static struct lock_class_key dsa_slave_netdev_xmit_lock_key; static void dsa_slave_set_lockdep_class_one(struct net_device *dev, struct netdev_queue *txq, @@ -1782,16 +1803,6 @@ int dsa_slave_create(struct dsa_port *port) slave_dev->netdev_ops = &dsa_slave_netdev_ops; if (ds->ops->port_max_mtu) slave_dev->max_mtu = ds->ops->port_max_mtu(ds, port->index); - if (cpu_dp->tag_ops->tail_tag) - slave_dev->needed_tailroom = cpu_dp->tag_ops->overhead; - else - slave_dev->needed_headroom = cpu_dp->tag_ops->overhead; - /* Try to save one extra realloc later in the TX path (in the master) - * by also inheriting the master's needed headroom and tailroom. - * The 8021q driver also does this. - */ - slave_dev->needed_headroom += master->needed_headroom; - slave_dev->needed_tailroom += master->needed_tailroom; SET_NETDEV_DEVTYPE(slave_dev, &dsa_type); netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one, @@ -1814,8 +1825,8 @@ int dsa_slave_create(struct dsa_port *port) p->dp = port; INIT_LIST_HEAD(&p->mall_tc_list); - p->xmit = cpu_dp->tag_ops->xmit; port->slave = slave_dev; + dsa_slave_setup_tagger(slave_dev); rtnl_lock(); ret = dsa_slave_change_mtu(slave_dev, ETH_DATA_LEN); diff --git a/net/dsa/switch.c b/net/dsa/switch.c index cc0b25f3adea..17518377a1fa 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -297,6 +297,84 @@ static int dsa_switch_vlan_del(struct dsa_switch *ds, return 0; } +static bool dsa_switch_tag_proto_match(struct dsa_switch *ds, int port, + struct dsa_notifier_tag_proto_info *info) +{ + if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) + return true; + + return false; +} + +static int dsa_switch_tag_proto_del(struct dsa_switch *ds, + struct dsa_notifier_tag_proto_info *info) +{ + int port; + + /* Check early if we can replace it, so we don't delete it + * for nothing and leave the switch dangling. + */ + if (!ds->ops->set_tag_protocol) + return -EOPNOTSUPP; + + /* The delete method is optional, just the setter is mandatory */ + if (!ds->ops->del_tag_protocol) + return 0; + + ASSERT_RTNL(); + + for (port = 0; port < ds->num_ports; port++) { + if (dsa_switch_tag_proto_match(ds, port, info)) { + ds->ops->del_tag_protocol(ds, port, + info->tag_ops->proto); + } + } + + return 0; +} + +static int dsa_switch_tag_proto_set(struct dsa_switch *ds, + struct dsa_notifier_tag_proto_info *info) +{ + int port, err; + + if (!ds->ops->set_tag_protocol) + return -EOPNOTSUPP; + + ASSERT_RTNL(); + + for (port = 0; port < ds->num_ports; port++) { + if (dsa_switch_tag_proto_match(ds, port, info)) { + err = ds->ops->set_tag_protocol(ds, port, + info->tag_ops->proto); + if (err) + return err; + + if (dsa_is_cpu_port(ds, port)) + dsa_port_set_tag_protocol(dsa_to_port(ds, port), + info->tag_ops); + } + } + + /* Now that changing the tag protocol can no longer fail, let's update + * the remaining bits which are "duplicated for faster access", and the + * bits that depend on the tagger, such as the MTU. + */ + for (port = 0; port < ds->num_ports; port++) { + if (dsa_is_user_port(ds, port)) { + struct net_device *slave; + + slave = dsa_to_port(ds, port)->slave; + dsa_slave_setup_tagger(slave); + + /* rtnl_mutex is held in dsa_tree_change_tag_proto */ + dsa_slave_change_mtu(slave, slave->mtu); + } + } + + return 0; +} + static int dsa_switch_event(struct notifier_block *nb, unsigned long event, void *info) { @@ -343,6 +421,12 @@ static int dsa_switch_event(struct notifier_block *nb, case DSA_NOTIFIER_MTU: err = dsa_switch_mtu(ds, info); break; + case DSA_NOTIFIER_TAG_PROTO_SET: + err = dsa_switch_tag_proto_set(ds, info); + break; + case DSA_NOTIFIER_TAG_PROTO_DEL: + err = dsa_switch_tag_proto_del(ds, info); + break; default: err = -EOPNOTSUPP; break; From patchwork Mon Jan 25 22:03:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12044531 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,URIBL_BLOCKED,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 7E42DC433E0 for ; Mon, 25 Jan 2021 22:10:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 508F92068D for ; Mon, 25 Jan 2021 22:10:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731937AbhAYWJ5 (ORCPT ); Mon, 25 Jan 2021 17:09:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59546 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733169AbhAYWGM (ORCPT ); Mon, 25 Jan 2021 17:06:12 -0500 Received: from mail-ed1-x52e.google.com (mail-ed1-x52e.google.com [IPv6:2a00:1450:4864:20::52e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A9722C06178B for ; Mon, 25 Jan 2021 14:04:37 -0800 (PST) Received: by mail-ed1-x52e.google.com with SMTP id z22so2719920edb.9 for ; Mon, 25 Jan 2021 14:04:37 -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 :mime-version:content-transfer-encoding; bh=dJmc0jCWZrW9fQ7F7zCRgOrJ/yeq1MSAQVnDxtE7aVA=; b=nI92JOBNIfB+O9DaJZxt1NwNgG44/9JN0NxWKFWqIvS4dD8eysvK38mm+k6Cvs19ld F/6SNOl6Gud8XeFW9uKXKFp8/jugWa7evfXMhDAikzzEHrQUjeMyRDXPCvWS9ueAgS1q HAmicPlQJRCbYtoCmjJIGYNQ6XjzRYyAKRqsJz2NrmFBUltP6PQURd9sxm1Hv8mLZWQQ Cyi0aDKfTTz2Ah1VRr8DTsZKuMuDjilpkf7qKupqGxpKwL8LlVkpb420I581h8qHYXrj t65xF4Q9TiG0y+EeKp+uidptz8eYuJhDlI0ZGuGpcXyuAfrJJRTAaoaI5d7uFkqoYbLa sIRQ== 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:mime-version:content-transfer-encoding; bh=dJmc0jCWZrW9fQ7F7zCRgOrJ/yeq1MSAQVnDxtE7aVA=; b=KmcGl+dpRsGUhxtGEC4QHZYRZ0CNwaOjYD1FqAoab5i4bvYvvGmulMFEh90WfuSNLR J4oxxVDhmLPJEYYvugRnc5WY1DLJXDW+fA7RYeovbFn9VWF2E44eJNa0ZvQJ45t+U2li oXGC0fFd1bIO4cE7q3U3ov6+2VapLmeC72WJO1WmcLh3pOAP5zG7G6xiqv6AI9G+kQb0 xYb7D0G+1WHN3v8Av70Lvhtza8lq/76K21CoU42WxjJS3a/HsYNuQjAQFc/EQhRBsbH+ ZXe32AKCMTYM5Pj1GqYpi/OOjUXu3xlzY5twLzLxQPmswJ5NdsIqL1+nT7NSpDvWgwNI yo6w== X-Gm-Message-State: AOAM531A/3MX0pvW7lcV9nMj8E8zDIl8JAI7zIrEWnSE26J2cTGkAGsS YyzwQPgWE1MujUEUB1DUN94= X-Google-Smtp-Source: ABdhPJxto36UApgwR15eJIUa8bRctJ4q6zXjSk/+WxTULKbgkpKkrnkNH+PvIMcVl2OTtl2M+qY/ig== X-Received: by 2002:aa7:d8c6:: with SMTP id k6mr2211161eds.265.1611612276399; Mon, 25 Jan 2021 14:04:36 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id s13sm1760555edi.92.2021.01.25.14.04.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 14:04:35 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Claudiu Manoil , Alexandre Belloni , Vladimir Oltean , UNGLinuxDriver@microchip.com Subject: [PATCH v7 net-next 09/11] net: dsa: felix: convert to the new .{set,del}_tag_protocol DSA API Date: Tue, 26 Jan 2021 00:03:31 +0200 Message-Id: <20210125220333.1004365-10-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210125220333.1004365-1-olteanv@gmail.com> References: <20210125220333.1004365-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Vladimir Oltean In expectation of the new tag_ocelot_8021q tagger implementation, we need to be able to do runtime switchover between one tagger and another. So we must implement the .set_tag_protocol() and .del_tag_protocol() for the current NPI-based tagger. We move the felix_npi_port_init function in expectation of the future driver configuration necessary for tag_ocelot_8021q: we would like to not have the NPI-related bits interspersed with the tag_8021q bits. Note that the NPI port is no longer configured when the .setup() method concludes - aka when ocelot_init() and ocelot_init_port() are called. So we need to set the replicator groups - the PGIDs - again, when the NPI port is configured - in .set_tag_protocol(). So we export and call ocelot_apply_bridge_fwd_mask(). The conversion from this: ocelot_write_rix(ocelot, ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)), ANA_PGID_PGID, PGID_UC); to this: cpu_flood = ANA_PGID_PGID_PGID(BIT(ocelot->num_phys_ports)); ocelot_rmw_rix(ocelot, cpu_flood, cpu_flood, ANA_PGID_PGID, PGID_UC); is perhaps non-trivial, but is nonetheless non-functional. The PGID_UC (replicator for unknown unicast) is already configured out of hardware reset to flood to all ports except ocelot->num_phys_ports (the CPU port module). All we change is that we use a read-modify-write to only add the CPU port module to the unknown unicast replicator, as opposed to doing a full write to the register. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- Changes in v7: None. Changes in v6: None. Changes in v5: Path is split from previous monolithic patch "net: dsa: felix: add new VLAN-based tagger". drivers/net/dsa/ocelot/felix.c | 150 +++++++++++++++++------ drivers/net/dsa/ocelot/felix.h | 1 + drivers/net/dsa/ocelot/felix_vsc9959.c | 1 + drivers/net/dsa/ocelot/seville_vsc9953.c | 1 + drivers/net/ethernet/mscc/ocelot.c | 3 +- include/soc/mscc/ocelot.h | 1 + 6 files changed, 120 insertions(+), 37 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 054e57dd4383..f45dfb800bcb 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright 2019 NXP Semiconductors +/* Copyright 2019-2021 NXP Semiconductors * * This is an umbrella module for all network switches that are * register-compatible with Ocelot and that perform I/O to their host CPU @@ -24,11 +24,118 @@ #include #include "felix.h" +/* The CPU port module is connected to the Node Processor Interface (NPI). This + * is the mode through which frames can be injected from and extracted to an + * external CPU, over Ethernet. In NXP SoCs, the "external CPU" is the ARM CPU + * running Linux, and this forms a DSA setup together with the enetc or fman + * DSA master. + */ +static void felix_npi_port_init(struct ocelot *ocelot, int port) +{ + ocelot->npi = port; + + ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M | + QSYS_EXT_CPU_CFG_EXT_CPU_PORT(port), + QSYS_EXT_CPU_CFG); + + /* NPI port Injection/Extraction configuration */ + ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_XTR_HDR, + ocelot->npi_xtr_prefix); + ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_INJ_HDR, + ocelot->npi_inj_prefix); + + /* Disable transmission of pause frames */ + ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 0); +} + +static void felix_npi_port_deinit(struct ocelot *ocelot, int port) +{ + /* Restore hardware defaults */ + int unused_port = ocelot->num_phys_ports + 2; + + ocelot->npi = -1; + + ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPU_PORT(unused_port), + QSYS_EXT_CPU_CFG); + + ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_XTR_HDR, + OCELOT_TAG_PREFIX_DISABLED); + ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_INJ_HDR, + OCELOT_TAG_PREFIX_DISABLED); + + /* Enable transmission of pause frames */ + ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 1); +} + +static int felix_setup_tag_npi(struct dsa_switch *ds, int cpu) +{ + struct ocelot *ocelot = ds->priv; + unsigned long cpu_flood; + + felix_npi_port_init(ocelot, cpu); + + /* Include the CPU port module (and indirectly, the NPI port) + * in the forwarding mask for unknown unicast - the hardware + * default value for ANA_FLOODING_FLD_UNICAST excludes + * BIT(ocelot->num_phys_ports), and so does ocelot_init, + * since Ocelot relies on whitelisting MAC addresses towards + * PGID_CPU. + * We do this because DSA does not yet perform RX filtering, + * and the NPI port does not perform source address learning, + * so traffic sent to Linux is effectively unknown from the + * switch's perspective. + */ + cpu_flood = ANA_PGID_PGID_PGID(BIT(ocelot->num_phys_ports)); + ocelot_rmw_rix(ocelot, cpu_flood, cpu_flood, ANA_PGID_PGID, PGID_UC); + + ocelot_apply_bridge_fwd_mask(ocelot); + + return 0; +} + +static void felix_teardown_tag_npi(struct dsa_switch *ds, int cpu) +{ + struct ocelot *ocelot = ds->priv; + + felix_npi_port_deinit(ocelot, cpu); +} + static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds, int port, enum dsa_tag_protocol mp) { - return DSA_TAG_PROTO_OCELOT; + struct ocelot *ocelot = ds->priv; + struct felix *felix = ocelot_to_felix(ocelot); + + return felix->tag_proto; +} + +static int felix_set_tag_protocol(struct dsa_switch *ds, int cpu, + enum dsa_tag_protocol proto) +{ + int err; + + switch (proto) { + case DSA_TAG_PROTO_OCELOT: + err = felix_setup_tag_npi(ds, cpu); + break; + default: + err = -EOPNOTSUPP; + } + + return err; +} + +static void felix_del_tag_protocol(struct dsa_switch *ds, int cpu, + enum dsa_tag_protocol proto) +{ + switch (proto) { + case DSA_TAG_PROTO_OCELOT: + felix_teardown_tag_npi(ds, cpu); + break; + default: + break; + } } static int felix_set_ageing_time(struct dsa_switch *ds, @@ -527,28 +634,6 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) return 0; } -/* The CPU port module is connected to the Node Processor Interface (NPI). This - * is the mode through which frames can be injected from and extracted to an - * external CPU, over Ethernet. - */ -static void felix_npi_port_init(struct ocelot *ocelot, int port) -{ - ocelot->npi = port; - - ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M | - QSYS_EXT_CPU_CFG_EXT_CPU_PORT(port), - QSYS_EXT_CPU_CFG); - - /* NPI port Injection/Extraction configuration */ - ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_XTR_HDR, - ocelot->npi_xtr_prefix); - ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_INJ_HDR, - ocelot->npi_inj_prefix); - - /* Disable transmission of pause frames */ - ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 0); -} - /* Hardware initialization done here so that we can allocate structures with * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing * us to allocate structures twice (leak memory) and map PCI memory twice @@ -578,10 +663,10 @@ static int felix_setup(struct dsa_switch *ds) } for (port = 0; port < ds->num_ports; port++) { - ocelot_init_port(ocelot, port); + if (dsa_is_unused_port(ds, port)) + continue; - if (dsa_is_cpu_port(ds, port)) - felix_npi_port_init(ocelot, port); + ocelot_init_port(ocelot, port); /* Set the default QoS Classification based on PCP and DEI * bits of vlan tag. @@ -593,15 +678,6 @@ static int felix_setup(struct dsa_switch *ds) if (err) return err; - /* Include the CPU port module in the forwarding mask for unknown - * unicast - the hardware default value for ANA_FLOODING_FLD_UNICAST - * excludes BIT(ocelot->num_phys_ports), and so does ocelot_init, since - * Ocelot relies on whitelisting MAC addresses towards PGID_CPU. - */ - ocelot_write_rix(ocelot, - ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)), - ANA_PGID_PGID, PGID_UC); - ds->mtu_enforcement_ingress = true; ds->assisted_learning_on_cpu_port = true; @@ -860,6 +936,8 @@ static int felix_sb_occ_tc_port_bind_get(struct dsa_switch *ds, int port, const struct dsa_switch_ops felix_switch_ops = { .get_tag_protocol = felix_get_tag_protocol, + .set_tag_protocol = felix_set_tag_protocol, + .del_tag_protocol = felix_del_tag_protocol, .setup = felix_setup, .teardown = felix_teardown, .set_ageing_time = felix_set_ageing_time, diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 994835cb9307..264b3bbdc4d1 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -48,6 +48,7 @@ struct felix { struct lynx_pcs **pcs; resource_size_t switch_base; resource_size_t imdio_base; + enum dsa_tag_protocol tag_proto; }; struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port); diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index f9711e69b8d5..e944868cc120 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1467,6 +1467,7 @@ static int felix_pci_probe(struct pci_dev *pdev, ds->ops = &felix_switch_ops; ds->priv = ocelot; felix->ds = ds; + felix->tag_proto = DSA_TAG_PROTO_OCELOT; err = dsa_register_switch(ds); if (err) { diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index 5e9bfdea50be..512f677a6c1c 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -1246,6 +1246,7 @@ static int seville_probe(struct platform_device *pdev) ds->ops = &felix_switch_ops; ds->priv = ocelot; felix->ds = ds; + felix->tag_proto = DSA_TAG_PROTO_OCELOT; err = dsa_register_switch(ds); if (err) { diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 714165c2f85a..ebc797a08506 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -889,7 +889,7 @@ int ocelot_get_ts_info(struct ocelot *ocelot, int port, } EXPORT_SYMBOL(ocelot_get_ts_info); -static void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot) +void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot) { int port; @@ -921,6 +921,7 @@ static void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot) } } } +EXPORT_SYMBOL(ocelot_apply_bridge_fwd_mask); void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state) { diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 93c22627dedd..fba24a0327d4 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -760,6 +760,7 @@ void ocelot_adjust_link(struct ocelot *ocelot, int port, struct phy_device *phydev); int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, bool enabled); void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state); +void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot); int ocelot_port_bridge_join(struct ocelot *ocelot, int port, struct net_device *bridge); int ocelot_port_bridge_leave(struct ocelot *ocelot, int port, From patchwork Mon Jan 25 22:03:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12044527 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,URIBL_BLOCKED,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 9D26AC433DB for ; Mon, 25 Jan 2021 22:09:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 76B9B216FD for ; Mon, 25 Jan 2021 22:09:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731749AbhAYWJP (ORCPT ); Mon, 25 Jan 2021 17:09:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59550 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733170AbhAYWGM (ORCPT ); Mon, 25 Jan 2021 17:06:12 -0500 Received: from mail-ed1-x52b.google.com (mail-ed1-x52b.google.com [IPv6:2a00:1450:4864:20::52b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8A7E3C06178C for ; Mon, 25 Jan 2021 14:04:39 -0800 (PST) Received: by mail-ed1-x52b.google.com with SMTP id dj23so17390032edb.13 for ; Mon, 25 Jan 2021 14:04:39 -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 :mime-version:content-transfer-encoding; bh=+7oq8IDCKinL7EW4mZq9kHGP8iSWMPHxRWaK0oqyJSw=; b=i4NDJMPEO9Z8wyUZF3fB/phSzjKJLuW6QoH9TA9VeIQ+fWcP5GGEdqM3Szin+EHj8y 4XLMckjOX3Vd+xehgebSlzEC8EHg1p133OlWPslg1gckkzzm6njg5FhepPOA/8mrRlDo 2yLQKLgeFMzBinLB1kXjX/LRO53sALz2bwjVOST+MV6XtwebLAhCoqXzJ0Ez5unChM3J ep9cUtAe1uiUUoai3QBVcpVo+pqvUIaLdPaeKFF5XPVkTlk/izQVu56xG5f86IgMgYL6 h7Z3tWTS45WCq6mJqE/cmMm57QTZ9i2R33tKFxG9RwzFTCokN7f746hfyqCfcrP6s4p5 KldQ== 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:mime-version:content-transfer-encoding; bh=+7oq8IDCKinL7EW4mZq9kHGP8iSWMPHxRWaK0oqyJSw=; b=hj3awBhOKReEWZ+D54hN//lEs8GkAQG6pjW5Qkoh5WPY67BWIXXZ0gZnIhUisBe8K6 SyOVJcyw+arOfrlY09+DIYU914LZflXOKFON2ZxvaW+hnBOf2kkTh8Rh5yOZOdCS9N03 qlJiSZKXIDbreQ2/QWGxHfDP71YS5HNbyxDpbvZWIbR039euj00zHaaHHoTSyc/CPB66 wM5E5VQuzLm6LQKmHRPcLtbZFzMQEse1P6y/v2G+91bfVnLdDQwgFnBN1xlgSOu6cM5T 52hegfzG38q+Y+WYkC8GOKSzYNVp+jttGsdIDorap02JUMP3S1wd2EMj9WZxDZnRm1wD NJtg== X-Gm-Message-State: AOAM530pjIaON23dq9BYkJhxcQNmmx6ipnyxSQ/GwjMJEfdCq6Xo/BsT NaKmdASWhzrs1/u+gar1UIk= X-Google-Smtp-Source: ABdhPJyFZ49LQ6Z0kcDTYV/UHrS2cOiCcw6nF82Ox/dfyYZU8RUsp9Em3Wl5Ry+plkRGq3dwYs7nGw== X-Received: by 2002:a05:6402:34e:: with SMTP id r14mr2232453edw.269.1611612278224; Mon, 25 Jan 2021 14:04:38 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id s13sm1760555edi.92.2021.01.25.14.04.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 14:04:37 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Claudiu Manoil , Alexandre Belloni , Vladimir Oltean , UNGLinuxDriver@microchip.com Subject: [PATCH v7 net-next 10/11] net: dsa: add a second tagger for Ocelot switches based on tag_8021q Date: Tue, 26 Jan 2021 00:03:32 +0200 Message-Id: <20210125220333.1004365-11-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210125220333.1004365-1-olteanv@gmail.com> References: <20210125220333.1004365-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Vladimir Oltean There are use cases for which the existing tagger, based on the NPI (Node Processor Interface) functionality, is insufficient. Namely: - Frames injected through the NPI port bypass the frame analyzer, so no source address learning is performed, no TSN stream classification, etc. - Flow control is not functional over an NPI port (PAUSE frames are encapsulated in the same Extraction Frame Header as all other frames) - There can be at most one NPI port configured for an Ocelot switch. But in NXP LS1028A and T1040 there are two Ethernet CPU ports. The non-NPI port is currently either disabled, or operated as a plain user port (albeit an internally-facing one). Having the ability to configure the two CPU ports symmetrically could pave the way for e.g. creating a LAG between them, to increase bandwidth seamlessly for the system. So there is a desire to have an alternative to the NPI mode. This change keeps the default tagger for the Seville and Felix switches as "ocelot", but it can be changed via the following device attribute: echo ocelot-8021q > /sys/class//dsa/tagging Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- Changes in v7: None. Changes in v6: None. Changes in v5: Path is split from previous monolithic patch "net: dsa: felix: add new VLAN-based tagger". MAINTAINERS | 1 + drivers/net/dsa/ocelot/Kconfig | 2 + include/net/dsa.h | 2 + net/dsa/Kconfig | 21 +++++++++-- net/dsa/Makefile | 1 + net/dsa/tag_ocelot_8021q.c | 68 ++++++++++++++++++++++++++++++++++ 6 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 net/dsa/tag_ocelot_8021q.c diff --git a/MAINTAINERS b/MAINTAINERS index 650deb973913..9f5d5bc3dd2e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12850,6 +12850,7 @@ F: drivers/net/dsa/ocelot/* F: drivers/net/ethernet/mscc/ F: include/soc/mscc/ocelot* F: net/dsa/tag_ocelot.c +F: net/dsa/tag_ocelot_8021q.c F: tools/testing/selftests/drivers/net/ocelot/* OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER diff --git a/drivers/net/dsa/ocelot/Kconfig b/drivers/net/dsa/ocelot/Kconfig index c110e82a7973..932b6b6fe817 100644 --- a/drivers/net/dsa/ocelot/Kconfig +++ b/drivers/net/dsa/ocelot/Kconfig @@ -6,6 +6,7 @@ config NET_DSA_MSCC_FELIX depends on NET_VENDOR_FREESCALE depends on HAS_IOMEM select MSCC_OCELOT_SWITCH_LIB + select NET_DSA_TAG_OCELOT_8021Q select NET_DSA_TAG_OCELOT select FSL_ENETC_MDIO select PCS_LYNX @@ -19,6 +20,7 @@ config NET_DSA_MSCC_SEVILLE depends on NET_VENDOR_MICROSEMI depends on HAS_IOMEM select MSCC_OCELOT_SWITCH_LIB + select NET_DSA_TAG_OCELOT_8021Q select NET_DSA_TAG_OCELOT select PCS_LYNX help diff --git a/include/net/dsa.h b/include/net/dsa.h index 0d8251de520f..865113c6da85 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -47,6 +47,7 @@ struct phylink_link_state; #define DSA_TAG_PROTO_RTL4_A_VALUE 17 #define DSA_TAG_PROTO_HELLCREEK_VALUE 18 #define DSA_TAG_PROTO_XRS700X_VALUE 19 +#define DSA_TAG_PROTO_OCELOT_8021Q_VALUE 20 enum dsa_tag_protocol { DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, @@ -69,6 +70,7 @@ enum dsa_tag_protocol { DSA_TAG_PROTO_RTL4_A = DSA_TAG_PROTO_RTL4_A_VALUE, DSA_TAG_PROTO_HELLCREEK = DSA_TAG_PROTO_HELLCREEK_VALUE, DSA_TAG_PROTO_XRS700X = DSA_TAG_PROTO_XRS700X_VALUE, + DSA_TAG_PROTO_OCELOT_8021Q = DSA_TAG_PROTO_OCELOT_8021Q_VALUE, }; struct packet_type; diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 2d226a5c085f..a45572cfb71a 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -105,11 +105,26 @@ config NET_DSA_TAG_RTL4_A the Realtek RTL8366RB. config NET_DSA_TAG_OCELOT - tristate "Tag driver for Ocelot family of switches" + tristate "Tag driver for Ocelot family of switches, using NPI port" select PACKING help - Say Y or M if you want to enable support for tagging frames for the - Ocelot switches (VSC7511, VSC7512, VSC7513, VSC7514, VSC9959). + Say Y or M if you want to enable NPI tagging for the Ocelot switches + (VSC7511, VSC7512, VSC7513, VSC7514, VSC9953, VSC9959). In this mode, + the frames over the Ethernet CPU port are prepended with a + hardware-defined injection/extraction frame header. Flow control + (PAUSE frames) over the CPU port is not supported when operating in + this mode. + +config NET_DSA_TAG_OCELOT_8021Q + tristate "Tag driver for Ocelot family of switches, using VLAN" + select NET_DSA_TAG_8021Q + help + Say Y or M if you want to enable support for tagging frames with a + custom VLAN-based header. Frames that require timestamping, such as + PTP, are not delivered over Ethernet but over register-based MMIO. + Flow control over the CPU port is functional in this mode. When using + this mode, less TCAM resources (VCAP IS1, IS2, ES0) are available for + use with tc-flower. config NET_DSA_TAG_QCA tristate "Tag driver for Qualcomm Atheros QCA8K switches" diff --git a/net/dsa/Makefile b/net/dsa/Makefile index 92cea2132241..44bc79952b8b 100644 --- a/net/dsa/Makefile +++ b/net/dsa/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o obj-$(CONFIG_NET_DSA_TAG_LAN9303) += tag_lan9303.o obj-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o obj-$(CONFIG_NET_DSA_TAG_OCELOT) += tag_ocelot.o +obj-$(CONFIG_NET_DSA_TAG_OCELOT_8021Q) += tag_ocelot_8021q.o obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o diff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c new file mode 100644 index 000000000000..09e10ade11f7 --- /dev/null +++ b/net/dsa/tag_ocelot_8021q.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright 2020-2021 NXP Semiconductors + * + * An implementation of the software-defined tag_8021q.c tagger format, which + * also preserves full functionality under a vlan_filtering bridge. It does + * this by using the TCAM engines for: + * - pushing the RX VLAN as a second, outer tag, on egress towards the CPU port + * - redirecting towards the correct front port based on TX VLAN and popping + * that on egress + */ +#include +#include "dsa_priv.h" + +static struct sk_buff *ocelot_xmit(struct sk_buff *skb, + struct net_device *netdev) +{ + struct dsa_port *dp = dsa_slave_to_port(netdev); + u16 tx_vid = dsa_8021q_tx_vid(dp->ds, dp->index); + u16 queue_mapping = skb_get_queue_mapping(skb); + u8 pcp = netdev_txq_to_tc(netdev, queue_mapping); + + return dsa_8021q_xmit(skb, netdev, ETH_P_8021Q, + ((pcp << VLAN_PRIO_SHIFT) | tx_vid)); +} + +static struct sk_buff *ocelot_rcv(struct sk_buff *skb, + struct net_device *netdev, + struct packet_type *pt) +{ + int src_port, switch_id, qos_class; + u16 vid, tci; + + skb_push_rcsum(skb, ETH_HLEN); + if (skb_vlan_tag_present(skb)) { + tci = skb_vlan_tag_get(skb); + __vlan_hwaccel_clear_tag(skb); + } else { + __skb_vlan_pop(skb, &tci); + } + skb_pull_rcsum(skb, ETH_HLEN); + + vid = tci & VLAN_VID_MASK; + src_port = dsa_8021q_rx_source_port(vid); + switch_id = dsa_8021q_rx_switch_id(vid); + qos_class = (tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; + + skb->dev = dsa_master_find_slave(netdev, switch_id, src_port); + if (!skb->dev) + return NULL; + + skb->offload_fwd_mark = 1; + skb->priority = qos_class; + + return skb; +} + +static struct dsa_device_ops ocelot_netdev_ops = { + .name = "ocelot-8021q", + .proto = DSA_TAG_PROTO_OCELOT_8021Q, + .xmit = ocelot_xmit, + .rcv = ocelot_rcv, + .overhead = VLAN_HLEN, +}; + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_OCELOT_8021Q); + +module_dsa_tag_driver(ocelot_netdev_ops); From patchwork Mon Jan 25 22:03:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12044533 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,URIBL_BLOCKED,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 0423FC433DB for ; Mon, 25 Jan 2021 22:10:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C87912068D for ; Mon, 25 Jan 2021 22:10:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731493AbhAYWKU (ORCPT ); Mon, 25 Jan 2021 17:10:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59548 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733168AbhAYWGM (ORCPT ); Mon, 25 Jan 2021 17:06:12 -0500 Received: from mail-ed1-x533.google.com (mail-ed1-x533.google.com [IPv6:2a00:1450:4864:20::533]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0A8ABC061794 for ; Mon, 25 Jan 2021 14:04:41 -0800 (PST) Received: by mail-ed1-x533.google.com with SMTP id g1so17424536edu.4 for ; Mon, 25 Jan 2021 14:04:40 -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 :mime-version:content-transfer-encoding; bh=GUQGTE4CBhe4VSwpEmAy4RGuWMhQDV9x1U5EKBQPKis=; b=iQpXMdMP7qDdrccgV5zGYVQiWFPbJAmxkhoi1PgJLPIteFLlPIN1XsxjsDUr3BVXke lNaKyOtQOCG+zI/7r5ohV1hGG3PeS6cLrmnupXmMAMlvJwK3Iwrt++A2UNQioUIkTYjX e7nf+KWjpZC4L59EcQlK+fPqOQasituhGpmuv3whT38P+dRK2GJmNIkD/EhwUflee1d0 Z148B3NL6PGG1XFZfaodhXkcHsuR1BBD+gd06lP3d8GkXLOyUpvKHuEmDsphLpYdLBwg nH0VwpA6idcJFgioNI5VNUV6Z8tWvAYsCZsAuvzSoPobz495o0rWtToAzIcJka8bmDHB SD4g== 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:mime-version:content-transfer-encoding; bh=GUQGTE4CBhe4VSwpEmAy4RGuWMhQDV9x1U5EKBQPKis=; b=PHxdY271Vw72RYlGKpLEpl+eS28j7o3+laiywNA6jsyN2fPKGdouiUz/wQSwifqK1X YBwhDWNlN5Y8F3/QBIS0vthyca39UP4P+nFwu3kxZy93wEB3q692NLi1VyZUm/WmkdxE vZV6vQb2i/YeMoATei5oHnqAypghA1eyiASW2EOISEtj9f+CuZMSQxPQYZoQR+GpM4Dq 0xqAfKgNKVmnvphBjvw3ocvXv7d114GNCjLoYcgzCOkdc1KEkgquD4dyECqdy7wzmmzV nwUPQ5Q+kJETHpaEioLwRJoW8otLmp4Opm6wGU13+sHmnpTtshze4q3IRumukm6HYlQN b0hw== X-Gm-Message-State: AOAM533wNarqX1ZXsBu9XQBNYR4NEO/bGdk7KaUqA5a5EaOtEs6tIfBK Hzv8YvDcg/ktCSUh86MEQLk= X-Google-Smtp-Source: ABdhPJyqpni0K6TYiFuSHQZYN4817cqkWaayRztxBoXQBcUEdD5lDt0LxoUJTO1E4w6deNRjIL+raQ== X-Received: by 2002:a05:6402:430c:: with SMTP id m12mr2272074edc.299.1611612279713; Mon, 25 Jan 2021 14:04:39 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id s13sm1760555edi.92.2021.01.25.14.04.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 14:04:38 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Claudiu Manoil , Alexandre Belloni , Vladimir Oltean , UNGLinuxDriver@microchip.com Subject: [PATCH v7 net-next 11/11] net: dsa: felix: perform switch setup for tag_8021q Date: Tue, 26 Jan 2021 00:03:33 +0200 Message-Id: <20210125220333.1004365-12-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210125220333.1004365-1-olteanv@gmail.com> References: <20210125220333.1004365-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Vladimir Oltean Unlike sja1105, the only other user of the software-defined tag_8021q.c tagger format, the implementation we choose for the Felix DSA switch driver preserves full functionality under a vlan_filtering bridge (i.e. IP termination works through the DSA user ports under all circumstances). The tag_8021q protocol just wants: - Identifying the ingress switch port based on the RX VLAN ID, as seen by the CPU. We achieve this by using the TCAM engines (which are also used for tc-flower offload) to push the RX VLAN as a second, outer tag, on egress towards the CPU port. - Steering traffic injected into the switch from the network stack towards the correct front port based on the TX VLAN, and consuming (popping) that header on the switch's egress. A tc-flower pseudocode of the static configuration done by the driver would look like this: $ tc qdisc add dev clsact $ for eth in swp0 swp1 swp2 swp3; do \ tc filter add dev egress flower indev ${eth} \ action vlan push id protocol 802.1ad; \ tc filter add dev ingress protocol 802.1Q flower vlan_id action vlan pop \ action mirred egress redirect dev ${eth}; \ done but of course since DSA does not register network interfaces for the CPU port, this configuration would be impossible for the user to do. Also, due to the same reason, it is impossible for the user to inadvertently delete these rules using tc. These rules do not collide in any way with tc-flower, they just consume some TCAM space, which is something we can live with. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- Changes in v7: Drop the rtnl_lock surrounding dsa_8021q_setup since some callers of .{set,del}_tag_protocol now hold the rtnl_mutex and we'd run into a deadlock if we took it. That's also why all callers needed to be converted to hold the lock, since otherwise dsa_8021q_setup would have no guarantees short of passing it a bool rtnl_is_held variable. Changes in v6: None. Changes in v5: Path is split from previous monolithic patch "net: dsa: felix: add new VLAN-based tagger". Changes in v4: - Support simultaneous compilation of tag_ocelot.c and tag_ocelot_8021q.c. - Support runtime switchover between these two taggers. - We are now actually performing cleanup instead of just probe-time setup, which is required for supporting tagger switchover. Changes in v3: - Use a per-port bool is_dsa_8021q_cpu instead of a single dsa_8021q_cpu variable, to be compatible with future work where there may be potentially multiple tag_8021q CPU ports in a LAG. - Initialize ocelot->npi = -1 in felix_8021q_cpu_port_init to ensure we don't mistakenly trigger NPI-specific code in ocelot. Changes in v2: Clean up the hardcoding of random VCAP filter IDs and the inclusion of a private ocelot header. drivers/net/dsa/ocelot/felix.c | 328 ++++++++++++++++++++++++ drivers/net/dsa/ocelot/felix.h | 1 + drivers/net/ethernet/mscc/ocelot.c | 33 ++- drivers/net/ethernet/mscc/ocelot_vcap.c | 1 + drivers/net/ethernet/mscc/ocelot_vcap.h | 3 - include/soc/mscc/ocelot.h | 1 + include/soc/mscc/ocelot_vcap.h | 3 + 7 files changed, 359 insertions(+), 11 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index f45dfb800bcb..85a09065eeac 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,327 @@ #include #include "felix.h" +static int felix_tag_8021q_rxvlan_add(struct felix *felix, int port, u16 vid, + bool pvid, bool untagged) +{ + struct ocelot_vcap_filter *outer_tagging_rule; + struct ocelot *ocelot = &felix->ocelot; + struct dsa_switch *ds = felix->ds; + int key_length, upstream, err; + + /* We don't need to install the rxvlan into the other ports' filtering + * tables, because we're just pushing the rxvlan when sending towards + * the CPU + */ + if (!pvid) + return 0; + + key_length = ocelot->vcap[VCAP_ES0].keys[VCAP_ES0_IGR_PORT].length; + upstream = dsa_upstream_port(ds, port); + + outer_tagging_rule = kzalloc(sizeof(struct ocelot_vcap_filter), + GFP_KERNEL); + if (!outer_tagging_rule) + return -ENOMEM; + + outer_tagging_rule->key_type = OCELOT_VCAP_KEY_ANY; + outer_tagging_rule->prio = 1; + outer_tagging_rule->id.cookie = port; + outer_tagging_rule->id.tc_offload = false; + outer_tagging_rule->block_id = VCAP_ES0; + outer_tagging_rule->type = OCELOT_VCAP_FILTER_OFFLOAD; + outer_tagging_rule->lookup = 0; + outer_tagging_rule->ingress_port.value = port; + outer_tagging_rule->ingress_port.mask = GENMASK(key_length - 1, 0); + outer_tagging_rule->egress_port.value = upstream; + outer_tagging_rule->egress_port.mask = GENMASK(key_length - 1, 0); + outer_tagging_rule->action.push_outer_tag = OCELOT_ES0_TAG; + outer_tagging_rule->action.tag_a_tpid_sel = OCELOT_TAG_TPID_SEL_8021AD; + outer_tagging_rule->action.tag_a_vid_sel = 1; + outer_tagging_rule->action.vid_a_val = vid; + + err = ocelot_vcap_filter_add(ocelot, outer_tagging_rule, NULL); + if (err) + kfree(outer_tagging_rule); + + return err; +} + +static int felix_tag_8021q_txvlan_add(struct felix *felix, int port, u16 vid, + bool pvid, bool untagged) +{ + struct ocelot_vcap_filter *untagging_rule, *redirect_rule; + struct ocelot *ocelot = &felix->ocelot; + struct dsa_switch *ds = felix->ds; + int upstream, err; + + /* tag_8021q.c assumes we are implementing this via port VLAN + * membership, which we aren't. So we don't need to add any VCAP filter + * for the CPU port. + */ + if (ocelot->ports[port]->is_dsa_8021q_cpu) + return 0; + + untagging_rule = kzalloc(sizeof(struct ocelot_vcap_filter), GFP_KERNEL); + if (!untagging_rule) + return -ENOMEM; + + redirect_rule = kzalloc(sizeof(struct ocelot_vcap_filter), GFP_KERNEL); + if (!redirect_rule) { + kfree(untagging_rule); + return -ENOMEM; + } + + upstream = dsa_upstream_port(ds, port); + + untagging_rule->key_type = OCELOT_VCAP_KEY_ANY; + untagging_rule->ingress_port_mask = BIT(upstream); + untagging_rule->vlan.vid.value = vid; + untagging_rule->vlan.vid.mask = VLAN_VID_MASK; + untagging_rule->prio = 1; + untagging_rule->id.cookie = port; + untagging_rule->id.tc_offload = false; + untagging_rule->block_id = VCAP_IS1; + untagging_rule->type = OCELOT_VCAP_FILTER_OFFLOAD; + untagging_rule->lookup = 0; + untagging_rule->action.vlan_pop_cnt_ena = true; + untagging_rule->action.vlan_pop_cnt = 1; + untagging_rule->action.pag_override_mask = 0xff; + untagging_rule->action.pag_val = port; + + err = ocelot_vcap_filter_add(ocelot, untagging_rule, NULL); + if (err) { + kfree(untagging_rule); + kfree(redirect_rule); + return err; + } + + redirect_rule->key_type = OCELOT_VCAP_KEY_ANY; + redirect_rule->ingress_port_mask = BIT(upstream); + redirect_rule->pag = port; + redirect_rule->prio = 1; + redirect_rule->id.cookie = port; + redirect_rule->id.tc_offload = false; + redirect_rule->block_id = VCAP_IS2; + redirect_rule->type = OCELOT_VCAP_FILTER_OFFLOAD; + redirect_rule->lookup = 0; + redirect_rule->action.mask_mode = OCELOT_MASK_MODE_REDIRECT; + redirect_rule->action.port_mask = BIT(port); + + err = ocelot_vcap_filter_add(ocelot, redirect_rule, NULL); + if (err) { + ocelot_vcap_filter_del(ocelot, untagging_rule); + kfree(redirect_rule); + return err; + } + + return 0; +} + +static int felix_tag_8021q_vlan_add(struct dsa_switch *ds, int port, u16 vid, + u16 flags) +{ + bool untagged = flags & BRIDGE_VLAN_INFO_UNTAGGED; + bool pvid = flags & BRIDGE_VLAN_INFO_PVID; + struct ocelot *ocelot = ds->priv; + + if (vid_is_dsa_8021q_rxvlan(vid)) + return felix_tag_8021q_rxvlan_add(ocelot_to_felix(ocelot), + port, vid, pvid, untagged); + + if (vid_is_dsa_8021q_txvlan(vid)) + return felix_tag_8021q_txvlan_add(ocelot_to_felix(ocelot), + port, vid, pvid, untagged); + + return 0; +} + +static int felix_tag_8021q_rxvlan_del(struct felix *felix, int port, u16 vid) +{ + struct ocelot_vcap_filter *outer_tagging_rule; + struct ocelot_vcap_block *block_vcap_es0; + struct ocelot *ocelot = &felix->ocelot; + + block_vcap_es0 = &ocelot->block[VCAP_ES0]; + + outer_tagging_rule = ocelot_vcap_block_find_filter_by_id(block_vcap_es0, + port, false); + /* In rxvlan_add, we had the "if (!pvid) return 0" logic to avoid + * installing outer tagging ES0 rules where they weren't needed. + * But in rxvlan_del, the API doesn't give us the "flags" anymore, + * so that forces us to be slightly sloppy here, and just assume that + * if we didn't find an outer_tagging_rule it means that there was + * none in the first place, i.e. rxvlan_del is called on a non-pvid + * port. This is most probably true though. + */ + if (!outer_tagging_rule) + return 0; + + return ocelot_vcap_filter_del(ocelot, outer_tagging_rule); +} + +static int felix_tag_8021q_txvlan_del(struct felix *felix, int port, u16 vid) +{ + struct ocelot_vcap_filter *untagging_rule, *redirect_rule; + struct ocelot_vcap_block *block_vcap_is1; + struct ocelot_vcap_block *block_vcap_is2; + struct ocelot *ocelot = &felix->ocelot; + int err; + + if (ocelot->ports[port]->is_dsa_8021q_cpu) + return 0; + + block_vcap_is1 = &ocelot->block[VCAP_IS1]; + block_vcap_is2 = &ocelot->block[VCAP_IS2]; + + untagging_rule = ocelot_vcap_block_find_filter_by_id(block_vcap_is1, + port, false); + if (!untagging_rule) + return 0; + + err = ocelot_vcap_filter_del(ocelot, untagging_rule); + if (err) + return err; + + redirect_rule = ocelot_vcap_block_find_filter_by_id(block_vcap_is2, + port, false); + if (!redirect_rule) + return 0; + + return ocelot_vcap_filter_del(ocelot, redirect_rule); +} + +static int felix_tag_8021q_vlan_del(struct dsa_switch *ds, int port, u16 vid) +{ + struct ocelot *ocelot = ds->priv; + + if (vid_is_dsa_8021q_rxvlan(vid)) + return felix_tag_8021q_rxvlan_del(ocelot_to_felix(ocelot), + port, vid); + + if (vid_is_dsa_8021q_txvlan(vid)) + return felix_tag_8021q_txvlan_del(ocelot_to_felix(ocelot), + port, vid); + + return 0; +} + +static const struct dsa_8021q_ops felix_tag_8021q_ops = { + .vlan_add = felix_tag_8021q_vlan_add, + .vlan_del = felix_tag_8021q_vlan_del, +}; + +/* Alternatively to using the NPI functionality, that same hardware MAC + * connected internally to the enetc or fman DSA master can be configured to + * use the software-defined tag_8021q frame format. As far as the hardware is + * concerned, it thinks it is a "dumb switch" - the queues of the CPU port + * module are now disconnected from it, but can still be accessed through + * register-based MMIO. + */ +static void felix_8021q_cpu_port_init(struct ocelot *ocelot, int port) +{ + ocelot->ports[port]->is_dsa_8021q_cpu = true; + ocelot->npi = -1; + + /* Overwrite PGID_CPU with the non-tagging port */ + ocelot_write_rix(ocelot, BIT(port), ANA_PGID_PGID, PGID_CPU); +} + +static void felix_8021q_cpu_port_deinit(struct ocelot *ocelot, int port) +{ + ocelot->ports[port]->is_dsa_8021q_cpu = false; + + /* Restore PGID_CPU */ + ocelot_write_rix(ocelot, BIT(ocelot->num_phys_ports), ANA_PGID_PGID, + PGID_CPU); +} + +static int felix_setup_tag_8021q(struct dsa_switch *ds, int cpu) +{ + struct ocelot *ocelot = ds->priv; + struct felix *felix = ocelot_to_felix(ocelot); + unsigned long cpu_flood; + int port, err; + + felix_8021q_cpu_port_init(ocelot, cpu); + + for (port = 0; port < ds->num_ports; port++) { + if (dsa_is_unused_port(ds, port)) + continue; + + /* This overwrites ocelot_init(): + * Do not forward BPDU frames to the CPU port module, + * for 2 reasons: + * - When these packets are injected from the tag_8021q + * CPU port, we want them to go out, not loop back + * into the system. + * - STP traffic ingressing on a user port should go to + * the tag_8021q CPU port, not to the hardware CPU + * port module. + */ + ocelot_write_gix(ocelot, + ANA_PORT_CPU_FWD_BPDU_CFG_BPDU_REDIR_ENA(0), + ANA_PORT_CPU_FWD_BPDU_CFG, port); + } + + /* In tag_8021q mode, the CPU port module is unused. So we + * want to disable flooding of any kind to the CPU port module, + * since packets going there will end in a black hole. + */ + cpu_flood = ANA_PGID_PGID_PGID(BIT(ocelot->num_phys_ports)); + ocelot_rmw_rix(ocelot, 0, cpu_flood, ANA_PGID_PGID, PGID_UC); + ocelot_rmw_rix(ocelot, 0, cpu_flood, ANA_PGID_PGID, PGID_MC); + + ocelot_apply_bridge_fwd_mask(ocelot); + + felix->dsa_8021q_ctx = kzalloc(sizeof(*felix->dsa_8021q_ctx), + GFP_KERNEL); + if (!felix->dsa_8021q_ctx) + return -ENOMEM; + + felix->dsa_8021q_ctx->ops = &felix_tag_8021q_ops; + felix->dsa_8021q_ctx->proto = htons(ETH_P_8021AD); + felix->dsa_8021q_ctx->ds = ds; + + err = dsa_8021q_setup(felix->dsa_8021q_ctx, true); + if (err) + goto out_free_dsa_8021_ctx; + + return 0; + +out_free_dsa_8021_ctx: + kfree(felix->dsa_8021q_ctx); + return err; +} + +static void felix_teardown_tag_8021q(struct dsa_switch *ds, int cpu) +{ + struct ocelot *ocelot = ds->priv; + struct felix *felix = ocelot_to_felix(ocelot); + int err, port; + + err = dsa_8021q_setup(felix->dsa_8021q_ctx, false); + if (err) + dev_err(ds->dev, "dsa_8021q_setup returned %d", err); + + kfree(felix->dsa_8021q_ctx); + + for (port = 0; port < ds->num_ports; port++) { + if (dsa_is_unused_port(ds, port)) + continue; + + /* Restore the logic from ocelot_init: + * do not forward BPDU frames to the front ports. + */ + ocelot_write_gix(ocelot, + ANA_PORT_CPU_FWD_BPDU_CFG_BPDU_REDIR_ENA(0xffff), + ANA_PORT_CPU_FWD_BPDU_CFG, + port); + } + + felix_8021q_cpu_port_deinit(ocelot, cpu); +} + /* The CPU port module is connected to the Node Processor Interface (NPI). This * is the mode through which frames can be injected from and extracted to an * external CPU, over Ethernet. In NXP SoCs, the "external CPU" is the ARM CPU @@ -119,6 +441,9 @@ static int felix_set_tag_protocol(struct dsa_switch *ds, int cpu, case DSA_TAG_PROTO_OCELOT: err = felix_setup_tag_npi(ds, cpu); break; + case DSA_TAG_PROTO_OCELOT_8021Q: + err = felix_setup_tag_8021q(ds, cpu); + break; default: err = -EOPNOTSUPP; } @@ -133,6 +458,9 @@ static void felix_del_tag_protocol(struct dsa_switch *ds, int cpu, case DSA_TAG_PROTO_OCELOT: felix_teardown_tag_npi(ds, cpu); break; + case DSA_TAG_PROTO_OCELOT_8021Q: + felix_teardown_tag_8021q(ds, cpu); + break; default: break; } diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 264b3bbdc4d1..9d4459f2fffb 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -48,6 +48,7 @@ struct felix { struct lynx_pcs **pcs; resource_size_t switch_base; resource_size_t imdio_base; + struct dsa_8021q_context *dsa_8021q_ctx; enum dsa_tag_protocol tag_proto; }; diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index ebc797a08506..4217d5e18689 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -891,16 +891,37 @@ EXPORT_SYMBOL(ocelot_get_ts_info); void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot) { + unsigned long cpu_fwd_mask = 0; int port; + /* If a DSA tag_8021q CPU exists, it needs to be unconditionally + * (i.e. regardless of whether the port is bridged or standalone) + * included in the regular forwarding path, as opposed to the + * hardware-based CPU port module which can be a destination for + * packets even if it isn't part of PGID_SRC. + */ + for (port = 0; port < ocelot->num_phys_ports; port++) + if (ocelot->ports[port]->is_dsa_8021q_cpu) + cpu_fwd_mask |= BIT(port); + /* Apply FWD mask. The loop is needed to add/remove the current port as * a source for the other ports. */ for (port = 0; port < ocelot->num_phys_ports; port++) { - if (ocelot->bridge_fwd_mask & BIT(port)) { - unsigned long mask = ocelot->bridge_fwd_mask & ~BIT(port); + /* Standalone ports forward only to DSA tag_8021q CPU ports */ + unsigned long mask = cpu_fwd_mask; + + /* The DSA tag_8021q CPU ports need to be able to forward + * packets to all other ports except for themselves + */ + if (ocelot->ports[port]->is_dsa_8021q_cpu) { + mask = GENMASK(ocelot->num_phys_ports - 1, 0); + mask &= ~cpu_fwd_mask; + } else if (ocelot->bridge_fwd_mask & BIT(port)) { int lag; + mask |= ocelot->bridge_fwd_mask & ~BIT(port); + for (lag = 0; lag < ocelot->num_phys_ports; lag++) { unsigned long bond_mask = ocelot->lags[lag]; @@ -912,13 +933,9 @@ void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot) break; } } - - ocelot_write_rix(ocelot, mask, - ANA_PGID_PGID, PGID_SRC + port); - } else { - ocelot_write_rix(ocelot, 0, - ANA_PGID_PGID, PGID_SRC + port); } + + ocelot_write_rix(ocelot, mask, ANA_PGID_PGID, PGID_SRC + port); } } EXPORT_SYMBOL(ocelot_apply_bridge_fwd_mask); diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c index b82fd4103a68..37a232911395 100644 --- a/drivers/net/ethernet/mscc/ocelot_vcap.c +++ b/drivers/net/ethernet/mscc/ocelot_vcap.c @@ -1009,6 +1009,7 @@ ocelot_vcap_block_find_filter_by_id(struct ocelot_vcap_block *block, int cookie, return NULL; } +EXPORT_SYMBOL(ocelot_vcap_block_find_filter_by_id); /* If @on=false, then SNAP, ARP, IP and OAM frames will not match on keys based * on destination and source MAC addresses, but only on higher-level protocol diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.h b/drivers/net/ethernet/mscc/ocelot_vcap.h index 3b0c7916056e..523611ccc48f 100644 --- a/drivers/net/ethernet/mscc/ocelot_vcap.h +++ b/drivers/net/ethernet/mscc/ocelot_vcap.h @@ -14,9 +14,6 @@ int ocelot_vcap_filter_stats_update(struct ocelot *ocelot, struct ocelot_vcap_filter *rule); -struct ocelot_vcap_filter * -ocelot_vcap_block_find_filter_by_id(struct ocelot_vcap_block *block, int id, - bool tc_offload); void ocelot_detect_vcap_constants(struct ocelot *ocelot); int ocelot_vcap_init(struct ocelot *ocelot); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index fba24a0327d4..6a61c499a30d 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -610,6 +610,7 @@ struct ocelot_port { phy_interface_t phy_mode; u8 *xmit_template; + bool is_dsa_8021q_cpu; }; struct ocelot { diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h index 76e01c927e17..25fd525aaf92 100644 --- a/include/soc/mscc/ocelot_vcap.h +++ b/include/soc/mscc/ocelot_vcap.h @@ -693,5 +693,8 @@ int ocelot_vcap_filter_add(struct ocelot *ocelot, struct netlink_ext_ack *extack); int ocelot_vcap_filter_del(struct ocelot *ocelot, struct ocelot_vcap_filter *rule); +struct ocelot_vcap_filter * +ocelot_vcap_block_find_filter_by_id(struct ocelot_vcap_block *block, int id, + bool tc_offload); #endif /* _OCELOT_VCAP_H_ */