From patchwork Sun May 10 16:42:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 219517 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=-9.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable 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 E61A7C54E4B for ; Sun, 10 May 2020 16:44:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C667720731 for ; Sun, 10 May 2020 16:44:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WDOd1kaF" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729385AbgEJQox (ORCPT ); Sun, 10 May 2020 12:44:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34828 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729057AbgEJQnc (ORCPT ); Sun, 10 May 2020 12:43:32 -0400 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D3B2CC061A0E; Sun, 10 May 2020 09:43:31 -0700 (PDT) Received: by mail-wm1-x344.google.com with SMTP id h4so15411882wmb.4; Sun, 10 May 2020 09:43:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=i3xdQfNNhGs9x7KATPUsqJauaICpGQwRxOGD+fuAb3E=; b=WDOd1kaFFfF1lWYkOl5N2PcGLxEpbfz7Esm+tYr4fNIZKYYKI0JOhhjTECCi7QjL4L 08Su9U7PR5HLZ4qojIQymZE7k/0yRKQCl7FVJhb9P79x/yueTtR1I808yr8YquSmP1tX wSsZgdns1vTP1pWWEOTyXRIIrUoN5qELGV2t/5enTI+MNU/qznCX4ZLwFfoTbcccnQNu ZcNb+xNnOjW4x3bjMfa9/ksBfxXAoHisxsdADVYZ35nVbTaXT96OVkgdtl6KwjYZPckw NdsOc1u+kqyfgcZab3saHgIXv+5vTA5VLzB1jSsyp4s+YRaRMsnozEMxtjm6Zt7y3N5q tkmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=i3xdQfNNhGs9x7KATPUsqJauaICpGQwRxOGD+fuAb3E=; b=rSTGcxm0+mJHt+4SUwIkDurgcsMCmK9gq0eovf10134etlzapMKX+OaUYS4sbqK5Zr ss9gfmfv/bLuF1k0VTYSgnJXIiZRlvSSEqntTCD6mjYhsRZpqzqqUzIDmSCb9dcebfnd uNd5la3yaDx7RNY854zElQcN8gRyaGOqi687J6w7Y7Wmwk4CY1ZwzCmTgwOaOKjVfggD c+dtIzHXXZqRIES0LrAgRrGrtVwtNonDxbvsb5tdCDRHAVUecKM+b0UkGqJEbY1b48+2 JCS4TSP3FJ8z9koly8aclXLUP7bbW/p91DE7J3jKF5u7JbyyEjyhR6dTtVws+OYc6+ed CJpQ== X-Gm-Message-State: AGi0PubSK/nHHNPcEGGTbB1wd1N4Bx1iOwPUWdFRkLOzSm3o8zLLIU6N HN0RnRfneFJ8mjY+KQmQo5XjZoUk X-Google-Smtp-Source: APiQypIEeFJc0XI3zCN/4DAndO81GyyjKAPeqV2gSbg+qYMYSWvIL/M3C690waMQ+nrRhSZBZl6iLw== X-Received: by 2002:a7b:cc83:: with SMTP id p3mr9078882wma.156.1589129010592; Sun, 10 May 2020 09:43:30 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:30 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 02/15] net: dsa: tag_8021q: introduce a vid_is_dsa_8021q helper Date: Sun, 10 May 2020 19:42:42 +0300 Message-Id: <20200510164255.19322-3-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean This function returns a boolean denoting whether the VLAN passed as argument is part of the 1024-3071 range that the dsa_8021q tagging scheme uses. Signed-off-by: Vladimir Oltean --- include/linux/dsa/8021q.h | 7 +++++++ net/dsa/tag_8021q.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/include/linux/dsa/8021q.h b/include/linux/dsa/8021q.h index b8daaec0896e..ebc245ff838a 100644 --- a/include/linux/dsa/8021q.h +++ b/include/linux/dsa/8021q.h @@ -50,6 +50,8 @@ int dsa_8021q_rx_switch_id(u16 vid); int dsa_8021q_rx_source_port(u16 vid); +bool vid_is_dsa_8021q(u16 vid); + #else int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int index, @@ -107,6 +109,11 @@ int dsa_8021q_rx_source_port(u16 vid) return 0; } +bool vid_is_dsa_8021q(u16 vid) +{ + return false; +} + #endif /* IS_ENABLED(CONFIG_NET_DSA_TAG_8021Q) */ #endif /* _NET_DSA_8021Q_H */ diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c index ff9c5bf64bda..4774ecd1f8fc 100644 --- a/net/dsa/tag_8021q.c +++ b/net/dsa/tag_8021q.c @@ -93,6 +93,13 @@ int dsa_8021q_rx_source_port(u16 vid) } EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port); +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); +} +EXPORT_SYMBOL_GPL(vid_is_dsa_8021q); + static int dsa_8021q_restore_pvid(struct dsa_switch *ds, int port) { struct bridge_vlan_info vinfo; From patchwork Sun May 10 16:42:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 219524 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=-9.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, 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 6B13BC54E4B for ; Sun, 10 May 2020 16:43:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4A0A620731 for ; Sun, 10 May 2020 16:43:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qmuC8DrO" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729144AbgEJQng (ORCPT ); Sun, 10 May 2020 12:43:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34834 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729124AbgEJQnd (ORCPT ); Sun, 10 May 2020 12:43:33 -0400 Received: from mail-wm1-x343.google.com (mail-wm1-x343.google.com [IPv6:2a00:1450:4864:20::343]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E643FC061A0C; Sun, 10 May 2020 09:43:32 -0700 (PDT) Received: by mail-wm1-x343.google.com with SMTP id g12so16295799wmh.3; Sun, 10 May 2020 09:43:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=S/ucj9FqaJZxqwK6ttNEH98kMzRsUXKRYHBKd01NMJ0=; b=qmuC8DrOSHDAALVQnKjGk39SZNRqnza6L0ea8eY8dl/g/XT06McJ2wGJxUkW2lvqRv zX7YdpS6aDg3Mx4FpRdvaSiYiYKY5SJ8r0lLHbqS2ZMNsER398QdyaxiY0qKrlegxCUm vqsVnYvgJGuxf0nlQVdA/IFGytgT+0hJ516TpfI7LZPhDfRa/qqf3tr2f3qhDqDQufSy ZvXUsajVF4xvji3QONCWgfyKwUkvrLR8tzUWpzGK7joCXp963sXPrceBe9BjFuTHbqYE C/Ip1tSsWdRJSYIx99XdA1dUXajyWwVo2jyYouwj8WmQVenSzjNnz3wawhGtxhsDIUIP Vl9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=S/ucj9FqaJZxqwK6ttNEH98kMzRsUXKRYHBKd01NMJ0=; b=H7MwZ5hFj4L8Fec34zNNiuyoFL3v9r0sCnT1ejUeiU3a3V9NvF2MVLzoKiGDJYYj21 ln+CW4oCyWOosfgjIyFv4t6cy/eK6Eaao01y8Yfjdjcpc25w4ODb772pKqBjiF4FHPSG Ca+l8zb+507+3OxTL1gaLTaFV5pMXFFVU45KYt1M4ZQVAUcu6GycoJKnDhsqycVKiY71 Eiw5fzTMui0T0aG2HuV5BQ5FWK3dSFwlamFUbGNv6/kuscezyLZwqKoOg68eoch8XkDw W547MJqBtVnPQ/zn5Qn/btVAJTSmrEKkG3eXu3gX3SCjgXwdbRJ3COgkvg1CEhKQ6jUl GMjw== X-Gm-Message-State: AGi0PuY7jSbzYOIs6bcviJuzAbAkpv0c6xPviSYM16pow1xSL/UB3yU1 //vPnHqdi2gML9EXJlg6FZQ= X-Google-Smtp-Source: APiQypLPuwUkRPgewra1ItZFSUUfJFbg+CHbvtR1qKra1pq50WTsDjHWt58lOp7rO4KbpLqZO8mSfw== X-Received: by 2002:a1c:7e4e:: with SMTP id z75mr22092030wmc.41.1589129011681; Sun, 10 May 2020 09:43:31 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:31 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 03/15] net: dsa: sja1105: keep the VLAN awareness state in a driver variable Date: Sun, 10 May 2020 19:42:43 +0300 Message-Id: <20200510164255.19322-4-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean Soon we'll add a third operating mode to the driver. Introduce a vlan_state to make things more easy to manage, and use it where applicable. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105.h | 6 ++++++ drivers/net/dsa/sja1105/sja1105_main.c | 16 ++++++++++++++++ include/linux/dsa/sja1105.h | 2 ++ net/dsa/tag_sja1105.c | 2 +- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index a64ace07b89f..5b2b275d01a7 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -178,6 +178,11 @@ struct sja1105_flow_block { int num_virtual_links; }; +enum sja1105_vlan_state { + SJA1105_VLAN_UNAWARE, + SJA1105_VLAN_FILTERING_FULL, +}; + struct sja1105_private { struct sja1105_static_config static_config; bool rgmii_rx_delay[SJA1105_NUM_PORTS]; @@ -193,6 +198,7 @@ struct sja1105_private { * the switch doesn't confuse them with one another. */ struct mutex mgmt_lock; + enum sja1105_vlan_state vlan_state; struct sja1105_tagger_data tagger_data; struct sja1105_ptp_data ptp_data; struct sja1105_tas_data tas_data; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index d5de9305df25..7dee9b282a1b 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1917,6 +1917,7 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) struct sja1105_l2_lookup_params_entry *l2_lookup_params; struct sja1105_general_params_entry *general_params; struct sja1105_private *priv = ds->priv; + enum sja1105_vlan_state state; struct sja1105_table *table; struct sja1105_rule *rule; u16 tpid, tpid2; @@ -1940,6 +1941,13 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) tpid2 = ETH_P_SJA1105; } + if (!enabled) + state = SJA1105_VLAN_UNAWARE; + else + state = SJA1105_VLAN_FILTERING_FULL; + + priv->vlan_state = state; + table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS]; general_params = table->entries; /* EtherType used to identify inner tagged (C-tag) VLAN traffic */ @@ -1985,6 +1993,14 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) return sja1105_setup_8021q_tagging(ds, !enabled); } +bool sja1105_can_use_vlan_as_tags(struct dsa_switch *ds) +{ + struct sja1105_private *priv = ds->priv; + + return priv->vlan_state != SJA1105_VLAN_FILTERING_FULL; +} +EXPORT_SYMBOL_GPL(sja1105_can_use_vlan_as_tags); + static void sja1105_vlan_add(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan) { diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h index fa5735c353cd..136481ce3c6f 100644 --- a/include/linux/dsa/sja1105.h +++ b/include/linux/dsa/sja1105.h @@ -61,4 +61,6 @@ struct sja1105_port { bool hwts_tx_en; }; +bool sja1105_can_use_vlan_as_tags(struct dsa_switch *ds); + #endif /* _NET_DSA_SJA1105_H */ diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index d553bf36bd41..5368cd34bcf4 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c @@ -74,7 +74,7 @@ static inline bool sja1105_is_meta_frame(const struct sk_buff *skb) */ static bool sja1105_filter(const struct sk_buff *skb, struct net_device *dev) { - if (!dsa_port_is_vlan_filtering(dev->dsa_ptr)) + if (sja1105_can_use_vlan_as_tags(dev->dsa_ptr->ds)) return true; if (sja1105_is_link_local(skb)) return true; From patchwork Sun May 10 16:42:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 219518 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=-9.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, 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 4C74EC54E8A for ; Sun, 10 May 2020 16:44:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1D3C4207DD for ; Sun, 10 May 2020 16:44:45 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mVQTYMOF" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729370AbgEJQoo (ORCPT ); Sun, 10 May 2020 12:44:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34836 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1728600AbgEJQne (ORCPT ); Sun, 10 May 2020 12:43:34 -0400 Received: from mail-wm1-x343.google.com (mail-wm1-x343.google.com [IPv6:2a00:1450:4864:20::343]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 261F9C061A0E; Sun, 10 May 2020 09:43:34 -0700 (PDT) Received: by mail-wm1-x343.google.com with SMTP id y24so16339347wma.4; Sun, 10 May 2020 09:43:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=E8h43DVwyQEgSe9HIpdWtHOas81wEn11zRRa4f/9ZqY=; b=mVQTYMOFooSM6RmZW+EMQJ9xmnGfScaL/MYmCMDzbroi11rHUC42IgfGQhzx0XNuEV jitnnpg5Y2S8DHErQvSv1XUQnrOKDQW+uD9SZy3ToF4bkS+cDZkqNT4g19QuKj9ekdhe gI+ZkGobmo/pameejq0LhGmoIQ9N0t25CjgyX2i95Dyp5vbD4HZvTbu7dG7L3WD8uetq LtVM7BrI/mSzDF6oRgQay+XTdkwgRtq5dhyr6sMgfn8VykPEx4xocL70CIUEPRlNAujY bFUTN/xQQW8ftmmwThBhBJnk+NQRk5TPVg2/FxYWtdrcYo7ch9D8u5j/+Z6GAXLKnR8c 3AIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=E8h43DVwyQEgSe9HIpdWtHOas81wEn11zRRa4f/9ZqY=; b=GgSnkQw00T0v8t07Twk+/uSJw3AYLwQUhjX4odqdWR37tTG3sijRxgcJgj3ZifCjDZ g7uCVhyLLycUrGaplotPN5Puwf9y1uBUJAw0vAEiEuhdE1GOuXWZGHoK4sJ2fHnX8X5S UnpNFzjYjjfAYa1VWBPZNRGNgV/o0JxRuuTvnLBdHIlzDG9Uvcr/42gFU4BZCMlseQIN /OPvRfv4UcvzLCauO+pV128nfs/Jb8pAREV+5wTN59s9UQiB8UCwOIoc4MTTjKb9mqK/ KzLjmfCPO1HgwAc0wyjaiWKF+EG5nEnbfScEc2RHJ7QOPzcaERC0qNnY6K743EiaG48e lGmQ== X-Gm-Message-State: AGi0PuaDMWL/ldXtA2DSyyQ2HZIzy5SpJ8fEFJVV2wg1taF3IsbwUAbt M5HSCSBTRJ9MabtShk1FSro= X-Google-Smtp-Source: APiQypKgVHOV8okpTdmr5fM/KeOlvti8GIAiuavgVTfCo94SN/jcs0VE92Tg0gYmnnvv+lJ5WwSlmg== X-Received: by 2002:a7b:c5d3:: with SMTP id n19mr19754955wmk.21.1589129012851; Sun, 10 May 2020 09:43:32 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:32 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 04/15] net: dsa: sja1105: deny alterations of dsa_8021q VLANs from the bridge Date: Sun, 10 May 2020 19:42:44 +0300 Message-Id: <20200510164255.19322-5-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean At the moment, this can never happen. The 2 modes that we operate in do not permit that: - SJA1105_VLAN_UNAWARE: we are guarded from bridge VLANs added by the user by the DSA core. We will later lift this restriction by setting ds->vlan_bridge_vtu = true, and that is where we'll need it. - SJA1105_VLAN_FILTERING_FULL: in this mode, dsa_8021q configuration is disabled. So the user is free to add these VLANs in the 1024-3071 range. The reason for the patch is that we'll introduce a third VLAN awareness state, where both dsa_8021q as well as the bridge are going to call our .port_vlan_add and .port_vlan_del methods. For that, we need a good way to discriminate between the 2. The easiest (and less intrusive way for upper layers) is to recognize the fact that dsa_8021q configurations are always driven by our driver - we _know_ when a .port_vlan_add method will be called from dsa_8021q because _we_ initiated it. So introduce an expect_dsa_8021q boolean which is only used, at the moment, for blacklisting VLANs in range 1024-3071 in the modes when dsa_8021q is active. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105.h | 1 + drivers/net/dsa/sja1105/sja1105_main.c | 31 +++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index 5b2b275d01a7..667056d0c819 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -198,6 +198,7 @@ struct sja1105_private { * the switch doesn't confuse them with one another. */ struct mutex mgmt_lock; + bool expect_dsa_8021q; enum sja1105_vlan_state vlan_state; struct sja1105_tagger_data tagger_data; struct sja1105_ptp_data ptp_data; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 7dee9b282a1b..78ec97850f96 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1811,15 +1811,19 @@ static int sja1105_crosschip_bridge_join(struct dsa_switch *ds, if (dsa_to_port(ds, port)->bridge_dev != br) continue; + other_priv->expect_dsa_8021q = true; rc = dsa_8021q_crosschip_bridge_join(ds, port, other_ds, other_port, br, &priv->crosschip_links); + other_priv->expect_dsa_8021q = false; if (rc) return rc; + priv->expect_dsa_8021q = true; rc = dsa_8021q_crosschip_bridge_join(other_ds, other_port, ds, port, br, &other_priv->crosschip_links); + priv->expect_dsa_8021q = false; if (rc) return rc; } @@ -1846,12 +1850,16 @@ static void sja1105_crosschip_bridge_leave(struct dsa_switch *ds, if (dsa_to_port(ds, port)->bridge_dev != br) continue; + other_priv->expect_dsa_8021q = true; dsa_8021q_crosschip_bridge_leave(ds, port, other_ds, other_port, br, &priv->crosschip_links); + other_priv->expect_dsa_8021q = false; + priv->expect_dsa_8021q = true; dsa_8021q_crosschip_bridge_leave(other_ds, other_port, ds, port, br, &other_priv->crosschip_links); + priv->expect_dsa_8021q = false; } } @@ -1862,8 +1870,10 @@ static int sja1105_replay_crosschip_vlans(struct dsa_switch *ds, bool enabled) int rc; list_for_each_entry(c, &priv->crosschip_links, list) { + priv->expect_dsa_8021q = true; rc = dsa_8021q_crosschip_link_apply(ds, c->port, c->other_ds, c->other_port, enabled); + priv->expect_dsa_8021q = false; if (rc) break; } @@ -1873,10 +1883,13 @@ static int sja1105_replay_crosschip_vlans(struct dsa_switch *ds, bool enabled) static int sja1105_setup_8021q_tagging(struct dsa_switch *ds, bool enabled) { + struct sja1105_private *priv = ds->priv; int rc, i; for (i = 0; i < SJA1105_NUM_PORTS; i++) { + priv->expect_dsa_8021q = true; rc = dsa_port_setup_8021q_tagging(ds, i, enabled); + priv->expect_dsa_8021q = false; if (rc < 0) { dev_err(ds->dev, "Failed to setup VLAN tagging for port %d: %d\n", i, rc); @@ -1901,10 +1914,26 @@ sja1105_get_tag_protocol(struct dsa_switch *ds, int port, return DSA_TAG_PROTO_SJA1105; } -/* This callback needs to be present */ static int sja1105_vlan_prepare(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan) { + struct sja1105_private *priv = ds->priv; + u16 vid; + + if (priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) + return 0; + + /* If the user wants best-effort VLAN filtering (aka vlan_filtering + * bridge plus tagging), be sure to at least deny alterations to the + * configuration done by dsa_8021q. + */ + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { + if (!priv->expect_dsa_8021q && vid_is_dsa_8021q(vid)) { + dev_err(ds->dev, "Range 1024-3071 reserved for dsa_8021q operation\n"); + return -EBUSY; + } + } + return 0; } From patchwork Sun May 10 16:42:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 219519 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=-9.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable 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 8C2C4C54E4B for ; Sun, 10 May 2020 16:44:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6A104207DD for ; Sun, 10 May 2020 16:44:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="vJrLPXUk" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729342AbgEJQob (ORCPT ); Sun, 10 May 2020 12:44:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34852 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729168AbgEJQni (ORCPT ); Sun, 10 May 2020 12:43:38 -0400 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6C7D5C061A0C; Sun, 10 May 2020 09:43:37 -0700 (PDT) Received: by mail-wm1-x344.google.com with SMTP id h4so15412081wmb.4; Sun, 10 May 2020 09:43:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6xcuiP37UyCaOrsW3hqo0Y2XODppUiFrZnzXTjx4S0k=; b=vJrLPXUk2QKRO15Se7GIMgGmGG/wAP1E3EtpeHrKXADxPBRuFX7iXjHEbTfvURnN1o Cn5eT89zwSVk+1i7z1vblEDVlYLpOL+R62CnkGZPQzvv9MDoeuAPFPK7H+hXUgd5ZWsv 2H28PjknhZWibXyOwm3hEcG+er/hKJ1KWwlx7wOtLyDx1hjQePB3fO3X1+fy0OD+QNpu bQNFObXWfIUAwQFoPrGG8KSzaXbLGF2LSWHpR+Miy/2gnssTzz+pEbdvjjDYvPx1b+9h FQ19piijLcv1A/GReY19t74091MllKLM2UzK9gCZVqdKSxSmE73u5huVYuhYq8sMSQXu TKdA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6xcuiP37UyCaOrsW3hqo0Y2XODppUiFrZnzXTjx4S0k=; b=tEGrx4iJRDS9XcQIgUGywavbd9HFEyybAulOLsYo+TlUaj35Codrh6eVvIICT/gDl+ nkVC4cV76QOw0nDI7p1U1MgoZZsRRIs7XE19dlemKkade9S540qJv0AJRB/LWjUVHx0g sbkc2kZyob6BqUTDYmS4Mi12i+73eUdlpG/14ESnplnOeNveT9clCZBrgxZbHSXWcLl8 BNneeKUi4zO6I36kFBDuJ/JsCu6w2+wQw9soAUcJZ44zTTM9kG1Sgrni+CxxiMZOjPfG urWjyeUxMdzonsB1HH2IAmSO3XLDm7R9YJqfy1/4ihjBOVGTV0nl4qOF3TJSgWmzTLjZ NsHA== X-Gm-Message-State: AGi0PuaNVf3t+0VrQcUrY+Aoys7pszdQBnnApSa+MRVnX3QqUUbKUG8r RG8bBnVYG2OuplxINsf4boM= X-Google-Smtp-Source: APiQypKsoR77XB6Q9xEtQ/cC2yoZ4pewQuFzXr9xnz9Y2UlEIYQUosHc6LBUO4u/Vf+7E0NZbY7rHw== X-Received: by 2002:a7b:c10b:: with SMTP id w11mr14146888wmi.146.1589129016216; Sun, 10 May 2020 09:43:36 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:35 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 07/15] net: dsa: sja1105: exit sja1105_vlan_filtering when called multiple times Date: Sun, 10 May 2020 19:42:47 +0300 Message-Id: <20200510164255.19322-8-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean VLAN filtering is a global property for sja1105, and that means that we rely on the DSA core to not call us more than once. But we need to introduce some per-port state for the tagger, namely the xmit_tpid, and the best place to do that is where the xmit_tpid changes, namely in sja1105_vlan_filtering. So at the moment, exit early from the function to avoid unnecessarily resetting the switch for each port call. Then we'll change the xmit_tpid prior to the early exit in the next patch. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 15db37067bf1..8cf17238bc6a 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -2141,6 +2141,9 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) else state = SJA1105_VLAN_FILTERING_FULL; + if (priv->vlan_state == state) + return 0; + priv->vlan_state = state; table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS]; From patchwork Sun May 10 16:42:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 219521 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=-9.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable 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 384D4C54E8A for ; Sun, 10 May 2020 16:44:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 125792082E for ; Sun, 10 May 2020 16:44:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="naL1fUrk" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729233AbgEJQnr (ORCPT ); Sun, 10 May 2020 12:43:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34860 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729184AbgEJQnj (ORCPT ); Sun, 10 May 2020 12:43:39 -0400 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 82C98C061A0E; Sun, 10 May 2020 09:43:38 -0700 (PDT) Received: by mail-wm1-x344.google.com with SMTP id k12so15373249wmj.3; Sun, 10 May 2020 09:43:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=wuNa9dUTzo5dhNeShT+Z0EUvQDKyte55bwDEiseFjgE=; b=naL1fUrkes4Xk2tRknh7wo+NnUipoSbirgCAzpRaj+3S39UKrOxEoR9cOTIcTjH+0L N+dpYjN8nERaL14WE10JwSHpiUD8600A46S6pLBE7MTF0VTwFkiwNJ/ecj1Acnc/jvRZ y1qEz8sWKcQ33mjm//4kD+ARAwv4KbSmAxgj0NyBy6VoA0FuzWTbMWIHhpcDXIvULpVd oydXaRBzWYMHTLm35qaiXe6XXXYk8l8w6g+TGpmYgI2aAxalhiPI6PNwigxRKgD/dyLr ywUma8C27v6IXrRKmaNHVAJdDcfobn9HYP+IaWojTaM3D/o5z9pjiLUs2HMyM0UOjwf9 cO/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=wuNa9dUTzo5dhNeShT+Z0EUvQDKyte55bwDEiseFjgE=; b=I6X9yEf1uqUC7Q4fuzRrX0Z0bwixvTSJvERO4H7za6DcisFKxbWjAyOaF2tJLMVkZV QeH5RDrJIURkr0L0B96pTNUYsM6/MPGVT0LG4+eqzvbOuEVfIMx4ypzDmSmcDJlcoq03 MW5K4T0ULsM2IvszoiBL+iBHEmyDqy+Zm8tcuMPowoopEG7DCyq4Sj/AfIAexuHW/237 UL9RdpZnuY7jv4niRxhyF7QzbMkUHt6dTm8Os8J5Q/IA0yawJkOdLozYJFGuMxX+iG9x ORlsjuSIlde1XVNOmm5/1pFv4Z7yTqES16tj5isFa4sbjUiOIKjsijuZjINiDtQfxlEw bxPA== X-Gm-Message-State: AGi0PuarZzkeFvcTrZv6vhUGR4IqSrb4QI5ap8JxPHf0Az39dBIa5fkj ia50zr0SY3IRmTA5WzlsX44= X-Google-Smtp-Source: APiQypK20K1daP+sQfApitxQsnIhmLeFGIKDF1+/V8mIJOiGnoTnaS9h2gaMrA73Ya3pUW7FE/LMrw== X-Received: by 2002:a7b:c8d4:: with SMTP id f20mr5281428wml.72.1589129017242; Sun, 10 May 2020 09:43:37 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:36 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 08/15] net: dsa: sja1105: prepare tagger for handling DSA tags and VLAN simultaneously Date: Sun, 10 May 2020 19:42:48 +0300 Message-Id: <20200510164255.19322-9-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean In VLAN-unaware mode, sja1105 uses VLAN tags with a custom TPID of 0xdadb. While in the yet-to-be introduced best_effort_vlan_filtering mode, it needs to work with normal VLAN TPID values. A complication arises when we must transmit a VLAN-tagged packet to the switch when it's in VLAN-aware mode. We need to construct a packet with 2 VLAN tags, and the switch will use the outer header for routing and pop it on egress. But sadly, here the 2 hardware generations don't behave the same: - E/T switches won't pop an ETH_P_8021AD tag on egress, it seems (packets will remain double-tagged). - P/Q/R/S switches will drop a packet with 2 ETH_P_8021Q tags (it looks like it tries to prevent VLAN hopping). But looks like the reverse is also true: - E/T switches have no problem popping the outer tag from packets with 2 ETH_P_8021Q tags. - P/Q/R/S will have no problem popping a single tag even if that is ETH_P_8021AD. So it is clear that if we want the hardware to work with dsa_8021q tagging in VLAN-aware mode, we need to send different TPIDs depending on revision. Keep that information in priv->info->qinq_tpid. The per-port tagger structure will hold an xmit_tpid value that depends not only upon the qinq_tpid, but also upon the VLAN awareness state itself (in case we must transmit using 0xdadb). Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105.h | 6 ++++++ drivers/net/dsa/sja1105/sja1105_main.c | 10 ++++++++++ drivers/net/dsa/sja1105/sja1105_spi.c | 6 ++++++ include/linux/dsa/sja1105.h | 2 ++ net/dsa/tag_sja1105.c | 17 +++++++---------- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index c80f1999c694..a019ffae38f1 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -87,6 +87,12 @@ struct sja1105_info { const struct sja1105_dynamic_table_ops *dyn_ops; const struct sja1105_table_ops *static_ops; const struct sja1105_regs *regs; + /* Both E/T and P/Q/R/S have quirks when it comes to popping the S-Tag + * from double-tagged frames. E/T will pop it only when it's equal to + * TPID from the General Parameters Table, while P/Q/R/S will only + * pop it when it's equal to TPID2. + */ + u16 qinq_tpid; int (*reset_cmd)(struct dsa_switch *ds); int (*setup_rgmii_delay)(const void *ctx, int port); /* Prototypes from include/net/dsa.h */ diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 8cf17238bc6a..34006b2def32 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -2136,6 +2136,15 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) tpid2 = ETH_P_SJA1105; } + for (port = 0; port < ds->num_ports; port++) { + struct sja1105_port *sp = &priv->ports[port]; + + if (enabled) + sp->xmit_tpid = priv->info->qinq_tpid; + else + sp->xmit_tpid = ETH_P_SJA1105; + } + if (!enabled) state = SJA1105_VLAN_UNAWARE; else @@ -2845,6 +2854,7 @@ static int sja1105_probe(struct spi_device *spi) goto out; } skb_queue_head_init(&sp->xmit_queue); + sp->xmit_tpid = ETH_P_SJA1105; } return 0; diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index 0be75c49e6c3..a0dacae803cc 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -512,6 +512,7 @@ struct sja1105_info sja1105e_info = { .part_no = SJA1105ET_PART_NO, .static_ops = sja1105e_table_ops, .dyn_ops = sja1105et_dyn_ops, + .qinq_tpid = ETH_P_8021Q, .ptp_ts_bits = 24, .ptpegr_ts_bytes = 4, .reset_cmd = sja1105et_reset_cmd, @@ -526,6 +527,7 @@ struct sja1105_info sja1105t_info = { .part_no = SJA1105ET_PART_NO, .static_ops = sja1105t_table_ops, .dyn_ops = sja1105et_dyn_ops, + .qinq_tpid = ETH_P_8021Q, .ptp_ts_bits = 24, .ptpegr_ts_bytes = 4, .reset_cmd = sja1105et_reset_cmd, @@ -540,6 +542,7 @@ struct sja1105_info sja1105p_info = { .part_no = SJA1105P_PART_NO, .static_ops = sja1105p_table_ops, .dyn_ops = sja1105pqrs_dyn_ops, + .qinq_tpid = ETH_P_8021AD, .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, @@ -555,6 +558,7 @@ struct sja1105_info sja1105q_info = { .part_no = SJA1105Q_PART_NO, .static_ops = sja1105q_table_ops, .dyn_ops = sja1105pqrs_dyn_ops, + .qinq_tpid = ETH_P_8021AD, .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, @@ -570,6 +574,7 @@ struct sja1105_info sja1105r_info = { .part_no = SJA1105R_PART_NO, .static_ops = sja1105r_table_ops, .dyn_ops = sja1105pqrs_dyn_ops, + .qinq_tpid = ETH_P_8021AD, .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, @@ -586,6 +591,7 @@ struct sja1105_info sja1105s_info = { .static_ops = sja1105s_table_ops, .dyn_ops = sja1105pqrs_dyn_ops, .regs = &sja1105pqrs_regs, + .qinq_tpid = ETH_P_8021AD, .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h index 136481ce3c6f..e47acf0965c5 100644 --- a/include/linux/dsa/sja1105.h +++ b/include/linux/dsa/sja1105.h @@ -9,6 +9,7 @@ #include #include +#include #include #define ETH_P_SJA1105 ETH_P_DSA_8021Q @@ -59,6 +60,7 @@ struct sja1105_port { struct sja1105_tagger_data *data; struct dsa_port *dp; bool hwts_tx_en; + u16 xmit_tpid; }; bool sja1105_can_use_vlan_as_tags(struct dsa_switch *ds); diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index 5368cd34bcf4..0a95fdd7bff8 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c @@ -96,6 +96,11 @@ static struct sk_buff *sja1105_defer_xmit(struct sja1105_port *sp, return NULL; } +static u16 sja1105_xmit_tpid(struct sja1105_port *sp) +{ + return sp->xmit_tpid; +} + static struct sk_buff *sja1105_xmit(struct sk_buff *skb, struct net_device *netdev) { @@ -111,15 +116,7 @@ static struct sk_buff *sja1105_xmit(struct sk_buff *skb, if (unlikely(sja1105_is_link_local(skb))) return sja1105_defer_xmit(dp->priv, skb); - /* If we are under a vlan_filtering bridge, IP termination on - * switch ports based on 802.1Q tags is simply too brittle to - * be passable. So just defer to the dsa_slave_notag_xmit - * implementation. - */ - if (dsa_port_is_vlan_filtering(dp)) - return skb; - - return dsa_8021q_xmit(skb, netdev, ETH_P_SJA1105, + return dsa_8021q_xmit(skb, netdev, sja1105_xmit_tpid(dp->priv), ((pcp << VLAN_PRIO_SHIFT) | tx_vid)); } @@ -258,7 +255,7 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, hdr = eth_hdr(skb); tpid = ntohs(hdr->h_proto); - is_tagged = (tpid == ETH_P_SJA1105); + is_tagged = (tpid == ETH_P_SJA1105 || tpid == ETH_P_8021Q); is_link_local = sja1105_is_link_local(skb); is_meta = sja1105_is_meta_frame(skb); From patchwork Sun May 10 16:42:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 219523 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=-9.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, 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 98D33C54E4B for ; Sun, 10 May 2020 16:43:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 69E482080C for ; Sun, 10 May 2020 16:43:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DTrdB0Ly" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729214AbgEJQno (ORCPT ); Sun, 10 May 2020 12:43:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34862 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729183AbgEJQnj (ORCPT ); Sun, 10 May 2020 12:43:39 -0400 Received: from mail-wm1-x342.google.com (mail-wm1-x342.google.com [IPv6:2a00:1450:4864:20::342]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 87B45C061A0C; Sun, 10 May 2020 09:43:39 -0700 (PDT) Received: by mail-wm1-x342.google.com with SMTP id n5so1409112wmd.0; Sun, 10 May 2020 09:43:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=t9KvHDraVVPmHpvZiB0/h0nDTyCPGJWmh64wEtbHJ+Q=; b=DTrdB0LylJIANXRrxiVKVFJiNGuWqowDtrC8DJJ5iILZGivzSWDlouwe3Uonv1yZHp GH6AoL6guuLtiv4C8tV3m0aHHUPaMmIGu8EnU6ehNgKk6IQy1M9VLCpTJ7XuNqOFJMSB EjGXq7yObAO7IcnQF0auLXMW94hdTG7wWEGI6z43N/liwG8tl7/hYqOi0FWQ/YyhZFwV Nz7V6u5yvM6nbLfoeu+yLidK+z79OqNgbQYhc6qeMrwCxixrzo2WDt9/mpdEHHpVP1vQ s0lw0Gjyg74t8+n8iXccv5OzGYaPkKHHE5HVxaY9SD1rZarEqSEPY08Tgx3rJzlCkBGR ivPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=t9KvHDraVVPmHpvZiB0/h0nDTyCPGJWmh64wEtbHJ+Q=; b=Kn9YUFvhWV9EhZfqVVDm18WZxsH1ml619lJqPAIssfbNIk55xXLA1FLSD0Lv6GquPB 0lJimK/LJaG8E/HzO1fCGs1KNz0BGdz6rY76k9ZPqjnnHnHGkBjo/OhEO1CLV4neHB0S M7wguEOMVpGaZ8bhj3dZb0sAWyP//IqVktKJ9Wjr/1GeRyXdMdWeqK9/5A2hbjPFSOYj hn4rMNX+3NDVvtreWzmwQQ+02AVlWdxofLc0vhSfuL5dezNPUheZa1v6svF9x30iVnTc 2E665gdYdOMyUz+RlUB5i94MalTuGat0hH7UOjcAC5qnAkvrQ5RWWL3BNVHm3nPez8NA Oq/w== X-Gm-Message-State: AGi0Pub2LdzyDK4T8Tsv5NdILaLudC4m0tLJnndf8aHr9+Apy2Nu/xZx j0Fx6TKmflgAq88esHQnLzU= X-Google-Smtp-Source: APiQypK+BXYktn4GfvAGyzcTUp7mwnwYXtA9XFtA5mpOpsRga3mHKxnh4E3HfYZqzxLEHhYUZKflBg== X-Received: by 2002:a1c:6142:: with SMTP id v63mr21164002wmb.61.1589129018242; Sun, 10 May 2020 09:43:38 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:37 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 09/15] net: dsa: tag_8021q: support up to 8 VLANs per port using sub-VLANs Date: Sun, 10 May 2020 19:42:49 +0300 Message-Id: <20200510164255.19322-10-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean For switches that support VLAN retagging, such as sja1105, we extend dsa_8021q by encoding a "sub-VLAN" into the remaining 3 free bits in the dsa_8021q tag. A sub-VLAN is nothing more than a number in the range 0-7, which serves as an index into a per-port driver lookup table. The sub-VLAN value of zero means that traffic is untagged (this is also backwards-compatible with dsa_8021q without retagging). The switch should be configured to retag VLAN-tagged traffic that gets transmitted towards the CPU port (and towards the CPU only). Example: bridge vlan add dev sw1p0 vid 100 The switch retags frames received on port 0, going to the CPU, and having VID 100, to the VID of 1104 (0x0450). In dsa_8021q language: | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | +-----------+-----+-----------------+-----------+-----------------------+ | DIR | SVL | SWITCH_ID | SUBVLAN | PORT | +-----------+-----+-----------------+-----------+-----------------------+ 0x0450 means: - DIR = 0b01: this is an RX VLAN - SUBVLAN = 0b001: this is subvlan #1 - SWITCH_ID = 0b001: this is switch 1 (see the name "sw1p0") - PORT = 0b0000: this is port 0 (see the name "sw1p0") The driver also remembers the "1 -> 100" mapping. In the hotpath, if the sub-VLAN from the tag encodes a non-untagged frame, this mapping is used to create a VLAN hwaccel tag, with the value of 100. Signed-off-by: Vladimir Oltean --- include/linux/dsa/8021q.h | 16 +++++++++++ net/dsa/tag_8021q.c | 56 +++++++++++++++++++++++++++++++++------ 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/include/linux/dsa/8021q.h b/include/linux/dsa/8021q.h index 404bd2cce642..311aa04e7520 100644 --- a/include/linux/dsa/8021q.h +++ b/include/linux/dsa/8021q.h @@ -20,6 +20,8 @@ struct dsa_8021q_crosschip_link { refcount_t refcount; }; +#define DSA_8021Q_N_SUBVLAN 8 + #if IS_ENABLED(CONFIG_NET_DSA_TAG_8021Q) int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int index, @@ -42,10 +44,14 @@ u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port); u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port); +u16 dsa_8021q_rx_vid_subvlan(struct dsa_switch *ds, int port, u16 subvlan); + int dsa_8021q_rx_switch_id(u16 vid); int dsa_8021q_rx_source_port(u16 vid); +u16 dsa_8021q_rx_subvlan(u16 vid); + bool vid_is_dsa_8021q(u16 vid); #else @@ -88,6 +94,11 @@ u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port) return 0; } +u16 dsa_8021q_rx_vid_subvlan(struct dsa_switch *ds, int port, u16 subvlan) +{ + return 0; +} + int dsa_8021q_rx_switch_id(u16 vid) { return 0; @@ -98,6 +109,11 @@ int dsa_8021q_rx_source_port(u16 vid) return 0; } +u16 dsa_8021q_rx_subvlan(u16 vid) +{ + return 0; +} + bool vid_is_dsa_8021q(u16 vid) { return false; diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c index 3236fbbf85b9..3052da668156 100644 --- a/net/dsa/tag_8021q.c +++ b/net/dsa/tag_8021q.c @@ -17,7 +17,7 @@ * * | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * +-----------+-----+-----------------+-----------+-----------------------+ - * | DIR | RSV | SWITCH_ID | RSV | PORT | + * | DIR | SVL | SWITCH_ID | SUBVLAN | PORT | * +-----------+-----+-----------------+-----------+-----------------------+ * * DIR - VID[11:10]: @@ -27,17 +27,24 @@ * These values make the special VIDs of 0, 1 and 4095 to be left * unused by this coding scheme. * - * RSV - VID[9]: - * To be used for further expansion of SWITCH_ID or for other purposes. - * Must be transmitted as zero and ignored on receive. + * SVL/SUBVLAN - { VID[9], VID[5:4] }: + * Sub-VLAN encoding. Valid only when DIR indicates an RX VLAN. + * * 0 (0b000): Field does not encode a sub-VLAN, either because + * received traffic is untagged, PVID-tagged or because a second + * VLAN tag is present after this tag and not inside of it. + * * 1 (0b001): Received traffic is tagged with a VID value private + * to the host. This field encodes the index in the host's lookup + * table through which the value of the ingress VLAN ID can be + * recovered. + * * 2 (0b010): Field encodes a sub-VLAN. + * ... + * * 7 (0b111): Field encodes a sub-VLAN. + * When DIR indicates a TX VLAN, SUBVLAN must be transmitted as zero + * (by the host) and ignored on receive (by the switch). * * SWITCH_ID - VID[8:6]: * Index of switch within DSA tree. Must be between 0 and 7. * - * RSV - VID[5:4]: - * To be used for further expansion of PORT or for other purposes. - * Must be transmitted as zero and ignored on receive. - * * PORT - VID[3:0]: * Index of switch port. Must be between 0 and 15. */ @@ -54,6 +61,18 @@ #define DSA_8021Q_SWITCH_ID(x) (((x) << DSA_8021Q_SWITCH_ID_SHIFT) & \ DSA_8021Q_SWITCH_ID_MASK) +#define DSA_8021Q_SUBVLAN_HI_SHIFT 9 +#define DSA_8021Q_SUBVLAN_HI_MASK GENMASK(9, 9) +#define DSA_8021Q_SUBVLAN_LO_SHIFT 4 +#define DSA_8021Q_SUBVLAN_LO_MASK GENMASK(4, 3) +#define DSA_8021Q_SUBVLAN_HI(x) (((x) & GENMASK(2, 2)) >> 2) +#define DSA_8021Q_SUBVLAN_LO(x) ((x) & GENMASK(1, 0)) +#define DSA_8021Q_SUBVLAN(x) \ + (((DSA_8021Q_SUBVLAN_LO(x) << DSA_8021Q_SUBVLAN_LO_SHIFT) & \ + DSA_8021Q_SUBVLAN_LO_MASK) | \ + ((DSA_8021Q_SUBVLAN_HI(x) << DSA_8021Q_SUBVLAN_HI_SHIFT) & \ + DSA_8021Q_SUBVLAN_HI_MASK)) + #define DSA_8021Q_PORT_SHIFT 0 #define DSA_8021Q_PORT_MASK GENMASK(3, 0) #define DSA_8021Q_PORT(x) (((x) << DSA_8021Q_PORT_SHIFT) & \ @@ -79,6 +98,13 @@ u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port) } EXPORT_SYMBOL_GPL(dsa_8021q_rx_vid); +u16 dsa_8021q_rx_vid_subvlan(struct dsa_switch *ds, int port, u16 subvlan) +{ + return DSA_8021Q_DIR_RX | DSA_8021Q_SWITCH_ID(ds->index) | + DSA_8021Q_PORT(port) | DSA_8021Q_SUBVLAN(subvlan); +} +EXPORT_SYMBOL_GPL(dsa_8021q_rx_vid_subvlan); + /* Returns the decoded switch ID from the RX VID. */ int dsa_8021q_rx_switch_id(u16 vid) { @@ -93,6 +119,20 @@ int dsa_8021q_rx_source_port(u16 vid) } EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port); +/* Returns the decoded subvlan from the RX VID. */ +u16 dsa_8021q_rx_subvlan(u16 vid) +{ + u16 svl_hi, svl_lo; + + svl_hi = (vid & DSA_8021Q_SUBVLAN_HI_MASK) >> + DSA_8021Q_SUBVLAN_HI_SHIFT; + svl_lo = (vid & DSA_8021Q_SUBVLAN_LO_MASK) >> + DSA_8021Q_SUBVLAN_LO_SHIFT; + + return (svl_hi << 2) | svl_lo; +} +EXPORT_SYMBOL_GPL(dsa_8021q_rx_subvlan); + bool vid_is_dsa_8021q(u16 vid) { return ((vid & DSA_8021Q_DIR_MASK) == DSA_8021Q_DIR_RX || From patchwork Sun May 10 16:42:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 219520 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=-9.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, 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 7FDE4C38A2A for ; Sun, 10 May 2020 16:44:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 54A55207DD for ; Sun, 10 May 2020 16:44:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YUNYevQ0" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729325AbgEJQoS (ORCPT ); Sun, 10 May 2020 12:44:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34880 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729215AbgEJQnp (ORCPT ); Sun, 10 May 2020 12:43:45 -0400 Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B0637C061A0C; Sun, 10 May 2020 09:43:43 -0700 (PDT) Received: by mail-wr1-x444.google.com with SMTP id e16so7922827wra.7; Sun, 10 May 2020 09:43:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=l8yu63bzu9EKtUcTab5iO3gnV0kmnc7EqpMOcQXFQvg=; b=YUNYevQ0UNIGvx85zB3sVCx9g7ar7pBDkt4kCRxexjEbek2e8/0934Ijp0s87zUBxE UDPKM9GQKs7r2HOlh968aJcYWhFm25QQPzqri2dU/okDOHjb4qfuGOG7vx3p9I3qLMwH KckumHE0kc64ueNfJ9z5C8eZC7Ofr9mlSeLToWi28dRa0tTqG3OwVoD0RYtPcK26Or8r RikAek5PEes7MpLo/L7U5vpImVdSJbZLRGPtA4l7u4rzkhFBqWOIRSlkQKcpTG3ggBdl WIIAL66suyiYNVd8p4PdaIgJBm2GQHWKvZA+0NmuV0Fb44ndBOjqSxNIuFEodBIjLOj9 EH7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=l8yu63bzu9EKtUcTab5iO3gnV0kmnc7EqpMOcQXFQvg=; b=nvNJ/7S4sJGLoXRHSXnWYrRyUhp24/uW7fm47lCRAzQ1OV5m5A9KFVaYeo+oOY8qfQ m9IcjlthLKBAAksfOT14dN0tv+TShADJAUYCDp8uOY8CHYAbK7G9PS/CTSjvcAMc36eQ +b4FxceZCWjWUArc9FUyXQQMMTLefSx+kfTPVQwITvCyD3yVHYbPuY1zfSU1WUGGeRiH TtASNNpsUWeReeOnveOhHATsRa/XDBVwDba8PeugMSXo8tVz0GO1xJ3aCPDjwcQo5UZe BOYRKPCl9xW4Bn66Xqr1rmYl9YWJSEYqyWzmucyOrhmDHYUmrvOmXMPJWVwCRM0Z2IM0 oNbw== X-Gm-Message-State: AGi0PuYkXBZ38+VgLgWc/CwFEUhpF5F/2iuUq5iuSAe18PezJ096sATZ XfagGS+uyyQUdrgkgN5i670= X-Google-Smtp-Source: APiQypIPQNCYU6ysbOb8zMT4G8P6PRZpRjQEND+e/XYCxKXrhzNPj535kJ7R9L/UB/AmSmlzmp+QFA== X-Received: by 2002:adf:8563:: with SMTP id 90mr13754478wrh.74.1589129022388; Sun, 10 May 2020 09:43:42 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:41 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 13/15] net: dsa: sja1105: implement a common frame memory partitioning function Date: Sun, 10 May 2020 19:42:53 +0300 Message-Id: <20200510164255.19322-14-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean There are 2 different features that require some reserved frame memory space: VLAN retagging and virtual links. Create a central function that modifies the static config and ensures frame memory is never overcommitted. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105.h | 2 + drivers/net/dsa/sja1105/sja1105_main.c | 37 +++++++++++++++++++ .../net/dsa/sja1105/sja1105_static_config.h | 1 + drivers/net/dsa/sja1105/sja1105_vl.c | 20 +--------- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index 1ecdfd6be4c2..198d2a7d7f95 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -244,6 +244,8 @@ enum sja1105_reset_reason { int sja1105_static_config_reload(struct sja1105_private *priv, enum sja1105_reset_reason reason); +void sja1105_frame_memory_partitioning(struct sja1105_private *priv); + /* From sja1105_spi.c */ int sja1105_xfer_buf(const struct sja1105_private *priv, sja1105_spi_rw_mode_t rw, u64 reg_addr, diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 4ea77e829d70..9e93a9af4913 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -412,6 +412,41 @@ static int sja1105_init_l2_forwarding_params(struct sja1105_private *priv) return 0; } +void sja1105_frame_memory_partitioning(struct sja1105_private *priv) +{ + struct sja1105_l2_forwarding_params_entry *l2_fwd_params; + struct sja1105_vl_forwarding_params_entry *vl_fwd_params; + struct sja1105_table *table; + int max_mem; + + /* VLAN retagging is implemented using a loopback port that consumes + * frame buffers. That leaves less for us. + */ + if (priv->vlan_state == SJA1105_VLAN_BEST_EFFORT) + max_mem = SJA1105_MAX_FRAME_MEMORY_RETAGGING; + else + max_mem = SJA1105_MAX_FRAME_MEMORY; + + table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING_PARAMS]; + l2_fwd_params = table->entries; + l2_fwd_params->part_spc[0] = max_mem; + + /* If we have any critical-traffic virtual links, we need to reserve + * some frame buffer memory for them. At the moment, hardcode the value + * at 100 blocks of 128 bytes of memory each. This leaves 829 blocks + * remaining for best-effort traffic. TODO: figure out a more flexible + * way to perform the frame buffer partitioning. + */ + if (!priv->static_config.tables[BLK_IDX_VL_FORWARDING].entry_count) + return; + + table = &priv->static_config.tables[BLK_IDX_VL_FORWARDING_PARAMS]; + vl_fwd_params = table->entries; + + l2_fwd_params->part_spc[0] -= SJA1105_VL_FRAME_MEMORY; + vl_fwd_params->partspc[0] = SJA1105_VL_FRAME_MEMORY; +} + static int sja1105_init_general_params(struct sja1105_private *priv) { struct sja1105_general_params_entry default_general_params = { @@ -2196,6 +2231,8 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) l2_lookup_params = table->entries; l2_lookup_params->shared_learn = want_tagging; + sja1105_frame_memory_partitioning(priv); + rc = sja1105_static_config_reload(priv, SJA1105_VLAN_FILTERING); if (rc) dev_err(ds->dev, "Failed to change VLAN Ethertype\n"); diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.h b/drivers/net/dsa/sja1105/sja1105_static_config.h index d96044d86b11..5946847bb5b9 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.h +++ b/drivers/net/dsa/sja1105/sja1105_static_config.h @@ -108,6 +108,7 @@ enum sja1105_blk_idx { #define SJA1105_MAX_FRAME_MEMORY 929 #define SJA1105_MAX_FRAME_MEMORY_RETAGGING 910 +#define SJA1105_VL_FRAME_MEMORY 100 #define SJA1105E_DEVICE_ID 0x9C00000Cull #define SJA1105T_DEVICE_ID 0x9E00030Eull diff --git a/drivers/net/dsa/sja1105/sja1105_vl.c b/drivers/net/dsa/sja1105/sja1105_vl.c index aa9b0b92f437..9ce2b15b65d8 100644 --- a/drivers/net/dsa/sja1105/sja1105_vl.c +++ b/drivers/net/dsa/sja1105/sja1105_vl.c @@ -5,7 +5,6 @@ #include #include "sja1105.h" -#define SJA1105_VL_FRAME_MEMORY 100 #define SJA1105_SIZE_VL_STATUS 8 /* The switch flow classification core implements TTEthernet, which 'thinks' in @@ -141,8 +140,6 @@ static bool sja1105_vl_key_lower(struct sja1105_vl_lookup_entry *a, static int sja1105_init_virtual_links(struct sja1105_private *priv, struct netlink_ext_ack *extack) { - struct sja1105_l2_forwarding_params_entry *l2_fwd_params; - struct sja1105_vl_forwarding_params_entry *vl_fwd_params; struct sja1105_vl_policing_entry *vl_policing; struct sja1105_vl_forwarding_entry *vl_fwd; struct sja1105_vl_lookup_entry *vl_lookup; @@ -153,10 +150,6 @@ static int sja1105_init_virtual_links(struct sja1105_private *priv, int max_sharindx = 0; int i, j, k; - table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING_PARAMS]; - l2_fwd_params = table->entries; - l2_fwd_params->part_spc[0] = SJA1105_MAX_FRAME_MEMORY; - /* Figure out the dimensioning of the problem */ list_for_each_entry(rule, &priv->flow_block.rules, list) { if (rule->type != SJA1105_RULE_VL) @@ -308,17 +301,6 @@ static int sja1105_init_virtual_links(struct sja1105_private *priv, if (!table->entries) return -ENOMEM; table->entry_count = 1; - vl_fwd_params = table->entries; - - /* Reserve some frame buffer memory for the critical-traffic virtual - * links (this needs to be done). At the moment, hardcode the value - * at 100 blocks of 128 bytes of memory each. This leaves 829 blocks - * remaining for best-effort traffic. TODO: figure out a more flexible - * way to perform the frame buffer partitioning. - */ - l2_fwd_params->part_spc[0] = SJA1105_MAX_FRAME_MEMORY - - SJA1105_VL_FRAME_MEMORY; - vl_fwd_params->partspc[0] = SJA1105_VL_FRAME_MEMORY; for (i = 0; i < num_virtual_links; i++) { unsigned long cookie = vl_lookup[i].flow_cookie; @@ -342,6 +324,8 @@ static int sja1105_init_virtual_links(struct sja1105_private *priv, } } + sja1105_frame_memory_partitioning(priv); + return 0; } From patchwork Sun May 10 16:42:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 219522 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=-9.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, 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 C864CC54E8A for ; Sun, 10 May 2020 16:43:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9F3A520722 for ; Sun, 10 May 2020 16:43:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="td7ha/KH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729272AbgEJQnv (ORCPT ); Sun, 10 May 2020 12:43:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34886 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729216AbgEJQnp (ORCPT ); Sun, 10 May 2020 12:43:45 -0400 Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 04C8EC061A0E; Sun, 10 May 2020 09:43:45 -0700 (PDT) Received: by mail-wr1-x443.google.com with SMTP id y16so739926wrs.3; Sun, 10 May 2020 09:43:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=QI0sGT61QNjkAsm4hnHTocIk57rUXJXZziq0gMlf4xw=; b=td7ha/KHaJ8Bq5ajDl0zi903V6ryU/sgabM6zVjagKzQxmKcR4Dvb1RbOYNwySxqZr MeWahe6SYmsn3w/Ci1SeqzWbXZrnOZBz0abslSpgEcHTKdLafQHrTyHSTNs17Jmq2T4L i79mMOnuYOT5y9U34ykqH/AdQDUsD8ElH1TE/TKdk8nQdqnhWKGkL5jHjAcwGFXNltbt OOBV/L0eoy5JYInUoTOxgXaZDA2/e8LThcoqsK8rSJw3yarHoKoMn/a5uzadYeka/IcP oTidrVzU2z8z5jNw3Y/Bz1KqvQrHJfblppBbUEZI93vKC4DYQN+Q/YN1XAuSxILHetZH emhQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=QI0sGT61QNjkAsm4hnHTocIk57rUXJXZziq0gMlf4xw=; b=IUviKqhAjhPrywz44/uumb+9W1CRWa6e8A2fF+cND5mCk4c2S4Y/ZMCzUmyYahSIM4 W/qsbmWkqR6zCBYI9Qb+o6QJ/+FU1pfHp6S7wRXV/1CfvH9j2+mbOUpp3vlsHK2F9sjB uS43q46dlIWqExCdJG5muVJx+9JRCWzPD+o/fpN30S+/wvqOjr7mbkYWN1P0gFWeSrm0 +Tz4ygQilQYby45CN0+TNuEngKhYjuBYt/zwDc4L2CfqE5dRWyVtUg9vqC+9M2XUzwwS ChlhzZEu0eq1WadvYJXd1p1mUATISIJnKrzoSztaoLX+dZ53iXHIYcV0nY1tvClEv+l8 U/2A== X-Gm-Message-State: AGi0PuaLn3Q84ba2k7o9u44XWz9+FP51uHZtiOcY/3MvTy8QVJJYII2G Uarlx4Q03dOcGsGmc9wTuxc= X-Google-Smtp-Source: APiQypIG6R4zKgnl/PGN2KxF+mf+XKvgHN9PT526RTpyHPzlGkwETkjQMaOgngnBHHmc4OjaQ+XEyQ== X-Received: by 2002:a5d:6702:: with SMTP id o2mr8246235wru.231.1589129023588; Sun, 10 May 2020 09:43:43 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:43 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 14/15] net: dsa: sja1105: implement VLAN retagging for dsa_8021q sub-VLANs Date: Sun, 10 May 2020 19:42:54 +0300 Message-Id: <20200510164255.19322-15-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean Expand the delta commit procedure for VLANs with additional logic for treating bridge_vlans in the newly introduced operating mode, SJA1105_VLAN_BEST_EFFORT. For every bridge VLAN on every user port, a sub-VLAN index is calculated and retagging rules are installed towards a dsa_8021q rx_vid that encodes that sub-VLAN index. This way, the tagger can identify the original VLANs. Extra care is taken for VLANs to still work as intended in cross-chip scenarios. Retagging may have unintended consequences for these because a sub-VLAN encoding that works for the CPU does not make any sense for a front-panel port. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105_main.c | 412 ++++++++++++++++++++++++- 1 file changed, 409 insertions(+), 3 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 9e93a9af4913..f974d2ace72b 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1849,6 +1849,57 @@ sja1105_get_tag_protocol(struct dsa_switch *ds, int port, return DSA_TAG_PROTO_SJA1105; } +static int sja1105_find_free_subvlan(u16 *subvlan_map, bool pvid) +{ + int subvlan; + + if (pvid) + return 0; + + for (subvlan = 1; subvlan < DSA_8021Q_N_SUBVLAN; subvlan++) + if (subvlan_map[subvlan] == VLAN_N_VID) + return subvlan; + + return -1; +} + +static int sja1105_find_subvlan(u16 *subvlan_map, u16 vid) +{ + int subvlan; + + for (subvlan = 0; subvlan < DSA_8021Q_N_SUBVLAN; subvlan++) + if (subvlan_map[subvlan] == vid) + return subvlan; + + return -1; +} + +static int sja1105_find_committed_subvlan(struct sja1105_private *priv, + int port, u16 vid) +{ + struct sja1105_port *sp = &priv->ports[port]; + + return sja1105_find_subvlan(sp->subvlan_map, vid); +} + +static void sja1105_init_subvlan_map(u16 *subvlan_map) +{ + int subvlan; + + for (subvlan = 0; subvlan < DSA_8021Q_N_SUBVLAN; subvlan++) + subvlan_map[subvlan] = VLAN_N_VID; +} + +static void sja1105_commit_subvlan_map(struct sja1105_private *priv, int port, + u16 *subvlan_map) +{ + struct sja1105_port *sp = &priv->ports[port]; + int subvlan; + + for (subvlan = 0; subvlan < DSA_8021Q_N_SUBVLAN; subvlan++) + sp->subvlan_map[subvlan] = subvlan_map[subvlan]; +} + static int sja1105_is_vlan_configured(struct sja1105_private *priv, u16 vid) { struct sja1105_vlan_lookup_entry *vlan; @@ -1865,9 +1916,29 @@ static int sja1105_is_vlan_configured(struct sja1105_private *priv, u16 vid) return -1; } +static int +sja1105_find_retagging_entry(struct sja1105_retagging_entry *retagging, + int count, int from_port, u16 from_vid, + u16 to_vid) +{ + int i; + + for (i = 0; i < count; i++) + if (retagging[i].ing_port == BIT(from_port) && + retagging[i].vlan_ing == from_vid && + retagging[i].vlan_egr == to_vid) + return i; + + /* Return an invalid entry index if not found */ + return -1; +} + static int sja1105_commit_vlans(struct sja1105_private *priv, - struct sja1105_vlan_lookup_entry *new_vlan) + struct sja1105_vlan_lookup_entry *new_vlan, + struct sja1105_retagging_entry *new_retagging, + int num_retagging) { + struct sja1105_retagging_entry *retagging; struct sja1105_vlan_lookup_entry *vlan; struct sja1105_table *table; int num_vlans = 0; @@ -1927,9 +1998,50 @@ static int sja1105_commit_vlans(struct sja1105_private *priv, vlan[k++] = new_vlan[i]; } + /* VLAN Retagging Table */ + table = &priv->static_config.tables[BLK_IDX_RETAGGING]; + retagging = table->entries; + + for (i = 0; i < table->entry_count; i++) { + rc = sja1105_dynamic_config_write(priv, BLK_IDX_RETAGGING, + i, &retagging[i], false); + if (rc) + return rc; + } + + if (table->entry_count) + kfree(table->entries); + + table->entries = kcalloc(num_retagging, table->ops->unpacked_entry_size, + GFP_KERNEL); + if (!table->entries) + return -ENOMEM; + + table->entry_count = num_retagging; + retagging = table->entries; + + for (i = 0; i < num_retagging; i++) { + retagging[i] = new_retagging[i]; + + /* Update entry */ + rc = sja1105_dynamic_config_write(priv, BLK_IDX_RETAGGING, + i, &retagging[i], true); + if (rc < 0) + return rc; + } + return 0; } +struct sja1105_crosschip_vlan { + struct list_head list; + u16 vid; + bool untagged; + int port; + int other_port; + struct dsa_switch *other_ds; +}; + struct sja1105_crosschip_switch { struct list_head list; struct dsa_switch *other_ds; @@ -2001,6 +2113,265 @@ sja1105_build_dsa_8021q_vlans(struct sja1105_private *priv, return 0; } +static int sja1105_build_subvlans(struct sja1105_private *priv, + u16 subvlan_map[][DSA_8021Q_N_SUBVLAN], + struct sja1105_vlan_lookup_entry *new_vlan, + struct sja1105_retagging_entry *new_retagging, + int *num_retagging) +{ + struct sja1105_bridge_vlan *v; + int k = *num_retagging; + + if (priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) + return 0; + + list_for_each_entry(v, &priv->bridge_vlans, list) { + int upstream = dsa_upstream_port(priv->ds, v->port); + int match, subvlan; + u16 rx_vid; + + /* Only sub-VLANs on user ports need to be applied. + * Bridge VLANs also include VLANs added automatically + * by DSA on the CPU port. + */ + if (!dsa_is_user_port(priv->ds, v->port)) + continue; + + subvlan = sja1105_find_subvlan(subvlan_map[v->port], + v->vid); + if (subvlan < 0) { + subvlan = sja1105_find_free_subvlan(subvlan_map[v->port], + v->pvid); + if (subvlan < 0) { + dev_err(priv->ds->dev, "No more free subvlans\n"); + return -ENOSPC; + } + } + + rx_vid = dsa_8021q_rx_vid_subvlan(priv->ds, v->port, subvlan); + + /* @v->vid on @v->port needs to be retagged to @rx_vid + * on @upstream. Assume @v->vid on @v->port and on + * @upstream was already configured by the previous + * iteration over bridge_vlans. + */ + match = rx_vid; + new_vlan[match].vlanid = rx_vid; + new_vlan[match].vmemb_port |= BIT(v->port); + new_vlan[match].vmemb_port |= BIT(upstream); + new_vlan[match].vlan_bc |= BIT(v->port); + new_vlan[match].vlan_bc |= BIT(upstream); + /* The "untagged" flag is set the same as for the + * original VLAN + */ + if (!v->untagged) + new_vlan[match].tag_port |= BIT(v->port); + /* But it's always tagged towards the CPU */ + new_vlan[match].tag_port |= BIT(upstream); + + /* The Retagging Table generates packet *clones* with + * the new VLAN. This is a very odd hardware quirk + * which we need to suppress by dropping the original + * packet. + * Deny egress of the original VLAN towards the CPU + * port. This will force the switch to drop it, and + * we'll see only the retagged packets. + */ + match = v->vid; + new_vlan[match].vlan_bc &= ~BIT(upstream); + + /* And the retagging itself */ + new_retagging[k].vlan_ing = v->vid; + new_retagging[k].vlan_egr = rx_vid; + new_retagging[k].ing_port = BIT(v->port); + new_retagging[k].egr_port = BIT(upstream); + if (k++ == SJA1105_MAX_RETAGGING_COUNT) { + dev_err(priv->ds->dev, "No more retagging rules\n"); + return -ENOSPC; + } + + subvlan_map[v->port][subvlan] = v->vid; + } + + *num_retagging = k; + + return 0; +} + +/* Sadly, in crosschip scenarios where the CPU port is also the link to another + * switch, we should retag backwards (the dsa_8021q vid to the original vid) on + * the CPU port of neighbour switches. + */ +static int +sja1105_build_crosschip_subvlans(struct sja1105_private *priv, + struct sja1105_vlan_lookup_entry *new_vlan, + struct sja1105_retagging_entry *new_retagging, + int *num_retagging) +{ + struct sja1105_crosschip_vlan *tmp, *pos; + struct dsa_8021q_crosschip_link *c; + struct sja1105_bridge_vlan *v, *w; + struct list_head crosschip_vlans; + int k = *num_retagging; + int rc = 0; + + if (priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) + return 0; + + INIT_LIST_HEAD(&crosschip_vlans); + + list_for_each_entry(c, &priv->crosschip_links, list) { + struct sja1105_private *other_priv = c->other_ds->priv; + + if (other_priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) + continue; + + /* Crosschip links are also added to the CPU ports. + * Ignore those. + */ + if (!dsa_is_user_port(priv->ds, c->port)) + continue; + if (!dsa_is_user_port(c->other_ds, c->other_port)) + continue; + + /* Search for VLANs on the remote port */ + list_for_each_entry(v, &other_priv->bridge_vlans, list) { + bool already_added = false; + bool we_have_it = false; + + if (v->port != c->other_port) + continue; + + /* If @v is a pvid on @other_ds, it does not need + * re-retagging, because its SVL field is 0 and we + * already allow that, via the dsa_8021q crosschip + * links. + */ + if (v->pvid) + continue; + + /* Search for the VLAN on our local port */ + list_for_each_entry(w, &priv->bridge_vlans, list) { + if (w->port == c->port && w->vid == v->vid) { + we_have_it = true; + break; + } + } + + if (!we_have_it) + continue; + + list_for_each_entry(tmp, &crosschip_vlans, list) { + if (tmp->vid == v->vid && + tmp->untagged == v->untagged && + tmp->port == c->port && + tmp->other_port == v->port && + tmp->other_ds == c->other_ds) { + already_added = true; + break; + } + } + + if (already_added) + continue; + + tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) { + dev_err(priv->ds->dev, "Failed to allocate memory\n"); + rc = -ENOMEM; + goto out; + } + tmp->vid = v->vid; + tmp->port = c->port; + tmp->other_port = v->port; + tmp->other_ds = c->other_ds; + tmp->untagged = v->untagged; + list_add(&tmp->list, &crosschip_vlans); + } + } + + list_for_each_entry(tmp, &crosschip_vlans, list) { + struct sja1105_private *other_priv = tmp->other_ds->priv; + int upstream = dsa_upstream_port(priv->ds, tmp->port); + int match, subvlan; + u16 rx_vid; + + subvlan = sja1105_find_committed_subvlan(other_priv, + tmp->other_port, + tmp->vid); + /* If this happens, it's a bug. The neighbour switch does not + * have a subvlan for tmp->vid on tmp->other_port, but it + * should, since we already checked for its vlan_state. + */ + if (WARN_ON(subvlan < 0)) { + rc = -EINVAL; + goto out; + } + + rx_vid = dsa_8021q_rx_vid_subvlan(tmp->other_ds, + tmp->other_port, + subvlan); + + /* The @rx_vid retagged from @tmp->vid on + * {@tmp->other_ds, @tmp->other_port} needs to be + * re-retagged to @tmp->vid on the way back to us. + * + * Assume the original @tmp->vid is already configured + * on this local switch, otherwise we wouldn't be + * retagging its subvlan on the other switch in the + * first place. We just need to add a reverse retagging + * rule for @rx_vid and install @rx_vid on our ports. + */ + match = rx_vid; + new_vlan[match].vlanid = rx_vid; + new_vlan[match].vmemb_port |= BIT(tmp->port); + new_vlan[match].vmemb_port |= BIT(upstream); + /* The "untagged" flag is set the same as for the + * original VLAN. And towards the CPU, it doesn't + * really matter, because @rx_vid will only receive + * traffic on that port. For consistency with other dsa_8021q + * VLANs, we'll keep the CPU port tagged. + */ + if (!tmp->untagged) + new_vlan[match].tag_port |= BIT(tmp->port); + new_vlan[match].tag_port |= BIT(upstream); + /* Deny egress of @rx_vid towards our front-panel port. + * This will force the switch to drop it, and we'll see + * only the re-retagged packets (having the original, + * pre-initial-retagging, VLAN @tmp->vid). + */ + new_vlan[match].vlan_bc &= ~BIT(tmp->port); + + /* On reverse retagging, the same ingress VLAN goes to multiple + * ports. So we have an opportunity to create composite rules + * to not waste the limited space in the retagging table. + */ + k = sja1105_find_retagging_entry(new_retagging, *num_retagging, + upstream, rx_vid, tmp->vid); + if (k < 0) { + if (*num_retagging == SJA1105_MAX_RETAGGING_COUNT) { + dev_err(priv->ds->dev, "No more retagging rules\n"); + rc = -ENOSPC; + goto out; + } + k = (*num_retagging)++; + } + /* And the retagging itself */ + new_retagging[k].vlan_ing = rx_vid; + new_retagging[k].vlan_egr = tmp->vid; + new_retagging[k].ing_port = BIT(upstream); + new_retagging[k].egr_port |= BIT(tmp->port); + } + +out: + list_for_each_entry_safe(tmp, pos, &crosschip_vlans, list) { + list_del(&tmp->list); + kfree(tmp); + } + + return rc; +} + static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify); static int sja1105_notify_crosschip_switches(struct sja1105_private *priv) @@ -2054,10 +2425,12 @@ static int sja1105_notify_crosschip_switches(struct sja1105_private *priv) static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) { + u16 subvlan_map[SJA1105_NUM_PORTS][DSA_8021Q_N_SUBVLAN]; + struct sja1105_retagging_entry *new_retagging; struct sja1105_vlan_lookup_entry *new_vlan; struct sja1105_table *table; + int i, num_retagging = 0; int rc; - int i; table = &priv->static_config.tables[BLK_IDX_VLAN_LOOKUP]; new_vlan = kcalloc(VLAN_N_VID, @@ -2065,9 +2438,23 @@ static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) if (!new_vlan) return -ENOMEM; + table = &priv->static_config.tables[BLK_IDX_VLAN_LOOKUP]; + new_retagging = kcalloc(SJA1105_MAX_RETAGGING_COUNT, + table->ops->unpacked_entry_size, GFP_KERNEL); + if (!new_retagging) { + kfree(new_vlan); + return -ENOMEM; + } + for (i = 0; i < VLAN_N_VID; i++) new_vlan[i].vlanid = VLAN_N_VID; + for (i = 0; i < SJA1105_MAX_RETAGGING_COUNT; i++) + new_retagging[i].vlan_ing = VLAN_N_VID; + + for (i = 0; i < priv->ds->num_ports; i++) + sja1105_init_subvlan_map(subvlan_map[i]); + /* Bridge VLANs */ rc = sja1105_build_bridge_vlans(priv, new_vlan); if (rc) @@ -2082,7 +2469,22 @@ static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) if (rc) goto out; - rc = sja1105_commit_vlans(priv, new_vlan); + /* Private VLANs necessary for dsa_8021q operation, which we need to + * determine on our own: + * - Sub-VLANs + * - Sub-VLANs of crosschip switches + */ + rc = sja1105_build_subvlans(priv, subvlan_map, new_vlan, new_retagging, + &num_retagging); + if (rc) + goto out; + + rc = sja1105_build_crosschip_subvlans(priv, new_vlan, new_retagging, + &num_retagging); + if (rc) + goto out; + + rc = sja1105_commit_vlans(priv, new_vlan, new_retagging, num_retagging); if (rc) goto out; @@ -2090,6 +2492,9 @@ static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) if (rc) goto out; + for (i = 0; i < priv->ds->num_ports; i++) + sja1105_commit_subvlan_map(priv, i, subvlan_map[i]); + if (notify) { rc = sja1105_notify_crosschip_switches(priv); if (rc) @@ -2098,6 +2503,7 @@ static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) out: kfree(new_vlan); + kfree(new_retagging); return rc; }