Received: by 2002:a05:6a10:9e8c:0:0:0:0 with SMTP id y12csp1568703pxx; Fri, 30 Oct 2020 13:11:08 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwOJmhnHOMy0QdxpELOpDUT7KxJ+hcdQC74cZwhm3Jeo2HlqP0sVg5OnilHMC0rKGC8i33e X-Received: by 2002:a17:906:4d03:: with SMTP id r3mr3980218eju.364.1604088668635; Fri, 30 Oct 2020 13:11:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1604088668; cv=none; d=google.com; s=arc-20160816; b=Cy6zN4o5kLi+XxtVt+QuS0S/XTfLfxvgEYwjV1q9VoskpcvyxCXwM7gwmn2J3nBBBn qtfEq/1hXzwUTASdEI6h2J5vjZVQR9wao8YCdm5gxDnadNCprxWDNszn48GTe1HaIRs5 Cuwh6keHIEXZ/WldZ/qHE2LiN9AmxaHoZXccKCJhVIakz5BpFSR6OpNJVsam+2ez1d4z N3snO91J7fLLdFmPdFBh/52zagfHz0nd2GivXWHQ5MAfjMmU+05S1x7jqA76PGWH0uRO G1HYJ+lfSQOMqa+vBn0qxOEi55PilXTwL1/OFaUvsx4yBct7vIOlRte1w5iOVWY2J0CR 4WMQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=sINLZzRvjCtUj4l1ugcfLeB492coR1IzG3yWTNfER3U=; b=09A+Knx69bD8Tn8w/t6Xhq0gkFF8bYM6ZfQKln0S9UMkfqG9NPpl5xbi+RIYlB/V0w UphbSHfDVaTq4bq76SCGpdR1/whdmfkCgjtl58d8f2tJLFE59SVi4DdgDpQsgEDk92Ek v2YtLhQoZ8hyE/tTi+PoAtV9gXZLRwnCzSt76k7m6j6dNdkzWcHGgLWrL7GO+STEjJsN pT5KDXKML2ix2rdISlITMb6C2y++m2uuBosxPGgxRP/bRqIK/EbMg3/2CkEM9B+BtONe wzsswk2jp2PGZjac9SiTHxdS2kmbopBf6XcjPxuBA7yWc8gVH2u05IhJiDU5WBOyUDwc b7uQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=XBEYzCX9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id k6si5647160edl.228.2020.10.30.13.10.46; Fri, 30 Oct 2020 13:11:08 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=XBEYzCX9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727801AbgJ3UHi (ORCPT + 99 others); Fri, 30 Oct 2020 16:07:38 -0400 Received: from fllv0016.ext.ti.com ([198.47.19.142]:37816 "EHLO fllv0016.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727747AbgJ3UHd (ORCPT ); Fri, 30 Oct 2020 16:07:33 -0400 Received: from fllv0034.itg.ti.com ([10.64.40.246]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id 09UK7SWp104233; Fri, 30 Oct 2020 15:07:28 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1604088448; bh=sINLZzRvjCtUj4l1ugcfLeB492coR1IzG3yWTNfER3U=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=XBEYzCX9uJu4NKjY0ERf1jURd1hRYVaBQymETbP26ZZT8A1XBZ6fQHA5A52bnxrzW iLldxEz+4x6SMI5PjOevaZY+2007F6dMLC4NXb/YPhOsptRWqi/EOe3lS5rT0uPxhy /KuPnom1QUB4+ZgcNzwmap1gs2H/d7D1OZxbuCiA= Received: from DFLE108.ent.ti.com (dfle108.ent.ti.com [10.64.6.29]) by fllv0034.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 09UK7Sfa055505 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 30 Oct 2020 15:07:28 -0500 Received: from DFLE102.ent.ti.com (10.64.6.23) by DFLE108.ent.ti.com (10.64.6.29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1979.3; Fri, 30 Oct 2020 15:07:27 -0500 Received: from fllv0039.itg.ti.com (10.64.41.19) by DFLE102.ent.ti.com (10.64.6.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1979.3 via Frontend Transport; Fri, 30 Oct 2020 15:07:27 -0500 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by fllv0039.itg.ti.com (8.15.2/8.15.2) with ESMTP id 09UK7QQv028907; Fri, 30 Oct 2020 15:07:27 -0500 From: Grygorii Strashko To: "David S. Miller" , , Jakub Kicinski , Vignesh Raghavendra CC: Sekhar Nori , , , "Reviewed-by : Jesse Brandeburg" , Grygorii Strashko Subject: [PATCH net-next v3 05/10] net: ethernet: ti: am65-cpsw: fix vlan offload for multi mac mode Date: Fri, 30 Oct 2020 22:07:02 +0200 Message-ID: <20201030200707.24294-6-grygorii.strashko@ti.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201030200707.24294-1-grygorii.strashko@ti.com> References: <20201030200707.24294-1-grygorii.strashko@ti.com> MIME-Version: 1.0 Content-Type: text/plain X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The VLAN offload for AM65x CPSW2G is implemented using existing ALE APIs, which are also used by legacy CPSW drivers. So, now it always adds current Ext. Port and Host as VLAN members when VLAN is added by 8021Q core (.ndo_vlan_rx_add_vid) and forcibly removes VLAN from ALE table in .ndo_vlan_rx_kill_vid(). This works as for AM65x CPSW2G (which has only one Ext. Port) as for legacy CPSW devices (which can't support same VLAN on more then one Port in multi mac (dual-mac) mode). But it doesn't work for the new J721E and AM64x multi port CPSWxG versions doesn't have such restrictions and allow to offload the same VLAN on any number of ports. Now the attempt to add same VLAN on two (or more) K3 CPSWxG Ports will cause: - VLAN members mask overwrite when VLAN is added - VLAN removal from ALE table when any Port removes VLAN This patch fixes an issue by: - switching to use cpsw_ale_vlan_add_modify() instead of cpsw_ale_add_vlan() when VLAN is added to ALE table, so VLAN members mask will not be overwritten; - Updates cpsw_ale_del_vlan() as: if more than one ext. Port is in VLAN member mask then remove only current port from VLAN member mask else remove VLAN ALE entry Example: add: P1 | P0 (Host) -> members mask: P1 | P0 add: P2 | P0 -> members mask: P2 | P1 | P0 rem: P1 | P0 -> members mask: P2 | P0 rem: P2 | P0 -> members mask: - The VLAN is forcibly removed if port_mask=0 passed to cpsw_ale_del_vlan() to preserve existing legacy CPSW drivers functionality. Signed-off-by: Grygorii Strashko Reviewed-by: Jesse Brandeburg --- drivers/net/ethernet/ti/am65-cpsw-nuss.c | 8 +++++--- drivers/net/ethernet/ti/cpsw_ale.c | 19 +++++++++++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index 65c5446e324e..fecaf6b8270f 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -241,8 +241,8 @@ static int am65_cpsw_nuss_ndo_slave_add_vid(struct net_device *ndev, if (!vid) unreg_mcast = port_mask; dev_info(common->dev, "Adding vlan %d to vlan filter\n", vid); - ret = cpsw_ale_add_vlan(common->ale, vid, port_mask, - unreg_mcast, port_mask, 0); + ret = cpsw_ale_vlan_add_modify(common->ale, vid, port_mask, + unreg_mcast, port_mask, 0); pm_runtime_put(common->dev); return ret; @@ -252,6 +252,7 @@ static int am65_cpsw_nuss_ndo_slave_kill_vid(struct net_device *ndev, __be16 proto, u16 vid) { struct am65_cpsw_common *common = am65_ndev_to_common(ndev); + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); int ret; if (!netif_running(ndev) || !vid) @@ -264,7 +265,8 @@ static int am65_cpsw_nuss_ndo_slave_kill_vid(struct net_device *ndev, } dev_info(common->dev, "Removing vlan %d from vlan filter\n", vid); - ret = cpsw_ale_del_vlan(common->ale, vid, 0); + ret = cpsw_ale_del_vlan(common->ale, vid, + BIT(port->port_id) | ALE_PORT_HOST); pm_runtime_put(common->dev); return ret; diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c index b1cce39eda17..cdc308a2aa3e 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.c +++ b/drivers/net/ethernet/ti/cpsw_ale.c @@ -694,7 +694,7 @@ int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask) int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask) { u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; - int idx; + int members, idx; idx = cpsw_ale_match_vlan(ale, vid); if (idx < 0) @@ -702,11 +702,22 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask) cpsw_ale_read(ale, idx, ale_entry); - if (port_mask) { - cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask); - } else { + /* if !port_mask - force remove VLAN (legacy). + * Check if there are other VLAN members ports + * if no - remove VLAN. + * if yes it means same VLAN was added to >1 port in multi port mode, so + * remove port_mask ports from VLAN ALE entry excluding Host port. + */ + members = cpsw_ale_vlan_get_fld(ale, ale_entry, ALE_ENT_VID_MEMBER_LIST); + members &= ~port_mask; + + if (!port_mask || !members) { + /* last port or force remove - remove VLAN */ cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0); cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); + } else { + port_mask &= ~ALE_PORT_HOST; + cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask); } cpsw_ale_write(ale, idx, ale_entry); -- 2.17.1