From patchwork Thu Sep 30 07:59:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaoliang Yang X-Patchwork-Id: 12527577 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 95EF2C433EF for ; Thu, 30 Sep 2021 07:50:54 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 5F7EF61527 for ; Thu, 30 Sep 2021 07:50:54 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 5F7EF61527 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=nxp.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id: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=B0clDnwZox69I6xknthG/EbL5zV8s9BphMp45otw3L4=; b=cGgd4JDeRysRmc dlKAGlURZyxON2tUcWa/iTXIyxjM7mtTbzVrVIeHSZuTWADZJT8+tNCdIrtl6jc2M4tCPDyroeD7y qxHYPzQexl5Kvp3utuhQn0MO96g+UwpkgrVmdpoy8Ur0a/WHGBpYzSbSsr8gr2V53UxSdxX6GRIvD bd9bMDSfneKIOhaYsLeARlDj3IjhlaqrpTFHxYTJza234RUE7GQM64OF6S/+Ib3vw/jfOMhesDkEP oymI9G66PGBnbK4LPQB0TWAMXYQoP1L9ec868Z7hGAbRVrEKL3JUOvqA2OZHHKOmLsSu5dPcH3wer uMwJBWNgsJ79MWhgNn1w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqq2-00DELK-33; Thu, 30 Sep 2021 07:50:42 +0000 Received: from inva021.nxp.com ([92.121.34.21]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqpb-00DECJ-6b; Thu, 30 Sep 2021 07:50:17 +0000 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 9C4892022E3; Thu, 30 Sep 2021 09:50:13 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 37C882017C0; Thu, 30 Sep 2021 09:50:13 +0200 (CEST) Received: from localhost.localdomain (mega.ap.freescale.net [10.192.208.232]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 7EBE7183AC89; Thu, 30 Sep 2021 15:50:10 +0800 (+08) From: Xiaoliang Yang To: davem@davemloft.net, linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: allan.nielsen@microchip.com, joergen.andreasen@microchip.com, UNGLinuxDriver@microchip.com, vinicius.gomes@intel.com, michael.chan@broadcom.com, vishal@chelsio.com, saeedm@mellanox.com, jiri@mellanox.com, idosch@mellanox.com, alexandre.belloni@bootlin.com, kuba@kernel.org, xiaoliang.yang_1@nxp.com, po.liu@nxp.com, vladimir.oltean@nxp.com, leoyang.li@nxp.com, f.fainelli@gmail.com, andrew@lunn.ch, vivien.didelot@gmail.com, claudiu.manoil@nxp.com, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com, horatiu.vultur@microchip.com Subject: [PATCH v6 net-next 1/8] net: mscc: ocelot: serialize access to the MAC table Date: Thu, 30 Sep 2021 15:59:41 +0800 Message-Id: <20210930075948.36981-2-xiaoliang.yang_1@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> References: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210930_005015_542538_32800645 X-CRM114-Status: GOOD ( 21.27 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: Vladimir Oltean DSA would like to remove the rtnl_lock from its SWITCHDEV_FDB_{ADD,DEL}_TO_DEVICE handlers, and the felix driver uses the same MAC table functions as ocelot. This means that the MAC table functions will no longer be implicitly serialized with respect to each other by the rtnl_mutex, we need to add a dedicated lock in ocelot for the non-atomic operations of selecting a MAC table row, reading/writing what we want and polling for completion. Signed-off-by: Vladimir Oltean Signed-off-by: Xiaoliang Yang --- drivers/net/ethernet/mscc/ocelot.c | 53 +++++++++++++++++++++++------- include/soc/mscc/ocelot.h | 3 ++ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 559177e6ded4..61ac49751230 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -20,11 +20,13 @@ struct ocelot_mact_entry { enum macaccess_entry_type type; }; +/* Must be called with &ocelot->mact_lock held */ static inline u32 ocelot_mact_read_macaccess(struct ocelot *ocelot) { return ocelot_read(ocelot, ANA_TABLES_MACACCESS); } +/* Must be called with &ocelot->mact_lock held */ static inline int ocelot_mact_wait_for_completion(struct ocelot *ocelot) { u32 val; @@ -36,6 +38,7 @@ static inline int ocelot_mact_wait_for_completion(struct ocelot *ocelot) TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US); } +/* Must be called with &ocelot->mact_lock held */ static void ocelot_mact_select(struct ocelot *ocelot, const unsigned char mac[ETH_ALEN], unsigned int vid) @@ -67,6 +70,7 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port, ANA_TABLES_MACACCESS_ENTRYTYPE(type) | ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_LEARN); unsigned int mc_ports; + int err; /* Set MAC_CPU_COPY if the CPU port is used by a multicast entry */ if (type == ENTRYTYPE_MACv4) @@ -79,18 +83,28 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port, if (mc_ports & BIT(ocelot->num_phys_ports)) cmd |= ANA_TABLES_MACACCESS_MAC_CPU_COPY; + mutex_lock(&ocelot->mact_lock); + ocelot_mact_select(ocelot, mac, vid); /* Issue a write command */ ocelot_write(ocelot, cmd, ANA_TABLES_MACACCESS); - return ocelot_mact_wait_for_completion(ocelot); + err = ocelot_mact_wait_for_completion(ocelot); + + mutex_unlock(&ocelot->mact_lock); + + return err; } EXPORT_SYMBOL(ocelot_mact_learn); int ocelot_mact_forget(struct ocelot *ocelot, const unsigned char mac[ETH_ALEN], unsigned int vid) { + int err; + + mutex_lock(&ocelot->mact_lock); + ocelot_mact_select(ocelot, mac, vid); /* Issue a forget command */ @@ -98,7 +112,11 @@ int ocelot_mact_forget(struct ocelot *ocelot, ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_FORGET), ANA_TABLES_MACACCESS); - return ocelot_mact_wait_for_completion(ocelot); + err = ocelot_mact_wait_for_completion(ocelot); + + mutex_unlock(&ocelot->mact_lock); + + return err; } EXPORT_SYMBOL(ocelot_mact_forget); @@ -114,7 +132,9 @@ static void ocelot_mact_init(struct ocelot *ocelot) | ANA_AGENCTRL_LEARN_IGNORE_VLAN, ANA_AGENCTRL); - /* Clear the MAC table */ + /* Clear the MAC table. We are not concurrent with anyone, so + * holding &ocelot->mact_lock is pointless. + */ ocelot_write(ocelot, MACACCESS_CMD_INIT, ANA_TABLES_MACACCESS); } @@ -1018,6 +1038,7 @@ int ocelot_port_fdb_do_dump(const unsigned char *addr, u16 vid, } EXPORT_SYMBOL(ocelot_port_fdb_do_dump); +/* Must be called with &ocelot->mact_lock held */ static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col, struct ocelot_mact_entry *entry) { @@ -1068,33 +1089,40 @@ static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col, int ocelot_fdb_dump(struct ocelot *ocelot, int port, dsa_fdb_dump_cb_t *cb, void *data) { + int err = 0; int i, j; + /* We could take the lock just around ocelot_mact_read, but doing so + * thousands of times in a row seems rather pointless and inefficient. + */ + mutex_lock(&ocelot->mact_lock); + /* Loop through all the mac tables entries. */ for (i = 0; i < ocelot->num_mact_rows; i++) { for (j = 0; j < 4; j++) { struct ocelot_mact_entry entry; bool is_static; - int ret; - ret = ocelot_mact_read(ocelot, port, i, j, &entry); + err = ocelot_mact_read(ocelot, port, i, j, &entry); /* If the entry is invalid (wrong port, invalid...), * skip it. */ - if (ret == -EINVAL) + if (err == -EINVAL) continue; - else if (ret) - return ret; + else if (err) + break; is_static = (entry.type == ENTRYTYPE_LOCKED); - ret = cb(entry.mac, entry.vid, is_static, data); - if (ret) - return ret; + err = cb(entry.mac, entry.vid, is_static, data); + if (err) + break; } } - return 0; + mutex_unlock(&ocelot->mact_lock); + + return err; } EXPORT_SYMBOL(ocelot_fdb_dump); @@ -2080,6 +2108,7 @@ int ocelot_init(struct ocelot *ocelot) mutex_init(&ocelot->stats_lock); mutex_init(&ocelot->ptp_lock); + mutex_init(&ocelot->mact_lock); spin_lock_init(&ocelot->ptp_clock_lock); snprintf(queue_name, sizeof(queue_name), "%s-stats", dev_name(ocelot->dev)); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 06706a9fd5b1..682cd058096c 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -674,6 +674,9 @@ struct ocelot { struct delayed_work stats_work; struct workqueue_struct *stats_queue; + /* Lock for serializing access to the MAC table */ + struct mutex mact_lock; + struct workqueue_struct *owq; u8 ptp:1; From patchwork Thu Sep 30 07:59:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaoliang Yang X-Patchwork-Id: 12527579 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23AEFC433EF for ; Thu, 30 Sep 2021 07:51:11 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id E12AF6142A for ; Thu, 30 Sep 2021 07:51:10 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org E12AF6142A Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=nxp.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id: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=auH6U5M6ZtNmhphdBq5HuV6haiWcscAnufEdnfwI4y0=; b=cdSv8mLMfZJ5E9 gDT2AQH/riH/jRXE9EICKVFYXTYDUj6HqFv0SQ94JQzJ+2iMJgyH8EuzrZmW4lt9QGq/fuEpZKb2p 7gFcRWFlgDgDp0FCZi63REHHiI3Ln4aJAKHeVAJy8ziObPT1ZShBdZpWxYYXia6xKmfYZzsLdoJxE cGS0gXGCmRCQT4KSyzM6++of1MDjm8KyUr99ePgr1+OtcgJZUEpz9C3F32nW9iYSUNqIrYu+YU4Vw zxlehJSW6ip2Wm9L5wyVeyXPetyvd8ChZ5XxUbKDMVUmzTtSie10uCz6x81oHwwhxTDVRicJj3Fdx +qOSgGWxbUrwRWXXXAZQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqqI-00DESa-Gp; Thu, 30 Sep 2021 07:50:58 +0000 Received: from inva020.nxp.com ([92.121.34.13]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqpd-00DED6-4o; Thu, 30 Sep 2021 07:50:18 +0000 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id DBF841A0B75; Thu, 30 Sep 2021 09:50:15 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 72A5A1A0B69; Thu, 30 Sep 2021 09:50:15 +0200 (CEST) Received: from localhost.localdomain (mega.ap.freescale.net [10.192.208.232]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id BBCA2183AC94; Thu, 30 Sep 2021 15:50:12 +0800 (+08) From: Xiaoliang Yang To: davem@davemloft.net, linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: allan.nielsen@microchip.com, joergen.andreasen@microchip.com, UNGLinuxDriver@microchip.com, vinicius.gomes@intel.com, michael.chan@broadcom.com, vishal@chelsio.com, saeedm@mellanox.com, jiri@mellanox.com, idosch@mellanox.com, alexandre.belloni@bootlin.com, kuba@kernel.org, xiaoliang.yang_1@nxp.com, po.liu@nxp.com, vladimir.oltean@nxp.com, leoyang.li@nxp.com, f.fainelli@gmail.com, andrew@lunn.ch, vivien.didelot@gmail.com, claudiu.manoil@nxp.com, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com, horatiu.vultur@microchip.com Subject: [PATCH v6 net-next 2/8] net: mscc: ocelot: add MAC table stream learn and lookup operations Date: Thu, 30 Sep 2021 15:59:42 +0800 Message-Id: <20210930075948.36981-3-xiaoliang.yang_1@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> References: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210930_005017_494762_C6EDF50B X-CRM114-Status: GOOD ( 15.13 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org ocelot_mact_learn_streamdata() can be used in VSC9959 to overwrite an FDB entry with stream data. The stream data includes SFID and SSID which can be used for PSFP and FRER set. ocelot_mact_lookup() can be used to check if the given {DMAC, VID} FDB entry is exist, and also can retrieve the DEST_IDX and entry type for the FDB entry. Signed-off-by: Xiaoliang Yang --- drivers/net/ethernet/mscc/ocelot.c | 79 ++++++++++++++++++++++++++++-- drivers/net/ethernet/mscc/ocelot.h | 13 ----- include/soc/mscc/ocelot.h | 22 +++++++++ 3 files changed, 98 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 61ac49751230..0e07ea5f851c 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -61,9 +61,9 @@ static void ocelot_mact_select(struct ocelot *ocelot, } -int ocelot_mact_learn(struct ocelot *ocelot, int port, - const unsigned char mac[ETH_ALEN], - unsigned int vid, enum macaccess_entry_type type) +static int __ocelot_mact_learn(struct ocelot *ocelot, int port, + const unsigned char mac[ETH_ALEN], + unsigned int vid, enum macaccess_entry_type type) { u32 cmd = ANA_TABLES_MACACCESS_VALID | ANA_TABLES_MACACCESS_DEST_IDX(port) | @@ -96,6 +96,19 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port, return err; } + +int ocelot_mact_learn(struct ocelot *ocelot, int port, + const unsigned char mac[ETH_ALEN], + unsigned int vid, enum macaccess_entry_type type) +{ + int ret; + + mutex_lock(&ocelot->mact_lock); + ret = __ocelot_mact_learn(ocelot, port, mac, vid, type); + mutex_unlock(&ocelot->mact_lock); + + return ret; +} EXPORT_SYMBOL(ocelot_mact_learn); int ocelot_mact_forget(struct ocelot *ocelot, @@ -120,6 +133,66 @@ int ocelot_mact_forget(struct ocelot *ocelot, } EXPORT_SYMBOL(ocelot_mact_forget); +int ocelot_mact_lookup(struct ocelot *ocelot, int *dst_idx, + const unsigned char mac[ETH_ALEN], + unsigned int vid, enum macaccess_entry_type *type) +{ + int val; + + mutex_lock(&ocelot->mact_lock); + + ocelot_mact_select(ocelot, mac, vid); + + /* Issue a read command with MACACCESS_VALID=1. */ + ocelot_write(ocelot, ANA_TABLES_MACACCESS_VALID | + ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_READ), + ANA_TABLES_MACACCESS); + + if (ocelot_mact_wait_for_completion(ocelot)) { + mutex_unlock(&ocelot->mact_lock); + return -ETIMEDOUT; + } + + /* Read back the entry flags */ + val = ocelot_read(ocelot, ANA_TABLES_MACACCESS); + + mutex_unlock(&ocelot->mact_lock); + + if (!(val & ANA_TABLES_MACACCESS_VALID)) + return -ENOENT; + + *dst_idx = ANA_TABLES_MACACCESS_DEST_IDX_X(val); + *type = ANA_TABLES_MACACCESS_ENTRYTYPE_X(val); + + return 0; +} +EXPORT_SYMBOL(ocelot_mact_lookup); + +int ocelot_mact_learn_streamdata(struct ocelot *ocelot, int dst_idx, + const unsigned char mac[ETH_ALEN], + unsigned int vid, + enum macaccess_entry_type type, + int sfid, int ssid) +{ + int ret; + + mutex_lock(&ocelot->mact_lock); + + ocelot_write(ocelot, + (sfid < 0 ? 0 : ANA_TABLES_STREAMDATA_SFID_VALID) | + ANA_TABLES_STREAMDATA_SFID(sfid) | + (ssid < 0 ? 0 : ANA_TABLES_STREAMDATA_SSID_VALID) | + ANA_TABLES_STREAMDATA_SSID(ssid), + ANA_TABLES_STREAMDATA); + + ret = __ocelot_mact_learn(ocelot, dst_idx, mac, vid, type); + + mutex_unlock(&ocelot->mact_lock); + + return ret; +} +EXPORT_SYMBOL(ocelot_mact_learn_streamdata); + static void ocelot_mact_init(struct ocelot *ocelot) { /* Configure the learning mode entries attributes: diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h index 1952d6a1b98a..a77050b13d18 100644 --- a/drivers/net/ethernet/mscc/ocelot.h +++ b/drivers/net/ethernet/mscc/ocelot.h @@ -54,19 +54,6 @@ struct ocelot_dump_ctx { int idx; }; -/* MAC table entry types. - * ENTRYTYPE_NORMAL is subject to aging. - * ENTRYTYPE_LOCKED is not subject to aging. - * ENTRYTYPE_MACv4 is not subject to aging. For IPv4 multicast. - * ENTRYTYPE_MACv6 is not subject to aging. For IPv6 multicast. - */ -enum macaccess_entry_type { - ENTRYTYPE_NORMAL = 0, - ENTRYTYPE_LOCKED, - ENTRYTYPE_MACv4, - ENTRYTYPE_MACv6, -}; - /* A (PGID) port mask structure, encoding the 2^ocelot->num_phys_ports * possibilities of egress port masks for L2 multicast traffic. * For a switch with 9 user ports, there are 512 possible port masks, but the diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 682cd058096c..d9129b478c6a 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -589,6 +589,19 @@ enum ocelot_sb_pool { OCELOT_SB_POOL_NUM, }; +/* MAC table entry types. + * ENTRYTYPE_NORMAL is subject to aging. + * ENTRYTYPE_LOCKED is not subject to aging. + * ENTRYTYPE_MACv4 is not subject to aging. For IPv4 multicast. + * ENTRYTYPE_MACv6 is not subject to aging. For IPv6 multicast. + */ +enum macaccess_entry_type { + ENTRYTYPE_NORMAL = 0, + ENTRYTYPE_LOCKED, + ENTRYTYPE_MACv4, + ENTRYTYPE_MACv6, +}; + #define OCELOT_QUIRK_PCS_PERFORMS_RATE_ADAPTATION BIT(0) #define OCELOT_QUIRK_QSGMII_PORTS_MUST_BE_UP BIT(1) @@ -907,6 +920,15 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port, bool tx_pause, bool rx_pause, unsigned long quirks); +int ocelot_mact_lookup(struct ocelot *ocelot, int *dst_idx, + const unsigned char mac[ETH_ALEN], + unsigned int vid, enum macaccess_entry_type *type); +int ocelot_mact_learn_streamdata(struct ocelot *ocelot, int dst_idx, + const unsigned char mac[ETH_ALEN], + unsigned int vid, + enum macaccess_entry_type type, + int sfid, int ssid); + #if IS_ENABLED(CONFIG_BRIDGE_MRP) int ocelot_mrp_add(struct ocelot *ocelot, int port, const struct switchdev_obj_mrp *mrp); From patchwork Thu Sep 30 07:59:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaoliang Yang X-Patchwork-Id: 12527581 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8421CC433EF for ; Thu, 30 Sep 2021 07:51:28 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 4B7896142A for ; Thu, 30 Sep 2021 07:51:28 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 4B7896142A Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=nxp.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id: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=pyxTDuNjz7/5N8iGz51qTU4KEQwzAzTQ2I9hv7KA0aU=; b=HkfPPOASWnqvIW EvOZ8G50G9cWDQchr+8pcai6qydk4r/Fn0oL7hXuJRvmrFYe2dKgZxSyLdQ1m5rPTJ+xlFFzvSrWZ ifkEs4+6QZ2Bb/FnQeNkdTv1ntREoJcp450NRJG0PU5pLuedTA0v8L+lZUlo+VW3dfimpkf8JR2tY /53RDWr2VGzNdXjh4Q+4Gdx1t7e6UDvaW1kJpNA+w9autYbryX52WrVqyiUKqiBBxGjBC5U4QlO7F QuH69IiN63EC3zF0bmWLdKIQcvjxT19iVQiPH/KEmfgNWNZI0tKRBB5YSN21KuqstOziiqppgaxcT Z/jerOzIFMEVz+K/8HSQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqqb-00DEbR-E1; Thu, 30 Sep 2021 07:51:17 +0000 Received: from inva021.nxp.com ([92.121.34.21]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqpf-00DEDm-6r; Thu, 30 Sep 2021 07:50:20 +0000 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id E8E7A2017C0; Thu, 30 Sep 2021 09:50:17 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id B02532017D6; Thu, 30 Sep 2021 09:50:17 +0200 (CEST) Received: from localhost.localdomain (mega.ap.freescale.net [10.192.208.232]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 04A03183AC89; Thu, 30 Sep 2021 15:50:14 +0800 (+08) From: Xiaoliang Yang To: davem@davemloft.net, linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: allan.nielsen@microchip.com, joergen.andreasen@microchip.com, UNGLinuxDriver@microchip.com, vinicius.gomes@intel.com, michael.chan@broadcom.com, vishal@chelsio.com, saeedm@mellanox.com, jiri@mellanox.com, idosch@mellanox.com, alexandre.belloni@bootlin.com, kuba@kernel.org, xiaoliang.yang_1@nxp.com, po.liu@nxp.com, vladimir.oltean@nxp.com, leoyang.li@nxp.com, f.fainelli@gmail.com, andrew@lunn.ch, vivien.didelot@gmail.com, claudiu.manoil@nxp.com, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com, horatiu.vultur@microchip.com Subject: [PATCH v6 net-next 3/8] net: mscc: ocelot: set vcap IS2 chain to goto PSFP chain Date: Thu, 30 Sep 2021 15:59:43 +0800 Message-Id: <20210930075948.36981-4-xiaoliang.yang_1@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> References: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210930_005019_550916_45C0DEDC X-CRM114-Status: GOOD ( 11.57 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Some chips in the ocelot series such as VSC9959 support Per-Stream Filtering and Policing(PSFP), which is processing after VCAP blocks. We set this block on chain 30000 and set vcap IS2 chain to goto PSFP chain if hardware support. Signed-off-by: Xiaoliang Yang Reviewed-by: Vladimir Oltean --- drivers/net/ethernet/mscc/ocelot_flower.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c index 8b843d3c9189..ce812194e44c 100644 --- a/drivers/net/ethernet/mscc/ocelot_flower.c +++ b/drivers/net/ethernet/mscc/ocelot_flower.c @@ -20,6 +20,9 @@ (1 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP) #define VCAP_IS2_CHAIN(lookup, pag) \ (2 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP + (pag)) +/* PSFP chain and block ID */ +#define PSFP_BLOCK_ID OCELOT_NUM_VCAP_BLOCKS +#define OCELOT_PSFP_CHAIN (3 * VCAP_BLOCK) static int ocelot_chain_to_block(int chain, bool ingress) { @@ -46,6 +49,9 @@ static int ocelot_chain_to_block(int chain, bool ingress) if (chain == VCAP_IS2_CHAIN(lookup, pag)) return VCAP_IS2; + if (chain == OCELOT_PSFP_CHAIN) + return PSFP_BLOCK_ID; + return -EOPNOTSUPP; } @@ -84,7 +90,8 @@ static bool ocelot_is_goto_target_valid(int goto_target, int chain, goto_target == VCAP_IS1_CHAIN(1) || goto_target == VCAP_IS1_CHAIN(2) || goto_target == VCAP_IS2_CHAIN(0, 0) || - goto_target == VCAP_IS2_CHAIN(1, 0)); + goto_target == VCAP_IS2_CHAIN(1, 0) || + goto_target == OCELOT_PSFP_CHAIN); if (chain == VCAP_IS1_CHAIN(0)) return (goto_target == VCAP_IS1_CHAIN(1)); @@ -111,7 +118,11 @@ static bool ocelot_is_goto_target_valid(int goto_target, int chain, if (chain == VCAP_IS2_CHAIN(0, pag)) return (goto_target == VCAP_IS2_CHAIN(1, pag)); - /* VCAP IS2 lookup 1 cannot jump anywhere */ + /* VCAP IS2 lookup 1 can goto to PSFP block if hardware support */ + for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++) + if (chain == VCAP_IS2_CHAIN(1, pag)) + return (goto_target == OCELOT_PSFP_CHAIN); + return false; } @@ -353,7 +364,7 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port, if (filter->goto_target == -1) { if ((filter->block_id == VCAP_IS2 && filter->lookup == 1) || - chain == 0) { + chain == 0 || filter->block_id == PSFP_BLOCK_ID) { allow_missing_goto_target = true; } else { NL_SET_ERR_MSG_MOD(extack, "Missing GOTO action"); From patchwork Thu Sep 30 07:59:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaoliang Yang X-Patchwork-Id: 12527583 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9236CC433EF for ; Thu, 30 Sep 2021 07:51:45 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 4F8D46135D for ; Thu, 30 Sep 2021 07:51:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 4F8D46135D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=nxp.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id: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=ghBOBAfZlHlk4az+FFdgoqaX88TeSl+ov/2cJfWYBRE=; b=NawdIG3ZdoDfRC CTiRoFW8Pjq/3ciNN9IcwLh7s4vntrazPIphxseUlsy41RE4krG9hRktWIehT5W1Aw4et6uElly/1 vAiByKNPoEaVy+zkXg7l9U+Ni6hqYTGUY7Lw/pBBTQ1tZ00274E0N/fGJv7Pz7QW4vvWIBqVLwzCH 9d06j9BoPLN+zxukvpSeeF7vnOWRCHpTBKhZnyHH1Nb/0vrbhC6UsKx3ZNf2A2FWkM9wmsTvTC/SZ HnOTFlaVBayH8+Ze8mU2HJMjnrxO1lzTOQW6qYVvfHg0Dtxl1EHUzWV/2zCCrUWj6exGmRcpyO0aJ OrGa9rNlY9RrTGalg8RQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqqs-00DEl7-2z; Thu, 30 Sep 2021 07:51:34 +0000 Received: from inva020.nxp.com ([92.121.34.13]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqph-00DEEd-MT; Thu, 30 Sep 2021 07:50:23 +0000 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 64B3B1A0B86; Thu, 30 Sep 2021 09:50:20 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id EF1DD1A17BD; Thu, 30 Sep 2021 09:50:19 +0200 (CEST) Received: from localhost.localdomain (mega.ap.freescale.net [10.192.208.232]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 41E81183ACDC; Thu, 30 Sep 2021 15:50:17 +0800 (+08) From: Xiaoliang Yang To: davem@davemloft.net, linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: allan.nielsen@microchip.com, joergen.andreasen@microchip.com, UNGLinuxDriver@microchip.com, vinicius.gomes@intel.com, michael.chan@broadcom.com, vishal@chelsio.com, saeedm@mellanox.com, jiri@mellanox.com, idosch@mellanox.com, alexandre.belloni@bootlin.com, kuba@kernel.org, xiaoliang.yang_1@nxp.com, po.liu@nxp.com, vladimir.oltean@nxp.com, leoyang.li@nxp.com, f.fainelli@gmail.com, andrew@lunn.ch, vivien.didelot@gmail.com, claudiu.manoil@nxp.com, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com, horatiu.vultur@microchip.com Subject: [PATCH v6 net-next 4/8] net: mscc: ocelot: add gate and police action offload to PSFP Date: Thu, 30 Sep 2021 15:59:44 +0800 Message-Id: <20210930075948.36981-5-xiaoliang.yang_1@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> References: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210930_005022_044356_BC3C6772 X-CRM114-Status: GOOD ( 17.17 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org PSFP support gate and police action. This patch add the gate and police action to flower parse action, check chain ID to determine which block to offload. Adding psfp callback functions to add, delete and update gate and police in PSFP table if hardware supports it. Signed-off-by: Xiaoliang Yang --- drivers/net/ethernet/mscc/ocelot.c | 3 ++ drivers/net/ethernet/mscc/ocelot_flower.c | 52 ++++++++++++++++++++++- include/soc/mscc/ocelot.h | 5 +++ include/soc/mscc/ocelot_vcap.h | 1 + 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 0e07ea5f851c..36a28fbb7faa 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -2203,6 +2203,9 @@ int ocelot_init(struct ocelot *ocelot) ocelot_vcap_init(ocelot); ocelot_cpu_port_init(ocelot); + if (ocelot->ops->psfp_init) + ocelot->ops->psfp_init(ocelot); + for (port = 0; port < ocelot->num_phys_ports; port++) { /* Clear all counters (5 groups) */ ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port) | diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c index ce812194e44c..daeaee99933d 100644 --- a/drivers/net/ethernet/mscc/ocelot_flower.c +++ b/drivers/net/ethernet/mscc/ocelot_flower.c @@ -220,10 +220,14 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port, filter->type = OCELOT_VCAP_FILTER_OFFLOAD; break; case FLOW_ACTION_POLICE: + if (filter->block_id == PSFP_BLOCK_ID) { + filter->type = OCELOT_PSFP_FILTER_OFFLOAD; + break; + } if (filter->block_id != VCAP_IS2 || filter->lookup != 0) { NL_SET_ERR_MSG_MOD(extack, - "Police action can only be offloaded to VCAP IS2 lookup 0"); + "Police action can only be offloaded to VCAP IS2 lookup 0 or PSFP"); return -EOPNOTSUPP; } if (filter->goto_target != -1) { @@ -356,6 +360,14 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port, filter->action.pcp_a_val = a->vlan.prio; filter->type = OCELOT_VCAP_FILTER_OFFLOAD; break; + case FLOW_ACTION_GATE: + if (filter->block_id != PSFP_BLOCK_ID) { + NL_SET_ERR_MSG_MOD(extack, + "Gate action can only be offloaded to PSFP chain"); + return -EOPNOTSUPP; + } + filter->type = OCELOT_PSFP_FILTER_OFFLOAD; + break; default: NL_SET_ERR_MSG_MOD(extack, "Cannot offload action"); return -EOPNOTSUPP; @@ -646,6 +658,10 @@ static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress, if (ret) return ret; + /* PSFP filter need to parse key by stream identification function. */ + if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) + return 0; + return ocelot_flower_parse_key(ocelot, port, ingress, f, filter); } @@ -718,6 +734,15 @@ int ocelot_cls_flower_replace(struct ocelot *ocelot, int port, if (filter->type == OCELOT_VCAP_FILTER_DUMMY) return ocelot_vcap_dummy_filter_add(ocelot, filter); + if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) { + kfree(filter); + if (ocelot->ops->psfp_filter_add) + return ocelot->ops->psfp_filter_add(ocelot, f); + + NL_SET_ERR_MSG_MOD(extack, "PSFP chain is not supported in HW"); + return -EOPNOTSUPP; + } + return ocelot_vcap_filter_add(ocelot, filter, f->common.extack); } EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace); @@ -733,6 +758,13 @@ int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, if (block_id < 0) return 0; + if (block_id == PSFP_BLOCK_ID) { + if (ocelot->ops->psfp_filter_del) + return ocelot->ops->psfp_filter_del(ocelot, f); + + return -EOPNOTSUPP; + } + block = &ocelot->block[block_id]; filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true); @@ -751,12 +783,25 @@ int ocelot_cls_flower_stats(struct ocelot *ocelot, int port, { struct ocelot_vcap_filter *filter; struct ocelot_vcap_block *block; + struct flow_stats stats; int block_id, ret; block_id = ocelot_chain_to_block(f->common.chain_index, ingress); if (block_id < 0) return 0; + if (block_id == PSFP_BLOCK_ID) { + if (ocelot->ops->psfp_stats_get) { + ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats); + if (ret) + return ret; + + goto stats_update; + } + + return -EOPNOTSUPP; + } + block = &ocelot->block[block_id]; filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true); @@ -767,7 +812,10 @@ int ocelot_cls_flower_stats(struct ocelot *ocelot, int port, if (ret) return ret; - flow_stats_update(&f->stats, 0x0, filter->stats.pkts, 0, 0x0, + stats.pkts = filter->stats.pkts; + +stats_update: + flow_stats_update(&f->stats, 0x0, stats.pkts, 0, 0x0, FLOW_ACTION_HW_STATS_IMMEDIATE); return 0; } diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index d9129b478c6a..a565abb49c32 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -564,6 +564,11 @@ struct ocelot_ops { u16 (*wm_enc)(u16 value); u16 (*wm_dec)(u16 value); void (*wm_stat)(u32 val, u32 *inuse, u32 *maxuse); + void (*psfp_init)(struct ocelot *ocelot); + int (*psfp_filter_add)(struct ocelot *ocelot, struct flow_cls_offload *f); + int (*psfp_filter_del)(struct ocelot *ocelot, struct flow_cls_offload *f); + int (*psfp_stats_get)(struct ocelot *ocelot, struct flow_cls_offload *f, + struct flow_stats *stats); }; struct ocelot_vcap_block { diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h index 25fd525aaf92..24b495ce140c 100644 --- a/include/soc/mscc/ocelot_vcap.h +++ b/include/soc/mscc/ocelot_vcap.h @@ -646,6 +646,7 @@ enum ocelot_vcap_filter_type { OCELOT_VCAP_FILTER_DUMMY, OCELOT_VCAP_FILTER_PAG, OCELOT_VCAP_FILTER_OFFLOAD, + OCELOT_PSFP_FILTER_OFFLOAD, }; struct ocelot_vcap_id { From patchwork Thu Sep 30 07:59:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaoliang Yang X-Patchwork-Id: 12527585 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7882EC433FE for ; Thu, 30 Sep 2021 07:52:14 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 3852E613CE for ; Thu, 30 Sep 2021 07:52:14 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 3852E613CE Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=nxp.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id: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=1L1SQ9S/r905OqHsvJM7VT9aBh7TwMxbW/lUe19lsFY=; b=VLANjcNaRla8wB j7QUVxdGBgLW2mtdXhQJ7d/2+Q3vdDSp0ao0+A29yZfVNwLai55o2B9KoZq042HFrlurc+1s0V9Zo i0UiCBHKFkwpLNYtBJyb5yumFEUochZJnkyBcQym3Am8eNzZ6EYFbn4G1RaZSecUL1nAlaiPBS7/7 ltVZBCtqjaukGeawimk00ct7GKoEvFAqgqzsQHsSC+sl5q+faRfwv7a6NeTKV70ETT30LooCFZMma BI0H8hz0Xg7cJaE+O2L9Vmui6tSk3I/85Lj0fuOg1fKpjfG3DN58y6h4LKa0FF6sM9iyxINw+SRWa qn8dfIjRZuk4BW23IzEg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqrI-00DF3o-K6; Thu, 30 Sep 2021 07:52:00 +0000 Received: from inva020.nxp.com ([92.121.34.13]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqpk-00DEFd-1g; Thu, 30 Sep 2021 07:50:26 +0000 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id C0F3F1A17C7; Thu, 30 Sep 2021 09:50:22 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 546E41A17C0; Thu, 30 Sep 2021 09:50:22 +0200 (CEST) Received: from localhost.localdomain (mega.ap.freescale.net [10.192.208.232]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 7F700183AC89; Thu, 30 Sep 2021 15:50:19 +0800 (+08) From: Xiaoliang Yang To: davem@davemloft.net, linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: allan.nielsen@microchip.com, joergen.andreasen@microchip.com, UNGLinuxDriver@microchip.com, vinicius.gomes@intel.com, michael.chan@broadcom.com, vishal@chelsio.com, saeedm@mellanox.com, jiri@mellanox.com, idosch@mellanox.com, alexandre.belloni@bootlin.com, kuba@kernel.org, xiaoliang.yang_1@nxp.com, po.liu@nxp.com, vladimir.oltean@nxp.com, leoyang.li@nxp.com, f.fainelli@gmail.com, andrew@lunn.ch, vivien.didelot@gmail.com, claudiu.manoil@nxp.com, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com, horatiu.vultur@microchip.com Subject: [PATCH v6 net-next 5/8] net: dsa: felix: support psfp filter on vsc9959 Date: Thu, 30 Sep 2021 15:59:45 +0800 Message-Id: <20210930075948.36981-6-xiaoliang.yang_1@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> References: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210930_005024_542641_6CCF4E42 X-CRM114-Status: GOOD ( 21.94 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org VSC9959 supports Per-Stream Filtering and Policing(PSFP) that complies with the IEEE 802.1Qci standard. The stream is identified by Null stream identification(DMAC and VLAN ID) defined in IEEE802.1CB. For PSFP, four tables need to be set up: stream table, stream filter table, stream gate table, and flow meter table. Identify the stream by parsing the tc flower keys and add it to the stream table. The stream filter table is automatically maintained, and its index is determined by SGID(flow gate index) and FMID(flow meter index). Signed-off-by: Xiaoliang Yang --- drivers/net/dsa/ocelot/felix_vsc9959.c | 449 ++++++++++++++++++++++++- include/soc/mscc/ocelot.h | 8 + include/soc/mscc/ocelot_ana.h | 10 + 3 files changed, 457 insertions(+), 10 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 11b42fd812e4..9e691b22bcfa 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -292,7 +293,7 @@ static const u32 vsc9959_sys_regmap[] = { REG_RESERVED(SYS_MMGT_FAST), REG_RESERVED(SYS_EVENTS_DIF), REG_RESERVED(SYS_EVENTS_CORE), - REG_RESERVED(SYS_CNT), + REG(SYS_CNT, 0x000000), REG(SYS_PTP_STATUS, 0x000f14), REG(SYS_PTP_TXSTAMP, 0x000f18), REG(SYS_PTP_NXT, 0x000f1c), @@ -1022,15 +1023,6 @@ static void vsc9959_wm_stat(u32 val, u32 *inuse, u32 *maxuse) *maxuse = val & GENMASK(11, 0); } -static const struct ocelot_ops vsc9959_ops = { - .reset = vsc9959_reset, - .wm_enc = vsc9959_wm_enc, - .wm_dec = vsc9959_wm_dec, - .wm_stat = vsc9959_wm_stat, - .port_to_netdev = felix_port_to_netdev, - .netdev_to_port = felix_netdev_to_port, -}; - static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) { struct felix *felix = ocelot_to_felix(ocelot); @@ -1346,6 +1338,443 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port, } } +#define VSC9959_PSFP_SFID_MAX 175 +#define VSC9959_PSFP_GATE_ID_MAX 183 +#define VSC9959_PSFP_POLICER_MAX 383 + +struct felix_stream { + struct list_head list; + unsigned long id; + bool type_update; + u8 dmac[ETH_ALEN]; + u16 vid; + s8 prio; + u8 sfid_valid; + u8 ssid_valid; + u32 sfid; + u32 ssid; +}; + +struct felix_stream_filter { + struct list_head list; + refcount_t refcount; + u32 index; + u8 enable; + u8 sg_valid; + u32 sgid; + u8 fm_valid; + u32 fmid; + u8 prio_valid; + u8 prio; + u32 maxsdu; +}; + +struct felix_stream_filter_counters { + u32 match; + u32 not_pass_gate; + u32 not_pass_sdu; + u32 red; +}; + +static int vsc9959_stream_identify(struct flow_cls_offload *f, + struct felix_stream *stream) +{ + struct flow_rule *rule = flow_cls_offload_flow_rule(f); + struct flow_dissector *dissector = rule->match.dissector; + + if (dissector->used_keys & + ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | + BIT(FLOW_DISSECTOR_KEY_BASIC) | + BIT(FLOW_DISSECTOR_KEY_VLAN) | + BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) + return -EOPNOTSUPP; + + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { + struct flow_match_eth_addrs match; + + flow_rule_match_eth_addrs(rule, &match); + ether_addr_copy(stream->dmac, match.key->dst); + if (!is_zero_ether_addr(match.mask->src)) + return -EOPNOTSUPP; + } else { + return -EOPNOTSUPP; + } + + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + struct flow_match_vlan match; + + flow_rule_match_vlan(rule, &match); + if (match.mask->vlan_priority) + stream->prio = match.key->vlan_priority; + else + stream->prio = -1; + + if (!match.mask->vlan_id) + return -EOPNOTSUPP; + stream->vid = match.key->vlan_id; + } else { + return -EOPNOTSUPP; + } + + stream->id = f->cookie; + + return 0; +} + +static int vsc9959_mact_stream_set(struct ocelot *ocelot, + struct felix_stream *stream, + struct netlink_ext_ack *extack) +{ + enum macaccess_entry_type type; + int ret, sfid, ssid; + u32 vid, dst_idx; + u8 mac[ETH_ALEN]; + + ether_addr_copy(mac, stream->dmac); + vid = stream->vid; + + /* Stream identification desn't support to add a stream with non + * existent MAC (The MAC entry has not been learned in MAC table). + */ + ret = ocelot_mact_lookup(ocelot, &dst_idx, mac, vid, &type); + if (ret) { + if (extack) + NL_SET_ERR_MSG_MOD(extack, "Stream is not learned in MAC table"); + return -EOPNOTSUPP; + } + + if ((stream->sfid_valid || stream->ssid_valid) && + type == ENTRYTYPE_NORMAL) { + stream->type_update = true; + type = ENTRYTYPE_LOCKED; + } + + if (!stream->sfid_valid && !stream->ssid_valid && stream->type_update) + type = ENTRYTYPE_NORMAL; + + sfid = stream->sfid_valid ? stream->sfid : -1; + ssid = stream->ssid_valid ? stream->ssid : -1; + + ret = ocelot_mact_learn_streamdata(ocelot, dst_idx, mac, vid, type, + sfid, ssid); + + return ret; +} + +static struct felix_stream * +vsc9959_stream_table_lookup(struct list_head *stream_list, + struct felix_stream *stream) +{ + struct felix_stream *tmp; + + list_for_each_entry(tmp, stream_list, list) + if (ether_addr_equal(tmp->dmac, stream->dmac) && + tmp->vid == stream->vid) + return tmp; + + return NULL; +} + +static int vsc9959_stream_table_add(struct ocelot *ocelot, + struct list_head *stream_list, + struct felix_stream *stream, + struct netlink_ext_ack *extack) +{ + struct felix_stream *stream_entry; + int ret; + + stream_entry = kzalloc(sizeof(*stream_entry), GFP_KERNEL); + if (!stream_entry) + return -ENOMEM; + + memcpy(stream_entry, stream, sizeof(*stream_entry)); + + ret = vsc9959_mact_stream_set(ocelot, stream_entry, extack); + if (ret) { + kfree(stream_entry); + return ret; + } + + list_add_tail(&stream_entry->list, stream_list); + + return 0; +} + +static struct felix_stream * +vsc9959_stream_table_get(struct list_head *stream_list, unsigned long id) +{ + struct felix_stream *tmp; + + list_for_each_entry(tmp, stream_list, list) + if (tmp->id == id) + return tmp; + + return NULL; +} + +static void vsc9959_stream_table_del(struct ocelot *ocelot, + struct felix_stream *stream) +{ + vsc9959_mact_stream_set(ocelot, stream, NULL); + + list_del(&stream->list); + kfree(stream); +} + +static u32 vsc9959_sfi_access_status(struct ocelot *ocelot) +{ + return ocelot_read(ocelot, ANA_TABLES_SFIDACCESS); +} + +static int vsc9959_psfp_sfi_set(struct ocelot *ocelot, + struct felix_stream_filter *sfi) +{ + u32 val; + + if (sfi->index > VSC9959_PSFP_SFID_MAX) + return -EINVAL; + + if (!sfi->enable) { + ocelot_write(ocelot, ANA_TABLES_SFIDTIDX_SFID_INDEX(sfi->index), + ANA_TABLES_SFIDTIDX); + + val = ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(SFIDACCESS_CMD_WRITE); + ocelot_write(ocelot, val, ANA_TABLES_SFIDACCESS); + + return readx_poll_timeout(vsc9959_sfi_access_status, ocelot, val, + (!ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(val)), + 10, 100000); + } + + if (sfi->sgid > VSC9959_PSFP_GATE_ID_MAX || + sfi->fmid > VSC9959_PSFP_POLICER_MAX) + return -EINVAL; + + ocelot_write(ocelot, + (sfi->sg_valid ? ANA_TABLES_SFIDTIDX_SGID_VALID : 0) | + ANA_TABLES_SFIDTIDX_SGID(sfi->sgid) | + (sfi->fm_valid ? ANA_TABLES_SFIDTIDX_POL_ENA : 0) | + ANA_TABLES_SFIDTIDX_POL_IDX(sfi->fmid) | + ANA_TABLES_SFIDTIDX_SFID_INDEX(sfi->index), + ANA_TABLES_SFIDTIDX); + + ocelot_write(ocelot, + (sfi->prio_valid ? ANA_TABLES_SFIDACCESS_IGR_PRIO_MATCH_ENA : 0) | + ANA_TABLES_SFIDACCESS_IGR_PRIO(sfi->prio) | + ANA_TABLES_SFIDACCESS_MAX_SDU_LEN(sfi->maxsdu) | + ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(SFIDACCESS_CMD_WRITE), + ANA_TABLES_SFIDACCESS); + + return readx_poll_timeout(vsc9959_sfi_access_status, ocelot, val, + (!ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(val)), + 10, 100000); +} + +static int vsc9959_psfp_sfi_table_add(struct ocelot *ocelot, + struct felix_stream_filter *sfi) +{ + struct felix_stream_filter *sfi_entry, *tmp; + struct list_head *pos, *q, *last; + struct ocelot_psfp_list *psfp; + u32 insert = 0; + int ret; + + psfp = &ocelot->psfp; + last = &psfp->sfi_list; + + list_for_each_safe(pos, q, &psfp->sfi_list) { + tmp = list_entry(pos, struct felix_stream_filter, list); + if (sfi->sg_valid == tmp->sg_valid && + sfi->fm_valid == tmp->fm_valid && + tmp->sgid == sfi->sgid && + tmp->fmid == sfi->fmid) { + sfi->index = tmp->index; + refcount_inc(&tmp->refcount); + return 0; + } + /* Make sure that the index is increasing in order. */ + if (tmp->index == insert) { + last = pos; + insert++; + } + } + sfi->index = insert; + + sfi_entry = kzalloc(sizeof(*sfi_entry), GFP_KERNEL); + if (!sfi_entry) + return -ENOMEM; + + memcpy(sfi_entry, sfi, sizeof(*sfi_entry)); + refcount_set(&sfi_entry->refcount, 1); + + ret = vsc9959_psfp_sfi_set(ocelot, sfi_entry); + if (ret) { + kfree(sfi_entry); + return ret; + } + + list_add(&sfi_entry->list, last); + + return 0; +} + +static void vsc9959_psfp_sfi_table_del(struct ocelot *ocelot, u32 index) +{ + struct felix_stream_filter *tmp, *n; + struct ocelot_psfp_list *psfp; + u8 z; + + psfp = &ocelot->psfp; + + list_for_each_entry_safe(tmp, n, &psfp->sfi_list, list) + if (tmp->index == index) { + z = refcount_dec_and_test(&tmp->refcount); + if (z) { + tmp->enable = 0; + vsc9959_psfp_sfi_set(ocelot, tmp); + list_del(&tmp->list); + kfree(tmp); + } + break; + } +} + +static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index, + struct felix_stream_filter_counters *counters) +{ + ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(index), + SYS_STAT_CFG_STAT_VIEW_M, + SYS_STAT_CFG); + + counters->match = ocelot_read_gix(ocelot, SYS_CNT, 0x200); + counters->not_pass_gate = ocelot_read_gix(ocelot, SYS_CNT, 0x201); + counters->not_pass_sdu = ocelot_read_gix(ocelot, SYS_CNT, 0x202); + counters->red = ocelot_read_gix(ocelot, SYS_CNT, 0x203); + + /* Clear the PSFP counter. */ + ocelot_write(ocelot, + SYS_STAT_CFG_STAT_VIEW(index) | + SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10), + SYS_STAT_CFG); +} + +static int vsc9959_psfp_filter_add(struct ocelot *ocelot, + struct flow_cls_offload *f) +{ + struct netlink_ext_ack *extack = f->common.extack; + struct felix_stream_filter sfi = {0}; + const struct flow_action_entry *a; + struct felix_stream *stream_entry; + struct felix_stream stream = {0}; + struct ocelot_psfp_list *psfp; + int ret, i; + + psfp = &ocelot->psfp; + + ret = vsc9959_stream_identify(f, &stream); + if (ret) { + NL_SET_ERR_MSG_MOD(extack, "Only can match on VID, PCP, and dest MAC"); + return ret; + } + + flow_action_for_each(i, a, &f->rule->action) { + switch (a->id) { + case FLOW_ACTION_GATE: + case FLOW_ACTION_POLICE: + default: + return -EOPNOTSUPP; + } + } + + /* Check if stream is set. */ + stream_entry = vsc9959_stream_table_lookup(&psfp->stream_list, &stream); + if (stream_entry) { + NL_SET_ERR_MSG_MOD(extack, "This stream is already added"); + return -EEXIST; + } + + sfi.prio_valid = (stream.prio < 0 ? 0 : 1); + sfi.prio = (sfi.prio_valid ? stream.prio : 0); + sfi.enable = 1; + + ret = vsc9959_psfp_sfi_table_add(ocelot, &sfi); + if (ret) + return ret; + + stream.sfid = sfi.index; + stream.sfid_valid = 1; + ret = vsc9959_stream_table_add(ocelot, &psfp->stream_list, + &stream, extack); + if (ret) + vsc9959_psfp_sfi_table_del(ocelot, stream.sfid); + + return ret; +} + +static int vsc9959_psfp_filter_del(struct ocelot *ocelot, + struct flow_cls_offload *f) +{ + struct ocelot_psfp_list *psfp; + struct felix_stream *stream; + + psfp = &ocelot->psfp; + + stream = vsc9959_stream_table_get(&psfp->stream_list, f->cookie); + if (!stream) + return -ENOMEM; + + vsc9959_psfp_sfi_table_del(ocelot, stream->sfid); + + stream->sfid_valid = 0; + vsc9959_stream_table_del(ocelot, stream); + + return 0; +} + +static int vsc9959_psfp_stats_get(struct ocelot *ocelot, + struct flow_cls_offload *f, + struct flow_stats *stats) +{ + struct felix_stream_filter_counters counters; + struct ocelot_psfp_list *psfp; + struct felix_stream *stream; + + psfp = &ocelot->psfp; + stream = vsc9959_stream_table_get(&psfp->stream_list, f->cookie); + if (!stream) + return -ENOMEM; + + vsc9959_psfp_counters_get(ocelot, stream->sfid, &counters); + + stats->pkts = counters.match; + stats->drops = counters.not_pass_gate + counters.not_pass_sdu + + counters.red; + + return 0; +} + +static void vsc9959_psfp_init(struct ocelot *ocelot) +{ + struct ocelot_psfp_list *psfp = &ocelot->psfp; + + INIT_LIST_HEAD(&psfp->stream_list); + INIT_LIST_HEAD(&psfp->sfi_list); + INIT_LIST_HEAD(&psfp->sgi_list); +} + +static const struct ocelot_ops vsc9959_ops = { + .reset = vsc9959_reset, + .wm_enc = vsc9959_wm_enc, + .wm_dec = vsc9959_wm_dec, + .wm_stat = vsc9959_wm_stat, + .port_to_netdev = felix_port_to_netdev, + .netdev_to_port = felix_netdev_to_port, + .psfp_init = vsc9959_psfp_init, + .psfp_filter_add = vsc9959_psfp_filter_add, + .psfp_filter_del = vsc9959_psfp_filter_del, + .psfp_stats_get = vsc9959_psfp_stats_get, +}; + static const struct felix_info felix_info_vsc9959 = { .target_io_res = vsc9959_target_io_res, .port_io_res = vsc9959_port_io_res, diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index a565abb49c32..61429ed06e72 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -582,6 +582,12 @@ struct ocelot_vlan { u16 vid; }; +struct ocelot_psfp_list { + struct list_head stream_list; + struct list_head sfi_list; + struct list_head sgi_list; +}; + enum ocelot_sb { OCELOT_SB_BUF, OCELOT_SB_REF, @@ -686,6 +692,8 @@ struct ocelot { struct ocelot_vcap_block block[3]; struct vcap_props *vcap; + struct ocelot_psfp_list psfp; + /* Workqueue to check statistics for overflow with its lock */ struct mutex stats_lock; u64 *stats; diff --git a/include/soc/mscc/ocelot_ana.h b/include/soc/mscc/ocelot_ana.h index 1669481d9779..67e0ae05a5ab 100644 --- a/include/soc/mscc/ocelot_ana.h +++ b/include/soc/mscc/ocelot_ana.h @@ -227,6 +227,11 @@ #define ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(x) ((x) & GENMASK(1, 0)) #define ANA_TABLES_SFIDACCESS_SFID_TBL_CMD_M GENMASK(1, 0) +#define SFIDACCESS_CMD_IDLE 0 +#define SFIDACCESS_CMD_READ 1 +#define SFIDACCESS_CMD_WRITE 2 +#define SFIDACCESS_CMD_INIT 3 + #define ANA_TABLES_SFIDTIDX_SGID_VALID BIT(26) #define ANA_TABLES_SFIDTIDX_SGID(x) (((x) << 18) & GENMASK(25, 18)) #define ANA_TABLES_SFIDTIDX_SGID_M GENMASK(25, 18) @@ -255,6 +260,11 @@ #define ANA_SG_CONFIG_REG_3_INIT_IPS(x) (((x) << 21) & GENMASK(24, 21)) #define ANA_SG_CONFIG_REG_3_INIT_IPS_M GENMASK(24, 21) #define ANA_SG_CONFIG_REG_3_INIT_IPS_X(x) (((x) & GENMASK(24, 21)) >> 21) +#define ANA_SG_CONFIG_REG_3_IPV_VALID BIT(24) +#define ANA_SG_CONFIG_REG_3_IPV_INVALID(x) (((x) << 24) & GENMASK(24, 24)) +#define ANA_SG_CONFIG_REG_3_INIT_IPV(x) (((x) << 21) & GENMASK(23, 21)) +#define ANA_SG_CONFIG_REG_3_INIT_IPV_M GENMASK(23, 21) +#define ANA_SG_CONFIG_REG_3_INIT_IPV_X(x) (((x) & GENMASK(23, 21)) >> 21) #define ANA_SG_CONFIG_REG_3_INIT_GATE_STATE BIT(25) #define ANA_SG_GCL_GS_CONFIG_RSZ 0x4 From patchwork Thu Sep 30 07:59:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaoliang Yang X-Patchwork-Id: 12527587 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BE736C433F5 for ; Thu, 30 Sep 2021 07:52:40 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 6F8AF61452 for ; Thu, 30 Sep 2021 07:52:40 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 6F8AF61452 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=nxp.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id: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=44oLL6blWPgGDqudVTLX1ElqMr7A/M0zCQ5PpJiQx88=; b=kcV7TDYiKMzI56 3Y/a+E15m2TB7xXoCkJEP5Cdd+OzRJv41wBzB17Xrz1oqBan91ZOqwY2laNRCv8+gYjvVHZ92h9OA JKAAioct73sUUMxU0BoROGyBhn/aLrPFO0aNdzpKWkZ+LrZ00/E+TcHPERniIJnZbxGA5F2eYRtc5 GPC+m9uEkob0aw17ik0jidHVGSwCi0Z+XoSuiWl1GEBWRUhVhUT+uPL5hWJNoNPRbVRorz0CgHMa6 qzk27XUl63H4IX36K8OA9rwiVqdComwKUvdecx33qiLgrLf72eNap3O7WCi9Z8WxpK3sFe2TmmBlv qpwjMx8SwFE10d/xTvBg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqrj-00DFMb-65; Thu, 30 Sep 2021 07:52:27 +0000 Received: from inva021.nxp.com ([92.121.34.21]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqpm-00DEGL-Fr; Thu, 30 Sep 2021 07:50:28 +0000 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 362E8200408; Thu, 30 Sep 2021 09:50:25 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 90C47200254; Thu, 30 Sep 2021 09:50:24 +0200 (CEST) Received: from localhost.localdomain (mega.ap.freescale.net [10.192.208.232]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id D9493183AD27; Thu, 30 Sep 2021 15:50:21 +0800 (+08) From: Xiaoliang Yang To: davem@davemloft.net, linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: allan.nielsen@microchip.com, joergen.andreasen@microchip.com, UNGLinuxDriver@microchip.com, vinicius.gomes@intel.com, michael.chan@broadcom.com, vishal@chelsio.com, saeedm@mellanox.com, jiri@mellanox.com, idosch@mellanox.com, alexandre.belloni@bootlin.com, kuba@kernel.org, xiaoliang.yang_1@nxp.com, po.liu@nxp.com, vladimir.oltean@nxp.com, leoyang.li@nxp.com, f.fainelli@gmail.com, andrew@lunn.ch, vivien.didelot@gmail.com, claudiu.manoil@nxp.com, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com, horatiu.vultur@microchip.com Subject: [PATCH v6 net-next 6/8] net: dsa: felix: add stream gate settings for psfp Date: Thu, 30 Sep 2021 15:59:46 +0800 Message-Id: <20210930075948.36981-7-xiaoliang.yang_1@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> References: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210930_005026_882295_74A9346B X-CRM114-Status: GOOD ( 19.52 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org This patch adds stream gate settings for PSFP. Use SGI table to store stream gate entries. Disable the gate entry when it is not used by any stream. Signed-off-by: Xiaoliang Yang --- drivers/net/dsa/ocelot/felix_vsc9959.c | 217 ++++++++++++++++++++++++- 1 file changed, 213 insertions(+), 4 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 9e691b22bcfa..cbfced355010 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -1341,6 +1342,8 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port, #define VSC9959_PSFP_SFID_MAX 175 #define VSC9959_PSFP_GATE_ID_MAX 183 #define VSC9959_PSFP_POLICER_MAX 383 +#define VSC9959_PSFP_GATE_LIST_NUM 4 +#define VSC9959_PSFP_GATE_CYCLETIME_MIN 5000 struct felix_stream { struct list_head list; @@ -1376,6 +1379,24 @@ struct felix_stream_filter_counters { u32 red; }; +struct felix_stream_gate { + u32 index; + u8 enable; + u8 ipv_valid; + u8 init_ipv; + u64 basetime; + u64 cycletime; + u64 cycletime_ext; + u32 num_entries; + struct action_gate_entry entries[0]; +}; + +struct felix_stream_gate_entry { + struct list_head list; + refcount_t refcount; + u32 index; +}; + static int vsc9959_stream_identify(struct flow_cls_offload *f, struct felix_stream *stream) { @@ -1618,6 +1639,18 @@ static int vsc9959_psfp_sfi_table_add(struct ocelot *ocelot, return 0; } +static struct felix_stream_filter * +vsc9959_psfp_sfi_table_get(struct list_head *sfi_list, u32 index) +{ + struct felix_stream_filter *tmp; + + list_for_each_entry(tmp, sfi_list, list) + if (tmp->index == index) + return tmp; + + return NULL; +} + static void vsc9959_psfp_sfi_table_del(struct ocelot *ocelot, u32 index) { struct felix_stream_filter *tmp, *n; @@ -1639,6 +1672,152 @@ static void vsc9959_psfp_sfi_table_del(struct ocelot *ocelot, u32 index) } } +static void vsc9959_psfp_parse_gate(const struct flow_action_entry *entry, + struct felix_stream_gate *sgi) +{ + sgi->index = entry->gate.index; + sgi->ipv_valid = (entry->gate.prio < 0) ? 0 : 1; + sgi->init_ipv = (sgi->ipv_valid) ? entry->gate.prio : 0; + sgi->basetime = entry->gate.basetime; + sgi->cycletime = entry->gate.cycletime; + sgi->num_entries = entry->gate.num_entries; + sgi->enable = 1; + + memcpy(sgi->entries, entry->gate.entries, + entry->gate.num_entries * sizeof(struct action_gate_entry)); +} + +static u32 vsc9959_sgi_cfg_status(struct ocelot *ocelot) +{ + return ocelot_read(ocelot, ANA_SG_ACCESS_CTRL); +} + +static int vsc9959_psfp_sgi_set(struct ocelot *ocelot, + struct felix_stream_gate *sgi) +{ + struct action_gate_entry *e; + struct timespec64 base_ts; + u32 interval_sum = 0; + u32 val; + int i; + + if (sgi->index > VSC9959_PSFP_GATE_ID_MAX) + return -EINVAL; + + ocelot_write(ocelot, ANA_SG_ACCESS_CTRL_SGID(sgi->index), + ANA_SG_ACCESS_CTRL); + + if (!sgi->enable) { + ocelot_rmw(ocelot, ANA_SG_CONFIG_REG_3_INIT_GATE_STATE, + ANA_SG_CONFIG_REG_3_INIT_GATE_STATE | + ANA_SG_CONFIG_REG_3_GATE_ENABLE, + ANA_SG_CONFIG_REG_3); + + return 0; + } + + if (sgi->cycletime < VSC9959_PSFP_GATE_CYCLETIME_MIN || + sgi->cycletime > NSEC_PER_SEC) + return -EINVAL; + + if (sgi->num_entries > VSC9959_PSFP_GATE_LIST_NUM) + return -EINVAL; + + vsc9959_new_base_time(ocelot, sgi->basetime, sgi->cycletime, &base_ts); + ocelot_write(ocelot, base_ts.tv_nsec, ANA_SG_CONFIG_REG_1); + val = lower_32_bits(base_ts.tv_sec); + ocelot_write(ocelot, val, ANA_SG_CONFIG_REG_2); + + val = upper_32_bits(base_ts.tv_sec); + ocelot_write(ocelot, + (sgi->ipv_valid ? ANA_SG_CONFIG_REG_3_IPV_VALID : 0) | + ANA_SG_CONFIG_REG_3_INIT_IPV(sgi->init_ipv) | + ANA_SG_CONFIG_REG_3_GATE_ENABLE | + ANA_SG_CONFIG_REG_3_LIST_LENGTH(sgi->num_entries) | + ANA_SG_CONFIG_REG_3_INIT_GATE_STATE | + ANA_SG_CONFIG_REG_3_BASE_TIME_SEC_MSB(val), + ANA_SG_CONFIG_REG_3); + + ocelot_write(ocelot, sgi->cycletime, ANA_SG_CONFIG_REG_4); + + e = sgi->entries; + for (i = 0; i < sgi->num_entries; i++) { + u32 ips = (e[i].ipv < 0) ? 0 : (e[i].ipv + 8); + + ocelot_write_rix(ocelot, ANA_SG_GCL_GS_CONFIG_IPS(ips) | + (e[i].gate_state ? + ANA_SG_GCL_GS_CONFIG_GATE_STATE : 0), + ANA_SG_GCL_GS_CONFIG, i); + + interval_sum += e[i].interval; + ocelot_write_rix(ocelot, interval_sum, ANA_SG_GCL_TI_CONFIG, i); + } + + ocelot_rmw(ocelot, ANA_SG_ACCESS_CTRL_CONFIG_CHANGE, + ANA_SG_ACCESS_CTRL_CONFIG_CHANGE, + ANA_SG_ACCESS_CTRL); + + return readx_poll_timeout(vsc9959_sgi_cfg_status, ocelot, val, + (!(ANA_SG_ACCESS_CTRL_CONFIG_CHANGE & val)), + 10, 100000); +} + +static int vsc9959_psfp_sgi_table_add(struct ocelot *ocelot, + struct felix_stream_gate *sgi) +{ + struct felix_stream_gate_entry *tmp; + struct ocelot_psfp_list *psfp; + int ret; + + psfp = &ocelot->psfp; + + list_for_each_entry(tmp, &psfp->sgi_list, list) + if (tmp->index == sgi->index) { + refcount_inc(&tmp->refcount); + return 0; + } + + tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + ret = vsc9959_psfp_sgi_set(ocelot, sgi); + if (ret) { + kfree(tmp); + return ret; + } + + tmp->index = sgi->index; + refcount_set(&tmp->refcount, 1); + list_add_tail(&tmp->list, &psfp->sgi_list); + + return 0; +} + +static void vsc9959_psfp_sgi_table_del(struct ocelot *ocelot, + u32 index) +{ + struct felix_stream_gate_entry *tmp, *n; + struct felix_stream_gate sgi = {0}; + struct ocelot_psfp_list *psfp; + u8 z; + + psfp = &ocelot->psfp; + + list_for_each_entry_safe(tmp, n, &psfp->sgi_list, list) + if (tmp->index == index) { + z = refcount_dec_and_test(&tmp->refcount); + if (z) { + sgi.index = index; + sgi.enable = 0; + vsc9959_psfp_sgi_set(ocelot, &sgi); + list_del(&tmp->list); + kfree(tmp); + } + break; + } +} + static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index, struct felix_stream_filter_counters *counters) { @@ -1666,8 +1845,9 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot, const struct flow_action_entry *a; struct felix_stream *stream_entry; struct felix_stream stream = {0}; + struct felix_stream_gate *sgi; struct ocelot_psfp_list *psfp; - int ret, i; + int ret, i, size; psfp = &ocelot->psfp; @@ -1680,6 +1860,18 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot, flow_action_for_each(i, a, &f->rule->action) { switch (a->id) { case FLOW_ACTION_GATE: + size = struct_size(sgi, entries, a->gate.num_entries); + sgi = kzalloc(size, GFP_KERNEL); + vsc9959_psfp_parse_gate(a, sgi); + ret = vsc9959_psfp_sgi_table_add(ocelot, sgi); + if (ret) { + kfree(sgi); + return ret; + } + sfi.sg_valid = 1; + sfi.sgid = sgi->index; + kfree(sgi); + break; case FLOW_ACTION_POLICE: default: return -EOPNOTSUPP; @@ -1690,7 +1882,8 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot, stream_entry = vsc9959_stream_table_lookup(&psfp->stream_list, &stream); if (stream_entry) { NL_SET_ERR_MSG_MOD(extack, "This stream is already added"); - return -EEXIST; + ret = -EEXIST; + goto err; } sfi.prio_valid = (stream.prio < 0 ? 0 : 1); @@ -1699,14 +1892,22 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot, ret = vsc9959_psfp_sfi_table_add(ocelot, &sfi); if (ret) - return ret; + goto err; stream.sfid = sfi.index; stream.sfid_valid = 1; ret = vsc9959_stream_table_add(ocelot, &psfp->stream_list, &stream, extack); - if (ret) + if (ret) { vsc9959_psfp_sfi_table_del(ocelot, stream.sfid); + goto err; + } + + return 0; + +err: + if (sfi.sg_valid) + vsc9959_psfp_sgi_table_del(ocelot, sfi.sgid); return ret; } @@ -1714,6 +1915,7 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot, static int vsc9959_psfp_filter_del(struct ocelot *ocelot, struct flow_cls_offload *f) { + static struct felix_stream_filter *sfi; struct ocelot_psfp_list *psfp; struct felix_stream *stream; @@ -1723,6 +1925,13 @@ static int vsc9959_psfp_filter_del(struct ocelot *ocelot, if (!stream) return -ENOMEM; + sfi = vsc9959_psfp_sfi_table_get(&psfp->sfi_list, stream->sfid); + if (!sfi) + return -ENOMEM; + + if (sfi->sg_valid) + vsc9959_psfp_sgi_table_del(ocelot, sfi->sgid); + vsc9959_psfp_sfi_table_del(ocelot, stream->sfid); stream->sfid_valid = 0; From patchwork Thu Sep 30 07:59:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaoliang Yang X-Patchwork-Id: 12527589 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 91BFAC433EF for ; Thu, 30 Sep 2021 07:53:10 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 6244361452 for ; Thu, 30 Sep 2021 07:53:10 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 6244361452 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=nxp.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id: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=SbII1L939Hj7/wWyiy2b0/XanDG1NtajucWlLh19ag8=; b=yyRfEahI0GjC6m 1RwLa1YzZ/GsRfPfWkCc+B506sflyD7F1OLhYZNhi3uM2JGCyzUHhCJ/LVhVcEb47l8K1arWU7iSO QkqgQCw7fYDi27QmdXXweQ6o0Q+3gaKsvl57Mp9YtE2+wwnL8YptX1KGa0Rr//OptEyYTNnwut6Jl RQ0lVgzn/iQrWDtDSKapDcnh4b+JWOy3iljVz1+5H2ul/alqx/87Tj9P14b9CtXhUYOdGNzlPNRZT 8xFVYQGfjZXoPz8wnOd8y5oXUnZeYmNQhQIDKH2Bm7xSi2EiBcdNU++mF0WFQ9s55P6SNaN1xpy1N ErK4/YrM+iGjV1eYxreg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqsC-00DFgU-RQ; Thu, 30 Sep 2021 07:52:56 +0000 Received: from inva021.nxp.com ([92.121.34.21]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqpo-00DEGu-NV; Thu, 30 Sep 2021 07:50:31 +0000 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 73489200386; Thu, 30 Sep 2021 09:50:27 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id CE8582017BE; Thu, 30 Sep 2021 09:50:26 +0200 (CEST) Received: from localhost.localdomain (mega.ap.freescale.net [10.192.208.232]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 21C10183AC89; Thu, 30 Sep 2021 15:50:24 +0800 (+08) From: Xiaoliang Yang To: davem@davemloft.net, linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: allan.nielsen@microchip.com, joergen.andreasen@microchip.com, UNGLinuxDriver@microchip.com, vinicius.gomes@intel.com, michael.chan@broadcom.com, vishal@chelsio.com, saeedm@mellanox.com, jiri@mellanox.com, idosch@mellanox.com, alexandre.belloni@bootlin.com, kuba@kernel.org, xiaoliang.yang_1@nxp.com, po.liu@nxp.com, vladimir.oltean@nxp.com, leoyang.li@nxp.com, f.fainelli@gmail.com, andrew@lunn.ch, vivien.didelot@gmail.com, claudiu.manoil@nxp.com, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com, horatiu.vultur@microchip.com Subject: [PATCH v6 net-next 7/8] net: mscc: ocelot: use index to set vcap policer Date: Thu, 30 Sep 2021 15:59:47 +0800 Message-Id: <20210930075948.36981-8-xiaoliang.yang_1@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> References: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210930_005029_268052_3A0FB7E7 X-CRM114-Status: GOOD ( 20.72 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Policer was previously automatically assigned from the highest index to the lowest index from policer pool. But police action of tc flower now uses index to set an police entry. This patch uses the police index to set vcap policers, so that one policer can be shared by multiple rules. Signed-off-by: Xiaoliang Yang --- drivers/net/dsa/ocelot/felix.c | 4 + drivers/net/dsa/ocelot/felix.h | 4 + drivers/net/dsa/ocelot/felix_vsc9959.c | 6 ++ drivers/net/dsa/ocelot/seville_vsc9953.c | 8 ++ drivers/net/ethernet/mscc/ocelot_flower.c | 15 +++ drivers/net/ethernet/mscc/ocelot_vcap.c | 103 +++++++++++++-------- drivers/net/ethernet/mscc/ocelot_vsc7514.c | 7 ++ include/soc/mscc/ocelot.h | 14 ++- 8 files changed, 123 insertions(+), 38 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 01c01bd0c854..a75b99e1f6d9 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -986,6 +986,10 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) ocelot->num_stats = felix->info->num_stats; ocelot->num_mact_rows = felix->info->num_mact_rows; ocelot->vcap = felix->info->vcap; + ocelot->vcap_pol.base = felix->info->vcap_pol_base; + ocelot->vcap_pol.max = felix->info->vcap_pol_max; + ocelot->vcap_pol.base2 = felix->info->vcap_pol_base2; + ocelot->vcap_pol.max2 = felix->info->vcap_pol_max2; ocelot->ops = felix->info->ops; ocelot->npi_inj_prefix = OCELOT_TAG_PREFIX_SHORT; ocelot->npi_xtr_prefix = OCELOT_TAG_PREFIX_SHORT; diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 54024b6f9498..2bfdb0d6ac3b 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -21,6 +21,10 @@ struct felix_info { int num_ports; int num_tx_queues; struct vcap_props *vcap; + u16 vcap_pol_base; + u16 vcap_pol_max; + u16 vcap_pol_base2; + u16 vcap_pol_max2; int switch_pci_bar; int imdio_pci_bar; const struct ptp_clock_info *ptp_caps; diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index cbfced355010..2856df471cf2 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -19,6 +19,8 @@ #include "felix.h" #define VSC9959_TAS_GCL_ENTRY_MAX 63 +#define VSC9959_VCAP_POLICER_BASE 63 +#define VSC9959_VCAP_POLICER_MAX 383 static const u32 vsc9959_ana_regmap[] = { REG(ANA_ADVLEARN, 0x0089a0), @@ -1994,6 +1996,10 @@ static const struct felix_info felix_info_vsc9959 = { .stats_layout = vsc9959_stats_layout, .num_stats = ARRAY_SIZE(vsc9959_stats_layout), .vcap = vsc9959_vcap_props, + .vcap_pol_base = VSC9959_VCAP_POLICER_BASE, + .vcap_pol_max = VSC9959_VCAP_POLICER_MAX, + .vcap_pol_base2 = 0, + .vcap_pol_max2 = 0, .num_mact_rows = 2048, .num_ports = 6, .num_tx_queues = OCELOT_NUM_TC, diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index de1d34a1f1e4..c998f57ca178 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -18,6 +18,10 @@ #define MSCC_MIIM_CMD_REGAD_SHIFT 20 #define MSCC_MIIM_CMD_PHYAD_SHIFT 25 #define MSCC_MIIM_CMD_VLD BIT(31) +#define VSC9953_VCAP_POLICER_BASE 11 +#define VSC9953_VCAP_POLICER_MAX 31 +#define VSC9953_VCAP_POLICER_BASE2 120 +#define VSC9953_VCAP_POLICER_MAX2 161 static const u32 vsc9953_ana_regmap[] = { REG(ANA_ADVLEARN, 0x00b500), @@ -1174,6 +1178,10 @@ static const struct felix_info seville_info_vsc9953 = { .stats_layout = vsc9953_stats_layout, .num_stats = ARRAY_SIZE(vsc9953_stats_layout), .vcap = vsc9953_vcap_props, + .vcap_pol_base = VSC9953_VCAP_POLICER_BASE, + .vcap_pol_max = VSC9953_VCAP_POLICER_MAX, + .vcap_pol_base2 = VSC9953_VCAP_POLICER_BASE2, + .vcap_pol_max2 = VSC9953_VCAP_POLICER_MAX2, .num_mact_rows = 2048, .num_ports = 10, .num_tx_queues = OCELOT_NUM_TC, diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c index daeaee99933d..3d306be77028 100644 --- a/drivers/net/ethernet/mscc/ocelot_flower.c +++ b/drivers/net/ethernet/mscc/ocelot_flower.c @@ -163,6 +163,7 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port, const struct flow_action_entry *a; enum ocelot_tag_tpid_sel tpid; int i, chain, egress_port; + u32 pol_ix, pol_max; u64 rate; if (!flow_action_basic_hw_stats_check(&f->rule->action, @@ -241,6 +242,20 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port, return -EOPNOTSUPP; } filter->action.police_ena = true; + + pol_ix = a->police.index + ocelot->vcap_pol.base; + pol_max = ocelot->vcap_pol.max; + + if (ocelot->vcap_pol.max2 && pol_ix > pol_max) { + pol_ix += ocelot->vcap_pol.base2 - pol_max - 1; + pol_max = ocelot->vcap_pol.max2; + } + + if (pol_ix >= pol_max) + return -EINVAL; + + filter->action.pol_ix = pol_ix; + rate = a->police.rate_bytes_ps; filter->action.pol.rate = div_u64(rate, 1000) * 8; filter->action.pol.burst = a->police.burst; diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c index 7945393a0655..1639c2780343 100644 --- a/drivers/net/ethernet/mscc/ocelot_vcap.c +++ b/drivers/net/ethernet/mscc/ocelot_vcap.c @@ -887,10 +887,18 @@ static void vcap_entry_set(struct ocelot *ocelot, int ix, return es0_entry_set(ocelot, ix, filter); } -static int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix, - struct ocelot_policer *pol) +struct vcap_policer_entry { + struct list_head list; + refcount_t refcount; + u32 pol_ix; +}; + +int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix, + struct ocelot_policer *pol) { struct qos_policer_conf pp = { 0 }; + struct vcap_policer_entry *tmp; + int ret; if (!pol) return -EINVAL; @@ -899,57 +907,74 @@ static int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix, pp.pir = pol->rate; pp.pbs = pol->burst; - return qos_policer_conf_set(ocelot, 0, pol_ix, &pp); + list_for_each_entry(tmp, &ocelot->vcap_pol.pol_list, list) + if (tmp->pol_ix == pol_ix) { + refcount_inc(&tmp->refcount); + return 0; + } + + tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + ret = qos_policer_conf_set(ocelot, 0, pol_ix, &pp); + if (ret) { + kfree(tmp); + return ret; + } + + tmp->pol_ix = pol_ix; + refcount_set(&tmp->refcount, 1); + list_add_tail(&tmp->list, &ocelot->vcap_pol.pol_list); + + return 0; } +EXPORT_SYMBOL(ocelot_vcap_policer_add); -static void ocelot_vcap_policer_del(struct ocelot *ocelot, - struct ocelot_vcap_block *block, - u32 pol_ix) +int ocelot_vcap_policer_del(struct ocelot *ocelot, u32 pol_ix) { - struct ocelot_vcap_filter *filter; struct qos_policer_conf pp = {0}; - int index = -1; - - if (pol_ix < block->pol_lpr) - return; - - list_for_each_entry(filter, &block->rules, list) { - index++; - if (filter->block_id == VCAP_IS2 && - filter->action.police_ena && - filter->action.pol_ix < pol_ix) { - filter->action.pol_ix += 1; - ocelot_vcap_policer_add(ocelot, filter->action.pol_ix, - &filter->action.pol); - is2_entry_set(ocelot, index, filter); + struct vcap_policer_entry *tmp, *n; + u8 z = 0; + + list_for_each_entry_safe(tmp, n, &ocelot->vcap_pol.pol_list, list) + if (tmp->pol_ix == pol_ix) { + z = refcount_dec_and_test(&tmp->refcount); + if (z) { + list_del(&tmp->list); + kfree(tmp); + } } - } - pp.mode = MSCC_QOS_RATE_MODE_DISABLED; - qos_policer_conf_set(ocelot, 0, pol_ix, &pp); + if (z) { + pp.mode = MSCC_QOS_RATE_MODE_DISABLED; + return qos_policer_conf_set(ocelot, 0, pol_ix, &pp); + } - block->pol_lpr++; + return 0; } +EXPORT_SYMBOL(ocelot_vcap_policer_del); -static void ocelot_vcap_filter_add_to_block(struct ocelot *ocelot, - struct ocelot_vcap_block *block, - struct ocelot_vcap_filter *filter) +static int ocelot_vcap_filter_add_to_block(struct ocelot *ocelot, + struct ocelot_vcap_block *block, + struct ocelot_vcap_filter *filter) { struct ocelot_vcap_filter *tmp; struct list_head *pos, *n; + int ret; if (filter->block_id == VCAP_IS2 && filter->action.police_ena) { - block->pol_lpr--; - filter->action.pol_ix = block->pol_lpr; - ocelot_vcap_policer_add(ocelot, filter->action.pol_ix, - &filter->action.pol); + ret = ocelot_vcap_policer_add(ocelot, filter->action.pol_ix, + &filter->action.pol); + if (ret) + return ret; } block->count++; if (list_empty(&block->rules)) { list_add(&filter->list, &block->rules); - return; + return 0; } list_for_each_safe(pos, n, &block->rules) { @@ -958,6 +983,8 @@ static void ocelot_vcap_filter_add_to_block(struct ocelot *ocelot, break; } list_add(&filter->list, pos->prev); + + return 0; } static bool ocelot_vcap_filter_equal(const struct ocelot_vcap_filter *a, @@ -1132,7 +1159,7 @@ int ocelot_vcap_filter_add(struct ocelot *ocelot, struct netlink_ext_ack *extack) { struct ocelot_vcap_block *block = &ocelot->block[filter->block_id]; - int i, index; + int i, index, ret; if (!ocelot_exclusive_mac_etype_filter_rules(ocelot, filter)) { NL_SET_ERR_MSG_MOD(extack, @@ -1141,7 +1168,9 @@ int ocelot_vcap_filter_add(struct ocelot *ocelot, } /* Add filter to the linked list */ - ocelot_vcap_filter_add_to_block(ocelot, block, filter); + ret = ocelot_vcap_filter_add_to_block(ocelot, block, filter); + if (ret) + return ret; /* Get the index of the inserted filter */ index = ocelot_vcap_block_get_filter_index(block, filter); @@ -1174,7 +1203,7 @@ static void ocelot_vcap_block_remove_filter(struct ocelot *ocelot, if (ocelot_vcap_filter_equal(filter, tmp)) { if (tmp->block_id == VCAP_IS2 && tmp->action.police_ena) - ocelot_vcap_policer_del(ocelot, block, + ocelot_vcap_policer_del(ocelot, tmp->action.pol_ix); list_del(pos); @@ -1350,13 +1379,13 @@ int ocelot_vcap_init(struct ocelot *ocelot) struct vcap_props *vcap = &ocelot->vcap[i]; INIT_LIST_HEAD(&block->rules); - block->pol_lpr = OCELOT_POLICER_DISCARD - 1; ocelot_vcap_detect_constants(ocelot, vcap); ocelot_vcap_init_one(ocelot, vcap); } INIT_LIST_HEAD(&ocelot->dummy_rules); + INIT_LIST_HEAD(&ocelot->vcap_pol.pol_list); return 0; } diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 5d01993f6be0..a57a359f2748 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -20,6 +20,9 @@ #include #include "ocelot.h" +#define VSC7514_VCAP_POLICER_BASE 128 +#define VSC7514_VCAP_POLICER_MAX 191 + static const u32 ocelot_ana_regmap[] = { REG(ANA_ADVLEARN, 0x009000), REG(ANA_VLANMASK, 0x009004), @@ -1128,6 +1131,10 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ocelot->num_flooding_pgids = 1; ocelot->vcap = vsc7514_vcap_props; + + ocelot->vcap_pol.base = VSC7514_VCAP_POLICER_BASE; + ocelot->vcap_pol.max = VSC7514_VCAP_POLICER_MAX; + ocelot->npi = -1; err = ocelot_init(ocelot); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 61429ed06e72..9b4b910505f9 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -571,10 +571,17 @@ struct ocelot_ops { struct flow_stats *stats); }; +struct ocelot_vcap_policer { + struct list_head pol_list; + u16 base; + u16 max; + u16 base2; + u16 max2; +}; + struct ocelot_vcap_block { struct list_head rules; int count; - int pol_lpr; }; struct ocelot_vlan { @@ -690,6 +697,7 @@ struct ocelot { struct list_head dummy_rules; struct ocelot_vcap_block block[3]; + struct ocelot_vcap_policer vcap_pol; struct vcap_props *vcap; struct ocelot_psfp_list psfp; @@ -942,6 +950,10 @@ int ocelot_mact_learn_streamdata(struct ocelot *ocelot, int dst_idx, enum macaccess_entry_type type, int sfid, int ssid); +int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix, + struct ocelot_policer *pol); +int ocelot_vcap_policer_del(struct ocelot *ocelot, u32 pol_ix); + #if IS_ENABLED(CONFIG_BRIDGE_MRP) int ocelot_mrp_add(struct ocelot *ocelot, int port, const struct switchdev_obj_mrp *mrp); From patchwork Thu Sep 30 07:59:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaoliang Yang X-Patchwork-Id: 12527591 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A0C2FC433EF for ; Thu, 30 Sep 2021 07:53:44 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 7600A61452 for ; Thu, 30 Sep 2021 07:53:44 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 7600A61452 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=nxp.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id: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=MKiJjknvT8/CXjPEf1FmS4StYRvdFOha1jVKI5ieqXQ=; b=B+GU0TdA1tUJAU TNuwEGz7BrC1vgy2DSryQQNTzXVi4bBLhcyhnyZqKBajFSYYx80+c1NeNMCyaHpGQOwyOiz6BzB1g nVwh+nroJYfT4sen475+giV7EfZ+r7sH0zyDMWfn5JOBt5dC7LMJmtmWG61K53oF7mfiE9DKs0QbU ew06CS8X0RP9gB5bfNni+mTKHJ+wia2i70Ogi8qMkX7qqSAdqqamFkaTcadI6z/Xio8KQKV0Jm4o9 uQJHlbALOoWxhRJVMnRm3Xr7Er16TOyBihaF4g8anAJ4ejUpmiE7aSJmgECeg9F6xifpL8UMoRUVC oifBp2QClQpdFDGL+BQQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqsm-00DG5N-Fb; Thu, 30 Sep 2021 07:53:32 +0000 Received: from inva021.nxp.com ([92.121.34.21]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVqpq-00DEHn-QZ; Thu, 30 Sep 2021 07:50:32 +0000 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 920832017C0; Thu, 30 Sep 2021 09:50:29 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 20696200408; Thu, 30 Sep 2021 09:50:29 +0200 (CEST) Received: from localhost.localdomain (mega.ap.freescale.net [10.192.208.232]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 5D3FC183AC94; Thu, 30 Sep 2021 15:50:26 +0800 (+08) From: Xiaoliang Yang To: davem@davemloft.net, linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: allan.nielsen@microchip.com, joergen.andreasen@microchip.com, UNGLinuxDriver@microchip.com, vinicius.gomes@intel.com, michael.chan@broadcom.com, vishal@chelsio.com, saeedm@mellanox.com, jiri@mellanox.com, idosch@mellanox.com, alexandre.belloni@bootlin.com, kuba@kernel.org, xiaoliang.yang_1@nxp.com, po.liu@nxp.com, vladimir.oltean@nxp.com, leoyang.li@nxp.com, f.fainelli@gmail.com, andrew@lunn.ch, vivien.didelot@gmail.com, claudiu.manoil@nxp.com, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com, horatiu.vultur@microchip.com Subject: [PATCH v6 net-next 8/8] net: dsa: felix: use vcap policer to set flow meter for psfp Date: Thu, 30 Sep 2021 15:59:48 +0800 Message-Id: <20210930075948.36981-9-xiaoliang.yang_1@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> References: <20210930075948.36981-1-xiaoliang.yang_1@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210930_005031_164653_B3C3A73A X-CRM114-Status: GOOD ( 12.52 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org This patch add police action to set flow meter table which is defined in IEEE802.1Qci. Flow metering is two rates two buckets and three color marker to policing the frames, we only enable one rate one bucket in this patch. Flow metering shares a same policer pool with VCAP policers, so the PSFP policer calls ocelot_vcap_policer_add() and ocelot_vcap_policer_del() to set flow meter police. Signed-off-by: Xiaoliang Yang --- drivers/net/dsa/ocelot/felix_vsc9959.c | 32 +++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 2856df471cf2..1699d8cd8366 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1343,6 +1343,7 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port, #define VSC9959_PSFP_SFID_MAX 175 #define VSC9959_PSFP_GATE_ID_MAX 183 +#define VSC9959_PSFP_POLICER_BASE 63 #define VSC9959_PSFP_POLICER_MAX 383 #define VSC9959_PSFP_GATE_LIST_NUM 4 #define VSC9959_PSFP_GATE_CYCLETIME_MIN 5000 @@ -1849,7 +1850,10 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot, struct felix_stream stream = {0}; struct felix_stream_gate *sgi; struct ocelot_psfp_list *psfp; + struct ocelot_policer pol; int ret, i, size; + u64 rate, burst; + u32 index; psfp = &ocelot->psfp; @@ -1868,13 +1872,33 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot, ret = vsc9959_psfp_sgi_table_add(ocelot, sgi); if (ret) { kfree(sgi); - return ret; + goto err; } sfi.sg_valid = 1; sfi.sgid = sgi->index; kfree(sgi); break; case FLOW_ACTION_POLICE: + index = a->police.index + VSC9959_PSFP_POLICER_BASE; + if (index > VSC9959_PSFP_POLICER_MAX) { + ret = -EINVAL; + goto err; + } + + rate = a->police.rate_bytes_ps; + burst = rate * PSCHED_NS2TICKS(a->police.burst); + pol = (struct ocelot_policer) { + .burst = div_u64(burst, PSCHED_TICKS_PER_SEC), + .rate = div_u64(rate, 1000) * 8, + }; + ret = ocelot_vcap_policer_add(ocelot, index, &pol); + if (ret) + goto err; + + sfi.fm_valid = 1; + sfi.fmid = index; + sfi.maxsdu = a->police.mtu; + break; default: return -EOPNOTSUPP; } @@ -1911,6 +1935,9 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot, if (sfi.sg_valid) vsc9959_psfp_sgi_table_del(ocelot, sfi.sgid); + if (sfi.fm_valid) + ocelot_vcap_policer_del(ocelot, sfi.fmid); + return ret; } @@ -1934,6 +1961,9 @@ static int vsc9959_psfp_filter_del(struct ocelot *ocelot, if (sfi->sg_valid) vsc9959_psfp_sgi_table_del(ocelot, sfi->sgid); + if (sfi->fm_valid) + ocelot_vcap_policer_del(ocelot, sfi->fmid); + vsc9959_psfp_sfi_table_del(ocelot, stream->sfid); stream->sfid_valid = 0;