From patchwork Tue Jan 19 23:07:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031007 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AD99CC433E0 for ; Tue, 19 Jan 2021 23:09:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7B75822CAD for ; Tue, 19 Jan 2021 23:09:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728226AbhASXJL (ORCPT ); Tue, 19 Jan 2021 18:09:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52104 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729387AbhASXIn (ORCPT ); Tue, 19 Jan 2021 18:08:43 -0500 Received: from mail-ej1-x62a.google.com (mail-ej1-x62a.google.com [IPv6:2a00:1450:4864:20::62a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CC218C061757 for ; Tue, 19 Jan 2021 15:08:01 -0800 (PST) Received: by mail-ej1-x62a.google.com with SMTP id a10so14280218ejg.10 for ; Tue, 19 Jan 2021 15:08:01 -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=yFdeO5pbvs0oUv+cj/w2+IaBK0rT2rHtLkBoBasLdpI=; b=tJKrWbqYtlGmIi0GJ7QAiMMxccgHNpFYfYPIsKmc8IfqCDfy1lgmDfXUzByaUomQXL 8kNMF1lKapQop7h4mqOsIybPeuJkB7CwiSVDBxBJetapEyD8zvzk4b16A84C7NbljQ+b NLFFOCCNe3c7pQWOeApoKfEnnEesgfw2P4HACxwayPUgC6X9GXoX0b/YvKmUAteuqMyi 1KgxjQ2B/p1BXyKFehzH/JAP7io+PY7TBxQqtOWaR3XPIu9+KMCvBvO7ZNnG/q84r7cE 9QNRiBDcQ94j/Pgh2pzoQ/KhlsdnmsvV3Sm1Y+9OHtSmivv82GPsNnAobqUlGij3gyKn lRbQ== 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=yFdeO5pbvs0oUv+cj/w2+IaBK0rT2rHtLkBoBasLdpI=; b=jZukHZG7SS/zwfNKBaYFEOpdncASl1VrleGuWU9nVmIR4nVy3aD41+YNRnGCGMmE2k f8ccX1vqoxnbFWf6FAH8dJMW6nt3sFZc6OEJrV0vkhGp/WMqTZhbRQTu6lfZsvRZqsL1 KNuHamceLSVP5FERpTxkFFGQrFrBcjld4U16KpQG/mo+1NULMTsg+F7FFkxOOMWJNIBx Bqk0fheziITBpgw3rFPLYeX/XaSLexC0C4uz943vofzgAfG2zpvFD2SYQgZ3tUGIXjRO 39133o8Ro0C3hfQ6N7x6SIMhjLKW4ZdWCUhx/mETONSgHHLYOlukaymNNCYVwsHlmXq/ jdDQ== X-Gm-Message-State: AOAM531lGVFCaV5ZvzhWMGTaqQww0UKoMt6PMF2D16Em00KaMgxeJ65X t/2C+P/+JQ1sArWVeZdM4mM= X-Google-Smtp-Source: ABdhPJxg+Iki1tTgufiC1gbpn7A0RSZEsPfpeTl1jFxIfaN1WoX3EQ5+8eOEsS+tPgi8f6FKYTolwA== X-Received: by 2002:a17:906:c9cc:: with SMTP id hk12mr2459254ejb.134.1611097680597; Tue, 19 Jan 2021 15:08:00 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.07.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:00 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 01/16] net: dsa: tag_8021q: add helpers to deduce whether a VLAN ID is RX or TX VLAN Date: Wed, 20 Jan 2021 01:07:34 +0200 Message-Id: <20210119230749.1178874-2-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 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 Tue Jan 19 23:07:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031063 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 38023C433DB for ; Tue, 19 Jan 2021 23:23:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EA04723109 for ; Tue, 19 Jan 2021 23:23:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727854AbhASXXd (ORCPT ); Tue, 19 Jan 2021 18:23:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52110 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729360AbhASXIo (ORCPT ); Tue, 19 Jan 2021 18:08:44 -0500 Received: from mail-ej1-x633.google.com (mail-ej1-x633.google.com [IPv6:2a00:1450:4864:20::633]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 66920C0613C1 for ; Tue, 19 Jan 2021 15:08:03 -0800 (PST) Received: by mail-ej1-x633.google.com with SMTP id b5so14472024ejv.4 for ; Tue, 19 Jan 2021 15:08:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FDsyfwst4c0czIRhONr9qvHKKKPRhaEJPzxKpA6O4Uc=; b=KeY9VGZ6nNzS39aWoFwi9GPBjyKN03WEvTYMmEaGu9g6bRoKwxs+ZWTm/OvZHu/BYo y7OwgyGrKTJWG5iadJnIsGQMFuSfbHrGDpUUgX8H2ymuIoqFjyX6qhf/OiAXVU+tNIt5 k34JYVmXcREOCiuwJhmw2hn9OPKIsu1J0L81jf2cM4dCxiWBHzRZT4rMNvX1BMSkHYIl 2o+hcvro4BKc9R+N4iBCA0P07IiwQH4QkBS5TRNQRqrK/siBtB4iXwjzOM8I+i9JyvnH fnlfKaQsHxe81YMI7O5u363avzitvVIrdajN8I97JO3/U2M/ciJ+If4YTYNJGB+LNcpR 0L2w== 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=FDsyfwst4c0czIRhONr9qvHKKKPRhaEJPzxKpA6O4Uc=; b=Aebw/EFFZukny8aXfJ1vGscvVHm0lVW+zfaZGG6skTOcEYF+Vi37ZgQYaU7rpu0fuq uLMj+UbedTxpeaflH+ik55z2puUSszeW33kTqFIlpm8dyRTTVXhM8lwhZ0Pd+gPxn2zT QY1UwDKAaySaHlz0aafNkjLCbOtmZS1eAfDwQCJRTDtBbj83CFTC9HLJyK+KyrWV2d3d pCbAtlYoARW+a8RKkANgGPtjkFciXqv3idl5/ikVdAAknWv1+lf+CR+LUEHoD2pydR7d CD2wvhdZ22Z9miKB3WZuYBbeQnPaGMMtFM9ei3P5trQxbxpfiws3Tsviktz4B+URqE0K v8lQ== X-Gm-Message-State: AOAM530CeWbKWg6StxGR9tcmOc8GvEBSgw2PhNlSOureF7U/QS2U/7zN 8Oi3nQCASsiEVzeKvwXheGs= X-Google-Smtp-Source: ABdhPJyNsAWpkkdYKlJcuZ4HdRM0D9u84lKm2R9Ft+yi7DiFrasPFUaDeXdQHqqX/Q4SpRqadnv57A== X-Received: by 2002:a17:906:d1cb:: with SMTP id bs11mr4159457ejb.535.1611097682061; Tue, 19 Jan 2021 15:08:02 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:01 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 02/16] net: mscc: ocelot: export VCAP structures to include/soc/mscc Date: Wed, 20 Jan 2021 01:07:35 +0200 Message-Id: <20210119230749.1178874-3-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 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 4585c35c24e5..9535a75b1c84 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 Tue Jan 19 23:07:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031011 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94214C433DB for ; Tue, 19 Jan 2021 23:10:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 660D622CAD for ; Tue, 19 Jan 2021 23:10:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729199AbhASXJe (ORCPT ); Tue, 19 Jan 2021 18:09:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52120 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726550AbhASXIp (ORCPT ); Tue, 19 Jan 2021 18:08:45 -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 D09FEC0613CF for ; Tue, 19 Jan 2021 15:08:04 -0800 (PST) Received: by mail-ed1-x52f.google.com with SMTP id d22so12549533edy.1 for ; Tue, 19 Jan 2021 15:08:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=eGvX6U43axVaOX1yNFaXXg71kFQHXi0dvh68GSZYEKk=; b=tCshWI5nLwzfKdqhYFBcwk58fAgaY6T+t4X0AHnj4OqRQrD8JhJGhkY9iIi+U4bDdh Ic18QXq3aCfwc5g6UiXO7l3/e2/JUVKDw9J/SMbQzDULyYBJjvVGHYNOXOX2LGwzhA33 kCEXQgX2TnsHJAlwzzcxpVhiTcTlBAcd1PPrQtaEuw6K33bTHX43binleBpCgpyIYezV RXcjSL5L2a4w6U0QrMagTwsQ4wnqYNBKzrwiudEhY9ObfEQt0OzwoPNyT8mr7So7TLdD kArEvgeEhEP2WFGU0OMf4ayBYg9mrrEUEA2LaMFiG9Vt5cxBnsUFqfEnipBgfRanxaO6 feTA== 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=eGvX6U43axVaOX1yNFaXXg71kFQHXi0dvh68GSZYEKk=; b=gf3dv2cLt3bYy4B7yA+b4snt0Jxh2gWIElAagdUirkEQfK7i/dE7blF4GR0TpgGOSh AbCxWLtjexv5+o9aA5P2IvTfza4gBIMFJ+GBcr2iKrDRCH7C3oJPF+Iaun4rG9lEBt9d wKzxxO/70px2OMCzhqTfFG/bfBvKSqVupCQLiFd2YXeUyjBrselPIFe2j5jxIttn648K BTqTVw32R6OjvJQZPHLeuR1r/78U5lqLO9ckIIwmk5zi9OAhPHR1cNRBrnRMtCi/Cql0 hXXPwN6huGCSLeA1YlZCn4cJ34PRw27LP3okYwWlj8iJEvpsQgLIdZIG3y8lFuLEBjXI /vJg== X-Gm-Message-State: AOAM533svgAo0pQ7ZYa29xXql/V271OU+NbnO6w6PSLp2dFsfHrebjJ7 PWMQWcX5g7V7lUSA608rRC0= X-Google-Smtp-Source: ABdhPJx/Exb+4ZNNdAZ5qBiQnmIGnnGhRTRe3WMvu/v3NbA2p/VH3GpAscC9qanLNxodfhGJ4sVjaQ== X-Received: by 2002:a05:6402:2207:: with SMTP id cq7mr5411955edb.272.1611097683619; Tue, 19 Jan 2021 15:08:03 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:03 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 03/16] net: mscc: ocelot: store a namespaced VCAP filter ID Date: Wed, 20 Jan 2021 01:07:36 +0200 Message-Id: <20210119230749.1178874-4-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 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 Tue Jan 19 23:07:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031009 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 72700C433DB for ; Tue, 19 Jan 2021 23:09:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2259522CAD for ; Tue, 19 Jan 2021 23:09:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728607AbhASXJT (ORCPT ); Tue, 19 Jan 2021 18:09:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52128 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726708AbhASXIr (ORCPT ); Tue, 19 Jan 2021 18:08:47 -0500 Received: from mail-ej1-x62a.google.com (mail-ej1-x62a.google.com [IPv6:2a00:1450:4864:20::62a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A42A0C0613D3 for ; Tue, 19 Jan 2021 15:08:06 -0800 (PST) Received: by mail-ej1-x62a.google.com with SMTP id l9so25195385ejx.3 for ; Tue, 19 Jan 2021 15:08:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Oci+XcNQZUIsVNYEJgvOjhWRF37YAlsRe2zEuUxbVNk=; b=PgwvhOaNg9AVnFk/ey5r7/qnqtUN81PRhq/9dbhh3GnC0ZeR/Ldf99qP+rZcyKLs4N OUrZCglF7XX3kvUJN1gVae99A+v0Jc+yDL5WGggh9l/MxhUQAPl+rVIJbbGwUx9ru894 3gLLKHUpiL+661+PMrioLlV3KctPMh/5PyuR1cFEYxbtTMpqyqcZzmP2nZG/IOsE3Pfp ipP94TCWjYKDo54GUzcy7dOk68NxOgoLTD8+lJ+0HpT4nKA5VgXD5WBGi44fts0eaTru 09XLhd3qFLBTSOzYpggKf51E3qFe50cbzgMKKLlJXTzvvhjqt117cDp5dPwlYbu3CKrN 58mg== 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=Oci+XcNQZUIsVNYEJgvOjhWRF37YAlsRe2zEuUxbVNk=; b=Q30EZL6Zk5GVItXUWgluHnticNiYciJMFs/4LrIlgfViM9M9D2g1d/Z0qtDHnzQbg7 9rOLalOQWm17k3qgjP/beLhncNzpexwoK967uBN5heGJe6K/5NYQijUjcGzpP1Upkf8Y XU/2ZrrxCOMnflzZQ5sOW2eM7kQpCy+XGGQW7A0aaSu/GemNsz9Q0NO7Vk6AcdlRI0/g 08j3++HQxz+dor+CMRvADazD4b+2cR4FJqWchwMZGZSeyXh5LrjQSPIOhteBu2Dyn9yX +IaN6iYxmxUT6IWHI0blroXEpsJCY096VsVMzJLmZ3Yw6zCDD78kVz0USCkW6tNRfZvw rcYg== X-Gm-Message-State: AOAM532LGTOMa6sqQBRaLp0xvtxgFjvE/dPBE/WSTnoaRusQ7C4Mtn+u /kVG2hfydIjuXXaDGtHu9yc= X-Google-Smtp-Source: ABdhPJyMZU3MJQGa3WAcvvasOhGi4GEqUFh4fa02kr11CUjx6I7GFLxDQB+MpURW4vFOTv7A7OaadQ== X-Received: by 2002:a17:906:1f45:: with SMTP id d5mr4527547ejk.76.1611097685439; Tue, 19 Jan 2021 15:08:05 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:04 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 04/16] net: mscc: ocelot: reapply bridge forwarding mask on bonding join/leave Date: Wed, 20 Jan 2021 01:07:37 +0200 Message-Id: <20210119230749.1178874-5-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 --- 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 a560d6be2a44..42d92a5b475d 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -876,10 +876,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; @@ -902,32 +934,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); @@ -1284,6 +1291,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; @@ -1317,6 +1325,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 Tue Jan 19 23:07:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031045 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 054CEC433E0 for ; Tue, 19 Jan 2021 23:22:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C997722DD3 for ; Tue, 19 Jan 2021 23:22:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729576AbhASXKk (ORCPT ); Tue, 19 Jan 2021 18:10:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52232 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728500AbhASXJQ (ORCPT ); Tue, 19 Jan 2021 18:09:16 -0500 Received: from mail-ed1-x535.google.com (mail-ed1-x535.google.com [IPv6:2a00:1450:4864:20::535]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3473BC0613D6 for ; Tue, 19 Jan 2021 15:08:08 -0800 (PST) Received: by mail-ed1-x535.google.com with SMTP id g1so22897581edu.4 for ; Tue, 19 Jan 2021 15:08:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FyMTgb9nXcUn+Nig+R0DDfuzanqX3vWBV8/pW6EP1RU=; b=IJdNZFEeUhDJl21QjRW0H2CTv8si0NnHK12wvlcWUZZERsq+HE8i9XdVvMC+IMv+E2 d8V2uJD3CrcI+0fNKc/zxtAXwwvLe25dqr0ClAK0YjfPdNr05wPMsDWhECjjfiYYFDzL PqSWG32w6EM+jf/vTOSv6BnOkWDA/OsLkbpyD92MrBt9CqvUn6UShurEGWbfKhEq3Jot RNapcNJRJgKHtOJSyvbxgKLGDsnVxRLcNbzZVFD6FTmWZHor50aTkkpPhsBSadz5oaVj /psyLHYRLWhlvcRMIeZhcjkWWwVKHU2NDMuI9K+aVBJFt2wCusiFnQWmztTlThf3tdax 5O+Q== 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=FyMTgb9nXcUn+Nig+R0DDfuzanqX3vWBV8/pW6EP1RU=; b=SPe2uR2PViCCACI8/ybinYhN/yyJXQqoaAwMlNZmnT2Wgzj6wvg8NotLtRCmIQWqrU 3bWFxnokpeGV8euIjhH9HxNalCVIOeptsjZMb6t3Gz7Bjvz8ukLq5NMCaZaC1fHaLaZA ZOj9s5vQFTsvEqTot66ZrfYLh0saqyYcW9WpkPNX9oyctaMvr4wgkuEXTjTLPxbCImmv V1PegKoKhykttmMcW+1WvAQF1auAINA+tXFWN3r8PkF7XyZRurF1aDgHbufWBiapgco8 7ccX04AJLXTOlV8GWVN46t9YNcOQ2t8IgTGY4glf+SM+yNjG+n/ZwoHcJNag0HhQDuqh BQ3g== X-Gm-Message-State: AOAM531wSL2fh2J7su03eQuNFklBr6j438QpbQL2B6e+wdsQlyZg7P35 Gyaris5z4WYc23m0fLTwK3w= X-Google-Smtp-Source: ABdhPJx65tCya4gFQH4/StpgmHTKMm0rna2WcTqxz2V0z5tpFlOvHMFYpIghHbK9/Cf5+TqXttlzYw== X-Received: by 2002:a50:acc1:: with SMTP id x59mr5150463edc.43.1611097686930; Tue, 19 Jan 2021 15:08:06 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:06 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 05/16] net: mscc: ocelot: don't use NPI tag prefix for the CPU port module Date: Wed, 20 Jan 2021 01:07:38 +0200 Message-Id: <20210119230749.1178874-6-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 --- 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 42d92a5b475d..acf7ef00e56b 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1346,9 +1346,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; } @@ -1378,9 +1378,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; } @@ -1465,9 +1465,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 Tue Jan 19 23:07:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031039 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 80A4EC433E6 for ; Tue, 19 Jan 2021 23:13:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3999F22D08 for ; Tue, 19 Jan 2021 23:13:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729769AbhASXMw (ORCPT ); Tue, 19 Jan 2021 18:12:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52234 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728514AbhASXJQ (ORCPT ); Tue, 19 Jan 2021 18:09:16 -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 DB1D7C0613ED for ; Tue, 19 Jan 2021 15:08:09 -0800 (PST) Received: by mail-ed1-x52e.google.com with SMTP id c6so16439061ede.0 for ; Tue, 19 Jan 2021 15:08:09 -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=GBMsG2AQTyl4hgvb77tEu4dhQjWr/F7ZRTICs0MAY/E=; b=JoYjtKSVvRKAizq03WKVZO3XnSKuHn783B5P9Iqcg7/EaSYu4VdpNhLSdzBCdfuizT lQpDh0MCl0eX0Z2gSkAar3Qm7WpLEB+CVc0zitP6S5ZvY9AyELuB+SMbfwZa0MHfAH8D 0zleZbL34L4EppWq0I49L5EocMVTBsIDNGrW8xbVVYNNOMuHCZ9wXgyaOOBPZvHfvunV 4Z/zyFecJANj7SrIgKgH2rcnvLRD7hX9D8xr790A3kYFnRKEpp7zM+ZUwo+PyF6TRJtw Dl4dzo1SShbKyDJ7VCu0LQggPFW7v25m/5o25Kha7lNXUcMqSwaJuOjAC58KctnFCAfx Tigw== 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=GBMsG2AQTyl4hgvb77tEu4dhQjWr/F7ZRTICs0MAY/E=; b=iLi/e5DvhbtWvHowNdCc3rFomZbDxM/gKQNcASvjb9bn1oXtxtWVrg4OpTTt/ckj1b kazq+HKKMlQDqXFKofkNYvjJdeK4uDiAMINOPYoi0dvRj1QmxAPfSgREPU+W1q5fD837 0JAvxVhO139TmAVO95yn1J0YEu5ZA4+B9/pTsqfpf+DBetBPljh+94q2UP6i6UYOrAgP /5HSPKPJsuc/rdzDog6p/rsSFK74zjaFYn2NmwHopvUj/1YY4Gyv3gchhGb8rfSaZqOa f75HC96HQxs0vhAO1X1E7+zs7kn4Ht5oJpL9a7/zcJJAisiO4Ie554MTP5IOIgddVCVu lWew== X-Gm-Message-State: AOAM5332wA6poNPoY7XJFJjCnzXVfU3LzZJ8zkjKId16sCAk/wabtz15 KcdADjzavGesabmYK/2Pg7o= X-Google-Smtp-Source: ABdhPJzLsf7J4OigpH8iyBYDNLkQ96tNOBvfJQk3ZGv5WwzowfxbF/q0cuNDG9uyezoL4voFBd4uxA== X-Received: by 2002:a05:6402:1682:: with SMTP id a2mr5363226edv.30.1611097688494; Tue, 19 Jan 2021 15:08:08 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:07 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 06/16] net: dsa: allow changing the tag protocol via the "tagging" device attribute Date: Wed, 20 Jan 2021 01:07:39 +0200 Message-Id: <20210119230749.1178874-7-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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. 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 --- Changes in v4: Patch is new. include/net/dsa.h | 17 ++++++++ net/dsa/dsa.c | 20 ++++++++++ net/dsa/dsa2.c | 84 ++++++++++++++++++++++++++++++++++++++-- net/dsa/dsa_priv.h | 18 +++++++++ net/dsa/master.c | 26 ++++++++++++- net/dsa/port.c | 10 ++++- net/dsa/slave.c | 35 +++++++++++------ net/dsa/switch.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 289 insertions(+), 17 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 2f5435d3d1db..aa0ba41e42d6 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -333,6 +333,8 @@ struct dsa_switch { /* devlink used to represent this switch device */ struct devlink *devlink; + struct mutex tagger_lock; + /* Number of switch port queues */ unsigned int num_tx_queues; @@ -480,9 +482,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. + * For all of these helpers, @port is the CPU port that gets set up. + */ 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 cc13549120e5..ec8b9e458d53 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -664,6 +664,11 @@ static int dsa_switch_setup(struct dsa_switch *ds) } } + /* The DSA_NOTIFIER_TAG_PROTO_* notifiers use this mutex, + * so initialize it first. + */ + mutex_init(&ds->tagger_lock); + err = dsa_switch_register_notifier(ds); if (err) goto unregister_devlink_ports; @@ -674,6 +679,22 @@ static int dsa_switch_setup(struct dsa_switch *ds) if (err < 0) goto unregister_notifier; + /* Iterate through ports list again, so that we notify the switch of + * its tagging protocol after setup(), but before we start registering + * the user ports, whose MTU configuration will depend upon the tagger. + */ + list_for_each_entry(dp, &ds->dst->ports, list) { + if (dp->ds != ds || !dsa_is_cpu_port(ds, dp->index)) + continue; + + if (ds->ops->set_tag_protocol) { + err = ds->ops->set_tag_protocol(ds, dp->index, + dp->tag_ops->proto); + if (err) + goto teardown; + } + } + devlink_params_publish(ds->devlink); if (!ds->slave_mii_bus && ds->ops->phy_read) { @@ -694,6 +715,9 @@ static int dsa_switch_setup(struct dsa_switch *ds) return 0; +teardown: + if (ds->ops->teardown) + ds->ops->teardown(ds); unregister_notifier: dsa_switch_unregister_notifier(ds); unregister_devlink_ports: @@ -718,6 +742,15 @@ static void dsa_switch_teardown(struct dsa_switch *ds) if (ds->slave_mii_bus && ds->ops->phy_read) mdiobus_unregister(ds->slave_mii_bus); + list_for_each_entry(dp, &ds->dst->ports, list) { + if (dp->ds != ds || !dsa_is_cpu_port(ds, dp->index)) + continue; + + if (ds->ops->del_tag_protocol) + ds->ops->del_tag_protocol(ds, dp->index, + dp->tag_ops->proto); + } + dsa_switch_unregister_notifier(ds); if (ds->ops->teardown) @@ -898,6 +931,53 @@ 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 = { + .tree_index = dst->index, + }; + struct dsa_port *dp; + int err; + + /* At the moment we don't allow changing the tag protocol under + * traffic. May revisit in the future. + */ + if (master->flags & IFF_UP) + return -EBUSY; + + list_for_each_entry(dp, &dst->ports, list) { + if (!dsa_is_user_port(dp->ds, dp->index)) + continue; + + if (dp->slave->flags & IFF_UP) + return -EBUSY; + } + + info.tag_ops = old_tag_ops; + err = dsa_broadcast(DSA_NOTIFIER_TAG_PROTO_DEL, &info); + if (err) + return err; + + info.tag_ops = tag_ops; + err = dsa_broadcast(DSA_NOTIFIER_TAG_PROTO_SET, &info); + if (err) + goto out_unwind_tagger; + + return 0; + +out_unwind_tagger: + info.tag_ops = old_tag_ops; + dsa_broadcast(DSA_NOTIFIER_TAG_PROTO_SET, &info); + return err; +} + static struct dsa_port *dsa_port_touch(struct dsa_switch *ds, int index) { struct dsa_switch_tree *dst = ds->dst; @@ -983,10 +1063,8 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master) dp->master = master; dp->type = DSA_PORT_TYPE_CPU; - dp->filter = tag_ops->filter; - dp->rcv = tag_ops->rcv; - dp->tag_ops = tag_ops; dp->dst = dst; + dsa_port_set_tag_protocol(dp, tag_ops); return 0; } diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 2ce46bb87703..637ad8684e4f 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,12 @@ struct dsa_notifier_mtu_info { int mtu; }; +/* DSA_NOTIFIER_TAG_PROTO_* */ +struct dsa_notifier_tag_proto_info { + int tree_index; + const struct dsa_device_ops *tag_ops; +}; + struct dsa_switchdev_event_work { struct dsa_switch *ds; int port; @@ -115,6 +123,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 +148,9 @@ static inline struct net_device *dsa_master_find_slave(struct net_device *dev, } /* port.c */ +int dsa_broadcast(unsigned long e, void *v); +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 +213,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) { @@ -283,6 +297,10 @@ 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_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 f5b0f72ee7cd..d48f3a588d9d 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -13,7 +13,7 @@ #include "dsa_priv.h" -static int dsa_broadcast(unsigned long e, void *v) +int dsa_broadcast(unsigned long e, void *v) { struct dsa_switch_tree *dst; int err = 0; @@ -536,6 +536,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..6bd048cac445 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -297,6 +297,96 @@ 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 (ds->dst->index == info->tree_index && dsa_is_cpu_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 err = 0, port; + + mutex_lock(&ds->tagger_lock); + + for (port = 0; port < ds->num_ports; port++) { + if (!dsa_switch_tag_proto_match(ds, port, info)) + continue; + + /* 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) { + err = -EOPNOTSUPP; + break; + } + + /* The delete method is optional, just the setter + * is mandatory + */ + if (ds->ops->del_tag_protocol) + ds->ops->del_tag_protocol(ds, port, + info->tag_ops->proto); + } + + mutex_unlock(&ds->tagger_lock); + + return err; +} + +static int dsa_switch_tag_proto_set(struct dsa_switch *ds, + struct dsa_notifier_tag_proto_info *info) +{ + bool proto_changed = false; + int port, err = 0; + + mutex_lock(&ds->tagger_lock); + + for (port = 0; port < ds->num_ports; port++) { + struct dsa_port *cpu_dp = dsa_to_port(ds, port); + + if (!dsa_switch_tag_proto_match(ds, port, info)) + continue; + + err = ds->ops->set_tag_protocol(ds, cpu_dp->index, + info->tag_ops->proto); + if (err) + goto out; + + dsa_port_set_tag_protocol(cpu_dp, info->tag_ops); + proto_changed = true; + } + + if (!proto_changed) + goto out; + + /* 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++) { + struct net_device *slave; + + if (!dsa_is_user_port(ds, port)) + continue; + + slave = dsa_to_port(ds, port)->slave; + dsa_slave_setup_tagger(slave); + + rtnl_lock(); + dsa_slave_change_mtu(slave, slave->mtu); + rtnl_unlock(); + } +out: + mutex_unlock(&ds->tagger_lock); + + return err; +} + static int dsa_switch_event(struct notifier_block *nb, unsigned long event, void *info) { @@ -343,6 +433,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 Tue Jan 19 23:07:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031061 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1B5B8C433DB for ; Tue, 19 Jan 2021 23:23:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D904622DD3 for ; Tue, 19 Jan 2021 23:23:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730040AbhASXWt (ORCPT ); Tue, 19 Jan 2021 18:22:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52104 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726491AbhASXJD (ORCPT ); Tue, 19 Jan 2021 18:09:03 -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 9D8B5C061786 for ; Tue, 19 Jan 2021 15:08:11 -0800 (PST) Received: by mail-ej1-x630.google.com with SMTP id 6so30914205ejz.5 for ; Tue, 19 Jan 2021 15:08:11 -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=eoaAf3VB2ZkBJEscAlighF3epDpYPmPmxeLjzaEE4XI=; b=c9+pKH44rKKTeEkS6CrH+pXLOMOJ5V3vFNg6YWESbluNB5gUqLZnyx+kzabu+8KvvL 2ACMLnumxPgccsgnjro3BdkXlKeiNaxjAQUXAUD+maMj8D6A5BtWX6sDq+0GZH8A6KLq i3ucla29Z1bKCkXkmQiDomM9cUx7O7+FmIy1A2digRInhMfcFRd76P3wk0+kF8kgk8Lg NH4gY9oEzDZfpE40A0XmBN2Tn9rcHKj/fJwE9J8cvXQYsxyjagI/bxl4Jbv3dxidaYvy M04Vk4xhMCH0gqydhyv9rMy6D5n59vlUAgAmehuqba92A8C8R7RAEhFLbJoJo22Cza8W vanQ== 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=eoaAf3VB2ZkBJEscAlighF3epDpYPmPmxeLjzaEE4XI=; b=PfWqqwX/Qy11dDXpQnOvALCwYo0wABYn6BIURx8AxBRiPMttPwRO3Kp5y3lvVB4wYM GRWAgbQsMtu0IviZtKsLDUMCOZn1P5TPMc+L+JmIs36RBRKXezX5A+xJJRzBDizZID+N 0qibXTClTHdkmaGWbuqLtJ9PveYX7Sc+CUzCuKY9SjKplc1mzwMKbuyb/5RZBzsTBNd5 8OdD2qfIZnjp5vxJNtnUd/kic9yRUacoHiXADPrPDwfSqn2BivzPr925CCmcMarN228k sI3rBacpv2WzP2XA/QvHWBcGAgFhEJGO/FasJxZ6WT9bhwxejfgkcytAiDZ5vo3S1GBZ KHqg== X-Gm-Message-State: AOAM531LTXaAAh3sckCVCsLwAVL1dPQ7EKwMbFQ3tm6k/XF7//mNLtBN BvhnGZES9zF78b9jODoanWw= X-Google-Smtp-Source: ABdhPJxo/yXQ1yMjXabi3MBt5qEP+27FXQeIH2hm10gXUosfCM641cHbziEQVDdcjlV/qCwzjxsCbw== X-Received: by 2002:a17:906:2ccb:: with SMTP id r11mr4467150ejr.39.1611097690097; Tue, 19 Jan 2021 15:08:10 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:09 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 07/16] net: dsa: felix: add new VLAN-based tagger Date: Wed, 20 Jan 2021 01:07:40 +0200 Message-Id: <20210119230749.1178874-8-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 patch brings an implementation of the software-defined tag_8021q.c tagger format, which also preserves full functionality under a vlan_filtering bridge (unlike sja1105, the only other user of tag_8021q). 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 Signed-off-by: Vladimir Oltean --- 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. MAINTAINERS | 1 + drivers/net/dsa/ocelot/Kconfig | 2 + drivers/net/dsa/ocelot/felix.c | 473 +++++++++++++++++++++-- drivers/net/dsa/ocelot/felix.h | 2 + drivers/net/dsa/ocelot/felix_vsc9959.c | 1 + drivers/net/dsa/ocelot/seville_vsc9953.c | 1 + drivers/net/ethernet/mscc/ocelot.c | 36 +- drivers/net/ethernet/mscc/ocelot_vcap.c | 1 + drivers/net/ethernet/mscc/ocelot_vcap.h | 3 - include/net/dsa.h | 2 + include/soc/mscc/ocelot.h | 2 + include/soc/mscc/ocelot_vcap.h | 3 + net/dsa/Kconfig | 21 +- net/dsa/Makefile | 1 + net/dsa/tag_ocelot_8021q.c | 68 ++++ 15 files changed, 566 insertions(+), 51 deletions(-) create mode 100644 net/dsa/tag_ocelot_8021q.c diff --git a/MAINTAINERS b/MAINTAINERS index 096b584e7fed..ae793658e6a5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12842,6 +12842,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/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 054e57dd4383..df43f4a40f83 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 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -24,11 +25,440 @@ #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; + + /* 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; + + return ocelot_vcap_filter_add(ocelot, outer_tagging_rule, NULL); +} + +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, +}; + 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; +} + +/* 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); +} + +/* 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; + + rtnl_lock(); + err = dsa_8021q_setup(felix->dsa_8021q_ctx, true); + rtnl_unlock(); + + 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; + + rtnl_lock(); + err = dsa_8021q_setup(felix->dsa_8021q_ctx, false); + rtnl_unlock(); + 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); +} + +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; + case DSA_TAG_PROTO_OCELOT_8021Q: + err = felix_setup_tag_8021q(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; + case DSA_TAG_PROTO_OCELOT_8021Q: + felix_teardown_tag_8021q(ds, cpu); + break; + default: + break; + } } static int felix_set_ageing_time(struct dsa_switch *ds, @@ -527,28 +957,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 +986,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 +1001,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 +1259,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..9d4459f2fffb 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -48,6 +48,8 @@ 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; }; 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 acf7ef00e56b..0cbd1bbbf365 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -876,18 +876,39 @@ 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) { + 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]; @@ -899,15 +920,12 @@ static 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); void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state) { 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/net/dsa.h b/include/net/dsa.h index aa0ba41e42d6..b942e8574a4b 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/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 93c22627dedd..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 { @@ -760,6 +761,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, 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_ */ 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 Tue Jan 19 23:07:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031021 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9995AC433E6 for ; Tue, 19 Jan 2021 23:11:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6FEDC23110 for ; Tue, 19 Jan 2021 23:11:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730004AbhASXLB (ORCPT ); Tue, 19 Jan 2021 18:11:01 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52278 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728865AbhASXJ2 (ORCPT ); Tue, 19 Jan 2021 18:09:28 -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 C74D3C061793 for ; Tue, 19 Jan 2021 15:08:12 -0800 (PST) Received: by mail-ed1-x536.google.com with SMTP id g24so23503993edw.9 for ; Tue, 19 Jan 2021 15:08:12 -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=3eU6kSjEOcWiIAeYb5djdb4+zYVSgxq7JRDf7QIRx6g=; b=n0ZPhrsxsHE2EdhLRRqLHZp8D6zgNG/HoCzqKH0ZWB8DFpZC/OkkRak2V83p7jG+y0 ZXrQSqu4ZDErsOBgc3UkZeHdI8lFqgyPNaGv4ouXpRdRV2SApD3WCt/IWWzUgO8VFeCP yYpMIy1QaOIIPfJxKFsDhEFP6xfXAK2EU7bCW1QZnZevcryB7xCftzB3g2t5u6u6jLcx yK4BdS8vIOP3msH5BwuULIbjHKdsZj9UldfzK+RTdsJE0sS6kC4G+TfRsKZebXlNXTzE HOnAwbafP24HbbshhDYIvAyOKytohVB0BXUua+VdpoKyhUCcnqZmnBtyZXH7vYgIpnt/ QELA== 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=3eU6kSjEOcWiIAeYb5djdb4+zYVSgxq7JRDf7QIRx6g=; b=eWiy26P8D6r5nugo5GFgGcg5FASg3+aDWsFwj/oHtt8SETQYiUreTZysCN+N7nGhGD ftbK2S98FLjih87Fm7YDMKbGBHMfpplo8fRmAuCsJOlJ+2XyeH41f2nU22SsexQrYDXO Ujv9f5imY0m4npKhRqcMOvQfk1HbiR5G20+375Uh/yJh0OI8gWGbagdQ34NY0/CIA0EN z8QKntZq7BvgabJ602eeAmNW9CyUC00sfWrLytCCArIff1AHGLb8xdKeghzujX117y41 oRUFta4bTtGxdwhQbrBVYO+RvsSNAgQ31KMmNIe1E3CyV1ZMF7PWDLGKcCKCKxR5yht5 Jxmg== X-Gm-Message-State: AOAM530C8h0kfSmgBePGPG1yz6cOSFmoawK8Rbpe1GHxGZd2tZs/JDns p7ZE+Lj4TstLT0J0tx1rDbiJMkockRE= X-Google-Smtp-Source: ABdhPJynZJe1FEhTIn9p9Up9kao6YyFxOQlt077IdZdmSNOB7aEdAvZFafllE9QMm6nttq+BggFWLQ== X-Received: by 2002:a05:6402:268a:: with SMTP id w10mr5161977edd.331.1611097691610; Tue, 19 Jan 2021 15:08:11 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:11 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 08/16] net: mscc: ocelot: stop returning IRQ_NONE in ocelot_xtr_irq_handler Date: Wed, 20 Jan 2021 01:07:41 +0200 Message-Id: <20210119230749.1178874-9-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 Since the xtr (extraction) IRQ of the ocelot switch is not shared, then if it fired, it means that some data must be present in the queues of the CPU port module. So simplify the code. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- Changes in v3: None. Changes in v2: None. Changes in v2: Patch is new. drivers/net/ethernet/mscc/ocelot_vsc7514.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 407244fe5b17..5140639910a6 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -604,10 +604,7 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) int i = 0, grp = 0; int err = 0; - if (!(ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp))) - return IRQ_NONE; - - do { + while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) { struct skb_shared_hwtstamps *shhwtstamps; struct ocelot_port_private *priv; struct ocelot_port *ocelot_port; @@ -702,7 +699,7 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) netif_rx(skb); dev->stats.rx_bytes += len; dev->stats.rx_packets++; - } while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)); + } if (err) while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) From patchwork Tue Jan 19 23:07:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031041 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AB8ABC433E0 for ; Tue, 19 Jan 2021 23:13:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7979E22CAD for ; Tue, 19 Jan 2021 23:13:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729908AbhASXNV (ORCPT ); Tue, 19 Jan 2021 18:13:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52120 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727200AbhASXJF (ORCPT ); Tue, 19 Jan 2021 18:09:05 -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 5645FC061794 for ; Tue, 19 Jan 2021 15:08:14 -0800 (PST) Received: by mail-ej1-x629.google.com with SMTP id r12so19536418ejb.9 for ; Tue, 19 Jan 2021 15:08:14 -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=AIdParNk1Bd+j3i7SFF4oov2pJIQA2uNY8WMxLWwkdk=; b=hyJQA0r+zzltPJYPEQ0YL63EI78pyHxw377TE7yBPwWG0LtsElun1RNcN87n5GL0J8 dJnz/dIUNLt3lT98XJYJnVZQc5Rxy6LdwMn/BDWx2oKdd/qupfnYgPGvDBBtzjkHcGnA J67t6ewuYb8Row2Y8uNtgwMJSOcG+XqOWJPyhgphwvvCNQsD6OqQzMaLWzXMQpgd7bw0 GwRDG96tUKcNck2zALKNTJqKCCYwlB53Oypfm0pAF4dlE8IOejWP/gc5qP+ipsGuCClM B6D8kLTw31WzEggd9XRDZZ/qIdJrzbMYAhJ9iJPIR5WjmbuFG0pXJTPGTGh+fBO6oW8z yX8g== 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=AIdParNk1Bd+j3i7SFF4oov2pJIQA2uNY8WMxLWwkdk=; b=Kg45LULrtNYY/aNisDrwZscF5djxYejvnwqMPfB2E4Ztenm2pNcpxfkEACPpO39Oek zTrUe5K3AUwgMTTY+FYqkR1c+heYu791/p8G5FfCnFg00526Vj5Vb1GZkE43sVZfa2hR h8ZqqeBvUmjMAJXrSEts5J4T449Sz0kev0o7TtrhaaGpZe4cg+KFixSSWl9Dw9hH02wx D43CQBhx0HuK83GETlP4UNWIgRnRtgy1qIVR5l1ZQX5jzYidBQLyzNLmk0l1sMIywmQj ijQ0a+XOxcJs2Qkj0D9WDqyh9MrGHBehlN1hpT9RTOfg6RQSU5IDmNv12ofNivYQJ8Go Rwxw== X-Gm-Message-State: AOAM5334sEpQLpqB4WDa0ETImdW9kxd+oRMkUFTg+kv1RXYInnTpUeb7 JhPDQJZfrYAuRpxJscUQEp+oZpunsCk= X-Google-Smtp-Source: ABdhPJwn40Rk34gZTQDksygYLoN1ec1ympCxhMtnOkJx6LZZEGZzoYgfAlhwR/u1ZFPefmKn5IBm7Q== X-Received: by 2002:a17:906:68d0:: with SMTP id y16mr4697136ejr.128.1611097693112; Tue, 19 Jan 2021 15:08:13 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:12 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 09/16] net: mscc: ocelot: only drain extraction queue on error Date: Wed, 20 Jan 2021 01:07:42 +0200 Message-Id: <20210119230749.1178874-10-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 It appears that the intention of this snippet of code is to not exit ocelot_xtr_irq_handler() while in the middle of extracting a frame. The problem in extracting it word by word is that future extraction attempts are really easy to get desynchronized, since the IRQ handler assumes that the first 16 bytes are the IFH, which give further information about the frame, such as frame length. But during normal operation, "err" will not be 0, but 4, set from here: for (i = 0; i < OCELOT_TAG_LEN / 4; i++) { err = ocelot_rx_frame_word(ocelot, grp, true, &ifh[i]); if (err != 4) break; } if (err != 4) break; In that case, draining the extraction queue is a no-op. So explicitly make this code execute only on negative err. Signed-off-by: Vladimir Oltean --- Changes in v4: None. Changes in v3: None. Changes in v2: Patch is new. drivers/net/ethernet/mscc/ocelot_vsc7514.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 5140639910a6..49089a014dda 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -701,7 +701,7 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) dev->stats.rx_packets++; } - if (err) + if (err < 0) while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) ocelot_read_rix(ocelot, QS_XTR_RD, grp); From patchwork Tue Jan 19 23:07:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031013 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 95A9FC433DB for ; Tue, 19 Jan 2021 23:10:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6F4B322CAD for ; Tue, 19 Jan 2021 23:10:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729084AbhASXJv (ORCPT ); Tue, 19 Jan 2021 18:09:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52128 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727273AbhASXJF (ORCPT ); Tue, 19 Jan 2021 18:09:05 -0500 Received: from mail-ed1-x532.google.com (mail-ed1-x532.google.com [IPv6:2a00:1450:4864:20::532]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1B68DC061796 for ; Tue, 19 Jan 2021 15:08:16 -0800 (PST) Received: by mail-ed1-x532.google.com with SMTP id bx12so9552377edb.8 for ; Tue, 19 Jan 2021 15:08:16 -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=INibe6ATFiOkyHe/BYMykgqKnyQ7hJMS326AbBxewGg=; b=m5Gnf9fMozqOQnFyILLbfeNdAcBtxGVqsm3eEt/wSTtZ26s60zMjRQMkGFEW+rKj9g yUfVuB2nT0q+MqbSb3kBSzcH37UO+ogPW0nZbrjkx3WSQrzb32A2Ap41wsZDXxGHWtl8 sr2rHgl7Fz3q0I6XowsxtJOQvx135k+VHHiWRKuXfolR8gv9cMUSLYV+nukKJqWngykF ETCYWjfmBLjSnyFJrrZuFVGtaJ6hZ6Ub1jGjItGkbSZQ9wsQOXLQbifbE/1nNLXW9NaJ 5M1nz3RJyembkvIckJTZ7rqS6x5N96xyqwAmWVyjxF+6KaTs53fmMnvWwDDxG/eeTun3 yI4w== 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=INibe6ATFiOkyHe/BYMykgqKnyQ7hJMS326AbBxewGg=; b=kcgA6NhBY1TtCpQtKnlyjyPJIsCSHEMUrpbrP+67IkPlZMPwCsiZTx7YqdJcNe7sHt dkI+gHO0SpHo1XRbGSc7mz8KDwZtRU+xNmdfzGjbye+WBgWoMR7shA4Zd16t41qLoHPg edA0iSzv0c7/Hf+Z/7pmwih/Q4ECn1C4+hkRA9GfQvQuQqMSTA4R9y0HQCKWdfyFEspg N5rI376brTvOEWNAxtbclxuXqwpiGzP20pbpAiuLMCUsmaWEQw/xF2rwHsa3cNMWNSQd fSZmykEP47PyXb3Ip3uWNnNxndYi7niEN00HQBEgeac6fjdilDMoIOq5uSKcm7uMbbDj 7afw== X-Gm-Message-State: AOAM531Il0V5AcEFiLKBW8K09337soKanaK5A1m3F/SbMjn0W34k/fcV nVU9WvXmeiwI/hyXN8mSdXgQuOTfs2I= X-Google-Smtp-Source: ABdhPJxTlE/fjeDP7fVpAKEz9JjU4WRdu+/EINxnNqU/sDGne71vQmMV0pc96fmzgAbXx+rPCSW6sQ== X-Received: by 2002:a50:fc8c:: with SMTP id f12mr5157323edq.225.1611097694894; Tue, 19 Jan 2021 15:08:14 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:14 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 10/16] net: mscc: ocelot: better error handling in ocelot_xtr_irq_handler Date: Wed, 20 Jan 2021 01:07:43 +0200 Message-Id: <20210119230749.1178874-11-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 ocelot_rx_frame_word() function can return a negative error code, however this isn't being checked for consistently. Errors being ignored have not been seen in practice though. Also, some constructs can be simplified by using "goto" instead of repeated "break" statements. Signed-off-by: Vladimir Oltean --- Changes in v4: None. Changes in v3: None. Changes in v2: Patch is new. drivers/net/ethernet/mscc/ocelot_vsc7514.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 49089a014dda..4bd3b59eba1b 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -619,12 +619,9 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) for (i = 0; i < OCELOT_TAG_LEN / 4; i++) { err = ocelot_rx_frame_word(ocelot, grp, true, &ifh[i]); if (err != 4) - break; + goto out; } - if (err != 4) - break; - /* At this point the IFH was read correctly, so it is safe to * presume that there is no error. The err needs to be reset * otherwise a frame could come in CPU queue between the while @@ -645,7 +642,7 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) if (unlikely(!skb)) { netdev_err(dev, "Unable to allocate sk_buff\n"); err = -ENOMEM; - break; + goto out; } buf_len = info.len - ETH_FCS_LEN; buf = (u32 *)skb_put(skb, buf_len); @@ -653,12 +650,21 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) len = 0; do { sz = ocelot_rx_frame_word(ocelot, grp, false, &val); + if (sz < 0) { + err = sz; + goto out; + } *buf++ = val; len += sz; } while (len < buf_len); /* Read the FCS */ sz = ocelot_rx_frame_word(ocelot, grp, false, &val); + if (sz < 0) { + err = sz; + goto out; + } + /* Update the statistics if part of the FCS was read before */ len -= ETH_FCS_LEN - sz; @@ -667,11 +673,6 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) *buf = val; } - if (sz < 0) { - err = sz; - break; - } - if (ocelot->ptp) { ocelot_ptp_gettime64(&ocelot->ptp_info, &ts); @@ -701,6 +702,7 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) dev->stats.rx_packets++; } +out: if (err < 0) while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) ocelot_read_rix(ocelot, QS_XTR_RD, grp); From patchwork Tue Jan 19 23:07:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031047 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6FC37C433E0 for ; Tue, 19 Jan 2021 23:22:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4533922DD3 for ; Tue, 19 Jan 2021 23:22:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729778AbhASXWk (ORCPT ); Tue, 19 Jan 2021 18:22:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52100 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727354AbhASXJF (ORCPT ); Tue, 19 Jan 2021 18:09:05 -0500 Received: from mail-ed1-x530.google.com (mail-ed1-x530.google.com [IPv6:2a00:1450:4864:20::530]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 90DDEC061798 for ; Tue, 19 Jan 2021 15:08:17 -0800 (PST) Received: by mail-ed1-x530.google.com with SMTP id dj23so20990926edb.13 for ; Tue, 19 Jan 2021 15:08:17 -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=iwCUNqLglIYcGVNIfzZGfQ5CfFXZV0rXFfVSZHPsXNc=; b=OsUuytmAk91454sP37H8sKX9ONiNQaQ0WwYxPOh5IfmGBN5SzbfMgp3BImxdL9zoHJ e3R9/ARS858ouAHoW6qv0xLLccTanK3lozA3KuZ5h8gb6zs+iTMKIibPr1EqSKxdV8gm zEDMVzt5T8xXyMkFN2DHZOXSv3ATQloYHO6hqgqtTAdhCBLfMz7k+sg6uNTk87lLpmyG QkO01pAU75usHYFN3mfAkNrWU0ASHeYQWuRjykirHoXtNrUVEHZdeCfbIWtgAhqeYkzW u2SO90HWfc0V1NekhNPj68wDDBKUwl+mBadbJhqjVaB8AH+0DRwtyM7NhF06n/s0vHk/ VYlg== 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=iwCUNqLglIYcGVNIfzZGfQ5CfFXZV0rXFfVSZHPsXNc=; b=YkM5XxqwyXxK83C40Vihr1rMNeH16QmGnWJBpmUBpOPCSO+3w0zarygqOy7KfLDuED tKQpCEkqg2IEqdTnFtaRX60q7JCMB2kbzlgXlkr7QK32mQrw7MpfJYbM3LstvaXdpkXH lJLRcHlknL5NrjeSl75qb3iCM/XIvrr1nHNAZ+W47UBUe3d0qLBkBuVUz9j2QzoXzoTF 186UBISPLpqhevvqETBRf7AV85Q7gz+lmgMWf5CD2uDOuLHyrDpYGXujyEF7wfbMoNZA PRTrrVlM7vUhVabzjfUCIkkq/jLeS/WaOyXoIVS5MMaUjSGX3OBmgoTZHfxnoF4+e7DW jhHw== X-Gm-Message-State: AOAM533wuTbqByCwoKThJm1y8OIjLuvoXIXJG4xk6aqpSmZTXv9klrZ6 8R3vtKXOtDOCA7kIQEwSk1k= X-Google-Smtp-Source: ABdhPJxhNKGe9dSXrXY2n5cp66gHi7rpW+HLplJdlyp0Yhme1FSV+/+tiiOBCH77H0B9pZEakJHP4Q== X-Received: by 2002:a50:e0c1:: with SMTP id j1mr5028835edl.253.1611097696362; Tue, 19 Jan 2021 15:08:16 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:15 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 11/16] net: mscc: ocelot: use DIV_ROUND_UP helper in ocelot_port_inject_frame Date: Wed, 20 Jan 2021 01:07:44 +0200 Message-Id: <20210119230749.1178874-12-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 This looks a bit nicer than the open-coded "(x + 3) % 4" idiom. Signed-off-by: Vladimir Oltean --- Changes in v3: None. Changes in v3: None. Changes in v2: Patch is new. drivers/net/ethernet/mscc/ocelot_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 9535a75b1c84..55847d2a83e1 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -563,7 +563,7 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev) ocelot_write_rix(ocelot, (__force u32)cpu_to_be32(ifh[i]), QS_INJ_WR, grp); - count = (skb->len + 3) / 4; + count = DIV_ROUND_UP(skb->len, 4); last = skb->len % 4; for (i = 0; i < count; i++) ocelot_write_rix(ocelot, ((u32 *)skb->data)[i], QS_INJ_WR, grp); From patchwork Tue Jan 19 23:07:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031023 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 18B0CC433DB for ; Tue, 19 Jan 2021 23:11:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E3CB922D08 for ; Tue, 19 Jan 2021 23:11:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727178AbhASXLh (ORCPT ); Tue, 19 Jan 2021 18:11:37 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52286 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728885AbhASXJb (ORCPT ); Tue, 19 Jan 2021 18:09:31 -0500 Received: from mail-ej1-x62d.google.com (mail-ej1-x62d.google.com [IPv6:2a00:1450:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 125B8C061799 for ; Tue, 19 Jan 2021 15:08:19 -0800 (PST) Received: by mail-ej1-x62d.google.com with SMTP id gx5so11659745ejb.7 for ; Tue, 19 Jan 2021 15:08:19 -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=ZliSiTHbWhN4Q9Qi+On5Z69APpvAVfrl10T1J9FJoWg=; b=t2fWu5DXZOiVwupKJ/eajXkfx5/SE3spdarWooNtp90kidhU0+BJajsI69y63nBmPJ yuI8qBu8RRIaRU5xqmPid0gsRjw12VgGYQPLIpuGqAk9/VJZ3A/npfj+8/oXGfVpCLhR FN07ADw6AjnW6wGaMIrDhqEe5dmXLge9YQLt1JCHu93se7qcHsLh6XfmlZdfmwKx3lYg WFrXGinHcoLNIuSXEzPNEyTaM8l1BtZ2Hu0EjrX3axZeR8HoyL7vhDgpHy62U/qiVakk +2D8vxzIi46fPi0igPSZ6DA6p6OHy/2cMe2uDZmnWJhlz9Ig4Vz5efh32hzpdfcPfzWy TOew== 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=ZliSiTHbWhN4Q9Qi+On5Z69APpvAVfrl10T1J9FJoWg=; b=C0J9ldvSFzoUMbJY3sb8cwYaxqtgeTI9yKg20R8MoSLnWLplvE3OrujpYtsFKEqYHa V+jHGaFVI4sbc51JnFGLw2AfmInBnUfY9EDP8WmzrbVlna0K8DQLgv5GLBUW9bfpsHlf XcWuocH6PS8/7bsZUoMpOaMX5QSCvwN288VPGtZTT30ah0a/FCTJkXcqNF6Ycjd0pUMb iQw5AYlch4yimlA+EgVfuiHosLjc3vTpwiz3DiVj5eJzRH4jiCuo2h/cOAd0SGNUaAuU EzvGvWrP49VpQbQ/JgJ7kcQ+W7kuJ5O/2YWtGz42d55xViBW3M4B/TdPmz4rS31nGjFe pDNA== X-Gm-Message-State: AOAM530QCfQ5aOvILfny61fVI9J389J57a9M5jBc74nUr5A2MIe5gUxt aBEYs6SqymYdc0vHrw6Wh+g= X-Google-Smtp-Source: ABdhPJxS3gUwnroP5EJ28ohisX5wVGPItiwOPkdqU0xkPH7pL3550WEQjQ4oNi2jZcviDSMg0/BzwA== X-Received: by 2002:a17:906:1701:: with SMTP id c1mr4315000eje.395.1611097697818; Tue, 19 Jan 2021 15:08:17 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:17 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 12/16] net: mscc: ocelot: refactor ocelot_port_inject_frame out of ocelot_port_xmit Date: Wed, 20 Jan 2021 01:07:45 +0200 Message-Id: <20210119230749.1178874-13-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 DSA driver will inject some frames through register MMIO, same as ocelot switchdev currently does. So we need to be able to reuse the common code. Signed-off-by: Vladimir Oltean --- Changes in v4: Added the missing EXPORT_SYMBOL bits for proper compilation as module. Changes in v3: None. Changes in v2: Patch is new. drivers/net/ethernet/mscc/ocelot.c | 80 +++++++++++++++++++++++++ drivers/net/ethernet/mscc/ocelot_net.c | 81 +++----------------------- include/soc/mscc/ocelot.h | 4 ++ 3 files changed, 91 insertions(+), 74 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 0cbd1bbbf365..506a997be8e7 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -561,6 +561,86 @@ void ocelot_get_txtstamp(struct ocelot *ocelot) } EXPORT_SYMBOL(ocelot_get_txtstamp); +/* Generate the IFH for frame injection + * + * The IFH is a 128bit-value + * bit 127: bypass the analyzer processing + * bit 56-67: destination mask + * bit 28-29: pop_cnt: 3 disables all rewriting of the frame + * bit 20-27: cpu extraction queue mask + * bit 16: tag type 0: C-tag, 1: S-tag + * bit 0-11: VID + */ +static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info) +{ + ifh[0] = IFH_INJ_BYPASS | ((0x1ff & info->rew_op) << 21); + ifh[1] = (0xf00 & info->port) >> 8; + ifh[2] = (0xff & info->port) << 24; + ifh[3] = (info->tag_type << 16) | info->vid; + + return 0; +} + +bool ocelot_can_inject(struct ocelot *ocelot, int grp) +{ + u32 val = ocelot_read(ocelot, QS_INJ_STATUS); + + if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp)))) + return false; + if (val & QS_INJ_STATUS_WMARK_REACHED(BIT(grp))) + return false; + + return true; +} +EXPORT_SYMBOL(ocelot_can_inject); + +void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp, + u32 rew_op, struct sk_buff *skb) +{ + struct frame_info info = {}; + u32 ifh[OCELOT_TAG_LEN / 4]; + unsigned int i, count, last; + + ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) | + QS_INJ_CTRL_SOF, QS_INJ_CTRL, grp); + + info.port = BIT(port); + info.tag_type = IFH_TAG_TYPE_C; + info.vid = skb_vlan_tag_get(skb); + info.rew_op = rew_op; + + ocelot_gen_ifh(ifh, &info); + + for (i = 0; i < OCELOT_TAG_LEN / 4; i++) + ocelot_write_rix(ocelot, (__force u32)cpu_to_be32(ifh[i]), + QS_INJ_WR, grp); + + count = DIV_ROUND_UP(skb->len, 4); + last = skb->len % 4; + for (i = 0; i < count; i++) + ocelot_write_rix(ocelot, ((u32 *)skb->data)[i], QS_INJ_WR, grp); + + /* Add padding */ + while (i < (OCELOT_BUFFER_CELL_SZ / 4)) { + ocelot_write_rix(ocelot, 0, QS_INJ_WR, grp); + i++; + } + + /* Indicate EOF and valid bytes in last word */ + ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) | + QS_INJ_CTRL_VLD_BYTES(skb->len < OCELOT_BUFFER_CELL_SZ ? 0 : last) | + QS_INJ_CTRL_EOF, + QS_INJ_CTRL, grp); + + /* Add dummy CRC */ + ocelot_write_rix(ocelot, 0, QS_INJ_WR, grp); + skb_tx_timestamp(skb); + + skb->dev->stats.tx_packets++; + skb->dev->stats.tx_bytes += skb->len; +} +EXPORT_SYMBOL(ocelot_port_inject_frame); + int ocelot_fdb_add(struct ocelot *ocelot, int port, const unsigned char *addr, u16 vid) { diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 55847d2a83e1..9a29d7d3b0e2 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -488,53 +488,20 @@ static int ocelot_port_stop(struct net_device *dev) return 0; } -/* Generate the IFH for frame injection - * - * The IFH is a 128bit-value - * bit 127: bypass the analyzer processing - * bit 56-67: destination mask - * bit 28-29: pop_cnt: 3 disables all rewriting of the frame - * bit 20-27: cpu extraction queue mask - * bit 16: tag type 0: C-tag, 1: S-tag - * bit 0-11: VID - */ -static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info) -{ - ifh[0] = IFH_INJ_BYPASS | ((0x1ff & info->rew_op) << 21); - ifh[1] = (0xf00 & info->port) >> 8; - ifh[2] = (0xff & info->port) << 24; - ifh[3] = (info->tag_type << 16) | info->vid; - - return 0; -} - -static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev) { struct ocelot_port_private *priv = netdev_priv(dev); - struct skb_shared_info *shinfo = skb_shinfo(skb); struct ocelot_port *ocelot_port = &priv->port; struct ocelot *ocelot = ocelot_port->ocelot; - u32 val, ifh[OCELOT_TAG_LEN / 4]; - struct frame_info info = {}; - u8 grp = 0; /* Send everything on CPU group 0 */ - unsigned int i, count, last; int port = priv->chip_port; + u32 rew_op = 0; - val = ocelot_read(ocelot, QS_INJ_STATUS); - if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp))) || - (val & QS_INJ_STATUS_WMARK_REACHED(BIT(grp)))) + if (!ocelot_can_inject(ocelot, 0)) return NETDEV_TX_BUSY; - ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) | - QS_INJ_CTRL_SOF, QS_INJ_CTRL, grp); - - info.port = BIT(port); - info.tag_type = IFH_TAG_TYPE_C; - info.vid = skb_vlan_tag_get(skb); - /* Check if timestamping is needed */ - if (ocelot->ptp && (shinfo->tx_flags & SKBTX_HW_TSTAMP)) { - info.rew_op = ocelot_port->ptp_cmd; + if (ocelot->ptp && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { + rew_op = ocelot_port->ptp_cmd; if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) { struct sk_buff *clone; @@ -547,45 +514,11 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev) ocelot_port_add_txtstamp_skb(ocelot, port, clone); - info.rew_op |= clone->cb[0] << 3; + rew_op |= clone->cb[0] << 3; } } - if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP) { - info.rew_op = ocelot_port->ptp_cmd; - if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) - info.rew_op |= skb->cb[0] << 3; - } - - ocelot_gen_ifh(ifh, &info); - - for (i = 0; i < OCELOT_TAG_LEN / 4; i++) - ocelot_write_rix(ocelot, (__force u32)cpu_to_be32(ifh[i]), - QS_INJ_WR, grp); - - count = DIV_ROUND_UP(skb->len, 4); - last = skb->len % 4; - for (i = 0; i < count; i++) - ocelot_write_rix(ocelot, ((u32 *)skb->data)[i], QS_INJ_WR, grp); - - /* Add padding */ - while (i < (OCELOT_BUFFER_CELL_SZ / 4)) { - ocelot_write_rix(ocelot, 0, QS_INJ_WR, grp); - i++; - } - - /* Indicate EOF and valid bytes in last word */ - ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) | - QS_INJ_CTRL_VLD_BYTES(skb->len < OCELOT_BUFFER_CELL_SZ ? 0 : last) | - QS_INJ_CTRL_EOF, - QS_INJ_CTRL, grp); - - /* Add dummy CRC */ - ocelot_write_rix(ocelot, 0, QS_INJ_WR, grp); - skb_tx_timestamp(skb); - - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; + ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb); kfree_skb(skb); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 6a61c499a30d..eb81d05da134 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -832,4 +832,8 @@ int ocelot_sb_occ_tc_port_bind_get(struct ocelot *ocelot, int port, enum devlink_sb_pool_type pool_type, u32 *p_cur, u32 *p_max); +bool ocelot_can_inject(struct ocelot *ocelot, int grp); +void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp, + u32 rew_op, struct sk_buff *skb); + #endif From patchwork Tue Jan 19 23:07:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031017 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7CBAEC433E0 for ; Tue, 19 Jan 2021 23:11:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 59B7F23109 for ; Tue, 19 Jan 2021 23:11:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729849AbhASXK6 (ORCPT ); Tue, 19 Jan 2021 18:10:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52288 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728901AbhASXJb (ORCPT ); Tue, 19 Jan 2021 18:09:31 -0500 Received: from mail-ed1-x529.google.com (mail-ed1-x529.google.com [IPv6:2a00:1450:4864:20::529]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7A8D9C06179A for ; Tue, 19 Jan 2021 15:08:20 -0800 (PST) Received: by mail-ed1-x529.google.com with SMTP id bx12so9552557edb.8 for ; Tue, 19 Jan 2021 15:08:20 -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=myj5i3kT7k2aekuHYKS754bdh8A9rqPaCuXnQ8l2Esk=; b=mnGbed7KH85ILw3m5+k37DkHQW+y0uIH2oiq62BjsjRhh5av3ChIxzmaFzJoQxAi+4 UwQhfMb0/Uk8LX4OVjriK4Hb1HACL0sSEEUEYFEbWKAnd8U7hQJIb8y7tYqryILI5hhD 29HiMj1nTjVuppK6FUD2/RenCi0pQbDSYcYzEMMUzBkL6GDRPDYE4oIrb+7hX/YKjzY8 H0PsSnNgxlf+835GkS1yeaBlshVv+GgfR2W+pt4y0jG4w1RSiLeZL8eawTYr4tqp1PCz iq1mYZZZzUGr045pwpLqYwjo2LMrzX8V7cT+OPfr/HtoABHkiTGxQyDG3dNZoMuDGkB1 Z+4w== 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=myj5i3kT7k2aekuHYKS754bdh8A9rqPaCuXnQ8l2Esk=; b=RJK/hOxfwOLvJjHi0R7JrSzT56je3Z4iRZqSoSVIP/noHzTYmF5jBVrTsjXwTDibEi KAayNoIskabQx4Mn324BYrmgzVei4mQT+iSlWKOR/kPIp7Pfn7/f/6cEB91YEHWSKKqX wVqqUaSIDlw94LdgvV+BL1joreSSQIVdL/ncO6bSkzvlvSuSpU9Qo8mpsJS+YAOkQoIP xXdUkqqmFqPpvA+DXzg7jJ6HdSeBftb11xnvU7oC20udb0ueOnmt2xwgjG2OcJdN5XvS ubZgWdkJ3Vg7Avcfj8wCgBQ8aJ2I+FMXYDY0cVB6Mon1jXSLRBzoqYyVmdK10lw8fNMH e4og== X-Gm-Message-State: AOAM533Pl7d5sAa//fVv34YiIsw5Tb4RMzITyHQWkWBLfVQJri2qwEoX FZ/gOHCH1RY0t2pBLjFe1Ho= X-Google-Smtp-Source: ABdhPJyadyD3lFNOcQc2QM2iI51BGIDROPjcMIf03hkHTVKCA/g5+B6sWlh5heg3yT3drNcnOYhZTw== X-Received: by 2002:aa7:cfda:: with SMTP id r26mr5063564edy.142.1611097699282; Tue, 19 Jan 2021 15:08:19 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:18 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 13/16] net: mscc: ocelot: export struct ocelot_frame_info Date: Wed, 20 Jan 2021 01:07:46 +0200 Message-Id: <20210119230749.1178874-14-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 Because felix DSA must now be able to extract a frame in 2 stages over MMIO (first the XFH then the frame data), it needs access to this internal ocelot structure that holds the unpacked information from the Extraction Frame Header. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- Changes in v4: None. Changes in v3: None. Changes in v2: Patch is new. drivers/net/ethernet/mscc/ocelot.c | 4 ++-- drivers/net/ethernet/mscc/ocelot.h | 9 --------- drivers/net/ethernet/mscc/ocelot_vsc7514.c | 4 ++-- include/soc/mscc/ocelot.h | 9 +++++++++ 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 506a997be8e7..adebec0be684 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -571,7 +571,7 @@ EXPORT_SYMBOL(ocelot_get_txtstamp); * bit 16: tag type 0: C-tag, 1: S-tag * bit 0-11: VID */ -static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info) +static int ocelot_gen_ifh(u32 *ifh, struct ocelot_frame_info *info) { ifh[0] = IFH_INJ_BYPASS | ((0x1ff & info->rew_op) << 21); ifh[1] = (0xf00 & info->port) >> 8; @@ -597,7 +597,7 @@ EXPORT_SYMBOL(ocelot_can_inject); void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp, u32 rew_op, struct sk_buff *skb) { - struct frame_info info = {}; + struct ocelot_frame_info info = {}; u32 ifh[OCELOT_TAG_LEN / 4]; unsigned int i, count, last; diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h index e8621dbc14f7..4585e5c5d9cb 100644 --- a/drivers/net/ethernet/mscc/ocelot.h +++ b/drivers/net/ethernet/mscc/ocelot.h @@ -32,15 +32,6 @@ #define OCELOT_PTP_QUEUE_SZ 128 -struct frame_info { - u32 len; - u16 port; - u16 vid; - u8 tag_type; - u16 rew_op; - u32 timestamp; /* rew_val */ -}; - struct ocelot_port_tc { bool block_shared; unsigned long offload_cnt; diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 4bd3b59eba1b..f07170ce76d9 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -532,7 +532,7 @@ static int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops) return 0; } -static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info) +static int ocelot_parse_ifh(u32 *_ifh, struct ocelot_frame_info *info) { u8 llen, wlen; u64 ifh[2]; @@ -606,10 +606,10 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) { struct skb_shared_hwtstamps *shhwtstamps; + struct ocelot_frame_info info = {}; struct ocelot_port_private *priv; struct ocelot_port *ocelot_port; u64 tod_in_ns, full_ts_in_ns; - struct frame_info info = {}; struct net_device *dev; u32 ifh[4], val, *buf; struct timespec64 ts; diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index eb81d05da134..d7169c56a64a 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -688,6 +688,15 @@ struct ocelot_policer { u32 burst; /* bytes */ }; +struct ocelot_frame_info { + u32 len; + u16 port; + u16 vid; + u8 tag_type; + u16 rew_op; + u32 timestamp; /* rew_val */ +}; + #define ocelot_read_ix(ocelot, reg, gi, ri) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri)) #define ocelot_read_gix(ocelot, reg, gi) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi)) #define ocelot_read_rix(ocelot, reg, ri) __ocelot_read_ix(ocelot, reg, reg##_RSZ * (ri)) From patchwork Tue Jan 19 23:07:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031025 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 558A3C433E0 for ; Tue, 19 Jan 2021 23:12:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1520922CAD for ; Tue, 19 Jan 2021 23:12:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730390AbhASXML (ORCPT ); Tue, 19 Jan 2021 18:12:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52290 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728939AbhASXJb (ORCPT ); Tue, 19 Jan 2021 18:09:31 -0500 Received: from mail-ej1-x633.google.com (mail-ej1-x633.google.com [IPv6:2a00:1450:4864:20::633]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 13961C06179B for ; Tue, 19 Jan 2021 15:08:22 -0800 (PST) Received: by mail-ej1-x633.google.com with SMTP id gx5so11659862ejb.7 for ; Tue, 19 Jan 2021 15:08:22 -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=P7kKL/+OugUcx6LWIDz42GgrMBWAikE8exfiS6P1fL0=; b=QYjsbfiCE46RDvx6Zg29KC/WYQSG0Bcd4eP6X/DRU4dN5RwUO81fOgtIgUkLDEDpg/ q45y2fQtZn+9SGDB/uIACvXo8K4yhzYrAGMa4WW+IlAI/P6MzA0wDmHuzFa/x7gCvdIh 1cgL/hYS7X6ZlIt18cQ5OgLDIVG54iLzj9cNxcESAn0uNsoEHrU3aqUHzf2HeeKNSBng ddfkVEAW44LAAkQuvJBsMEP5gASq4EQwtbfSkUxyIv0JbjkKK4AXwRM4c6m3CR4CwvbI MdGObEiqPBh9IWqg/N061nnDsCPhgzp0HuBjVVAQpu7bymyiXotV6Kl4quCyE1bzJO8G Oy8g== 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=P7kKL/+OugUcx6LWIDz42GgrMBWAikE8exfiS6P1fL0=; b=RfofEUlG8Ow5DG6QOv7A2LhqLawy3Avu7630MP6o7+VuNBAHt+mSMNB4QR99njRZLj KDeSIm3VTq60xDOWH3/taIxMlelZNmUY8K7S2b9O+/4mIbGQIpBz0LSQtp7kT61OLY/z ZMj1ZGisK+vk5pWCr7eR9Gitwa7qLdPck2Glc94rgNrKn2g+jsHu1jm7topPByxS6+Kg Nbu/v2GqFnvYYAa5JJpPHhn7p7fx9rAwn4VYsxdYveg5QVIUy9Bczn5SfxiCRaYLJp1r 8ejLwVKn71Pl96xxpMk3uABrL/kCzkl5XFB4ZB8pVvRLD39b51DoPCFVLIO+UpF3S9wp wC1Q== X-Gm-Message-State: AOAM530X0IUmPUWc4pcE+3qFu38xV5hdpFclER/MU7C30zFgvsOCWW3P yZ+5DigN4vY4ODc+2NOQoEw= X-Google-Smtp-Source: ABdhPJw9zFHCg5N5ffr/BV5TslKWwZWluscKMt4z6JbYuPLfm4gkXIx9lQYFF/LP20M5gsmUZuDa8w== X-Received: by 2002:a17:906:eca7:: with SMTP id qh7mr4453069ejb.437.1611097700765; Tue, 19 Jan 2021 15:08:20 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:20 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 14/16] net: mscc: ocelot: refactor ocelot_xtr_irq_handler into ocelot_xtr_poll Date: Wed, 20 Jan 2021 01:07:47 +0200 Message-Id: <20210119230749.1178874-15-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 Since the felix DSA driver will need to poll the CPU port module for extracted frames as well, let's create some common functions that read an Extraction Frame Header, and then an skb, from a CPU extraction group. This is so complicated, because the procedure to retrieve a struct net_device pointer based on the source port is different for DSA and switchdev. So this is the reason why the polling function is split in the middle. The ocelot_xtr_poll_xfh() permits the caller to get a struct net_device pointer based on the XFH port field, then pass this to the ocelot_xtr_poll_frame() function. Signed-off-by: Vladimir Oltean --- Changes in v4: Add the missing EXPORT_SYMBOL bits. Changes in v3: None. Changes in v2: Patch is new. drivers/net/ethernet/mscc/ocelot.c | 165 +++++++++++++++++++++ drivers/net/ethernet/mscc/ocelot_vsc7514.c | 158 ++------------------ include/soc/mscc/ocelot.h | 6 + 3 files changed, 181 insertions(+), 148 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index adebec0be684..25f51b82e1b8 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -12,6 +12,9 @@ #define TABLE_UPDATE_SLEEP_US 10 #define TABLE_UPDATE_TIMEOUT_US 100000 +#define IFH_EXTRACT_BITFIELD64(x, o, w) \ + (((x) >> (o)) & GENMASK_ULL((w) - 1, 0)) + struct ocelot_mact_entry { u8 mac[ETH_ALEN]; u16 vid; @@ -561,6 +564,168 @@ void ocelot_get_txtstamp(struct ocelot *ocelot) } EXPORT_SYMBOL(ocelot_get_txtstamp); +static int ocelot_parse_xfh(u32 *_ifh, struct ocelot_frame_info *info) +{ + u8 llen, wlen; + u64 ifh[2]; + + ifh[0] = be64_to_cpu(((__force __be64 *)_ifh)[0]); + ifh[1] = be64_to_cpu(((__force __be64 *)_ifh)[1]); + + wlen = IFH_EXTRACT_BITFIELD64(ifh[0], 7, 8); + llen = IFH_EXTRACT_BITFIELD64(ifh[0], 15, 6); + + info->len = OCELOT_BUFFER_CELL_SZ * wlen + llen - 80; + + info->timestamp = IFH_EXTRACT_BITFIELD64(ifh[0], 21, 32); + + info->port = IFH_EXTRACT_BITFIELD64(ifh[1], 43, 4); + + info->tag_type = IFH_EXTRACT_BITFIELD64(ifh[1], 16, 1); + info->vid = IFH_EXTRACT_BITFIELD64(ifh[1], 0, 12); + + return 0; +} + +static int ocelot_rx_frame_word(struct ocelot *ocelot, u8 grp, bool ifh, + u32 *rval) +{ + u32 val; + u32 bytes_valid; + + val = ocelot_read_rix(ocelot, QS_XTR_RD, grp); + if (val == XTR_NOT_READY) { + if (ifh) + return -EIO; + + do { + val = ocelot_read_rix(ocelot, QS_XTR_RD, grp); + } while (val == XTR_NOT_READY); + } + + switch (val) { + case XTR_ABORT: + return -EIO; + case XTR_EOF_0: + case XTR_EOF_1: + case XTR_EOF_2: + case XTR_EOF_3: + case XTR_PRUNED: + bytes_valid = XTR_VALID_BYTES(val); + val = ocelot_read_rix(ocelot, QS_XTR_RD, grp); + if (val == XTR_ESCAPE) + *rval = ocelot_read_rix(ocelot, QS_XTR_RD, grp); + else + *rval = val; + + return bytes_valid; + case XTR_ESCAPE: + *rval = ocelot_read_rix(ocelot, QS_XTR_RD, grp); + + return 4; + default: + *rval = val; + + return 4; + } +} + +int ocelot_xtr_poll_xfh(struct ocelot *ocelot, int grp, + struct ocelot_frame_info *info) +{ + u32 ifh[OCELOT_TAG_LEN / 4]; + int i, err = 0; + + for (i = 0; i < OCELOT_TAG_LEN / 4; i++) { + err = ocelot_rx_frame_word(ocelot, grp, true, &ifh[i]); + if (err != 4) + return (err < 0) ? err : -EIO; + } + + ocelot_parse_xfh(ifh, info); + + return 0; +} +EXPORT_SYMBOL(ocelot_xtr_poll_xfh); + +int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, + struct net_device *dev, + struct ocelot_frame_info *info, + struct sk_buff **nskb) +{ + struct skb_shared_hwtstamps *shhwtstamps; + u64 tod_in_ns, full_ts_in_ns; + struct timespec64 ts; + int sz, len, buf_len; + struct sk_buff *skb; + u32 val, *buf; + int err = 0; + + skb = netdev_alloc_skb(dev, info->len); + if (unlikely(!skb)) { + netdev_err(dev, "Unable to allocate sk_buff\n"); + err = -ENOMEM; + goto out; + } + + buf_len = info->len - ETH_FCS_LEN; + buf = (u32 *)skb_put(skb, buf_len); + + len = 0; + do { + sz = ocelot_rx_frame_word(ocelot, grp, false, &val); + if (sz < 0) { + err = sz; + goto out; + } + *buf++ = val; + len += sz; + } while (len < buf_len); + + /* Read the FCS */ + sz = ocelot_rx_frame_word(ocelot, grp, false, &val); + if (sz < 0) { + err = sz; + goto out; + } + + /* Update the statistics if part of the FCS was read before */ + len -= ETH_FCS_LEN - sz; + + if (unlikely(dev->features & NETIF_F_RXFCS)) { + buf = (u32 *)skb_put(skb, ETH_FCS_LEN); + *buf = val; + } + + if (ocelot->ptp) { + ocelot_ptp_gettime64(&ocelot->ptp_info, &ts); + + tod_in_ns = ktime_set(ts.tv_sec, ts.tv_nsec); + if ((tod_in_ns & 0xffffffff) < info->timestamp) + full_ts_in_ns = (((tod_in_ns >> 32) - 1) << 32) | + info->timestamp; + else + full_ts_in_ns = (tod_in_ns & GENMASK_ULL(63, 32)) | + info->timestamp; + + shhwtstamps = skb_hwtstamps(skb); + memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); + shhwtstamps->hwtstamp = full_ts_in_ns; + } + + /* Everything we see on an interface that is in the HW bridge + * has already been forwarded. + */ + if (ocelot->bridge_mask & BIT(info->port)) + skb->offload_fwd_mark = 1; + + skb->protocol = eth_type_trans(skb, dev); + *nskb = skb; +out: + return err; +} +EXPORT_SYMBOL(ocelot_xtr_poll_frame); + /* Generate the IFH for frame injection * * The IFH is a 128bit-value diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index f07170ce76d9..317ee2395b89 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -18,8 +18,6 @@ #include #include "ocelot.h" -#define IFH_EXTRACT_BITFIELD64(x, o, w) (((x) >> (o)) & GENMASK_ULL((w) - 1, 0)) - static const u32 ocelot_ana_regmap[] = { REG(ANA_ADVLEARN, 0x009000), REG(ANA_VLANMASK, 0x009004), @@ -532,173 +530,37 @@ static int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops) return 0; } -static int ocelot_parse_ifh(u32 *_ifh, struct ocelot_frame_info *info) -{ - u8 llen, wlen; - u64 ifh[2]; - - ifh[0] = be64_to_cpu(((__force __be64 *)_ifh)[0]); - ifh[1] = be64_to_cpu(((__force __be64 *)_ifh)[1]); - - wlen = IFH_EXTRACT_BITFIELD64(ifh[0], 7, 8); - llen = IFH_EXTRACT_BITFIELD64(ifh[0], 15, 6); - - info->len = OCELOT_BUFFER_CELL_SZ * wlen + llen - 80; - - info->timestamp = IFH_EXTRACT_BITFIELD64(ifh[0], 21, 32); - - info->port = IFH_EXTRACT_BITFIELD64(ifh[1], 43, 4); - - info->tag_type = IFH_EXTRACT_BITFIELD64(ifh[1], 16, 1); - info->vid = IFH_EXTRACT_BITFIELD64(ifh[1], 0, 12); - - return 0; -} - -static int ocelot_rx_frame_word(struct ocelot *ocelot, u8 grp, bool ifh, - u32 *rval) -{ - u32 val; - u32 bytes_valid; - - val = ocelot_read_rix(ocelot, QS_XTR_RD, grp); - if (val == XTR_NOT_READY) { - if (ifh) - return -EIO; - - do { - val = ocelot_read_rix(ocelot, QS_XTR_RD, grp); - } while (val == XTR_NOT_READY); - } - - switch (val) { - case XTR_ABORT: - return -EIO; - case XTR_EOF_0: - case XTR_EOF_1: - case XTR_EOF_2: - case XTR_EOF_3: - case XTR_PRUNED: - bytes_valid = XTR_VALID_BYTES(val); - val = ocelot_read_rix(ocelot, QS_XTR_RD, grp); - if (val == XTR_ESCAPE) - *rval = ocelot_read_rix(ocelot, QS_XTR_RD, grp); - else - *rval = val; - - return bytes_valid; - case XTR_ESCAPE: - *rval = ocelot_read_rix(ocelot, QS_XTR_RD, grp); - - return 4; - default: - *rval = val; - - return 4; - } -} - static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) { struct ocelot *ocelot = arg; - int i = 0, grp = 0; - int err = 0; + int grp = 0, err; while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) { - struct skb_shared_hwtstamps *shhwtstamps; struct ocelot_frame_info info = {}; struct ocelot_port_private *priv; struct ocelot_port *ocelot_port; - u64 tod_in_ns, full_ts_in_ns; struct net_device *dev; - u32 ifh[4], val, *buf; - struct timespec64 ts; - int sz, len, buf_len; struct sk_buff *skb; - for (i = 0; i < OCELOT_TAG_LEN / 4; i++) { - err = ocelot_rx_frame_word(ocelot, grp, true, &ifh[i]); - if (err != 4) - goto out; - } - - /* At this point the IFH was read correctly, so it is safe to - * presume that there is no error. The err needs to be reset - * otherwise a frame could come in CPU queue between the while - * condition and the check for error later on. And in that case - * the new frame is just removed and not processed. - */ - err = 0; + err = ocelot_xtr_poll_xfh(ocelot, grp, &info); + if (err) + break; - ocelot_parse_ifh(ifh, &info); + if (WARN_ON(info.port >= ocelot->num_phys_ports)) + goto out; ocelot_port = ocelot->ports[info.port]; priv = container_of(ocelot_port, struct ocelot_port_private, port); dev = priv->dev; - skb = netdev_alloc_skb(dev, info.len); - - if (unlikely(!skb)) { - netdev_err(dev, "Unable to allocate sk_buff\n"); - err = -ENOMEM; - goto out; - } - buf_len = info.len - ETH_FCS_LEN; - buf = (u32 *)skb_put(skb, buf_len); - - len = 0; - do { - sz = ocelot_rx_frame_word(ocelot, grp, false, &val); - if (sz < 0) { - err = sz; - goto out; - } - *buf++ = val; - len += sz; - } while (len < buf_len); - - /* Read the FCS */ - sz = ocelot_rx_frame_word(ocelot, grp, false, &val); - if (sz < 0) { - err = sz; - goto out; - } - - /* Update the statistics if part of the FCS was read before */ - len -= ETH_FCS_LEN - sz; - - if (unlikely(dev->features & NETIF_F_RXFCS)) { - buf = (u32 *)skb_put(skb, ETH_FCS_LEN); - *buf = val; - } - - if (ocelot->ptp) { - ocelot_ptp_gettime64(&ocelot->ptp_info, &ts); - - tod_in_ns = ktime_set(ts.tv_sec, ts.tv_nsec); - if ((tod_in_ns & 0xffffffff) < info.timestamp) - full_ts_in_ns = (((tod_in_ns >> 32) - 1) << 32) | - info.timestamp; - else - full_ts_in_ns = (tod_in_ns & GENMASK_ULL(63, 32)) | - info.timestamp; - - shhwtstamps = skb_hwtstamps(skb); - memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); - shhwtstamps->hwtstamp = full_ts_in_ns; - } - - /* Everything we see on an interface that is in the HW bridge - * has already been forwarded. - */ - if (ocelot->bridge_mask & BIT(info.port)) - skb->offload_fwd_mark = 1; + err = ocelot_xtr_poll_frame(ocelot, grp, dev, &info, &skb); + if (err) + break; - skb->protocol = eth_type_trans(skb, dev); if (!skb_defer_rx_timestamp(skb)) netif_rx(skb); - dev->stats.rx_bytes += len; + dev->stats.rx_bytes += info.len; dev->stats.rx_packets++; } diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index d7169c56a64a..3036ffc6b79d 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -844,5 +844,11 @@ int ocelot_sb_occ_tc_port_bind_get(struct ocelot *ocelot, int port, bool ocelot_can_inject(struct ocelot *ocelot, int grp); void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp, u32 rew_op, struct sk_buff *skb); +int ocelot_xtr_poll_xfh(struct ocelot *ocelot, int grp, + struct ocelot_frame_info *info); +int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, + struct net_device *dev, + struct ocelot_frame_info *info, + struct sk_buff **skb); #endif From patchwork Tue Jan 19 23:07:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031015 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9752FC433DB for ; Tue, 19 Jan 2021 23:10:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 622FF23108 for ; Tue, 19 Jan 2021 23:10:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729500AbhASXJz (ORCPT ); Tue, 19 Jan 2021 18:09:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52110 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727874AbhASXJH (ORCPT ); Tue, 19 Jan 2021 18:09:07 -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 99AA2C06179C for ; Tue, 19 Jan 2021 15:08:23 -0800 (PST) Received: by mail-ed1-x52b.google.com with SMTP id d22so12550294edy.1 for ; Tue, 19 Jan 2021 15:08:23 -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=LyxXxRvUi0bAhOVvWuRP0bt/YzjpiLdip9bHEJV8C+U=; b=uq4tuAZpesYvLbyALjIIVFU8pwdB8e9dEXffFz8ylANfdWBSrwhws7z/hHDVuYvl6a EvuDX2W46DsHn6f5dS2hnPKwy6jnF6pVgyZK6tHFW0f/RFG8VExvRFd7+g/HThwP8xeI lA+fKfZXJMuSBP3qep/DgCWLAkd7b4MVC63LK1KKTPBrJWS8hqIy355q5/jSV4U61oWO i38gcNdhXuuaGGGXD7APanpnsYs6Ij3OYFVRTH6n1iN8oyQ0DoMuq0cwtSROTsO+NuGv CQOLLlwuVrT3bqGZpWwCQ89+q1nzgqxi5E6fddbV6odRo1dPHSBqfeG31JXxCiAubqIF nhLA== 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=LyxXxRvUi0bAhOVvWuRP0bt/YzjpiLdip9bHEJV8C+U=; b=s5K7QgRo7W+2DU1iXZJy+1z3i4ou63KoDIiecd8NsKSNQ/mVwPwhR4r8ECUPt0b7jx fPCTx0NUh1KBYmq3d2nBswjyRspl6HDyyHLGmVxI9VtSqS5Mn4QvnwlYaBRq9lPSmy2M 72k6qhY4Z1S6w1NQSBKNsr1LGadhOppvbghj6NmCaGi5eEC5obouSXOQx2cfV8bbmXZE YHpU5LMdZuVuNwN3gizcByOuga6Q2njQ14EtuJ7mTf5JrCg0iVOi42XkFSNkqRXv20tD FktTK3RPwd3FNnX7lnNZP5IXPatIOGCs33SOfDgXl2bgbxZzDGLQczQgxTMcq1taSv5Y deCw== X-Gm-Message-State: AOAM532XPrpHsG0vQ2G4Fy3a+Wpm1gQvSAjmKhie7fuD8Z/DtXpfEimr 8JaROHByjyggQaSmjvBTswU= X-Google-Smtp-Source: ABdhPJwPBYRMZy4KmKPYGRMR/0H5d5lvLEHyJ/xPqdTscV8wYQoaJOfsudjVM5j4Ufpy/A6vZSxGlA== X-Received: by 2002:a05:6402:34c5:: with SMTP id w5mr5227889edc.65.1611097702242; Tue, 19 Jan 2021 15:08:22 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:21 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 15/16] net: dsa: felix: setup MMIO filtering rules for PTP when using tag_8021q Date: Wed, 20 Jan 2021 01:07:48 +0200 Message-Id: <20210119230749.1178874-16-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 Since the tag_8021q tagger is software-defined, it has no means by itself for retrieving hardware timestamps of PTP event messages. Because we do want to support PTP on ocelot even with tag_8021q, we need to use the CPU port module for that. The RX timestamp is present in the Extraction Frame Header. And because we can't use NPI mode which redirects the CPU queues to an "external CPU" (meaning the ARM CPU running Linux), then we need to poll the CPU port module through the MMIO registers to retrieve TX and RX timestamps. Sadly, on NXP LS1028A, the Felix switch was integrated into the SoC without wiring the extraction IRQ line to the ARM GIC. So, if we want to be notified of any PTP packets received on the CPU port module, we have a problem. There is a possible workaround, which is to use the Ethernet CPU port as a notification channel that packets are available on the CPU port module as well. When a PTP packet is received by the DSA tagger (without timestamp, of course), we go to the CPU extraction queues, poll for it there, then we drop the original Ethernet packet and masquerade the packet retrieved over MMIO (plus the timestamp) as the original when we inject it up the stack. Create a quirk in struct felix is selected by the Felix driver (but not by Seville, since that doesn't support PTP at all). We want to do this such that the workaround is minimally invasive for future switches that don't require this workaround. The only traffic for which we need timestamps is PTP traffic, so add a redirection rule to the CPU port module for this. Currently we only have the need for PTP over L2, so redirection rules for UDP ports 319 and 320 are TBD for now. Note that for the workaround of matching of PTP-over-Ethernet-port with PTP-over-MMIO queues to work properly, both channels need to be absolutely lossless. There are two parts to achieving that: - We keep flow control enabled on the tag_8021q CPU port - We put the DSA master interface in promiscuous mode, so it will never drop a PTP frame (for the profiles we are interested in, these are sent to the multicast MAC addresses of 01-80-c2-00-00-0e and 01-1b-19-00-00-00). Signed-off-by: Vladimir Oltean Reported-by: kernel test robot --- Changes in v4: - Actually perform teardown. - Squash with next one-line patch "net: dsa: felix: use promisc on master for PTP with tag_8021q". Changes in v3: Make as much use as possible of dsa_is_cpu_port and dsa_upstream_port as possible instead of ocelot->dsa_8021q_cpu. Changes in v2: Patch is new. drivers/net/dsa/ocelot/felix.c | 127 ++++++++++++++++++++++++- drivers/net/dsa/ocelot/felix.h | 13 +++ drivers/net/dsa/ocelot/felix_vsc9959.c | 1 + net/dsa/tag_ocelot_8021q.c | 1 + 4 files changed, 138 insertions(+), 4 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index df43f4a40f83..cb05d795ef05 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -231,6 +231,120 @@ static const struct dsa_8021q_ops felix_tag_8021q_ops = { .vlan_del = felix_tag_8021q_vlan_del, }; +/* Set up a VCAP IS2 rule for delivering PTP frames to the CPU port module. + * If the quirk_no_xtr_irq is in place, then also copy those PTP frames to the + * tag_8021q CPU port. + */ +static int felix_setup_mmio_filtering(struct felix *felix) +{ + unsigned long user_ports = 0, cpu_ports = 0; + struct ocelot_vcap_filter *redirect_rule; + struct ocelot_vcap_filter *tagging_rule; + struct ocelot *ocelot = &felix->ocelot; + struct dsa_switch *ds = felix->ds; + int port, ret; + + tagging_rule = kzalloc(sizeof(struct ocelot_vcap_filter), GFP_KERNEL); + if (!tagging_rule) + return -ENOMEM; + + redirect_rule = kzalloc(sizeof(struct ocelot_vcap_filter), GFP_KERNEL); + if (!redirect_rule) { + kfree(tagging_rule); + return -ENOMEM; + } + + for (port = 0; port < ocelot->num_phys_ports; port++) { + if (dsa_is_user_port(ds, port)) + user_ports |= BIT(port); + if (dsa_is_cpu_port(ds, port)) + cpu_ports |= BIT(port); + } + + tagging_rule->key_type = OCELOT_VCAP_KEY_ETYPE; + *(u16 *)tagging_rule->key.etype.etype.value = htons(ETH_P_1588); + *(u16 *)tagging_rule->key.etype.etype.mask = 0xffff; + tagging_rule->ingress_port_mask = user_ports; + tagging_rule->prio = 1; + tagging_rule->id.cookie = ocelot->num_phys_ports; + tagging_rule->id.tc_offload = false; + tagging_rule->block_id = VCAP_IS1; + tagging_rule->type = OCELOT_VCAP_FILTER_OFFLOAD; + tagging_rule->lookup = 0; + tagging_rule->action.pag_override_mask = 0xff; + tagging_rule->action.pag_val = ocelot->num_phys_ports; + + ret = ocelot_vcap_filter_add(ocelot, tagging_rule, NULL); + if (ret) { + kfree(tagging_rule); + kfree(redirect_rule); + return ret; + } + + redirect_rule->key_type = OCELOT_VCAP_KEY_ANY; + redirect_rule->ingress_port_mask = user_ports; + redirect_rule->pag = ocelot->num_phys_ports; + redirect_rule->prio = 1; + redirect_rule->id.cookie = ocelot->num_phys_ports; + 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.cpu_copy_ena = true; + if (felix->info->quirk_no_xtr_irq) { + /* Redirect to the tag_8021q CPU but also copy PTP packets to + * the CPU port module + */ + redirect_rule->action.mask_mode = OCELOT_MASK_MODE_REDIRECT; + redirect_rule->action.port_mask = cpu_ports; + } else { + /* Trap PTP packets only to the CPU port module (which is + * redirected to the NPI port) + */ + redirect_rule->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY; + redirect_rule->action.port_mask = 0; + } + + ret = ocelot_vcap_filter_add(ocelot, redirect_rule, NULL); + if (ret) { + ocelot_vcap_filter_del(ocelot, tagging_rule); + kfree(redirect_rule); + return ret; + } + + return 0; +} + +static int felix_teardown_mmio_filtering(struct felix *felix) +{ + struct ocelot_vcap_filter *tagging_rule, *redirect_rule; + struct ocelot_vcap_block *block_vcap_is1; + struct ocelot_vcap_block *block_vcap_is2; + struct ocelot *ocelot = &felix->ocelot; + int err; + + block_vcap_is1 = &ocelot->block[VCAP_IS1]; + block_vcap_is2 = &ocelot->block[VCAP_IS2]; + + tagging_rule = ocelot_vcap_block_find_filter_by_id(block_vcap_is1, + ocelot->num_phys_ports, + false); + if (!tagging_rule) + return -ENOENT; + + err = ocelot_vcap_filter_del(ocelot, tagging_rule); + if (err) + return err; + + redirect_rule = ocelot_vcap_block_find_filter_by_id(block_vcap_is2, + ocelot->num_phys_ports, + false); + if (!redirect_rule) + return -ENOENT; + + return ocelot_vcap_filter_del(ocelot, redirect_rule); +} + static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds, int port, enum dsa_tag_protocol mp) @@ -370,9 +484,9 @@ static int felix_setup_tag_8021q(struct dsa_switch *ds, int cpu) 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. + /* In tag_8021q mode, the CPU port module is unused, except for PTP + * frames. 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); @@ -393,7 +507,7 @@ static int felix_setup_tag_8021q(struct dsa_switch *ds, int cpu) err = dsa_8021q_setup(felix->dsa_8021q_ctx, true); rtnl_unlock(); - return err; + return felix_setup_mmio_filtering(felix); } static void felix_teardown_tag_8021q(struct dsa_switch *ds, int cpu) @@ -402,6 +516,11 @@ static void felix_teardown_tag_8021q(struct dsa_switch *ds, int cpu) struct felix *felix = ocelot_to_felix(ocelot); int err, port; + err = felix_teardown_mmio_filtering(felix); + if (err) + dev_err(ds->dev, "felix_teardown_mmio_filtering returned %d", + err); + rtnl_lock(); err = dsa_8021q_setup(felix->dsa_8021q_ctx, false); rtnl_unlock(); diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 9d4459f2fffb..eb85eac361db 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -23,6 +23,19 @@ struct felix_info { int switch_pci_bar; int imdio_pci_bar; const struct ptp_clock_info *ptp_caps; + + /* Some Ocelot switches are integrated into the SoC without the + * extraction IRQ line connected to the ARM GIC. By enabling this + * workaround, the few packets that are delivered to the CPU port + * module (currently only PTP) are copied not only to the hardware CPU + * port module, but also to the 802.1Q Ethernet CPU port, and polling + * the extraction registers is triggered once the DSA tagger sees a PTP + * frame. The Ethernet frame is only used as a notification: it is + * dropped, and the original frame is extracted over MMIO and annotated + * with the RX timestamp. + */ + bool quirk_no_xtr_irq; + int (*mdio_bus_alloc)(struct ocelot *ocelot); void (*mdio_bus_free)(struct ocelot *ocelot); void (*phylink_validate)(struct ocelot *ocelot, int port, diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index e944868cc120..38224c0169c0 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1379,6 +1379,7 @@ static const struct felix_info felix_info_vsc9959 = { .num_tx_queues = OCELOT_NUM_TC, .switch_pci_bar = 4, .imdio_pci_bar = 0, + .quirk_no_xtr_irq = true, .ptp_caps = &vsc9959_ptp_caps, .mdio_bus_alloc = vsc9959_mdio_bus_alloc, .mdio_bus_free = vsc9959_mdio_bus_free, diff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c index 09e10ade11f7..7bd45b66e9a4 100644 --- a/net/dsa/tag_ocelot_8021q.c +++ b/net/dsa/tag_ocelot_8021q.c @@ -60,6 +60,7 @@ static struct dsa_device_ops ocelot_netdev_ops = { .xmit = ocelot_xmit, .rcv = ocelot_rcv, .overhead = VLAN_HLEN, + .promisc_on_master = true, }; MODULE_LICENSE("GPL v2"); From patchwork Tue Jan 19 23:07:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12031019 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.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 65ADFC433DB for ; Tue, 19 Jan 2021 23:11:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3AAF922D08 for ; Tue, 19 Jan 2021 23:11:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729694AbhASXKy (ORCPT ); Tue, 19 Jan 2021 18:10:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52300 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729254AbhASXJc (ORCPT ); Tue, 19 Jan 2021 18:09:32 -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 0F8CAC06179E for ; Tue, 19 Jan 2021 15:08:25 -0800 (PST) Received: by mail-ed1-x533.google.com with SMTP id g24so23504507edw.9 for ; Tue, 19 Jan 2021 15:08:24 -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=fgm6ZOMHI0u+kF/ZGYnyPYnDY+w03WpGr5j5FQOeS54=; b=MM9BSQuoKwYMbPvxdjLFFChnDbQcdOWGg1eEMvib04uQtPCu6jhBlse/CmhokNsXKc BmYUzhB+EDc0qJ0at8nJeVVILfskuqodh1cJh+Zyd9un0Wb44OurejX3uI8dU9YQLz51 /LxckCJM+vc+cSAjv7Ro3xieiC6oiUW3J/C/OFchYFHgzM1tTKvgQos9HUy8/CWUKkMU rQGM8easVCIU6/IBRSSzwbBEtFfGohM0S/wzXCUvNmW887j7xZD3SBkViWJGzneHAaFo HsIc0Tvawtpkta50EkvYh3dboxgzjsJIMrz+I2EtXRRQnkK6P7B1dRG645ebroNW31+W S0/g== 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=fgm6ZOMHI0u+kF/ZGYnyPYnDY+w03WpGr5j5FQOeS54=; b=gqLgbzCTm6aGwTPP9YFhJ/InCy/7EgxD5tRm5f9ZjwkqiccD3aTJiOU+8nCVjTcOUG RPHG9oy1ys1CdaTbUmRIl7UMXBccu31eKx3FkQR7Dt9EJb9dNnGTnrBLFZ+2leghKil+ xVxs2TyArH15EcfAOZMCKOY5055sUkwbYqtpjVDPt13oTphgEWk4JA7CS4GI+1KygYKU WQ20rKbbZQi8qYHbEb2k3BxPz2am+Sfx3SRWn2L+JgbfNVcy/n3BhPFIYWf9zakd8H8r /UbZ3204pA5YLuH8VCu2HBBB43GDm+A+RoedJoWICbgG/TEW6WV4Ek+HO/NBnUZW2B3Y 4xUg== X-Gm-Message-State: AOAM533LABNRoT+wfGIJj3iEiXEeuNDyEo8mrNMkQd5yKdrVKUMJgBKL N4M6k4VTIrm4drfg5LIv6zo= X-Google-Smtp-Source: ABdhPJx8Af4rsQA0ovCbGtzuRd2o8ZVkyxvIDgcKVtob3LiPxs4o4VVBPK9Lst70KQdNKf8xtUix2w== X-Received: by 2002:a05:6402:4242:: with SMTP id g2mr5237032edb.103.1611097703740; Tue, 19 Jan 2021 15:08:23 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id lh26sm94197ejb.119.2021.01.19.15.08.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 15:08:23 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Andrew Lunn , Florian Fainelli , Vivien Didelot , Richard Cochran , Claudiu Manoil , Alexandru Marginean , Alexandre Belloni , Xiaoliang Yang , Hongbo Wang , Vladimir Oltean , Po Liu , Yangbo Lu , Maxim Kochetkov , Eldar Gasanov , Andrey L , UNGLinuxDriver@microchip.com Subject: [PATCH v4 net-next 16/16] net: dsa: tag_ocelot_8021q: add support for PTP timestamping Date: Wed, 20 Jan 2021 01:07:49 +0200 Message-Id: <20210119230749.1178874-17-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210119230749.1178874-1-olteanv@gmail.com> References: <20210119230749.1178874-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 On TX, use the result of the ptp_classify_raw() BPF classifier from dsa_skb_tx_timestamp() to divert some frames over to the MMIO-based injection registers. On RX, set up a VCAP IS2 rule that redirects the frames with an EtherType for 1588 to the CPU port module (for MMIO based extraction) and, if the "no XTR IRQ" workaround is in place, copies them to the dsa_8021q CPU port as well (for notification). There is a conflict between the VCAP IS2 trapping rule and the semantics of the BPF classifier. Namely, ptp_classify_raw() deems general messages as non-timestampable, but still, those are trapped to the CPU port module since they have an EtherType of ETH_P_1588. So, if the "no XTR IRQ" workaround is in place, we need to run another BPF classifier on the frames extracted over MMIO, to avoid duplicates being sent to the stack (once over Ethernet, once over MMIO). It doesn't look like it's possible to install VCAP IS2 rules based on keys extracted from the 1588 frame headers. Signed-off-by: Vladimir Oltean --- Changes in v4: Now draining the CPU queues by continuously reading QS_XTR_READ, same as Ocelot, instead of one-time asserting QS_XTR_FLUSH, which actually needed a sleep to be effective. Changes in v3: None. Changes in v2: Patch is new. drivers/net/dsa/ocelot/felix.c | 81 ++++++++++++++++++++++ drivers/net/ethernet/mscc/ocelot.c | 7 ++ drivers/net/ethernet/mscc/ocelot_vsc7514.c | 3 +- include/soc/mscc/ocelot.h | 1 + net/dsa/tag_ocelot_8021q.c | 24 +++++++ 5 files changed, 114 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index cb05d795ef05..72ab34194897 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -312,6 +313,15 @@ static int felix_setup_mmio_filtering(struct felix *felix) return ret; } + /* The ownership of the CPU port module's queues might have just been + * transferred to the tag_8021q tagger from the NPI-based tagger. + * So there might still be all sorts of crap in the queues. On the + * other hand, the MMIO-based matching of PTP frames is very brittle, + * so we need to be careful that there are no extra frames to be + * dequeued over MMIO, since we would never know to discard them. + */ + ocelot_drain_cpu_queue(ocelot, 0); + return 0; } @@ -1159,6 +1169,67 @@ static int felix_hwtstamp_set(struct dsa_switch *ds, int port, return ocelot_hwstamp_set(ocelot, port, ifr); } +static bool felix_check_xtr_pkt(struct ocelot *ocelot, unsigned int ptp_type) +{ + struct felix *felix = ocelot_to_felix(ocelot); + int err, grp = 0; + + if (felix->tag_proto == DSA_TAG_PROTO_OCELOT) + return false; + + if (!felix->info->quirk_no_xtr_irq) + return false; + + if (ptp_type == PTP_CLASS_NONE) + return false; + + while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) { + struct ocelot_frame_info info = {}; + struct dsa_port *dp; + struct sk_buff *skb; + unsigned int type; + + err = ocelot_xtr_poll_xfh(ocelot, grp, &info); + if (err) + break; + + if (WARN_ON(info.port >= ocelot->num_phys_ports)) + goto out; + + dp = dsa_to_port(felix->ds, info.port); + + err = ocelot_xtr_poll_frame(ocelot, grp, dp->slave, + &info, &skb); + if (err) + break; + + /* We trap to the CPU port module all PTP frames, but + * felix_rxtstamp() only gets called for event frames. + * So we need to avoid sending duplicate general + * message frames by running a second BPF classifier + * here and dropping those. + */ + __skb_push(skb, ETH_HLEN); + + type = ptp_classify_raw(skb); + + __skb_pull(skb, ETH_HLEN); + + if (type == PTP_CLASS_NONE) { + kfree_skb(skb); + continue; + } + + netif_rx(skb); + } + +out: + if (err < 0) + ocelot_drain_cpu_queue(ocelot, 0); + + return true; +} + static bool felix_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb, unsigned int type) { @@ -1169,6 +1240,16 @@ static bool felix_rxtstamp(struct dsa_switch *ds, int port, struct timespec64 ts; u64 tstamp, val; + /* If the "no XTR IRQ" workaround is in use, tell DSA to defer this skb + * for RX timestamping. Then free it, and poll for its copy through + * MMIO in the CPU port module, and inject that into the stack from + * ocelot_xtr_poll(). + */ + if (felix_check_xtr_pkt(ocelot, type)) { + kfree_skb(skb); + return true; + } + ocelot_ptp_gettime64(&ocelot->ptp_info, &ts); tstamp = ktime_set(ts.tv_sec, ts.tv_nsec); diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 25f51b82e1b8..f41fa0a8e883 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -806,6 +806,13 @@ void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp, } EXPORT_SYMBOL(ocelot_port_inject_frame); +void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp) +{ + while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) + ocelot_read_rix(ocelot, QS_XTR_RD, grp); +} +EXPORT_SYMBOL(ocelot_drain_cpu_queue); + int ocelot_fdb_add(struct ocelot *ocelot, int port, const unsigned char *addr, u16 vid) { diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 317ee2395b89..1e56d12deb0e 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -566,8 +566,7 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) out: if (err < 0) - while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) - ocelot_read_rix(ocelot, QS_XTR_RD, grp); + ocelot_drain_cpu_queue(ocelot, 0); return IRQ_HANDLED; } diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 3036ffc6b79d..2a115e7b4610 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -850,5 +850,6 @@ int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, struct net_device *dev, struct ocelot_frame_info *info, struct sk_buff **skb); +void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp); #endif diff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c index 7bd45b66e9a4..e6f2e7931efa 100644 --- a/net/dsa/tag_ocelot_8021q.c +++ b/net/dsa/tag_ocelot_8021q.c @@ -9,6 +9,8 @@ * that on egress */ #include +#include +#include #include "dsa_priv.h" static struct sk_buff *ocelot_xmit(struct sk_buff *skb, @@ -18,6 +20,28 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb, 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); + struct sk_buff *clone = DSA_SKB_CB(skb)->clone; + + /* TX timestamping was requested, so inject through MMIO */ + if (clone) { + struct ocelot *ocelot = dp->ds->priv; + struct ocelot_port *ocelot_port; + int port = dp->index; + u32 rew_op; + + ocelot_port = ocelot->ports[port]; + rew_op = ocelot_port->ptp_cmd; + + /* Retrieve timestamp ID populated inside skb->cb[0] of the + * clone by ocelot_port_add_txtstamp_skb + */ + if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) + rew_op |= clone->cb[0] << 3; + + ocelot_port_inject_frame(ocelot, dp->index, 0, rew_op, skb); + + return NULL; + } return dsa_8021q_xmit(skb, netdev, ETH_P_8021Q, ((pcp << VLAN_PRIO_SHIFT) | tx_vid));