From patchwork Tue Jul 17 15:36:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ido Schimmel X-Patchwork-Id: 10529877 X-Patchwork-Delegate: idosch@idosch.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4F988603ED for ; Tue, 17 Jul 2018 15:41:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BFBC0296D4 for ; Tue, 17 Jul 2018 15:41:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BE18D296DE; Tue, 17 Jul 2018 15:41:31 +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 7313C296EA for ; Tue, 17 Jul 2018 15:41:30 +0000 (UTC) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 41VPdh3sl6zF3JX for ; Wed, 18 Jul 2018 01:41:28 +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="AN0LDs0O"; 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.0.59; helo=eur02-am5-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="AN0LDs0O"; dkim-atps=neutral Received: from EUR02-AM5-obe.outbound.protection.outlook.com (mail-eopbgr00059.outbound.protection.outlook.com [40.107.0.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 41VPYY2V2rzF3Hg for ; Wed, 18 Jul 2018 01:37:53 +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=eG84Jr8sva+D/2YA1aB8wqxrRQfJgiQJRoLYDgdgcew=; b=AN0LDs0OsmZrnETLEr1+ZtJixFGmivFfwJl7VBBPPdvYvKPU62ZjX3ZP3Wf6hdeCIBMTXikvmpoYzrfqViwzi65Ko3gYkkiU78p1spga6cRF4jPbwVhyfdMxubs1VTw/QIfNi0zuBLsPer8LsQN97hUoLMvqgciNmGWGvtnJNXM= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=idosch@mellanox.com; Received: from splinter.mtl.com (193.47.165.251) by HE1PR0501MB2330.eurprd05.prod.outlook.com (2603:10a6:3:27::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.952.21; Tue, 17 Jul 2018 15:37:41 +0000 From: Ido Schimmel To: linux-internal@mellanox.com Subject: [PATCH RESEND net-next mlxsw 16/18] mlxsw: spectrum_acl: Add A-TCAM rule insertion and deletion Date: Tue, 17 Jul 2018 18:36:55 +0300 Message-Id: <20180717153657.16324-17-idosch@mellanox.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180717153657.16324-1-idosch@mellanox.com> References: <20180717153657.16324-1-idosch@mellanox.com> MIME-Version: 1.0 X-Originating-IP: [193.47.165.251] X-ClientProxiedBy: AM0PR02CA0020.eurprd02.prod.outlook.com (2603:10a6:208:3e::33) To HE1PR0501MB2330.eurprd05.prod.outlook.com (2603:10a6:3:27::23) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 529c0930-e42c-44bd-c723-08d5ebfb3c1c X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652040)(8989117)(5600053)(711020)(48565401081)(2017052603328)(7153060)(7193020); SRVR:HE1PR0501MB2330; X-Microsoft-Exchange-Diagnostics: 1; HE1PR0501MB2330; 3:LRHrPis6/Fa0UDpO+g6U2q3G1dm1pc76yO5XUEb+ZzIbgiEl4yqbkEZN212YZDrqEgqS8ZgtOGlY/mrKQCneuLQD23+3cqdB4S9FR1iRcbP6fJniYU8ojPNtefbj9iTOhxVlvkipdeJ5Df0vT+MaFOzyNmQUJ1GPsHGfV0Zd+TPartym0joLAyxlkrrFHAdP2IigxNCqGVqMRMCI+49uD5PSL1HMMqeOGu8iH4OVu40D0mFq2zMdvSKQWBFl8+Bv; 25:gwXaCHxvYO1VzoKJ73TIHMgRIxGhfy3xga+HH+lxHJwF7yuuGggw2BIxbj7BliyqJ3Ewc5CSPF/gIkxM/f9uEj2EyBCKRk1J+t4KsKVX6SSGk8ccb+OlmKLxqoM+88clTtnO4/FZVG8t02O46rDyaqjt9w6cJocEu4xX9W9jOThRohxi9WrNueknIs3JVcxOQnEXtcjovkfTLSCS2LFL5NKCOfiswxuf2td82B/yduL9s4fTznoDpVQldBnExVLRnNc7rpjXduuZ53xDGfIEenhswVazFt1ye2WMVqJ7rOBe8i6vqRdhvUC7STQ6ppCqmQG84u5g5GbisgrCcxBcGQ==; 31:s35UmuZZLHg3WDRMvo0y6weZZe99sujkxQAamYRUPTxYtZFam5ycGUE5grMBbkCRvtUmwLFwE2GCopsJtNDkSAp/7P9DaE4NnkdbkIkms0rBLnTYDUPOflr7oxAP55aqUwrXhGfcAiG4SxZAy4wiT57lgpSPJv1dRny6RIxaYsiIjZ+xrzBjIk4zbpt5MzqStl+D9f9n1wwwp4/En5cWuzh7gIhCoh9Vmvn2mUNzAec= X-MS-TrafficTypeDiagnostic: HE1PR0501MB2330: X-Microsoft-Exchange-Diagnostics: 1; HE1PR0501MB2330; 20:hK6+AZhFUghlQzmt198+mG+4GgORxSYCkrAS8Mf835noe7Er/ZmInl+I5vTPMoTzmtu0DjuBGQue72eVX3V0uo0OvbeRG8ei+58WnZzULmdizfWSMLG2+OTabHXGzhWhNpeYNWhFSgvm3TlH/kBFnqhQZW2yrDHWqbV7aWvD9wRCBl8JztkPO0LOzT1YiztuBVxGIxRwkyjzfMMKvRGJwXQDMpnJV5dZE1gNzIhZudO+Z8KTaGvjD5SoSziiktHpXjn6jkUnw3OzSPosul/owLbqytfYik3DTUUyvtn9ObKrW++maPHgoFS2KLeijY34/ESTqIHHCN0vw0A5J9EwdFKuakPRijk09rHmE95Vcf5EniT44K8qc1x98xSJFupom0APmKRCqiWATXxDda1Z84rmYDBoNjoybZzNr5TfVTcFk7jLAFYcFgDNzoFpVJWH1jECGTtpa3mAIY8H987M3cPzTjYKXW+Kqhi+1xC1SQCXfPfGdk2wbjlsXfK6Ob70; 4:tLFDG/KrXiQGmaLU+OAG+v4hmtoCFIVNzDai70YU9v0J4ES3qZXQiWP3ffSytN6nZU+LGraChIKUGnJByJAXGsn/Q0ow6w+nWUffhe4P+/9Hdk44g83bxnqomaK3BXe+sK1U/WeFUvtlCxubb4E8+bdJ4NFjBXolA+RbRWCd/nR8Ur56zaibrdlTduSxS2AuULrbhpd4KIF4fRoPl+doPS0vB0X4dtyPnhsruE2YZpxde9GZ5YU0JNsW3VY2xTfxBOnGdtW7HsGED9Qgl4IR3Q== 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)(93006095)(93001095)(10201501046)(3002001)(6055026)(149027)(150027)(6041310)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123564045)(20161123558120)(20161123562045)(6072148)(201708071742011)(7699016); SRVR:HE1PR0501MB2330; BCL:0; PCL:0; RULEID:; SRVR:HE1PR0501MB2330; X-Forefront-PRVS: 073631BD3D X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(1496009)(396003)(39860400002)(346002)(136003)(376002)(366004)(189003)(199004)(51416003)(2906002)(8676002)(476003)(8936002)(6506007)(956004)(81156014)(2616005)(6486002)(2351001)(26005)(386003)(81166006)(16526019)(107886003)(53416004)(486006)(105586002)(446003)(4326008)(11346002)(34206002)(106356001)(66066001)(53936002)(47776003)(76176011)(68736007)(478600001)(6512007)(316002)(50226002)(50466002)(52116002)(7736002)(2361001)(3846002)(14444005)(16586007)(305945005)(37006003)(97736004)(86362001)(6116002)(36756003)(217873002)(1076002)(48376002)(6636002)(5660300001)(6666003)(25786009); DIR:OUT; SFP:1101; SCL:1; SRVR:HE1PR0501MB2330; H:splinter.mtl.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:1; A:1; Received-SPF: None (protection.outlook.com: mellanox.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; HE1PR0501MB2330; 23:67ZJdKyi0UjQrR0fb8QNy+wjkjkelbMAXBX0bGc?= =?us-ascii?Q?tzRl4EDKQZAnFEVsEjQ73RORKZlSJQXVaThCHbQcJQIBLUZw9ys346KBVdk7?= =?us-ascii?Q?vsvfYv0Bqfs5VG9rY++El5Hgt6CsVGM9bdWtjYjF0WUYbKKM0DUm6vDZQeEy?= =?us-ascii?Q?xZdL64R7ccVTWQADYbekbn6U7Je+iWlgaLpDI1RhY/SFfR4ZSgU3kt70tNQ0?= =?us-ascii?Q?ZVZH+gMn3JYEy7sRcnQvy9FacEuLTUls0IjZg1uku63/ZT9220R90W+9+pm8?= =?us-ascii?Q?syMGIiwl54AojGkgfs3Km/OiWLp2Yik/ptrzwtZ8fICBE7EA48hYzOxmuTut?= =?us-ascii?Q?AY3twaRaupOtkRs1rFQ32GEXXmc0XqyrIZGUqMlNtHaiZiZV22sKNRmlXDL8?= =?us-ascii?Q?s6b7bQ/cqv7HV3fYLEK4NMiFN56gAIH+9+qiWzW73FmbhbNM38QT/W0yGFup?= =?us-ascii?Q?ArgkaqFWIv6QtipiFuoEsr2tBqIoDo/iW73wyeVXUAwvCVgnHXvJ2oXys8pB?= =?us-ascii?Q?h49HBV8NHLb9HWaklzL16GI0kG9lR7q0MwCWyK3O6EToDH9TQyFbqK2zvSLt?= =?us-ascii?Q?Bv6ueKLs8T/PYKzQDRaQ8+r5mOCzTO8RBDIpGyRa+CMZcq1VFu3ZntXIeZMX?= =?us-ascii?Q?k6CqTNE7ae/haetc42rvBUA6ZR3B/uIX0hSSeYNYmSSP4c/A7oik1BeFZNjN?= =?us-ascii?Q?2gxCur65ObCL2QIQMTxEtelGo+VrtsbJohBYJAVL5tWcZYLlOUwOVP+F0w8F?= =?us-ascii?Q?pyNXH6+naOh9SrGuItHPEsxQ/TqnUq80OT+qjtWr4Iks+Se0CdSlTHaTeHh1?= =?us-ascii?Q?JLXXA+AIobWjWWbW6ad6kefJyhInbuq1emmVV/81GbqbqOepu0STb3CVmioC?= =?us-ascii?Q?KUDQyBH1XjXNv4+zzKIkVcUoNjj06Y1f0grk7wRWti2xkT7+EZpFxVBrfpAs?= =?us-ascii?Q?5pzFlIOvmPtSaRoTDEkSP/nFwJVBTsLETmSqDxcnAO7k1KCw3TXYqMrrwyCz?= =?us-ascii?Q?rjwoBkirCqJyIzEQFX/1VfxhYRhZUSVh7GPqVvrhZKmDU8snQTvRjz9ZsxPA?= =?us-ascii?Q?0XJxpnn0JBPCIMF410wuA+408MhHVGlxgLtP8EZTH+oJywL9aaWsQ14ylUkT?= =?us-ascii?Q?GkyGmc9+guO8pUqaUhaUFvNSy5jmJnHHwOiHM8RMS06idiYLwjhTKLteMYif?= =?us-ascii?Q?9E0wzeWOE3IPPnSumwt4xPKs+zO6k6Tqu4BctLeoMkC6VGEcvZmKt1akeHSZ?= =?us-ascii?Q?HcxHkLO0O86zU5Tebbn+iPC26ZpnIdMJdGvdUcRSUYpMdqWYk14HiaCz6qPB?= =?us-ascii?Q?f0s5ngHWBLuxP47UvY4RTkk+G/DNjDQnmGnj5krGnm8LizlRYnElJ2XhYniB?= =?us-ascii?Q?k3SqoaA=3D=3D?= X-Microsoft-Antispam-Message-Info: JLVNYSLumQsMwmS9TnN1oqDrIiT/59e4TdpY7++mJexqz1eSHkCGzPkoHGQ8gA96SBx7CuY9VNv6fLP3tYud+Lz01gtmLrhkfysqjyU2+3QyJ7vnSzPWRANqTDYLhvioWYJFINtS2XU73oP+Ql+aCV1Vu9u4LSWPzGChe5NwfjtLCaN7ZmLTDprYunYoOI1weh+TCUZuaUPW+l5nbMgaiXZUmkuGixAsJ6mjZOAYhIqniGf//vTiWHuyjXc4ijuknNxiu21pp8oA4WNTaJQ7PmhoigCobEpVYqPwpGTL3mvrVmw/McxqhtYfA2evrw84e1LPAuMfAui9DlkVBA9NNMtpsTBn1djqJNG68z7MEVo= X-Microsoft-Exchange-Diagnostics: 1; HE1PR0501MB2330; 6:95kUDzWWZu8dNtMMAceTaSd4QiUvPfhADMfDW1kFdf1UfDlgXq5RAxxkF9bCkV3aAj11FduhEGJrF+/z+fF81zyNtoKb4t4E9NuOcO0aNC+8mvXPjCG6cxbUUTKl1CnDZpAvlRM0mwqVJbgHtKwEDeBu0wSlC9e36PDM7u4ZlyCpm9oTba8f4EflhK/is+w1o1BiTPJIUFaS8AsI6I+u0ntp1SWP15uHF9+mPsMHco2ukgleZ/rwjxSKNXgXq03O88ouAFTbggowV4QHr/jy65NrGXoInCeNNK4hPSpaqdiA48wSJJAqy9Pyn9wvnXX0oBHqljIM9rQOM/64nwtZIWNyofqN/8PgUy+t7Pm7KP2vxgsHUq0Y7C5ERDLjq0Kfthbm6lC8zzGFMmJNPD8v2rufVy0jZVqfSbPhFV9u1Ce0oZzHc73m6FzVUPIWLReFgCPBOIRkM9Qywjgj/Nk9EQ==; 5:uoEr6YgsPhz3fgvsDS27vdsJUhE3t9LPvGS/s9NmBZ2+aOkmSd6g5zUxfwSu8xevwzdrInp/QiicHYPl+tQGRDdlhy942B4MO+BlhBXi0VjqiS2bMJYEnpGxa/jcd7pKYK091zR5p2xAZda53LWQs82xWNYEneRqZNB0th8HoVo=; 24:1ysXZh3XkNOhTGM0NbhDoMwc6kf5kcxhkiRnUuqcgXw6aCg8SCrgz+0BNOQJL3SUZ1NswclUgabAiSi4mM8FOmA6BEAT6wZuvV3MBtQ2k+o= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; HE1PR0501MB2330; 7:c97R+iOAP+cXrZfeYu1vqEvbHdi6idhQSDN2cx6rLOFaASJ1WLAdxLKAjPYgoGVPRcdFLePgybkwW3RpSl2ccMfMIkbGoRXXxPOwoyeorvTyRM5vsp4wmf6mwnqeWtn9KNHNS35VsIUbAe+E19MOO/HtZWt9ILLtHqJ37KOva/G9jKodu03SUWg5oPbVu5ACTCMH+cu5hLoN1W9gqBtcgsKU8Pnl7C0fjVZWQnWwlijkBxhUdy+wdEAAbKSuQoqJ X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Jul 2018 15:37:41.4224 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 529c0930-e42c-44bd-c723-08d5ebfb3c1c X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1PR0501MB2330 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 --- .../ethernet/mellanox/mlxsw/spectrum_acl_atcam.c | 403 ++++++++++++++++++++- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 22 ++ 2 files changed, 424 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 037f1af1c72d..b7edbd3fa868 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c @@ -34,12 +34,276 @@ */ #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_range(afk, region->key_info, &rulei->values, + ht_key.enc_key, + 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 +342,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, @@ -85,16 +350,152 @@ 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) { + int err; + aregion->region = region; aregion->atcam = atcam; mlxsw_sp_acl_atcam_region_type_init(aregion); - return 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; + + return err; + +err_erp_region_init: + aregion->ops->fini(aregion); +err_ops_init: + rhashtable_destroy(&aregion->entries_ht); + return err; } void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion) { 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; + int err; + + mlxsw_afk_encode(afk, region->key_info, &rulei->values, + aentry->ht_key.enc_key, mask); + + 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,