From patchwork Mon Dec 23 09:25:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: MD Danish Anwar X-Patchwork-Id: 13918631 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7FE64E7718B for ; Mon, 23 Dec 2024 09:30:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type: Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date :Subject:CC:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=6cZrHKkJFMqtSt9H2JnEWM9Ru6S2s3la+DRB+YAd7WM=; b=VzjHFX+DpPThbTPU4TzoCAgEPn C+FtgSjBOLYU+v0L4ieRDQANODO/e9E2PpfaOgaF4Lmnz8UMEsuCHxmwRFYYQNF1ypqyq04RjB+et 1cTt8kolNqrIZezhZ7tKY5dWZKyOlfKlDqlbYu6S0UvX3duNuPDfElFuDYS3cjBmcC96k8nJFEIvv XdTy3cBc+XGb6D/5tIJSpoWwi5L+C4wOUwR/wEwSi0qb85YujWGjg+WpQeMBUFo2+NZmQOXEEAp/7 DTb71yaR67JzEzljijJSJ8uayZIU5isqBD4yhCxNyjCwnCJ7+paMO7uJjcv/cpW5WuK3mF5QTeYZV q8pwBngA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tPel9-00000009eWO-42GO; Mon, 23 Dec 2024 09:29:55 +0000 Received: from lelvem-ot02.ext.ti.com ([198.47.23.235]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tPehj-00000009e7g-0B0e for linux-arm-kernel@lists.infradead.org; Mon, 23 Dec 2024 09:26:24 +0000 Received: from fllv0035.itg.ti.com ([10.64.41.0]) by lelvem-ot02.ext.ti.com (8.15.2/8.15.2) with ESMTPS id 4BN9Q5QY856700 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 23 Dec 2024 03:26:05 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1734945965; bh=6cZrHKkJFMqtSt9H2JnEWM9Ru6S2s3la+DRB+YAd7WM=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=jruOE6ETw61vjGzZi37i4d2di4SACsbLisaHsG727tdhy6jSejPHJnSvoc36SFTtn dX8btz2Kt/M0ZpP7+R0fmRgFos+a+rAX/DKi4M2s/pK5lL9fYRuUkJw0Rl/BhGSnV7 gMJMn0WDhb07RXk3DCGiYmkXrSPO/C5iISBSbt7g= Received: from DLEE103.ent.ti.com (dlee103.ent.ti.com [157.170.170.33]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 4BN9Q541093123 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 23 Dec 2024 03:26:05 -0600 Received: from DLEE113.ent.ti.com (157.170.170.24) by DLEE103.ent.ti.com (157.170.170.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Mon, 23 Dec 2024 03:26:04 -0600 Received: from lelvsmtp5.itg.ti.com (10.180.75.250) by DLEE113.ent.ti.com (157.170.170.24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Mon, 23 Dec 2024 03:26:04 -0600 Received: from fllv0122.itg.ti.com (fllv0122.itg.ti.com [10.247.120.72]) by lelvsmtp5.itg.ti.com (8.15.2/8.15.2) with ESMTP id 4BN9Q4m9012184; Mon, 23 Dec 2024 03:26:04 -0600 Received: from localhost (danish-tpc.dhcp.ti.com [10.24.69.25]) by fllv0122.itg.ti.com (8.14.7/8.14.7) with ESMTP id 4BN9Q3Pi006706; Mon, 23 Dec 2024 03:26:04 -0600 From: MD Danish Anwar To: , , , , , , , , , , , CC: , , , , Vignesh Raghavendra , Roger Quadros , , Larysa Zaremba , Michal Swiatkowski Subject: [PATCH net-next v2 2/3] net: ti: icssg-prueth: Add Multicast Filtering support for VLAN in MAC mode Date: Mon, 23 Dec 2024 14:55:56 +0530 Message-ID: <20241223092557.2077526-3-danishanwar@ti.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241223092557.2077526-1-danishanwar@ti.com> References: <20241223092557.2077526-1-danishanwar@ti.com> MIME-Version: 1.0 X-C2ProcessedOrg: 333ef613-75bf-4e12-a4b1-8e3623f5dcea X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241223_012623_194920_2DCC7479 X-CRM114-Status: GOOD ( 21.13 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add multicast filtering support for VLAN interfaces in dual EMAC mode for ICSSG driver. The driver uses vlan_for_each() API to get the list of available vlans. The driver then sync mc addr of vlan interface with a locally mainatined list emac->vlan_mcast_list[vid] using __hw_addr_sync_multiple() API. The driver then calls the sync / unsync callbacks and based on whether the ndev is vlan or not, driver passes appropriate vid to FDB helper functions. This commit also exports __hw_addr_sync_multiple() in order to use it from the ICSSG driver. Signed-off-by: MD Danish Anwar --- drivers/net/ethernet/ti/icssg/icssg_prueth.c | 67 ++++++++++++++++---- drivers/net/ethernet/ti/icssg/icssg_prueth.h | 6 ++ include/linux/netdevice.h | 3 + net/core/dev_addr_lists.c | 7 +- 4 files changed, 66 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index 1663941e59e3..ed8b5a3184d6 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -472,30 +472,44 @@ const struct icss_iep_clockops prueth_iep_clockops = { static int icssg_prueth_add_mcast(struct net_device *ndev, const u8 *addr) { - struct prueth_emac *emac = netdev_priv(ndev); - int port_mask = BIT(emac->port_id); + struct net_device *real_dev; + struct prueth_emac *emac; + int port_mask; + u8 vlan_id; - port_mask |= icssg_fdb_lookup(emac, addr, 0); - icssg_fdb_add_del(emac, addr, 0, port_mask, true); - icssg_vtbl_modify(emac, 0, port_mask, port_mask, true); + vlan_id = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : PRUETH_DFLT_VLAN_MAC; + real_dev = is_vlan_dev(ndev) ? vlan_dev_real_dev(ndev) : ndev; + emac = netdev_priv(real_dev); + + port_mask = BIT(emac->port_id) | icssg_fdb_lookup(emac, addr, vlan_id); + icssg_fdb_add_del(emac, addr, vlan_id, port_mask, true); + icssg_vtbl_modify(emac, vlan_id, port_mask, port_mask, true); return 0; } static int icssg_prueth_del_mcast(struct net_device *ndev, const u8 *addr) { - struct prueth_emac *emac = netdev_priv(ndev); - int port_mask = BIT(emac->port_id); + struct net_device *real_dev; + struct prueth_emac *emac; int other_port_mask; + int port_mask; + u8 vlan_id; + + vlan_id = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : PRUETH_DFLT_VLAN_MAC; + real_dev = is_vlan_dev(ndev) ? vlan_dev_real_dev(ndev) : ndev; + emac = netdev_priv(real_dev); - other_port_mask = port_mask ^ icssg_fdb_lookup(emac, addr, 0); + port_mask = BIT(emac->port_id); + other_port_mask = port_mask ^ icssg_fdb_lookup(emac, addr, vlan_id); - icssg_fdb_add_del(emac, addr, 0, port_mask, false); - icssg_vtbl_modify(emac, 0, port_mask, port_mask, false); + icssg_fdb_add_del(emac, addr, vlan_id, port_mask, false); + icssg_vtbl_modify(emac, vlan_id, port_mask, port_mask, false); if (other_port_mask) { - icssg_fdb_add_del(emac, addr, 0, other_port_mask, true); - icssg_vtbl_modify(emac, 0, other_port_mask, other_port_mask, true); + icssg_fdb_add_del(emac, addr, vlan_id, other_port_mask, true); + icssg_vtbl_modify(emac, vlan_id, other_port_mask, + other_port_mask, true); } return 0; @@ -531,6 +545,25 @@ static int icssg_prueth_hsr_del_mcast(struct net_device *ndev, const u8 *addr) return 0; } +static int icssg_update_vlan_mcast(struct net_device *vdev, int vid, + void *args) +{ + struct prueth_emac *emac = args; + + if (!vdev || !vid) + return 0; + + netif_addr_lock_bh(vdev); + __hw_addr_sync_multiple(&emac->vlan_mcast_list[vid], &vdev->mc, + vdev->addr_len); + netif_addr_unlock_bh(vdev); + + __hw_addr_sync_dev(&emac->vlan_mcast_list[vid], vdev, + icssg_prueth_add_mcast, icssg_prueth_del_mcast); + + return 0; +} + /** * emac_ndo_open - EMAC device open * @ndev: network adapter device @@ -772,12 +805,17 @@ static void emac_ndo_set_rx_mode_work(struct work_struct *work) return; } - if (emac->prueth->is_hsr_offload_mode) + if (emac->prueth->is_hsr_offload_mode) { __dev_mc_sync(ndev, icssg_prueth_hsr_add_mcast, icssg_prueth_hsr_del_mcast); - else + } else { __dev_mc_sync(ndev, icssg_prueth_add_mcast, icssg_prueth_del_mcast); + if (rtnl_trylock()) { + vlan_for_each(ndev, icssg_update_vlan_mcast, emac); + rtnl_unlock(); + } + } } /** @@ -828,6 +866,7 @@ static int emac_ndo_vlan_rx_add_vid(struct net_device *ndev, if (prueth->is_hsr_offload_mode) port_mask |= BIT(PRUETH_PORT_HOST); + __hw_addr_init(&emac->vlan_mcast_list[vid]); netdev_dbg(emac->ndev, "VID add vid:%u port_mask:%X untag_mask %X\n", vid, port_mask, untag_mask); diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index f5c1d473e9f9..4da8b87408b5 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -83,6 +83,10 @@ #define ICSS_CMD_ADD_FILTER 0x7 #define ICSS_CMD_ADD_MAC 0x8 +/* VLAN Filtering Related MACROs */ +#define PRUETH_DFLT_VLAN_MAC 0 +#define MAX_VLAN_ID 256 + /* In switch mode there are 3 real ports i.e. 3 mac addrs. * however Linux sees only the host side port. The other 2 ports * are the switch ports. @@ -201,6 +205,8 @@ struct prueth_emac { /* RX IRQ Coalescing Related */ struct hrtimer rx_hrtimer; unsigned long rx_pace_timeout_ns; + + struct netdev_hw_addr_list vlan_mcast_list[MAX_VLAN_ID]; }; /** diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 2593019ad5b1..3ee833e9b6f7 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -4689,6 +4689,9 @@ int devm_register_netdev(struct device *dev, struct net_device *ndev); /* General hardware address lists handling functions */ int __hw_addr_sync(struct netdev_hw_addr_list *to_list, struct netdev_hw_addr_list *from_list, int addr_len); +int __hw_addr_sync_multiple(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len); void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, struct netdev_hw_addr_list *from_list, int addr_len); int __hw_addr_sync_dev(struct netdev_hw_addr_list *list, diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 166e404f7c03..90716bd736f3 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -242,9 +242,9 @@ static void __hw_addr_unsync_one(struct netdev_hw_addr_list *to_list, __hw_addr_del_entry(from_list, ha, false, false); } -static int __hw_addr_sync_multiple(struct netdev_hw_addr_list *to_list, - struct netdev_hw_addr_list *from_list, - int addr_len) +int __hw_addr_sync_multiple(struct netdev_hw_addr_list *to_list, + struct netdev_hw_addr_list *from_list, + int addr_len) { int err = 0; struct netdev_hw_addr *ha, *tmp; @@ -260,6 +260,7 @@ static int __hw_addr_sync_multiple(struct netdev_hw_addr_list *to_list, } return err; } +EXPORT_SYMBOL(__hw_addr_sync_multiple); /* This function only works where there is a strict 1-1 relationship * between source and destination of they synch. If you ever need to