From patchwork Tue Jul 24 14:29:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ido Schimmel X-Patchwork-Id: 10542305 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 35B97112E for ; Tue, 24 Jul 2018 14:43:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 21CD0212D6 for ; Tue, 24 Jul 2018 14:43:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1649928C86; Tue, 24 Jul 2018 14:43:18 +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 99BF4212D6 for ; Tue, 24 Jul 2018 14:43:16 +0000 (UTC) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 41Zh1G6JpDzDrq8 for ; Wed, 25 Jul 2018 00:43: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="aJ+dpj71"; 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=104.47.0.68; helo=eur01-he1-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="aJ+dpj71"; dkim-atps=neutral Received: from EUR01-HE1-obe.outbound.protection.outlook.com (mail-he1eur01on0068.outbound.protection.outlook.com [104.47.0.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 41ZgkS0d3gzF0Pl for ; Wed, 25 Jul 2018 00:30:23 +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=3E32+nr8R4frCIr7q8ML9MwDhUbFQ17rLrwOApcn51c=; b=aJ+dpj710SPXV+j3JSYonpEsrAhUG69sMyo3ey+x7X2XC52AdgebKm6AcZ+QFsFHt05hQ3W4xznDiyO+/GRE7A1uSntu10CvcWCxL6sn9xKo2PtcOHt6X38XMzZlAe7Zey4Rs9zY/DRGj/Ry6dN1vLXHxJVfSTUjrMXfOGrvYjI= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=idosch@mellanox.com; Received: from splinter.mtl.com (193.47.165.251) by AM4PR0501MB2322.eurprd05.prod.outlook.com (2603:10a6:200:53::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.973.16; Tue, 24 Jul 2018 14:30:09 +0000 From: Ido Schimmel To: linux-internal@mellanox.com Subject: [PATCH net-next mlxsw v4 16/18] mlxsw: spectrum_acl: Add A-TCAM rule insertion and deletion Date: Tue, 24 Jul 2018 17:29:24 +0300 Message-Id: <20180724142926.13033-17-idosch@mellanox.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180724142926.13033-1-idosch@mellanox.com> References: <20180724142926.13033-1-idosch@mellanox.com> MIME-Version: 1.0 X-Originating-IP: [193.47.165.251] X-ClientProxiedBy: VI1P189CA0018.EURP189.PROD.OUTLOOK.COM (2603:10a6:802:2a::31) To AM4PR0501MB2322.eurprd05.prod.outlook.com (2603:10a6:200:53::23) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: ada1caf6-ea34-47b4-a6e1-08d5f171f5c7 X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: BCL:0; PCL:0; RULEID:(7020095)(4652040)(8989117)(5600073)(711020)(4618075)(2017052603328)(7153060)(7193020); SRVR:AM4PR0501MB2322; X-Microsoft-Exchange-Diagnostics: 1; AM4PR0501MB2322; 3:EhQLhkuYzBXhbHCtLZ3FOuDsVVL37WzyePhhTGGgKsiMnTIyyfU46vI3Nh7wM1W0pAYxJRb2kErUtuOEVGc9DXUIxOFeZf5cJabRDxhkOeNtg2czzEzAf0NjTYu8sY6XYK+br8maKefY5nP3IHwWbie7iVkHvMsZ1pt+yIK0LJdoH5x12kzvTMbo7Ci7Te+My+ptpb5Rw5UXtdQAkm2rXT4Nb5FddSJXWjUQXrdT0lpqvqQ4zhPxe0VQ/HosE/TV; 25:iCQddmczCpAs9coOH44/mdoDYDKiM3zN7eumv1Syi9HAxEasZL0SLsl+zyHkgCoWdOOF4vdsEmrBsYGuu1a/sddyhxo448oGjmRZflb07qL3d+eSTQMlE9esmR+ITqYlit5pT+CIedGhoKeF2TKVKMpS/q9rluKvigx4ecUFGj71s0RjHzafbOUi83pGD3Suspxvhb/JGcvoMOLYDOKJ/0mClXXdzaqnSq1TK0moYK1qVSKH1kVTh5U1XjdYPUd0r5vcmGU5vLJ/y2EfxVlfFT1XIbmCiJMiv38ag4P7NF8zuCj2pDiYFCdcx6hzq/7iFt8bATrE2zOcaZLn93eWqw==; 31:X1u6SQYK4+slr0NE/oP6W3/LcBHvF/lqaK95JQ2nxYRSL8mt/lu/qt72EZAjyoWwIIyB6xyMCSumUgeVaw6vrzKHP1DdnlvNTlrzZFqGc6yiYj/kO/wk83MrxdvK4jdbTrNVR8LaX6zd3trrju4CNt00q6mxYyJ/LxMXY7XvTc1jKCs3075j78KgzB9ouhb5A/jzzAUHj3EG7aSdFEiz8HTFWQobfysN+QWdiuFune0= X-MS-TrafficTypeDiagnostic: AM4PR0501MB2322: X-Microsoft-Exchange-Diagnostics: 1; AM4PR0501MB2322; 20:tbqHWQM4f7LY/y1tUDJxz0DaC3CKymbJ0mDmzwChnI8N79avcSdk1ay25hFxGawbp/B9sKXHHVIH9NMo+KM/CS2GA2TKe6JNDU3bLgO+xbbSp8317STIRm8pmYJ173SMk1FqkyghF57NeCE7vDV7ubehifGtGbkzjrYM9mOastrveSlhGOYU3ZWulCudahUSHR9wVer/DkiQcdiO9udIYecnYSc6uu9Iy52Q8eClf4xuqgJLtcsjWPetm+QOqAJwpXkwVb8uhcHuUIz+GRLQLpPsCZXf0lSshkEWe3gSSArw+SaL2l26+/vrkxMVXwAYpL2T1qeDjD6LVRutHoOhxjCx0Mk2w3XQwRflPPxLXfmr8GquQ5JKPrDWfrtrqUUiJK1OUDq5bd9qIc1rB7Ce/PAKaxvYYP65Kx6RMKEak4+R3aZBW2jv30ZU7Cwl/Oh1e1fwh86MeaTMAoDSIJLvYboQuCaKVOVQeCn4tAUJYzM1Y9sis2LYfa7rT4jxBYgD; 4:i27OCs3vuSatGQe6iXgxe+viMlnXGt5wT/GTcRdtIcSnL1Exl+ewcBkgGiy1swGa+OOr4lOvdl3YTfg4fcku2NtpOi6XPYAxHGrk27Dsh2BwKDn7VUrlpz++bNLopLWc3E5m2tMq9we6T8d+rDoepED3K3gt0P7ETF44AGv1sHsQw0kxIijatPX42RTfbIiaAQmASS8760jIsMXKp2NCQ6wrwubg+FoGlf+DOoswRAbGtiVwuvgEJS2giOEDv9PuhqxdyLUcOYp61jtb+M4yRw== 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)(10201501046)(3002001)(93006095)(93001095)(3231311)(944501410)(52105095)(6055026)(149027)(150027)(6041310)(20161123558120)(20161123562045)(20161123564045)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(6072148)(201708071742011)(7699016); SRVR:AM4PR0501MB2322; BCL:0; PCL:0; RULEID:; SRVR:AM4PR0501MB2322; X-Forefront-PRVS: 0743E8D0A6 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(1496009)(346002)(396003)(376002)(39860400002)(366004)(136003)(199004)(189003)(53936002)(97736004)(7736002)(305945005)(446003)(34206002)(107886003)(6512007)(486006)(4326008)(25786009)(26005)(478600001)(6486002)(11346002)(16526019)(6116002)(105586002)(2616005)(956004)(16586007)(53416004)(316002)(3846002)(66066001)(1076002)(47776003)(2361001)(5660300001)(68736007)(51416003)(50226002)(2906002)(76176011)(8936002)(37006003)(106356001)(81156014)(86362001)(8676002)(386003)(36756003)(81166006)(6636002)(48376002)(2351001)(52116002)(6666003)(14444005)(476003)(50466002)(6506007); DIR:OUT; SFP:1101; SCL:1; SRVR:AM4PR0501MB2322; 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; AM4PR0501MB2322; 23:0SByVhpr7YAM4V9ppYGNx1E87Oea454Mmn/kxRF?= hja/9kP5UkVgkji1/IakJecDbLCrGKKecC2WevuPIc6gYcVyHCXhIg94oMFIn5HlBI7XL5caZUf3JW3SoqZnN6+5UtqqtxCk2asq1fZou/myHus+UOdBAW2pJRjYNbn3NmPTHC2vlR/lOBMVDxoADEAUZChkGWydVoU4k+pW1K4N/HqzozJFGgIGcE4KTAv99I03Rd1kC1dimedCes/nDzgH/jtfj+XtpqaL7k7dntKh4D7MYr2efpfgsmbe0rNRKLadL8hkOxtW5oRfJ90kKhfqTfKSI2uvWhZUGn59FXw201YtlSg+6GlrL02SzTaGfliO/8ZoyhpPPRFT0Cx3xOOPDhufphPO6S31/EFK42D66kIIDGgG9IybbZtH1xRCRSt+b/xmBVwuljbGuWr4uLIbedQ0Bq2kbLdhxpaHIRfjyvcJEiCriwvAgvlTtNAsCF4jwJK3fVKzNtco9PrwUZxyNwGswv3654BJsQ5WBFdmEsn9ZkXAKoMbWeDr83GP6eCE2DXg0iszes/NxMCyD/sjDyGzu8fc0g6UG48yNN2XK2ZKu4b6epyTsB0wKIPOouj+krjzNubva9IipHT/PWUmnlVI9fx5pBVBIlta/EIrN734sPoztgL+ogC3SwE/Vu36/vfSoJe79zTJyF2/tc3norzHt1ysHVV5VevCUO3lan0xNXDUAvVZf0x8+jUt04MtL4Er+wa/UZyH9sK6TA4pegCB+87BeBHYw4Rvqnn8XdbjcwrVjIbbBCzRQu1a4t30RdQe36lPJaL/d+IoVTQ82lxXClCHHGaXVxGGoHCiEhufTdYW9B5OYC8oUnfy9OImJmjtS/UdpkjDYtK/OaR+W6A/EjZ13ZagF416oQt/PmLlYA5vXdZ/m5C4AfgjnfXunX3Ifm0jj+t2btG9Z+hjbdU4uDcuL7hbGN8l6UBq5sCxeI+nBDMjB48qHjXybST1O7OLF8dTlPFyU9ACKGQtG1STgMP3q4Yz0L+9i7sHx3s8Yvl/+Wv0h7LpkA9yFZmXuScEvD/xuvvnL0UYZU87r55mT6prMHYXHnIAZDSzl4DqG5v3O4P5wXuHrBQFClYZMEWIwon7jifSiiyjK12vrpHc76/g6nsAageTJ04XQIi48nBvYcOviMrmq0btIEdp63XgQuAj8navdQT9Qh4htSl6+EOWTmLjqXEQH0Cc3iyf8Jsj698hF4sevGQDw2jJ8+G0j/VjCl5H8Id06aWXLJUmn/JMqA/FnjDw7grg11VUCDLxIxRcEl3Zjw1WYXi5rma2caT4FQVGiPX1ls3gP X-Microsoft-Antispam-Message-Info: ulVgCUsAFrsXy+ufF0eDxIOOUOWMdB9yxVBUuSuFkjlR23Z8lexaXaHHJfj99xJS950CPVGBrSWd++GBCNIK1ABRTS2Fo53dbYYi9YAl/yaneD9WiL/P0cKHVNCCd37IpqOtfwZnw+PuI73XTD0xJBd8/w+9vz/CknQWWjVuhpUi4NoIjchOJF8p7ZKLd0rrnXw+3g5zDeQPaqzRsMJrb4vjpX/VKkCtZlBvt4iNOp0uoOW/GUvip2l5mokREP7vaLYnt4ghL5Vwq1eaUklGCVW1rwoJBe9fqm1PPM/3ezs6+tl5E7Q6mR/O3coj/08mAEn1OF09C2nKZAIvN1OTwvz2N3BXLzuc4AoZxrSp+yo= X-Microsoft-Exchange-Diagnostics: 1; AM4PR0501MB2322; 6:fyY2fUl8IE4g0uB5Dis48L/io3puOSYbd+EZ8XOK+6+x2dpKvrWXVo8qPkrm3mIFiRLHwmoLC0ZuGAbMDfWruLSgnPt9vW9vEccz6fmqr5xdRF6X5E9cOA6lqbAQOcUK6W912vOvq0kyHnxXNeb+5FLKrycgVJp/QmS74weLLhqKLpinoRapyIYlu0HwFklt9F2Hb3Ez9r/zHslwaeUxI4u7hGf6kCgFQdIcAVe/2QrO3S4E8TnFnVxjZ/SXPgZO7EKqMAOkvujevA5134WlAeWBMKsow0kfptlgeO2X9lejGsDP7ir8aEmKlqNOlBdd6x6L2AW2H1QhhRn9RN+GxivKNI68Bvd7WEHDIONyxiBdpEeO+e540KzLz9MeuC/PTKA6dR3ENRPBjuZBKem87dmnnoDnGcHtem7yTGapX2nRcbgoB6aG9zTGsiIusFeY/CjbC+lFziQhI892p8S8dw==; 5:6OFejp1Og9rQdkIoZO7/NxM6JUxTdrmRSTlvY0z9r4jWtAySJs4aws+w0DBJbkq8Tm6F15JhIDWzxXyq21Hs0JAXNhWsXeHOgbt3iY1BWkiu8SsRgr0a+n27icW5nydS8XrQBv+9HHyiA2PZ8cy/A1IgJjfsmF2tpMVCOPe13Ew=; 7:uL4xW39Dnh6MkoV/dkpm/2llU4gsjRS4wFPTkwypjtdzAR6WtdA9nQkgGZmiukFM+iF3cjV4TrG+u8YWRe2IecH1RwppYQCiXa6Pk45fM8yh8pXr/yNPtpK+XLfz4z/B7XlBZFH1eEFInVs9l+vi7eSwsW1kiy2EJyHWW1iR7TdR/oQMpddS+BLvVJtMdm8DfSDTK/1GF3gfo45g88NAQThYiLOuBjsC7bnLz3ilWMHPt+RhUBjBFZDj60N1zrJx SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Jul 2018 14:30:09.3800 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: ada1caf6-ea34-47b4-a6e1-08d5f171f5c7 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM4PR0501MB2322 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: v3: * Insert rules into C-TCAM from A-TCAM code instead of Spectrum-2 code * Introduce 'achunk' that encapsulates 'cchunk' (like we already do with 'aentry' and 'aregion') v2: * Do not break lines at 80 chars where cure is worse than the disease .../mellanox/mlxsw/spectrum2_acl_tcam.c | 8 +- .../mellanox/mlxsw/spectrum_acl_atcam.c | 443 +++++++++++++++++- .../mellanox/mlxsw/spectrum_acl_erp.c | 5 + .../mellanox/mlxsw/spectrum_acl_tcam.h | 34 ++ 4 files changed, 485 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c index bef2329bb233..aef366148cc3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c @@ -54,7 +54,7 @@ struct mlxsw_sp2_acl_tcam_chunk { }; struct mlxsw_sp2_acl_tcam_entry { - struct mlxsw_sp_acl_ctcam_entry centry; + struct mlxsw_sp_acl_atcam_entry aentry; struct mlxsw_afa_block *act_block; }; @@ -185,8 +185,8 @@ static int mlxsw_sp2_acl_tcam_entry_add(struct mlxsw_sp *mlxsw_sp, entry->act_block = rulei->act_block; return mlxsw_sp_acl_ctcam_entry_add(mlxsw_sp, ®ion->aregion.cregion, - &chunk->cchunk, &entry->centry, - rulei, true); + &chunk->cchunk, + &entry->aentry.centry, rulei, true); } static void mlxsw_sp2_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp, @@ -198,7 +198,7 @@ static void mlxsw_sp2_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp2_acl_tcam_entry *entry = entry_priv; mlxsw_sp_acl_ctcam_entry_del(mlxsw_sp, ®ion->aregion.cregion, - &chunk->cchunk, &entry->centry); + &chunk->cchunk, &entry->aentry.centry); } static int diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c index 50b4576b4921..d551f0431248 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c @@ -34,12 +34,275 @@ */ #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 bool +mlxsw_sp_acl_atcam_is_centry(const struct mlxsw_sp_acl_atcam_entry *aentry) +{ + return mlxsw_sp_acl_erp_is_ctcam_erp(aentry->erp); +} + +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 +341,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,9 +355,16 @@ 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) @@ -103,6 +374,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; } @@ -110,6 +385,172 @@ 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); +} + +void mlxsw_sp_acl_atcam_chunk_init(struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_atcam_chunk *achunk, + unsigned int priority) +{ + mlxsw_sp_acl_ctcam_chunk_init(&aregion->cregion, &achunk->cchunk, + priority); +} + +void mlxsw_sp_acl_atcam_chunk_fini(struct mlxsw_sp_acl_atcam_chunk *achunk) +{ + mlxsw_sp_acl_ctcam_chunk_fini(&achunk->cchunk); +} + +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); +} + +static 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; +} + +static 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_entry_add(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_atcam_chunk *achunk, + struct mlxsw_sp_acl_atcam_entry *aentry, + struct mlxsw_sp_acl_rule_info *rulei) +{ + int err; + + err = __mlxsw_sp_acl_atcam_entry_add(mlxsw_sp, aregion, aentry, rulei); + if (!err) + return 0; + + /* It is possible we failed to add the rule to the A-TCAM due to + * exceeded number of masks. Try to spill into C-TCAM. + */ + err = mlxsw_sp_acl_ctcam_entry_add(mlxsw_sp, &aregion->cregion, + &achunk->cchunk, &aentry->centry, + rulei, true); + if (!err) + return 0; + + 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_chunk *achunk, + struct mlxsw_sp_acl_atcam_entry *aentry) +{ + if (mlxsw_sp_acl_atcam_is_centry(aentry)) + mlxsw_sp_acl_ctcam_entry_del(mlxsw_sp, &aregion->cregion, + &achunk->cchunk, &aentry->centry); + else + __mlxsw_sp_acl_atcam_entry_del(mlxsw_sp, aregion, aentry); } int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c index e26efa451d4a..bb07723a0577 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c @@ -150,6 +150,11 @@ static const struct mlxsw_sp_acl_erp_table_ops erp_no_mask_ops = { .erp_destroy = mlxsw_sp_acl_erp_no_mask_destroy, }; +bool mlxsw_sp_acl_erp_is_ctcam_erp(const struct mlxsw_sp_acl_erp *erp) +{ + return erp->key.ctcam; +} + u8 mlxsw_sp_acl_erp_id(const struct mlxsw_sp_acl_erp *erp) { return erp->id; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index 718e96de2860..fb6f9a521ddb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -163,11 +163,31 @@ 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_chunk { + struct mlxsw_sp_acl_ctcam_chunk cchunk; +}; + +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_ctcam_entry centry; + 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, @@ -177,6 +197,19 @@ 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); +void mlxsw_sp_acl_atcam_chunk_init(struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_atcam_chunk *achunk, + unsigned int priority); +void mlxsw_sp_acl_atcam_chunk_fini(struct mlxsw_sp_acl_atcam_chunk *achunk); +int mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_atcam_region *aregion, + struct mlxsw_sp_acl_atcam_chunk *achunk, + 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_chunk *achunk, + 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, @@ -184,6 +217,7 @@ void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp, 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); struct mlxsw_sp_acl_erp * mlxsw_sp_acl_erp_get(struct mlxsw_sp_acl_atcam_region *aregion,