From patchwork Sun Aug 12 15:57:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tal Bar X-Patchwork-Id: 10563751 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CC143139A for ; Sun, 12 Aug 2018 20:38:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B7E0C28F8D for ; Sun, 12 Aug 2018 20:38:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AAAAE28F94; Sun, 12 Aug 2018 20:38:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=2.0 tests=BAD_ENC_HEADER,BAYES_00, DKIM_SIGNED,MAILING_LIST_MULTI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 57FFC28F8D for ; Sun, 12 Aug 2018 20:38:17 +0000 (UTC) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 41pW066yMYzF0Rr for ; Mon, 13 Aug 2018 06:38:14 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=mellanox.com Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=Mellanox.com header.i=@Mellanox.com header.b="Ao/nqQOF"; dkim-atps=neutral X-Original-To: linux-mlxsw@lists.ozlabs.org Delivered-To: linux-mlxsw@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=mellanox.com (client-ip=40.107.5.59; helo=eur03-ve1-obe.outbound.protection.outlook.com; envelope-from=talb@mellanox.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=mellanox.com Authentication-Results: lists.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=Mellanox.com header.i=@Mellanox.com header.b="Ao/nqQOF"; dkim-atps=neutral Received: from EUR03-VE1-obe.outbound.protection.outlook.com (mail-eopbgr50059.outbound.protection.outlook.com [40.107.5.59]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 41pVzn35TBzF0Rr for ; Mon, 13 Aug 2018 06:37:56 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=0Ka7O5xQOKm+eLieFcr5yx93qJvbqJnzHFejozaO4BM=; b=Ao/nqQOF2y3LMjQQoZ0PqjFBHIYju+3bLF7cZqfnjutF2c1J7ioZH+pQcoKOgU5p07iaUDEE8ZImQ3NRMR5JVuwR3UKvY3AdA9yDNzcKzDjlapSfaR+4jwiCeSklDRAsM9YO9jlUi54iObW1yTtuvQFW9VCIbzaqCa5P8K6dP8s= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=talb@mellanox.com; Received: from dev-r-vrt-156.mtr.labs.mlnx (37.142.13.130) by DB6PR05MB3287.eurprd05.prod.outlook.com (2603:10a6:6:1b::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1038.19; Sun, 12 Aug 2018 15:57:44 +0000 From: Tal Bar To: idosch@mellanox.com, jiri@mellanox.com Subject: [net-next mlxsw v10 3/3] mlxsw: spectrum_acl: Add utilization of the prune library Date: Sun, 12 Aug 2018 18:57:21 +0300 Message-Id: <1534089441-20653-4-git-send-email-talb@mellanox.com> X-Mailer: git-send-email 2.8.0 In-Reply-To: <1534089441-20653-1-git-send-email-talb@mellanox.com> References: <1534089441-20653-1-git-send-email-talb@mellanox.com> MIME-Version: 1.0 X-Originating-IP: [37.142.13.130] X-ClientProxiedBy: AM4PR05CA0001.eurprd05.prod.outlook.com (2603:10a6:205::14) To DB6PR05MB3287.eurprd05.prod.outlook.com (2603:10a6:6:1b::29) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: c31e1bfc-0f28-453a-48fa-08d6006c57f8 X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: BCL:0; PCL:0; RULEID:(7020095)(4652040)(8989117)(5600074)(711020)(4618075)(2017052603328)(7153060)(7193020); SRVR:DB6PR05MB3287; X-Microsoft-Exchange-Diagnostics: 1; DB6PR05MB3287; 3:p62oDnLqAdwh8IFj2w2Gxy1XtU7ilqW18mI64RklxC3FpVJhcd+r1JZOd3USwNXfBhn3isA02y6LNLSF6jZiEXJbzAT8krGseXoheU0J8rWWW/E7b+ZI7MyaO6H8LUCmjufMVGYV5/NDKeus0MHUHB4UqmuWCKOGCdEMHoRk/CJmySwHDQqUtP61MUvCI0DgHMnySZ+Bs7mJOy5zL2Zcd6l6YKWq016HBwufDR1O2lcKjYYvAdrhnS2Gpo5qK6Vl; 25:CzAyv4gU+CC72MSBJKWc/Od0OZuEQBtXfc1kuFcH+Z5yXGKVeWYkqP8K42EUYBPD8BlCFTl7JSEoPfB2HwLG0bM+L5XSMNSfDontu1xxKOFeYWqITdzQVO9H3i1gN6by2U/vEKXG762mrZr0z8PMN3RS/tWyca0S2H7h+/ImX1RKGoF5v9ztX0meGtkkBG4CLK78Au3dMbby0Vs6HAOeT2qaKI9rWpJuud++rHzX8fq1vhbRZ20GXJb0nEw+iz35t14AD71rQznSZKDlZJKe/Xi7d/cF8TsNsfND+F/sLMhxL57icWiPNlSbT2+PbO3yy+akb8v6m/sHz1liJLomGg==; 31:eVVvK0lbR8N5nmtqmrpuNM1JTlrulqGUdomNxDjQ2MOq3pxXfHqF1Iz2W767oSOjCSoKvsxEH7cMS351xjBCo6KH1nSaR+y+E5o4S8rixAP5kArH67qXEnWxtlqAODfC5Awhu0fmsqeMDOUzzOgtnKKmlMrlnJMvSLn7xQmmJf2LMg5kM60bdix9v424B+zactidgEMnRqoYlFPG/+8s4PuhJQuYwzhkWggrj8pVu0U= X-MS-TrafficTypeDiagnostic: DB6PR05MB3287: X-Microsoft-Exchange-Diagnostics: 1; DB6PR05MB3287; 20:R+P/trnGqEhDzdsot5AyHePIOdScngv5JR52dc20Pf22PERCgLBJNvfgXcVl+7jv/5b2tOdpDdZrj8ScbYeKOLbfds8W128CRPhLhNHhIDTnsbsXqYJB/nLBXMip8mcrJcxS/s7nYZuJOCMziYmaAu1v8rXxbos32vkeNU1e6tB0LOUsbQVIpllQuQWA5xR96Cg3mVQTtuRrYD/pfd1QRSqkVvEyDxbEY+NWrhpgNWRzEzKp7dXi3EguwMDY9kfdevHs7hlnWJapbEtOLvtRvbhleHv87wjg8YKm2WWt7JhLI69Ke7lC+kHmyTGxUtWsAPWfA9wOaAwRZoXtxhcgTp9R08BhRoGUneaoa2nkkUkTq1HoRB3L+N2LLoFiwd5nFsMGeP1gbecnwy06hoIzrUKlFwtIEi0xpN2QryVW8a7Lw9dnnydNBwZLTbaMVXo5P6l4ppnDKiZikeXusOhOquMC+dF9gU0sB18H9StPL66oI4vhgfnIXs84wiYcKW3g; 4:2D2JdW7ycKypBv16ey7ezfyG6ahVgOX46HGk9O/tOrDX8ZfqsV12nR+VH4oExDYt/Uu4zQP7Ej/mssqmrCQYVmSAEpVu5NBcLe2+MB4L9+e8McWFxb58efXXvaK1bEoDsde5tH7vDaLRGdlrHelfhMSyiLuWA0EGlPvNi18zfXQbKWE2E4mxmp4763PQkNY0Vd3ai7/t8bTLH3ksOWAjPEoq03HV6K14cEqN/QlPlQYg2zbj0nyIt6Qx2x40o0tZF9cYgjWnDIKKFTFu0pzrlA== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(5005006)(8121501046)(3002001)(10201501046)(3231311)(944501410)(52105095)(93006095)(93001095)(6055026)(149027)(150027)(6041310)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123562045)(20161123564045)(20161123558120)(20161123560045)(6072148)(201708071742011)(7699016); SRVR:DB6PR05MB3287; BCL:0; PCL:0; RULEID:; SRVR:DB6PR05MB3287; X-Forefront-PRVS: 0762FFD075 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(396003)(346002)(376002)(136003)(366004)(39860400002)(199004)(189003)(6512007)(53946003)(6636002)(2616005)(50226002)(6506007)(386003)(81166006)(81156014)(53936002)(956004)(6116002)(68736007)(8676002)(86362001)(8936002)(6486002)(2906002)(3846002)(11346002)(14444005)(5660300001)(16526019)(52116002)(106356001)(50466002)(48376002)(47776003)(66066001)(25786009)(36756003)(316002)(16586007)(305945005)(4326008)(6666003)(26005)(7736002)(476003)(478600001)(105586002)(85306007)(446003)(107886003)(486006)(76176011)(51416003)(97736004); DIR:OUT; SFP:1101; SCL:1; SRVR:DB6PR05MB3287; H:dev-r-vrt-156.mtr.labs.mlnx; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; Received-SPF: None (protection.outlook.com: mellanox.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; DB6PR05MB3287; 23:sIStNIeyxVtNkUpYUi1cVsABUuq21ZmtMtOBRl+pV?= 39WrFQToPNZN01eb1Iivivhm4nKl0hv/N1Q0HExIef9GPBMULGLtJKJE5pa5qeTRKarD19B98O6WzcyED3DuzSIWF5m8lU3hpmPS2kTLBLnyPQPAdvNFoh0SQWqSHLXWDDm91dtWrybfp25Ufxa3Es5+UU+/uRXhU80J85SNsxMWKqhOvcpYxEt6XHKsg6Rv3Ibx0eZWPS7ZG4kpoeIdMSi2VOOQRLgTf/ViAiVg2h9pTRoteaOu1XC0jm2SFh48NzEILrzcnLrcBxtzqhWH8AnpoZj+TzejD2+fVvayUFkBHTackdGTXhkT8x9UlAw7KHbbu6duTUdgBh5j9L5jnN83lpsF4CgH2209W9tOFDiGolYZYI/S/O5wyyXznQZtqMWQtFP0tmWNkVm8g8j3Tf+/dFXijkqMs9KOKjF3de6pSt0IBC4FQuNp8ao7ZCWYOn9r/Ue7xBrWDnor+52IQB6uAsVAI93U/CIEzuu817C8OUtIRXyOxv4ZcFy14hSJLzYD6IhEfqxiH893RNYx8xNtsh6Ds1O/9ucFq75OzKoDqX1d9mcCObBrkfNFna/31AwRkZBbo1ik7R8meKUi0Vt/M1z4c7OZ+3kKnNAj9PvEbjBfCv+VdiWNrJhGHfpHEmkCW1hub3/gwhazh1CC4UY0D7pLhRrYqLXaRGq2iJlUPe9l9x6RBDRsDN5zVKi/Pl40trnM8wtKt1/kmYANl93LlFFndypxz0ozdPbhsua++Jj9y73+iydpTcsyUY+d3KXCZWikRN+O6XDm6hwQ/BmdcE/y+SaOc+NypdlXzDtWayU9sYzmrGLwnEnzaQDcgCEAJBvGWvtEc+VA8OosOPI9AxPMjWoyTZO96jKJ9s4jO+Y9gGMcRoJUJ09IgVbWJlWDgI7pYe7UUNigFGHx09+Z6/HEi7nkrK4xEhPuw5BUfgmgBbk5MnGIbn2CazKY9BxWNnipxvjWIATgJQL1TgXwJsaHeNJ0yTkbwRIgwq1oTh/ny+PM9WMSLr2wvX4kqlLoRFlvw27i80mE3qw+NX/bQi1loTDdwAQcTfVPabkgcoxi22Gd9qxrLtWHX3yTjVIFrQn2Bdqg8Lk6iEFiwSKv0pfAz3yDBWCTAiQygg2J/Y9DFytxsfmKiFRykymLHoQZBADHZGkth0iz9dhtXwR4vTa8wzX3q4GQiN0IJ1Hgw== X-Microsoft-Antispam-Message-Info: ScLBWJbWHtNDY4EMsXZk/KZxNQJYRim9a9BLBsdAfLfHtDJZLrPWT02manHiifkb6KG+sbaOhHDEXjQ3Rooi9V0qv1aR64Vw1AvWHwFqrS0S59sNV7pNqMkf1YEtUhVl77vWtFr5UR5c/MycCpbWUmLGGeUAXz57tx052sU7bka58auz2wL1aOF7bNKTO1X03ZGSTBWPP1gVLgksz4o1huev9Sv60kHRhfhmYW1fbFe+TYUQiZ10+dR2ayVszbklW70MtFFv4VDaVIm7DcBjwJVEJDzju9GXuUGBBYRW1fjfSx18gtejMBqj9WfHx4j7Liv8wpAw5kuI9ax37S028IFJ0Hodo9KCJzcap5BKoUg= X-Microsoft-Exchange-Diagnostics: 1; DB6PR05MB3287; 6:pGuyELImLhKjNm+4FUQPZAppDAwrFcvzdkqjHwzISgbDEzltOERCHqEaz1h2IgOO42jVf50P06BNcp+joL/N3dTrfMpvK8uhrzqxMZSYZCcrAeUN4Ci3XcssRIC5P7d+uW+Lx3BoAndxKANJ3IxDkvdcNvhBPRhmAs+HyQs3f/yse5rvWSrA7KGO9SSx9nKolTr7GyTLAM2OoEDe/yIIxgplIBo/JEbQcoMZCndM9P1mYtLIjlJBmw3hCMeeoORY60dtYd1AOieJPLj/80tKZBF0yHci4u/ajL63WTfZmpo2uAOMZnNlecPg+gui7joTjLCqL5C1s/XQ5qKorMJJFYzRNBAEza3BIRf6r7hRmrJ0dKCo81QnR9H0P4VQk382c7o1NRsF1RL/rnBAp2SWNoenJz6rh9F/LjQU7e66HOsGpuACCse9twPZfrhCspuzW68MN/3Bkf0B72aBns9Mew==; 5:AseC/F/bhUX42fytfIW4GblmoaAdBJYU3No9i+rqwtE25olPuEZoAPb5VoX2/i72qmjOuJeeoQ3mNk8gVOkerbn7l6pfH39kBuIQTOBQ+gms8zbPKoIri2Pi97iVh7V0fr1XdVMwy4IO0VnZ9CUvfuqa2sUDv5YgQEVhwcBGPnU=; 7:i+eE6Mij66WePjvPhB5QDS3THLrkV7TF3eP/nPR5XsH9gtdgg+xcZBotAqtVHtIIZ6ieZiKb5XA7dLF/jkF25F2GwDGMmzHdnHPm7tPurOQ41T5VzrJhnUsOSmXxiQKSku3V9rLVT8Xm87Wm4RCsh8eRO341I9Q2IlJbmOGoC7fV81r0YThWl0csEAHax07CxTUp96XjBXcYiZ1EO50EC4PwcTRiYR9JEpsQ1PVt2kpOJs0eRBTas/Ly2OZVCojn SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2018 15:57:44.3125 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: c31e1bfc-0f28-453a-48fa-08d6006c57f8 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6PR05MB3287 X-BeenThere: linux-mlxsw@lists.ozlabs.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: mlxsw driver development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-internal@mellanox.com Errors-To: linux-mlxsw-bounces+patchwork-linux-mlxsw=patchwork.kernel.org@lists.ozlabs.org X-Virus-Scanned: ClamAV using ClamSMTP A packet needs to be evaluated against a data base of rules. For A-TCAM the ASIC has to do up to 16 lookups, 1 per ERP. In order to reduce the number of lookups the driver utilize the prube library. In Spectrum-2 the every rule has a prune_vector and a ctcam_prune. The prune_vector instruct the ASIC which ERPs are not relevant for further lookups and the ctcam_prune instructs the ASIC to do lookup on the C-TCAM. The driver set the vector according to rule priority and the ctcam_prune of the matched rule. That increase the performance, since ASIC make only the needed lookups. There is a special case for 8 key blocks region type. The ASIC support prune vector of all 1's (prune) or all 0's (do lookup). In the driver we choose to set all 0's therefore the performance will be less then optimal but correct. Signed-off-by: Tal Bar --- drivers/net/ethernet/mellanox/mlxsw/Kconfig | 1 + drivers/net/ethernet/mellanox/mlxsw/reg.h | 16 ++- .../ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c | 3 +- .../ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c | 154 ++++++++++++++++++++- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 8 ++ .../ethernet/mellanox/mlxsw/spectrum_acl_atcam.c | 138 ++++++++++++++++-- .../ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c | 7 +- .../net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c | 61 +++++++- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 9 +- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 42 +++++- 10 files changed, 408 insertions(+), 31 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig index 8a291eb..7e6b518 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig +++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig @@ -80,6 +80,7 @@ config MLXSW_SPECTRUM depends on IPV6_GRE || IPV6_GRE=n select GENERIC_ALLOCATOR select PARMAN + select PRUNE select MLXFW default m ---help--- diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 6e8b619..4931cdf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2760,13 +2760,24 @@ MLXSW_ITEM32(reg, ptce3, large_entry_key_id, 0x98, 0, 24); */ MLXSW_ITEM32(reg, ptce3, action_pointer, 0xA0, 0, 24); +static inline void +mlxsw_reg_ptce3_prune_vector_pack(char *payload, + unsigned long *prune_vector, + unsigned long size) +{ + unsigned long bit; + + for_each_set_bit(bit, prune_vector, size) + mlxsw_reg_ptce3_prune_vector_set(payload, bit, true); +} + static inline void mlxsw_reg_ptce3_pack(char *payload, bool valid, enum mlxsw_reg_ptce3_op op, u32 priority, const char *tcam_region_info, const char *key, u8 erp_id, - bool large_exists, u32 lkey_id, - u32 action_pointer) + bool prune_ctcam, bool large_exists, + u32 lkey_id, u32 action_pointer) { MLXSW_REG_ZERO(ptce3, payload); mlxsw_reg_ptce3_v_set(payload, valid); @@ -2775,6 +2786,7 @@ static inline void mlxsw_reg_ptce3_pack(char *payload, bool valid, mlxsw_reg_ptce3_tcam_region_info_memcpy_to(payload, tcam_region_info); mlxsw_reg_ptce3_flex2_key_blocks_memcpy_to(payload, key); mlxsw_reg_ptce3_erp_id_set(payload, erp_id); + mlxsw_reg_ptce3_prune_ctcam_set(payload, prune_ctcam); mlxsw_reg_ptce3_large_exists_set(payload, large_exists); mlxsw_reg_ptce3_large_entry_key_id_set(payload, lkey_id); mlxsw_reg_ptce3_action_pointer_set(payload, action_pointer); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c index 2a9eac9..e1ddaf4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c @@ -30,7 +30,8 @@ struct mlxsw_sp1_acl_tcam_entry { static int mlxsw_sp1_acl_ctcam_region_entry_insert(struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_ctcam_entry *centry, - const char *mask) + const char *key, const char *mask, + u32 priority) { return 0; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c index 8ca77f3..835108a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c @@ -2,6 +2,7 @@ /* Copyright (c) 2018 Mellanox Technologies. All rights reserved */ #include +#include #include "spectrum.h" #include "spectrum_acl_tcam.h" @@ -27,14 +28,139 @@ struct mlxsw_sp2_acl_tcam_entry { struct mlxsw_afa_block *act_block; }; +struct mlxsw_afa_block * +mlxsw_sp2_acl_tcam_aentry_act_block(struct mlxsw_sp_acl_atcam_entry *aentry) +{ + struct mlxsw_sp2_acl_tcam_entry *entry; + + entry = container_of(aentry, struct mlxsw_sp2_acl_tcam_entry, aentry); + return entry->act_block; +} + +void +mlxsw_sp2_acl_tcam_prune_vector_bit_set(struct mlxsw_sp_acl_erp *erp, + struct mlxsw_sp_acl_atcam_entry *aentry, + bool pruned) +{ + if (pruned) + __set_bit(mlxsw_sp_acl_erp_index(erp), aentry->prune_bitmap); + else + __clear_bit(mlxsw_sp_acl_erp_index(erp), aentry->prune_bitmap); +} + +static void +mlxsw_sp2_acl_tcam_prune_update(struct mlxsw_sp_acl_erp *erp, + struct mlxsw_sp_acl_atcam_entry *aentry) +{ + struct mlxsw_sp_acl_atcam_region *aregion; + struct mlxsw_sp *mlxsw_sp; + u32 priority; + int err; + + aregion = mlxsw_sp_acl_erp_aregion(erp); + mlxsw_sp = aregion->region->mlxsw_sp; + priority = aentry->prune_item->priority; + + err = mlxsw_sp_acl_tcam_priority_get(mlxsw_sp, + aentry->prune_item->priority, + &priority, true); + if (err) { + WARN(err, "Failed to retrieve rule priority while updating rule with priority %u\n", + aentry->prune_item->priority); + return; + } + err = mlxsw_sp_acl_atcam_region_entry_update(mlxsw_sp, aregion, aentry, + priority); + if (err) { + WARN(err, "Failed to updating prune vector while update rule with priority %u\n", + aentry->prune_item->priority); + return; + } +} + +static void +mlxsw_sp2_acl_tcam_prune_ctcam_update(struct mlxsw_sp_acl_erp *erp, + struct mlxsw_sp_acl_atcam_entry *aentry, + bool pruned) +{ + bool ctcam_pruned = aentry->num_ctcam_erps_scan > 0 ? true : false; + + pruned ? aentry->num_ctcam_erps_scan-- : aentry->num_ctcam_erps_scan++; + + if ((aentry->num_ctcam_erps_scan > 0 && !ctcam_pruned) || + (ctcam_pruned & !aentry->num_ctcam_erps_scan)) + mlxsw_sp2_acl_tcam_prune_update(erp, aentry); +} + +static void +mlxsw_sp2_acl_tcam_prune_vector_update(struct mlxsw_sp_acl_erp *erp, + struct mlxsw_sp_acl_atcam_entry *aentry, + bool pruned) +{ + mlxsw_sp2_acl_tcam_prune_vector_bit_set(erp, aentry, pruned); + mlxsw_sp2_acl_tcam_prune_update(erp, aentry); +} + +static void +mlxsw_sp2_acl_tcam_prune_notification_handler(struct mlxsw_sp_acl_erp *erp, + struct mlxsw_sp_acl_atcam_entry + *aentry, + bool pruned) +{ + enum mlxsw_sp_acl_atcam_region_type region_type; + bool ctcam_erp, ctcam_entry; + + region_type = mlxsw_sp_acl_erp_region_type(aentry->erp); + ctcam_entry = mlxsw_sp_acl_erp_is_ctcam_erp(aentry->erp); + ctcam_erp = mlxsw_sp_acl_erp_is_ctcam_erp(erp); + + /* Discard notification: + * For ctcam rule prune vector is irrelevant + * For 8KB region type we should always not prune + */ + if (!ctcam_entry && region_type != MLXSW_SP_ACL_ATCAM_REGION_TYPE_8KB) { + if (ctcam_erp) + mlxsw_sp2_acl_tcam_prune_ctcam_update(erp, aentry, + pruned); + else + mlxsw_sp2_acl_tcam_prune_vector_update(erp, aentry, + pruned); + } +} + +static void +mlxsw_sp2_acl_atcam_entry_prune_notify(struct list_head *prune_item_notify_list, + struct prune_table *table, bool pruned) +{ + struct mlxsw_sp_acl_atcam_entry *aentry; + struct mlxsw_sp_acl_erp *erp; + struct prune_item *item; + + list_for_each_entry(item, prune_item_notify_list, list) { + aentry = item->priv; + erp = prune_table_priv(table); + mlxsw_sp2_acl_tcam_prune_notification_handler(erp, aentry, + pruned); + } +} + +static const struct prune_ops mlxsw_sp2_acl_atcam_prune_ops = { + .prune_item_notify = mlxsw_sp2_acl_atcam_entry_prune_notify +}; + static int mlxsw_sp2_acl_ctcam_region_entry_insert(struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_ctcam_entry *centry, - const char *mask) + const char *key, + const char *mask, + u32 priority) { struct mlxsw_sp_acl_atcam_region *aregion; struct mlxsw_sp_acl_atcam_entry *aentry; + struct prune_item *prune_item; struct mlxsw_sp_acl_erp *erp; + bool non_def_prune_vector; + int err; aregion = mlxsw_sp_acl_tcam_cregion_aregion(cregion); aentry = mlxsw_sp_acl_tcam_centry_aentry(centry); @@ -44,7 +170,25 @@ mlxsw_sp2_acl_ctcam_region_entry_insert(struct mlxsw_sp_acl_ctcam_region *cregio return PTR_ERR(erp); aentry->erp = erp; + bitmap_from_arr32(aentry->key_bitmap, (void *) key, + MLXSW_SP_ACL_TCAM_MASK_LEN); + + prune_item = prune_item_create(aregion->region->prune, + mlxsw_sp_acl_erp_prune_table(erp), + priority, aentry->key_bitmap, aentry, + &non_def_prune_vector); + if (IS_ERR(prune_item)) { + err = PTR_ERR(prune_item); + goto err_prune_item_create; + } + aentry->prune_item = prune_item; + aentry->num_ctcam_erps_scan = 0; + return 0; + +err_prune_item_create: + mlxsw_sp_acl_erp_put(aregion, erp); + return err; } static void @@ -53,10 +197,15 @@ mlxsw_sp2_acl_ctcam_region_entry_remove(struct mlxsw_sp_acl_ctcam_region *cregio { struct mlxsw_sp_acl_atcam_region *aregion; struct mlxsw_sp_acl_atcam_entry *aentry; + int err; aregion = mlxsw_sp_acl_tcam_cregion_aregion(cregion); aentry = mlxsw_sp_acl_tcam_centry_aentry(centry); + err = prune_item_destroy(aentry->prune_item); + WARN(err, "Failed to destroy prune item while removing rule with priority %u\n", + aentry->prune_item->priority); + mlxsw_sp_acl_erp_put(aregion, aentry->erp); } @@ -148,7 +297,8 @@ mlxsw_sp2_acl_tcam_region_init(struct mlxsw_sp *mlxsw_sp, void *region_priv, return mlxsw_sp_acl_atcam_region_init(mlxsw_sp, &tcam->atcam, ®ion->aregion, _region, - &mlxsw_sp2_acl_ctcam_region_ops); + &mlxsw_sp2_acl_ctcam_region_ops, + &mlxsw_sp2_acl_atcam_prune_ops); } static void diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index 2658a51..ed8270d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -847,6 +848,10 @@ int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp) if (err) goto err_acl_ops_init; + err = prune_init(); + if (err) + goto err_prune_init; + /* Create the delayed work for the rule activity_update */ INIT_DELAYED_WORK(&acl->rule_activity_update.dw, mlxsw_sp_acl_rul_activity_update_work); @@ -854,6 +859,8 @@ int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp) mlxsw_core_schedule_dw(&acl->rule_activity_update.dw, 0); return 0; +err_prune_init: + mlxsw_sp_acl_tcam_fini(mlxsw_sp, &acl->tcam); err_acl_ops_init: mlxsw_sp_fid_put(fid); err_fid_get: @@ -870,6 +877,7 @@ void mlxsw_sp_acl_fini(struct mlxsw_sp *mlxsw_sp) struct mlxsw_sp_acl *acl = mlxsw_sp->acl; cancel_delayed_work_sync(&mlxsw_sp->acl->rule_activity_update.dw); + prune_fini(); mlxsw_sp_acl_tcam_fini(mlxsw_sp, &acl->tcam); WARN_ON(!list_empty(&acl->rules)); mlxsw_sp_fid_put(acl->dummy_fid); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c index 2dda028..97dedbf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "reg.h" #include "core.h" @@ -317,7 +318,9 @@ mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_tcam_region *region, - const struct mlxsw_sp_acl_ctcam_region_ops *ops) + const struct mlxsw_sp_acl_ctcam_region_ops *ops, + const struct prune_ops + *mlxsw_acl_atcam_prune_ops) { int err; @@ -339,9 +342,17 @@ mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, region, ops); if (err) goto err_ctcam_region_init; + region->prune = prune_create(MLXSW_SP_ACL_TCAM_MASK_LEN, + mlxsw_acl_atcam_prune_ops, region); + if (IS_ERR(region->prune)) { + err = PTR_ERR(region->prune); + goto err_prune_create; + } return 0; +err_prune_create: + mlxsw_sp_acl_ctcam_region_fini(&aregion->cregion); err_ctcam_region_init: mlxsw_sp_acl_erp_region_fini(aregion); err_erp_region_init: @@ -353,6 +364,7 @@ mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion) { + prune_destroy(aregion->region->prune); mlxsw_sp_acl_ctcam_region_fini(&aregion->cregion); mlxsw_sp_acl_erp_region_fini(aregion); aregion->ops->fini(aregion); @@ -376,19 +388,16 @@ static int mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_atcam_entry *aentry, - struct mlxsw_sp_acl_rule_info *rulei) + struct mlxsw_sp_acl_rule_info *rulei, + u32 priority) { struct mlxsw_sp_acl_tcam_region *region = aregion->region; u8 erp_id = mlxsw_sp_acl_erp_id(aentry->erp); struct mlxsw_sp_acl_atcam_lkey_id *lkey_id; char ptce3_pl[MLXSW_REG_PTCE3_LEN]; - u32 kvdl_index, priority; + u32 kvdl_index; int err; - err = mlxsw_sp_acl_tcam_priority_get(mlxsw_sp, rulei, &priority, true); - if (err) - return err; - lkey_id = aregion->ops->lkey_id_get(aregion, rulei, erp_id); if (IS_ERR(lkey_id)) return PTR_ERR(lkey_id); @@ -398,8 +407,11 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, mlxsw_reg_ptce3_pack(ptce3_pl, true, MLXSW_REG_PTCE3_OP_WRITE_WRITE, priority, region->tcam_region_info, aentry->ht_key.enc_key, erp_id, + !(aentry->num_ctcam_erps_scan > 0), refcount_read(&lkey_id->refcnt) != 1, lkey_id->id, kvdl_index); + mlxsw_reg_ptce3_prune_vector_pack(ptce3_pl, aentry->prune_bitmap, + MLXSW_SP_ACL_ERP_MAX_PER_REGION); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl); if (err) goto err_ptce3_write; @@ -411,6 +423,35 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, return err; } +int +mlxsw_sp_acl_atcam_region_entry_update(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_atcam_entry *aentry, + u32 priority) +{ + struct mlxsw_sp_acl_tcam_region *region = aregion->region; + struct mlxsw_sp_acl_atcam_lkey_id *lkey_id; + char ptce3_pl[MLXSW_REG_PTCE3_LEN]; + struct mlxsw_afa_block *act_block; + u32 kvdl_index; + u8 erp_id; + + erp_id = mlxsw_sp_acl_erp_id(aentry->erp); + lkey_id = aentry->lkey_id; + act_block = mlxsw_sp2_acl_tcam_aentry_act_block(aentry); + kvdl_index = mlxsw_afa_block_first_kvdl_index(act_block); + + mlxsw_reg_ptce3_pack(ptce3_pl, true, MLXSW_REG_PTCE3_OP_WRITE_UPDATE, + priority, region->tcam_region_info, + aentry->ht_key.enc_key, erp_id, + !(aentry->num_ctcam_erps_scan > 0), + refcount_read(&lkey_id->refcnt) != 1, lkey_id->id, + kvdl_index); + mlxsw_reg_ptce3_prune_vector_pack(ptce3_pl, aentry->prune_bitmap, + MLXSW_SP_ACL_ERP_MAX_PER_REGION); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl); +} + static void mlxsw_sp_acl_atcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, @@ -423,12 +464,56 @@ mlxsw_sp_acl_atcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp, mlxsw_reg_ptce3_pack(ptce3_pl, false, MLXSW_REG_PTCE3_OP_WRITE_WRITE, 0, region->tcam_region_info, aentry->ht_key.enc_key, - erp_id, refcount_read(&lkey_id->refcnt) != 1, + erp_id, !(aentry->num_ctcam_erps_scan > 0), + refcount_read(&lkey_id->refcnt) != 1, lkey_id->id, 0); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl); aregion->ops->lkey_id_put(aregion, lkey_id); } +void mlxsw_sp_acl_atcam_prune_vector_to_bitmap(bool non_def_prune_vector, + struct mlxsw_sp_acl_atcam_entry + *aentry) +{ + enum mlxsw_sp_acl_atcam_region_type region_type; + struct prune_vector_item *vector_item; + struct list_head *prune_vector_list; + struct mlxsw_sp_acl_erp *erp; + struct prune_table *table; + + region_type = mlxsw_sp_acl_erp_region_type(aentry->erp); + if (region_type == MLXSW_SP_ACL_ATCAM_REGION_TYPE_8KB) { + /* Note: For SP-2 a region with 8 key blocks must be set to + * either to all 1's or all 0's. + * The driver set it to all 0's so this rule doesn't prune + * any other rules. + */ + bitmap_zero(aentry->prune_bitmap, + MLXSW_SP_ACL_ERP_MAX_PER_REGION); + return; + } + bitmap_fill(aentry->prune_bitmap, MLXSW_SP_ACL_ERP_MAX_PER_REGION); + + if (!non_def_prune_vector) /* prune all erps */ + return; + + /* set the relevant erps for further lookups */ + prune_vector_list = prune_item_prune_vector(aentry->prune_item); + list_for_each_entry(vector_item, prune_vector_list, list) { + if (!vector_item->pruned) { + table = vector_item->table; + erp = prune_table_priv(table); + if (mlxsw_sp_acl_erp_is_ctcam_erp(erp)) { + /* look-up towards the CTCAM */ + aentry->num_ctcam_erps_scan++; + continue; + } + mlxsw_sp2_acl_tcam_prune_vector_bit_set(erp, aentry, + false); + } + } +} + static int __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, @@ -436,21 +521,32 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei) { struct mlxsw_sp_acl_tcam_region *region = aregion->region; - char mask[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN] = { 0 }; struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl); + char mask[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN] = { 0 }; + struct prune_item *prune_item; struct mlxsw_sp_acl_erp *erp; unsigned int blocks_count; + bool non_def_prune_vector; + u32 priority; int err; blocks_count = mlxsw_afk_key_info_blocks_count_get(region->key_info); mlxsw_afk_encode(afk, region->key_info, &rulei->values, aentry->ht_key.enc_key, mask, 0, blocks_count - 1); + err = mlxsw_sp_acl_tcam_priority_get(mlxsw_sp, rulei->priority, + &priority, true); + if (err) + return err; + erp = mlxsw_sp_acl_erp_get(aregion, mask, false); if (IS_ERR(erp)) return PTR_ERR(erp); + aentry->erp = erp; aentry->ht_key.erp_id = mlxsw_sp_acl_erp_id(erp); + bitmap_from_arr32(aentry->key_bitmap, (void *) aentry->ht_key.enc_key, + MLXSW_SP_ACL_TCAM_MASK_LEN); /* We can't insert identical rules into the A-TCAM, so fail and * let the rule spill into C-TCAM @@ -461,14 +557,30 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, if (err) goto err_rhashtable_insert; + prune_item = prune_item_create(aregion->region->prune, + mlxsw_sp_acl_erp_prune_table(erp), + rulei->priority, aentry->key_bitmap, + aentry, &non_def_prune_vector); + if (IS_ERR(prune_item)) { + err = PTR_ERR(prune_item); + goto err_prune_item_create; + } + aentry->prune_item = prune_item; + aentry->num_ctcam_erps_scan = 0; + + mlxsw_sp_acl_atcam_prune_vector_to_bitmap(non_def_prune_vector, + aentry); err = mlxsw_sp_acl_atcam_region_entry_insert(mlxsw_sp, aregion, aentry, - rulei); + rulei, priority); if (err) goto err_rule_insert; return 0; err_rule_insert: + if (!prune_item_destroy(aentry->prune_item)) + WARN(1, "Failed to destroy prune item\n"); +err_prune_item_create: rhashtable_remove_fast(&aregion->entries_ht, &aentry->ht_node, mlxsw_sp_acl_atcam_entries_ht_params); err_rhashtable_insert: @@ -481,7 +593,13 @@ __mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_atcam_entry *aentry) { + int err; + mlxsw_sp_acl_atcam_region_entry_remove(mlxsw_sp, aregion, aentry); + err = prune_item_destroy(aentry->prune_item); + WARN(err, "Failed to destroy prune item while removing rule with priority %u\n", + aentry->prune_item->priority); + rhashtable_remove_fast(&aregion->entries_ht, &aentry->ht_node, mlxsw_sp_acl_atcam_entries_ht_params); mlxsw_sp_acl_erp_put(aregion, aentry->erp); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c index e3c6fe8..79c7a7f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c @@ -53,8 +53,8 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, char *key; int err; - err = mlxsw_sp_acl_tcam_priority_get(mlxsw_sp, rulei, &priority, - fillup_priority); + err = mlxsw_sp_acl_tcam_priority_get(mlxsw_sp, rulei->priority, + &priority, fillup_priority); if (err) return err; @@ -67,7 +67,8 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, mlxsw_afk_encode(afk, region->key_info, &rulei->values, key, mask, 0, blocks_count - 1); - err = cregion->ops->entry_insert(cregion, centry, mask); + err = cregion->ops->entry_insert(cregion, centry, key, mask, + rulei->priority); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c index 0a4fd3c..762af2d11 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "core.h" #include "reg.h" @@ -18,7 +19,6 @@ /* gen_pool_alloc() returns 0 when allocation fails, so use an offset */ #define MLXSW_SP_ACL_ERP_GENALLOC_OFFSET 0x100 -#define MLXSW_SP_ACL_ERP_MAX_PER_REGION 16 struct mlxsw_sp_acl_erp_core { unsigned int erpt_entries_size[MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX + 1]; @@ -35,12 +35,13 @@ struct mlxsw_sp_acl_erp_key { struct mlxsw_sp_acl_erp { struct mlxsw_sp_acl_erp_key key; u8 id; - u8 index; + u8 index; /* used for erp index in prune vector */ refcount_t refcnt; DECLARE_BITMAP(mask_bitmap, MLXSW_SP_ACL_TCAM_MASK_LEN); struct list_head list; struct rhash_head ht_node; struct mlxsw_sp_acl_erp_table *erp_table; + struct prune_table *prune_table; }; struct mlxsw_sp_acl_erp_master_mask { @@ -129,6 +130,28 @@ u8 mlxsw_sp_acl_erp_id(const struct mlxsw_sp_acl_erp *erp) return erp->id; } +u8 mlxsw_sp_acl_erp_index(const struct mlxsw_sp_acl_erp *erp) +{ + return erp->index; +} +struct prune_table * +mlxsw_sp_acl_erp_prune_table(const struct mlxsw_sp_acl_erp *erp) +{ + return erp->prune_table; +} + +enum mlxsw_sp_acl_atcam_region_type +mlxsw_sp_acl_erp_region_type(const struct mlxsw_sp_acl_erp *erp) +{ + return erp->erp_table->aregion->type; +} + +struct mlxsw_sp_acl_atcam_region * +mlxsw_sp_acl_erp_aregion(const struct mlxsw_sp_acl_erp *erp) +{ + return erp->erp_table->aregion; +} + static unsigned int mlxsw_sp_acl_erp_table_entry_size(const struct mlxsw_sp_acl_erp_table *erp_table) { @@ -245,6 +268,7 @@ mlxsw_sp_acl_erp_generic_create(struct mlxsw_sp_acl_erp_table *erp_table, struct mlxsw_sp_acl_erp_key *key) { struct mlxsw_sp_acl_erp *erp; + struct prune *prune; int err; erp = kzalloc(sizeof(*erp), GFP_KERNEL); @@ -272,8 +296,19 @@ mlxsw_sp_acl_erp_generic_create(struct mlxsw_sp_acl_erp_table *erp_table, if (err) goto err_rhashtable_insert; + prune = erp_table->aregion->region->prune; + erp->prune_table = prune_table_create(prune, erp->mask_bitmap, + MLXSW_SP_ACL_TCAM_MASK_LEN, + erp); + if (IS_ERR(erp->prune_table)) { + err = PTR_ERR(erp->prune_table); + goto err_prune_table_create; + } return erp; +err_prune_table_create: + rhashtable_remove_fast(&erp_table->erp_ht, &erp->ht_node, + mlxsw_sp_acl_erp_ht_params); err_rhashtable_insert: mlxsw_sp_acl_erp_master_mask_clear(erp_table, erp); err_master_mask_set: @@ -288,8 +323,12 @@ mlxsw_sp_acl_erp_generic_create(struct mlxsw_sp_acl_erp_table *erp_table, static void mlxsw_sp_acl_erp_generic_destroy(struct mlxsw_sp_acl_erp *erp) { + int err; struct mlxsw_sp_acl_erp_table *erp_table = erp->erp_table; + err = prune_table_destroy(erp->prune_table); + WARN(err, "Failed to destroy prune table\n"); + rhashtable_remove_fast(&erp_table->erp_ht, &erp->ht_node, mlxsw_sp_acl_erp_ht_params); mlxsw_sp_acl_erp_master_mask_clear(erp_table, erp); @@ -688,6 +727,7 @@ __mlxsw_sp_acl_erp_ctcam_mask_create(struct mlxsw_sp_acl_erp_table *erp_table, struct mlxsw_sp_acl_erp_key *key) { struct mlxsw_sp_acl_erp *erp; + struct prune *prune; int err; erp = kzalloc(sizeof(*erp), GFP_KERNEL); @@ -710,6 +750,15 @@ __mlxsw_sp_acl_erp_ctcam_mask_create(struct mlxsw_sp_acl_erp_table *erp_table, if (err) goto err_rhashtable_insert; + prune = erp_table->aregion->region->prune; + erp->prune_table = prune_table_create(prune, erp->mask_bitmap, + MLXSW_SP_ACL_TCAM_MASK_LEN, + erp); + if (IS_ERR(erp->prune_table)) { + err = PTR_ERR(erp->prune_table); + goto err_prune_table_create; + } + err = mlxsw_sp_acl_erp_region_ctcam_enable(erp_table); if (err) goto err_erp_region_ctcam_enable; @@ -720,6 +769,9 @@ __mlxsw_sp_acl_erp_ctcam_mask_create(struct mlxsw_sp_acl_erp_table *erp_table, return erp; err_erp_region_ctcam_enable: + if (prune_table_destroy(erp->prune_table)) + WARN(1, "Failed to destroy prune table err %d\n", err); +err_prune_table_create: rhashtable_remove_fast(&erp_table->erp_ht, &erp->ht_node, mlxsw_sp_acl_erp_ht_params); err_rhashtable_insert: @@ -765,8 +817,12 @@ static void mlxsw_sp_acl_erp_ctcam_mask_destroy(struct mlxsw_sp_acl_erp *erp) { struct mlxsw_sp_acl_erp_table *erp_table = erp->erp_table; + int err; mlxsw_sp_acl_erp_region_ctcam_disable(erp_table); + err = prune_table_destroy(erp->prune_table); + WARN(err, "Failed to destroy prune table\n"); + rhashtable_remove_fast(&erp_table->erp_ht, &erp->ht_node, mlxsw_sp_acl_erp_ht_params); mlxsw_sp_acl_erp_master_mask_clear(erp_table, erp); @@ -862,7 +918,6 @@ mlxsw_sp_acl_erp_second_mask_create(struct mlxsw_sp_acl_erp_table *erp_table, err = PTR_ERR(erp); goto err_erp_create; } - err = mlxsw_sp_acl_erp_index_get(erp_table, &erp->index); if (err) goto err_erp_index_get; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index e171513..2b392e9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "reg.h" #include "core.h" @@ -82,8 +83,8 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, } int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_rule_info *rulei, - u32 *priority, bool fillup_priority) + u32 rule_priority, u32 *priority, + bool fillup_priority) { u64 max_priority; @@ -96,11 +97,11 @@ int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp, return -EIO; max_priority = MLXSW_CORE_RES_GET(mlxsw_sp->core, KVD_SIZE); - if (rulei->priority > max_priority) + if (rule_priority > max_priority) return -EINVAL; /* Unlike in TC, in HW, higher number means higher priority. */ - *priority = max_priority - rulei->priority; + *priority = max_priority - rule_priority; return 0; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index 219a4e2..3b67782 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -6,6 +6,7 @@ #include #include +#include #include "reg.h" #include "spectrum.h" @@ -27,9 +28,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam); int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_rule_info *rulei, - u32 *priority, bool fillup_priority); - + u32 rule_priority, u32 *priority, + bool fillup_priority); struct mlxsw_sp_acl_profile_ops { size_t ruleset_priv_size; int (*ruleset_add)(struct mlxsw_sp *mlxsw_sp, @@ -58,6 +58,7 @@ mlxsw_sp_acl_tcam_profile_ops(struct mlxsw_sp *mlxsw_sp, #define MLXSW_SP_ACL_TCAM_REGION_BASE_COUNT 16 #define MLXSW_SP_ACL_TCAM_REGION_RESIZE_STEP 16 +#define MLXSW_SP_ACL_ERP_MAX_PER_REGION 16 #define MLXSW_SP_ACL_TCAM_CATCHALL_PRIO (~0U) @@ -75,6 +76,7 @@ struct mlxsw_sp_acl_tcam_region { char tcam_region_info[MLXSW_REG_PXXX_TCAM_REGION_INFO_LEN]; struct mlxsw_afk_key_info *key_info; struct mlxsw_sp *mlxsw_sp; + struct prune *prune; unsigned long priv[0]; /* priv has to be always the last item */ }; @@ -96,7 +98,9 @@ struct mlxsw_sp_acl_ctcam_entry { struct mlxsw_sp_acl_ctcam_region_ops { int (*entry_insert)(struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_ctcam_entry *centry, - const char *mask); + const char *key, + const char *mask, + u32 priority); void (*entry_remove)(struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_ctcam_entry *centry); }; @@ -168,6 +172,11 @@ struct mlxsw_sp_acl_atcam_entry { struct mlxsw_sp_acl_ctcam_entry centry; struct mlxsw_sp_acl_atcam_lkey_id *lkey_id; struct mlxsw_sp_acl_erp *erp; + struct prune_item *prune_item; + DECLARE_BITMAP(key_bitmap, MLXSW_SP_ACL_TCAM_MASK_LEN); + DECLARE_BITMAP(prune_bitmap, MLXSW_SP_ACL_ERP_MAX_PER_REGION); + /* Counts the number of ctcam erps that the rule should scan */ + unsigned int num_ctcam_erps_scan; }; static inline struct mlxsw_sp_acl_atcam_region * @@ -189,7 +198,9 @@ mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_tcam_region *region, - const struct mlxsw_sp_acl_ctcam_region_ops *ops); + const struct mlxsw_sp_acl_ctcam_region_ops *ops, + const struct prune_ops + *mlxsw_acl_atcam_prune_ops); void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion); void mlxsw_sp_acl_atcam_chunk_init(struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_atcam_chunk *achunk, @@ -208,11 +219,22 @@ int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam); void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam); - +int +mlxsw_sp_acl_atcam_region_entry_update(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_atcam_entry *aentry, + u32 priority); struct mlxsw_sp_acl_erp; bool mlxsw_sp_acl_erp_is_ctcam_erp(const struct mlxsw_sp_acl_erp *erp); u8 mlxsw_sp_acl_erp_id(const struct mlxsw_sp_acl_erp *erp); +u8 mlxsw_sp_acl_erp_index(const struct mlxsw_sp_acl_erp *erp); +struct prune_table * +mlxsw_sp_acl_erp_prune_table(const struct mlxsw_sp_acl_erp *erp); +enum mlxsw_sp_acl_atcam_region_type +mlxsw_sp_acl_erp_region_type(const struct mlxsw_sp_acl_erp *erp); +struct mlxsw_sp_acl_atcam_region * +mlxsw_sp_acl_erp_aregion(const struct mlxsw_sp_acl_erp *erp); struct mlxsw_sp_acl_erp * mlxsw_sp_acl_erp_get(struct mlxsw_sp_acl_atcam_region *aregion, const char *mask, bool ctcam); @@ -225,4 +247,12 @@ int mlxsw_sp_acl_erps_init(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_acl_erps_fini(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam); +struct mlxsw_afa_block; + +struct mlxsw_afa_block * +mlxsw_sp2_acl_tcam_aentry_act_block(struct mlxsw_sp_acl_atcam_entry *aentry); +void +mlxsw_sp2_acl_tcam_prune_vector_bit_set(struct mlxsw_sp_acl_erp *erp, + struct mlxsw_sp_acl_atcam_entry *aentry, + bool pruned); #endif