From patchwork Sun Jul 22 13:17:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ido Schimmel X-Patchwork-Id: 10539331 X-Patchwork-Delegate: jiri@resnulli.us 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 7B5DB96FA for ; Sun, 22 Jul 2018 13:19:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 66580281F9 for ; Sun, 22 Jul 2018 13:19:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5A4F928384; Sun, 22 Jul 2018 13:19:21 +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 1081B28372 for ; Sun, 22 Jul 2018 13:19:20 +0000 (UTC) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 41YQFL2bMjzDqtW for ; Sun, 22 Jul 2018 23:19:18 +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="EjAs+zyC"; 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.8.57; helo=eur04-vi1-obe.outbound.protection.outlook.com; envelope-from=idosch@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="EjAs+zyC"; dkim-atps=neutral Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-eopbgr80057.outbound.protection.outlook.com [40.107.8.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 41YQDD6SpTzDr0q for ; Sun, 22 Jul 2018 23:18:20 +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=zPo/03O2c5PoAwPEcNlKU6FqLE47ug6WUT2+zKCcA80=; b=EjAs+zyC1b/f15TbpVfiwqGxIEhMzA7+HoAQVlPdXhbwaDWkFqkp1ccdGmKyGzQoNgANJyNVpADyMQwZepruPHdbOid6nBV9VI3zSF9MIeql3Tk5Y8MkFH7S2dyD26ZzHvaKCfj8eXzQOjHBZRDFpD7gHtwmM33uMRtLeo6B6Cg= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=idosch@mellanox.com; Received: from splinter.mtl.com (193.47.165.251) by HE1PR0501MB2331.eurprd05.prod.outlook.com (2603:10a6:3:27::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.973.20; Sun, 22 Jul 2018 13:18:11 +0000 From: Ido Schimmel To: linux-internal@mellanox.com Subject: [PATCH net-next mlxsw 16/18] mlxsw: spectrum_acl: Add A-TCAM rule insertion and deletion Date: Sun, 22 Jul 2018 16:17:10 +0300 Message-Id: <20180722131712.30578-17-idosch@mellanox.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180722131712.30578-1-idosch@mellanox.com> References: <20180722131712.30578-1-idosch@mellanox.com> MIME-Version: 1.0 X-Originating-IP: [193.47.165.251] X-ClientProxiedBy: AM0PR01CA0036.eurprd01.prod.exchangelabs.com (2603:10a6:208:69::49) To HE1PR0501MB2331.eurprd05.prod.outlook.com (2603:10a6:3:27::24) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 20a1d460-fa3f-4957-aca9-08d5efd59386 X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: BCL:0; PCL:0; RULEID:(7020095)(4652040)(8989117)(5600073)(711020)(4618075)(2017052603328)(7153060)(7193020); SRVR:HE1PR0501MB2331; X-Microsoft-Exchange-Diagnostics: 1; HE1PR0501MB2331; 3:55N9sWS50Lzkhhqt6k5c4Ja8p4knTcJc35kaXL41okfODEY7tdNzGmT+UF+UvI0glnQ+s46gI5OsAwRVirnlTgZLC2IdRK3B53164BBXaXGw1NNwiy2Kz9PzXOP9K2k7NVxH58r5fT2G2CBVWKbbuULd1oTia9A5cY1Tdfrm6/B6E6WHNxv5A4SPrQzm11uZ5tC3xguSfaiByNkhShqoBYuZBbrBCdbR1CCMS+W+co2UsR4fMV9Gu5yIkdzqq0wx; 25:LXuI5Pw1u8dZ5D3DQ+id87/RUYJv+39rRRVgh7YyQed3XSzZE9CYnb50/UgsoTJS4aj3OLtwEz4Ml3z8Wn4JxmN/0n/QKKffcKrXfE9cYrqd62AhhRcIMjOVUJsWD7HV0dKg1sSPBBO8sH50qPJwTa9ADww8HMXWSt445AYQr4iF+jhQ7gnhIrFxcm/Xj9V6i2m9SWAKoC0htZz2Ttb2J/+Sme9/HbDlGJnomYBzvniCu2ei9Lbd1Z+JLGNVUU0JQED1/aZmRR5jvqnHEDo8pHq4SZWwmjca8w9bpBYWkR0ZmKnMXS0MhQXLKeJAOib9TDSpe5rL6qaPFCR285KYHA==; 31:32Y0DPOhZLA/fdkCKBG62TigxGIBC3d4UEzIBeWyJE4RQbbleXVPlhHRq7f+p8QAo6ymSQobZJcBzawJyTSyIOYQJEpz7DX6pHjMqkfxywrhLpSss92i+M/ey1LDxQhI4utgZdAac5sbv1qlZqp5Avnf02279MT50cDuvY1Opnt8RtIeW809/GJa93xxCIiAJRP++bVflJZz1t6fYEhiwLPOj363owU78uBM7vq2H3s= X-MS-TrafficTypeDiagnostic: HE1PR0501MB2331: X-Microsoft-Exchange-Diagnostics: 1; HE1PR0501MB2331; 20:1vD1h1F4byWlXY9upEUQtuFiVlBMmgpzGfgwMBjxpduAeH9xkY5pBghhoaGXZjXBo20N7m/+KZBOmC2GDJOItuYJNl93+fRFOu7jmyQEQ9WOBD1D5XqHEo2bLMyPtQykof0lPRAfzPqiRKlXyfTabE6DvUghOcz6U8CeT7JgKEC6MGGPhXs9BxWKNq1ptw2Xq9Fo/ur6mpebf2yNx6h1yeMzEy3TUxTxaZHPD2p2yhh3g0uyY8crxRmHj1BJauWlhBqiDoddXlvZIepZBSUizGMR4EJiYvyUhgizXHHGWPm52/f/fgKwxoThFAhEqBGpUzhIL9I1F4sLykuF/BAQvLXckA+ACQziEcebblZkuCe7Vh2Et9C5oM0zfmmZYMGZ3EjniLvQYdi+8kGogqMN/i0PxdTUakTPXTyquZb7b5opBPxcYi8L5KwvW0qNAmm3Grlxwj+WkQRpYPxQpEcyKWAll0fe1cuNq8d+g24X7sxobTj27ZkQJvImGlLgPmpl; 4:hec4yXILR2Sjka55c+6pWCN87jeeLnKCxGjgcPIDlPS3gL8mmSSZ6tVE+4vXw1gBe59OvA38rp+Jui2N6mQGifprPCl8rNYLPz8NY2j74KL2JZlxI4v6oSBPsYzV/fT/YjfIqGwg7I2o6utg0Z/8hOLm0p8WxVRvcuxNnDHXOG5T0c2lMKN/HTPHQ0DPwi7dO5+kBfttZDWEgJG64eqTeLvBE1T0JOlZBfpDgQQNZySX4u9dqKzNI72Nap/J6C+brN3l4NRhmqB32hdzHWhxIg== 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)(8121501046)(5005006)(3231311)(944501410)(52105095)(3002001)(93006095)(93001095)(10201501046)(6055026)(149027)(150027)(6041310)(20161123564045)(20161123562045)(20161123558120)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(6072148)(201708071742011)(7699016); SRVR:HE1PR0501MB2331; BCL:0; PCL:0; RULEID:; SRVR:HE1PR0501MB2331; X-Forefront-PRVS: 0741C77572 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(1496009)(376002)(366004)(136003)(346002)(396003)(39860400002)(199004)(189003)(47776003)(956004)(14444005)(81156014)(106356001)(66066001)(3846002)(6116002)(2361001)(486006)(97736004)(68736007)(81166006)(1076002)(36756003)(4326008)(2906002)(86362001)(16526019)(11346002)(26005)(105586002)(6636002)(386003)(6506007)(478600001)(446003)(8676002)(8936002)(5660300001)(53936002)(48376002)(34206002)(107886003)(50226002)(76176011)(316002)(53416004)(305945005)(476003)(6512007)(25786009)(2616005)(2351001)(37006003)(7736002)(51416003)(16586007)(50466002)(52116002)(6486002); DIR:OUT; SFP:1101; SCL:1; SRVR:HE1PR0501MB2331; H:splinter.mtl.com; 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; HE1PR0501MB2331; 23:+URvLPJEF3GeP0BiSaF5Aj+izri8JDE4YtA9/BP?= 54lIasGudku2yXMo02bXPV+Y0A9P8z5+j9ERHZFDUjGsgtpLaT0ORuaF7kxMvqoeDGmw9gesvvfa2ZsCd+DeG70TX6mGezjD6ISA0bY7EG4Da+Ph6wAholzAtER/R6O1sBsEwGGJtLfsFqY7VoZ+3r8ttLnHO6O2l3Lb8v7+/JGpavl+37YXqOWiNzuJ6MXJjVF5vrJbCs24iG7VV/63IBQmI9/WtjEhjat8Nu2MBgJmqS1jcBadZMmLgZWtbnJwXytBS0fQ33nBuOEzEfE1RzpJJX1R2XRkmTMssO3ttHJPqmJfdfXrJOrpmodcED06lMzTInD9RmSJ0UtZrWg6p/snXE9pSqeKVOTEY0hbEN4Ik0opv4E+cuvH33v6DUiAkB16w6GzsDIdE2lcpVnOKi1F4dmUbikWBdYqJsApO3sG/d7ycH6KTjIaNGDDCytlGmpxWt8R06PsdefWVQOLcHMQt9KrRaT+uSbcNbmE8szHJuLozShrtWawDY0g+bG6dshumgEHTk8TX6zApwmg0/P7exslnRP5rAb4dYlPNKhdtakOm3h8mvwa2lhDs7fN0qoXcr+mqIDOq1St0tqjQ1uMtAyQeMmxR/8v5UHmPSi0NQr7r1+XiZF+WUo0VZE0B+0VdlAZ3HSvfw0+y0MnzjSmKSgM8KAZL3USgR/zZGnwD52AvecDZw7Mv2qTydU/bK06WkS3Gby52nKjBK6ecf4puvw4obCaTxuyGDqXWdzVVPG3lydvlj4v42NoRv5HqYpMNlAcOARIid7H7s9z41SsH/vIvVnqcPql2r1I0reGeyDuqNw4hnqAt21EJ127Dg4zu/tbwLN13T8qTuYgNql1k/vtTms7sChVCUfowyxDIic1i3pu+m+v2vydDiKzpFL7flzI4kA5zAeHNSQCDZEx0PEDbB9HVFSrLR55RYnrEKIcPj2/Iyuwld+4RD2UJYOR9VCQtm2NCQ1x7hsFm4sPGz+xAtn+aiUMQGaYzXL6gXSBfjNrf+gUDCwRqOe8tfO0CLJKkjj898qarLDC0A4vABUYHrvrKauaDtxvDv789dPpdKvMcICd/uGSr2GBov94j/R+UY+GIM5u3fIc0lqeyM+DI1HV85+UP6KC3jLq2rl5FxshaSsPu938JsNHyIVixATfu557qMWW33EwHwdBVtfSqRSG6GRwUsQUHth5q98MOqyHOSx+Eu+diek2p87OmL5RbtD3ZIehCDy4iSi+6q5mjG9+tzwTKpcIPCadjZ2LBwj9TlkdIxjR//gRV6JY= X-Microsoft-Antispam-Message-Info: Ufrvb+Mo2PpP5f4DzJS1Zn2eg1aq6l+wEVKNdAV3kV0kIiD+4B7yBgB/NsGgvXN76GiQNOpU+uludF2TBsmu6T7A6t/aYdlqh2MUoKh5GYgJbHp28Vi8ZFA9MWepu+RXk79ROCtjDQKH3r9jkEUmMODt2/x+Yso74w1EM86T4ROzP4q69vjRyYpZteWg6kGo8D/4P+CC8hCBLNOOFleTd9eHTvQjqtYu6pl+SDtf4fgz157N4U0dxPGOanEl+42fUQ8Z+/E0mFF/ei9qmkD1ifcJWOx/Q4D7j+r2HBwYqXY3MnM7IVjaWXMyY4ic1J+uVnMIplzjsUq39jcvR9FM4mstmGxJVHR80Td5sYc+ljs= X-Microsoft-Exchange-Diagnostics: 1; HE1PR0501MB2331; 6:rMBl5SUTFTqvggM5umHmA2CYRbwTZOnmIVT4IlZYH1AOASiPgalbDPv8t7ur/5/N0UE+HXWqUzJ1U2fn+RtBKdXgmdOPNsZGSZsOpXyiNHHYE/yrnmB5w9gd45LuR3Ym3rtuvQDISjkGUh59inly+40oOFUaPLK3RbZ3owTiIGpRwYXw+86Vzfcj6NEW05+oZqOx/S8tjDTa0GbsU+mwb6Kb9NoJmE2X/jwp5xxcqZrWif/qVbZTCgtlniHM4N3ckl2Ig+WCdK6xVBnlHTxmxwIy6wEZNdKOfUqSJz5KzUzPKouWnjs/RoLhZH2Ha592y+4DsQCSZG66suRpRsB1iAbUmF4IZjuC9YQT3qomlufKu4MjWI6+4EUb+fKgAomeYRwzj+7OX3J7pBLDJQQq5imhtM9FJxACkj3SKcJM5/aOhBoraBAxw/6AOttRe9/nHG2YHA76WgeaT18w+kC4Tw==; 5:44P3TdKMHPAbtcNefJpmUPFidH2YRuyvDneG1iPKNnTFp+8VAHHoh8Lguy/mJBjPay9sMc6tm/RciXuPZTEByBh3WSn3N6iTFTNtN64PIwGYzz1TrEQUI1x/10OQy9nEly8iIrAvIw+EQDgfa2mzFK4gd83jmeYjnNEWqUskurI=; 7:2nNkhliD6LQuNPWA0m8XH5aj0m/AJw7vDnSfhUpcJkj9/lqUVTWIOBpAtQej8UnxLyOg9rYkcdPgisbNRndYyJyft+iwOrCH6P2sUAvstC9+fl+C7vGFyIHUyvuhnlFq59OkuiCL8wEhuKFT0PRfLfE/3BvAOSPm63m3OJKdmdb1wgZHVAZIG1VAhpEMAxjedDed8LFMwzTPVTHRKt6rDAwcj2Rb8ifStI8gwC+v5ProI8bwRZXZe0Vh0qerNhDJ SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jul 2018 13:18:11.9317 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 20a1d460-fa3f-4957-aca9-08d5efd59386 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1PR0501MB2331 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: , Errors-To: linux-mlxsw-bounces+patchwork-linux-mlxsw=patchwork.kernel.org@lists.ozlabs.org X-Virus-Scanned: ClamAV using ClamSMTP Implement rule insertion and deletion into the A-TCAM before we flip the driver to start using the A-TCAM. Rule insertion into the A-TCAM is very similar to C-TCAM, but there are subtle differences between regions of different sizes (i.e., different number of key blocks). Specifically, as explained in "mlxsw: spectrum_acl: Allow encoding a partial key", in 12 key blocks regions a rule is split into two and the two halves of the rule are linked using a "large entry key ID". Such differences are abstracted away by using different region operations per region type. Signed-off-by: Ido Schimmel Reviewed-by: Jiri Pirko --- Notes: v2: * Do not break lines at 80 chars where cure is worse than the disease .../mellanox/mlxsw/spectrum_acl_atcam.c | 388 +++++++++++++++++- .../mellanox/mlxsw/spectrum_acl_tcam.h | 22 + 2 files changed, 409 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c index c13f08e9e907..9d2791a6d1a9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c @@ -34,12 +34,269 @@ */ #include +#include #include +#include +#include +#include #include "reg.h" #include "core.h" #include "spectrum.h" #include "spectrum_acl_tcam.h" +#include "core_acl_flex_keys.h" + +#define MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_START 6 +#define MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_END 11 + +struct mlxsw_sp_acl_atcam_lkey_id_ht_key { + char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* MSB blocks */ + u8 erp_id; +}; + +struct mlxsw_sp_acl_atcam_lkey_id { + struct rhash_head ht_node; + struct mlxsw_sp_acl_atcam_lkey_id_ht_key ht_key; + refcount_t refcnt; + u32 id; +}; + +struct mlxsw_sp_acl_atcam_region_ops { + int (*init)(struct mlxsw_sp_acl_atcam_region *aregion); + void (*fini)(struct mlxsw_sp_acl_atcam_region *aregion); + struct mlxsw_sp_acl_atcam_lkey_id * + (*lkey_id_get)(struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_rule_info *rulei, u8 erp_id); + void (*lkey_id_put)(struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_atcam_lkey_id *lkey_id); +}; + +struct mlxsw_sp_acl_atcam_region_generic { + struct mlxsw_sp_acl_atcam_lkey_id dummy_lkey_id; +}; + +struct mlxsw_sp_acl_atcam_region_12kb { + struct rhashtable lkey_ht; + unsigned int max_lkey_id; + unsigned long *used_lkey_id; +}; + +static const struct rhashtable_params mlxsw_sp_acl_atcam_lkey_id_ht_params = { + .key_len = sizeof(struct mlxsw_sp_acl_atcam_lkey_id_ht_key), + .key_offset = offsetof(struct mlxsw_sp_acl_atcam_lkey_id, ht_key), + .head_offset = offsetof(struct mlxsw_sp_acl_atcam_lkey_id, ht_node), +}; + +static const struct rhashtable_params mlxsw_sp_acl_atcam_entries_ht_params = { + .key_len = sizeof(struct mlxsw_sp_acl_atcam_entry_ht_key), + .key_offset = offsetof(struct mlxsw_sp_acl_atcam_entry, ht_key), + .head_offset = offsetof(struct mlxsw_sp_acl_atcam_entry, ht_node), +}; + +static int +mlxsw_sp_acl_atcam_region_generic_init(struct mlxsw_sp_acl_atcam_region *aregion) +{ + struct mlxsw_sp_acl_atcam_region_generic *region_generic; + + region_generic = kzalloc(sizeof(*region_generic), GFP_KERNEL); + if (!region_generic) + return -ENOMEM; + + refcount_set(®ion_generic->dummy_lkey_id.refcnt, 1); + aregion->priv = region_generic; + + return 0; +} + +static void +mlxsw_sp_acl_atcam_region_generic_fini(struct mlxsw_sp_acl_atcam_region *aregion) +{ + kfree(aregion->priv); +} + +static struct mlxsw_sp_acl_atcam_lkey_id * +mlxsw_sp_acl_atcam_generic_lkey_id_get(struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_rule_info *rulei, + u8 erp_id) +{ + struct mlxsw_sp_acl_atcam_region_generic *region_generic; + + region_generic = aregion->priv; + return ®ion_generic->dummy_lkey_id; +} + +static void +mlxsw_sp_acl_atcam_generic_lkey_id_put(struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_atcam_lkey_id *lkey_id) +{ +} + +static const struct mlxsw_sp_acl_atcam_region_ops +mlxsw_sp_acl_atcam_region_generic_ops = { + .init = mlxsw_sp_acl_atcam_region_generic_init, + .fini = mlxsw_sp_acl_atcam_region_generic_fini, + .lkey_id_get = mlxsw_sp_acl_atcam_generic_lkey_id_get, + .lkey_id_put = mlxsw_sp_acl_atcam_generic_lkey_id_put, +}; + +static int +mlxsw_sp_acl_atcam_region_12kb_init(struct mlxsw_sp_acl_atcam_region *aregion) +{ + struct mlxsw_sp *mlxsw_sp = aregion->region->mlxsw_sp; + struct mlxsw_sp_acl_atcam_region_12kb *region_12kb; + size_t alloc_size; + u64 max_lkey_id; + int err; + + if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, ACL_MAX_LARGE_KEY_ID)) + return -EIO; + + max_lkey_id = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_LARGE_KEY_ID); + region_12kb = kzalloc(sizeof(*region_12kb), GFP_KERNEL); + if (!region_12kb) + return -ENOMEM; + + alloc_size = BITS_TO_LONGS(max_lkey_id) * sizeof(unsigned long); + region_12kb->used_lkey_id = kzalloc(alloc_size, GFP_KERNEL); + if (!region_12kb->used_lkey_id) { + err = -ENOMEM; + goto err_used_lkey_id_alloc; + } + + err = rhashtable_init(®ion_12kb->lkey_ht, + &mlxsw_sp_acl_atcam_lkey_id_ht_params); + if (err) + goto err_rhashtable_init; + + region_12kb->max_lkey_id = max_lkey_id; + aregion->priv = region_12kb; + + return 0; + +err_rhashtable_init: + kfree(region_12kb->used_lkey_id); +err_used_lkey_id_alloc: + kfree(region_12kb); + return err; +} + +static void +mlxsw_sp_acl_atcam_region_12kb_fini(struct mlxsw_sp_acl_atcam_region *aregion) +{ + struct mlxsw_sp_acl_atcam_region_12kb *region_12kb = aregion->priv; + + rhashtable_destroy(®ion_12kb->lkey_ht); + kfree(region_12kb->used_lkey_id); + kfree(region_12kb); +} + +static struct mlxsw_sp_acl_atcam_lkey_id * +mlxsw_sp_acl_atcam_lkey_id_create(struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_atcam_lkey_id_ht_key *ht_key) +{ + struct mlxsw_sp_acl_atcam_region_12kb *region_12kb = aregion->priv; + struct mlxsw_sp_acl_atcam_lkey_id *lkey_id; + u32 id; + int err; + + id = find_first_zero_bit(region_12kb->used_lkey_id, + region_12kb->max_lkey_id); + if (id < region_12kb->max_lkey_id) + __set_bit(id, region_12kb->used_lkey_id); + else + return ERR_PTR(-ENOBUFS); + + lkey_id = kzalloc(sizeof(*lkey_id), GFP_KERNEL); + if (!lkey_id) { + err = -ENOMEM; + goto err_lkey_id_alloc; + } + + lkey_id->id = id; + memcpy(&lkey_id->ht_key, ht_key, sizeof(*ht_key)); + refcount_set(&lkey_id->refcnt, 1); + + err = rhashtable_insert_fast(®ion_12kb->lkey_ht, + &lkey_id->ht_node, + mlxsw_sp_acl_atcam_lkey_id_ht_params); + if (err) + goto err_rhashtable_insert; + + return lkey_id; + +err_rhashtable_insert: + kfree(lkey_id); +err_lkey_id_alloc: + __clear_bit(id, region_12kb->used_lkey_id); + return ERR_PTR(err); +} + +static void +mlxsw_sp_acl_atcam_lkey_id_destroy(struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_atcam_lkey_id *lkey_id) +{ + struct mlxsw_sp_acl_atcam_region_12kb *region_12kb = aregion->priv; + u32 id = lkey_id->id; + + rhashtable_remove_fast(®ion_12kb->lkey_ht, &lkey_id->ht_node, + mlxsw_sp_acl_atcam_lkey_id_ht_params); + kfree(lkey_id); + __clear_bit(id, region_12kb->used_lkey_id); +} + +static struct mlxsw_sp_acl_atcam_lkey_id * +mlxsw_sp_acl_atcam_12kb_lkey_id_get(struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_rule_info *rulei, + u8 erp_id) +{ + struct mlxsw_sp_acl_atcam_region_12kb *region_12kb = aregion->priv; + struct mlxsw_sp_acl_tcam_region *region = aregion->region; + struct mlxsw_sp_acl_atcam_lkey_id_ht_key ht_key = {{ 0 } }; + struct mlxsw_sp *mlxsw_sp = region->mlxsw_sp; + struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl); + struct mlxsw_sp_acl_atcam_lkey_id *lkey_id; + + mlxsw_afk_encode(afk, region->key_info, &rulei->values, ht_key.enc_key, + NULL, MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_START, + MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_END); + ht_key.erp_id = erp_id; + lkey_id = rhashtable_lookup_fast(®ion_12kb->lkey_ht, &ht_key, + mlxsw_sp_acl_atcam_lkey_id_ht_params); + if (lkey_id) { + refcount_inc(&lkey_id->refcnt); + return lkey_id; + } + + return mlxsw_sp_acl_atcam_lkey_id_create(aregion, &ht_key); +} + +static void +mlxsw_sp_acl_atcam_12kb_lkey_id_put(struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_atcam_lkey_id *lkey_id) +{ + if (refcount_dec_and_test(&lkey_id->refcnt)) + mlxsw_sp_acl_atcam_lkey_id_destroy(aregion, lkey_id); +} + +static const struct mlxsw_sp_acl_atcam_region_ops +mlxsw_sp_acl_atcam_region_12kb_ops = { + .init = mlxsw_sp_acl_atcam_region_12kb_init, + .fini = mlxsw_sp_acl_atcam_region_12kb_fini, + .lkey_id_get = mlxsw_sp_acl_atcam_12kb_lkey_id_get, + .lkey_id_put = mlxsw_sp_acl_atcam_12kb_lkey_id_put, +}; + +static const struct mlxsw_sp_acl_atcam_region_ops * +mlxsw_sp_acl_atcam_region_ops_arr[] = { + [MLXSW_SP_ACL_ATCAM_REGION_TYPE_2KB] = + &mlxsw_sp_acl_atcam_region_generic_ops, + [MLXSW_SP_ACL_ATCAM_REGION_TYPE_4KB] = + &mlxsw_sp_acl_atcam_region_generic_ops, + [MLXSW_SP_ACL_ATCAM_REGION_TYPE_8KB] = + &mlxsw_sp_acl_atcam_region_generic_ops, + [MLXSW_SP_ACL_ATCAM_REGION_TYPE_12KB] = + &mlxsw_sp_acl_atcam_region_12kb_ops, +}; int mlxsw_sp_acl_atcam_region_associate(struct mlxsw_sp *mlxsw_sp, u16 region_id) @@ -78,6 +335,7 @@ mlxsw_sp_acl_atcam_region_type_init(struct mlxsw_sp_acl_atcam_region *aregion) region_type = MLXSW_SP_ACL_ATCAM_REGION_TYPE_12KB; aregion->type = region_type; + aregion->ops = mlxsw_sp_acl_atcam_region_ops_arr[region_type]; } int mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, @@ -91,10 +349,19 @@ int mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, aregion->atcam = atcam; mlxsw_sp_acl_atcam_region_type_init(aregion); - err = mlxsw_sp_acl_erp_region_init(aregion); + err = rhashtable_init(&aregion->entries_ht, + &mlxsw_sp_acl_atcam_entries_ht_params); if (err) return err; + err = aregion->ops->init(aregion); + if (err) + goto err_ops_init; + + err = mlxsw_sp_acl_erp_region_init(aregion); + if (err) + goto err_erp_region_init; + err = mlxsw_sp_acl_ctcam_region_init(mlxsw_sp, &aregion->cregion, region); if (err) @@ -104,6 +371,10 @@ int mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, err_ctcam_region_init: mlxsw_sp_acl_erp_region_fini(aregion); +err_erp_region_init: + aregion->ops->fini(aregion); +err_ops_init: + rhashtable_destroy(&aregion->entries_ht); return err; } @@ -111,6 +382,121 @@ void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion) { mlxsw_sp_acl_ctcam_region_fini(&aregion->cregion); mlxsw_sp_acl_erp_region_fini(aregion); + aregion->ops->fini(aregion); + rhashtable_destroy(&aregion->entries_ht); +} + +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_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; + 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); + aentry->lkey_id = lkey_id; + + kvdl_index = mlxsw_afa_block_first_kvdl_index(rulei->act_block); + 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, + refcount_read(&lkey_id->refcnt) != 1, lkey_id->id, + kvdl_index); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl); + if (err) + goto err_ptce3_write; + + return 0; + +err_ptce3_write: + aregion->ops->lkey_id_put(aregion, lkey_id); + return err; +} + +static void +mlxsw_sp_acl_atcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_atcam_entry *aentry) +{ + struct mlxsw_sp_acl_atcam_lkey_id *lkey_id = aentry->lkey_id; + struct mlxsw_sp_acl_tcam_region *region = aregion->region; + u8 erp_id = mlxsw_sp_acl_erp_id(aentry->erp); + char ptce3_pl[MLXSW_REG_PTCE3_LEN]; + + 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, + lkey_id->id, 0); + mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl); + aregion->ops->lkey_id_put(aregion, lkey_id); +} + +int mlxsw_sp_acl_atcam_entry_add(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_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); + struct mlxsw_sp_acl_erp *erp; + unsigned int blocks_count; + 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); + + 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); + + /* We can't insert identical rules into the A-TCAM, so fail and + * let the rule spill into C-TCAM + */ + err = rhashtable_lookup_insert_fast(&aregion->entries_ht, + &aentry->ht_node, + mlxsw_sp_acl_atcam_entries_ht_params); + if (err) + goto err_rhashtable_insert; + + err = mlxsw_sp_acl_atcam_region_entry_insert(mlxsw_sp, aregion, aentry, + rulei); + if (err) + goto err_rule_insert; + + return 0; + +err_rule_insert: + rhashtable_remove_fast(&aregion->entries_ht, &aentry->ht_node, + mlxsw_sp_acl_atcam_entries_ht_params); +err_rhashtable_insert: + mlxsw_sp_acl_erp_put(aregion, erp); + return err; +} + +void 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) +{ + mlxsw_sp_acl_atcam_region_entry_remove(mlxsw_sp, aregion, aentry); + rhashtable_remove_fast(&aregion->entries_ht, &aentry->ht_node, + mlxsw_sp_acl_atcam_entries_ht_params); + mlxsw_sp_acl_erp_put(aregion, aentry->erp); } int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index 51f7e2327603..6d904c1dbdc2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -162,11 +162,26 @@ struct mlxsw_sp_acl_atcam { }; struct mlxsw_sp_acl_atcam_region { + struct rhashtable entries_ht; /* A-TCAM only */ struct mlxsw_sp_acl_ctcam_region cregion; + const struct mlxsw_sp_acl_atcam_region_ops *ops; struct mlxsw_sp_acl_tcam_region *region; struct mlxsw_sp_acl_atcam *atcam; enum mlxsw_sp_acl_atcam_region_type type; struct mlxsw_sp_acl_erp_table *erp_table; + void *priv; +}; + +struct mlxsw_sp_acl_atcam_entry_ht_key { + char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key */ + u8 erp_id; +}; + +struct mlxsw_sp_acl_atcam_entry { + struct rhash_head ht_node; + struct mlxsw_sp_acl_atcam_entry_ht_key ht_key; + struct mlxsw_sp_acl_atcam_lkey_id *lkey_id; + struct mlxsw_sp_acl_erp *erp; }; int mlxsw_sp_acl_atcam_region_associate(struct mlxsw_sp *mlxsw_sp, @@ -176,6 +191,13 @@ int mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_tcam_region *region); void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion); +int mlxsw_sp_acl_atcam_entry_add(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); +void 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 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,