From patchwork Tue Jul 24 14:29:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ido Schimmel X-Patchwork-Id: 10542291 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 465AF112E for ; Tue, 24 Jul 2018 14:42:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3387928AF4 for ; Tue, 24 Jul 2018 14:42:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 27D8328708; Tue, 24 Jul 2018 14:42:58 +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 D2E0228AF4 for ; Tue, 24 Jul 2018 14:42:56 +0000 (UTC) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 41Zh0v1F2DzDrVM for ; Wed, 25 Jul 2018 00:42:55 +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="s57dQtOh"; 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.88; 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="s57dQtOh"; dkim-atps=neutral Received: from EUR01-HE1-obe.outbound.protection.outlook.com (mail-he1eur01on0088.outbound.protection.outlook.com [104.47.0.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 41ZgkH6bwVzF0xF for ; Wed, 25 Jul 2018 00:30:15 +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=jOock+rMZWXlwc1PHf01urHEaSKwXdnvB7mTtpbRXys=; b=s57dQtOh6r6GFWVfgSbnjGFH+9i5jXHdRqm9apGKSzb/9sbQm4xBYFPLQg+Up4hn0iodGogbfb99DWd8JxqaLbkD/+GDl/Pz2yVciizTCIhmARdBqCYxrAUEsFilLggSMAd5nhO/JgghZ8dXZSXMJvWUckrzteWTh+MOk10nYOk= 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:01 +0000 From: Ido Schimmel To: linux-internal@mellanox.com Subject: [PATCH net-next mlxsw v4 08/18] mlxsw: spectrum_acl: Add support for C-TCAM eRPs Date: Tue, 24 Jul 2018 17:29:16 +0300 Message-Id: <20180724142926.13033-9-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: 0bd263d7-1a4e-490b-1928-08d5f171f10a 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:fvUC+trJohQwp9OEcaLtpKhP4TO9GzHj3yxoP1azVPRWS3s6VBlk7Q7tk17g4TzFMQA1vow79z8jIKwaT1mx0BHBgnnhBv7wG8z4YQxrDgOceSGAcaJVLDuCN/F2um8If7cNaAbUoY37Q9srTreAhZ9M+7V5B62mpZNOrEzAwjVE0xVoyCA8yidMaizlT4rY1A3q0liFS5M62RFCC+tiH1+4imMR73yFSXmLOBiITcxWRnTPh2vuD6dgVRf9OOxZ; 25:gXfLQ45ZzRp9pD++avVbBM3YXBs9MyUPDYgd933Impt9Z6IvAw4Xel90dXtTqo4+YJDzTTLnru3BYP7lMLqRRqM32/PGdDRddkKlyXpxdyvXsSsJx9ENuCBz3JahdpD6xHnJBuTDTxodLIkMQ0eIWCk+Gs8WP232i8RR0zqxYiyHkppZpYmBBIrzDiZUs4cwx7Dw/EyhM7uCr883fExbGWXDwHRTIDsN1MRS7eR7sSjPlfRnkbvDk8cG2RF4T5PNAiQOLUdyVyOexMCJJ0mpo4wQah+4aTvhQBWfv0gfqnkrQsEFMxLTJkVfgvXqg2jE9nFZQiHt+FdyjsjLaFmDbg==; 31:94Rh2yhRLFeR0UV7/TbIDlwZwu5hqpAkOPSScx3//5wvPSrwtwI+1kkjTz5V67yRe+9Bker2Bos4vAlWnUZ51S4zekh5rZnmT0l6v8gUPkC4KsHiCJO/J/J1TBo7tYmSyA6zxJtq4LCgvSu7b4zUVMLK7ekE/rx+JPi87vIoicYpyrYxj64t8iM+RI8ip0ND1HydrkkRvgNAaW/7KPuFk8JWbIukhXkUbZ16cygJtRI= X-MS-TrafficTypeDiagnostic: AM4PR0501MB2322: X-Microsoft-Exchange-Diagnostics: 1; AM4PR0501MB2322; 20:3lhAmvmEBdTxRa1wr9WTwZNQyZukM9dpipeGvSyqZRdy1BgwGyX/O9s1AME/yCy9Dm5RqfOq2gbq/QTEcXySSMzf95CTeHzK//4j2gBd5QmM/otD+Ax7f+sH58N/y9SDUjYigPfUiTur+V+l9g/ASQWnkGQkDjeTKoLICBbIvIdrZM50fiyAerJn66aUneMWt+K9vayQKgHDsyYjnMC47fdskNoh3U6gLNcUDKQrxUQeHSNiUy814LPT9MhEwDbkNSztvXKjDp7qbCMODPeXOsD7jvVSEHfOZvaGXQFmSmch+x0x6K9bFEvrBuAg4SEYpRLT8OSXh/+K8sTghPpE0d2gmE2iEiExNhVQnZAxeVTUoi0gFW8hwVVA6heigiuXonhhJ2XFegsU5RQ8tCEVLwoS/gLjhTAYJfexWx88wh7ypAHuZa7d5zjo/BEpkrzo17YhM+YbbgOSRJYFssdK9wfxppHVsb0iW2a4I0L8NBcofusNY20JD68nemyKctOl; 4:DEx3R1DI3Pc/v4OUU9XjJBVZIRbliFtHxHEv5hTXa4pXLQTyRJ/7Vde6+ZE3nONdPL9o6FahvQOFSmej3K1vF6mTF1nzrRHeg1gFTJ8N8xYqYeVAoigbnSEHLdIXJ+Tqm520PUfEky6g3qdLP+2hF3zkLnEOK19V+XeputX1UbP4tRuJz6qiPT7STrWT1wlAYNd4xx3zRmV5n6bQnqGlIdlKfnU1AgTJ5539gKTXQrL9mrEyZSaNsk090yfJCLRk6FmqomLtjbFz8Kq+pUZcew== 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:LQ7EU0mv7kLHYg9vFGFQPcSlF9yEIi+BGk5Kr05?= b+fFzKToFYSKwCEpqzJRyu1h+lME+yQOut7QBCg2vhigTO4AjgnqFfc2jAstBUFcNXQwdzXr7eWkzQufC0GRI48sBT1on+9AswlUxC89jM5bXUd88t9XeiHZ9sg5xz0ik55pMVKnFrzSiXHWnU8fDKDvUd5GYPhJmGUWX9wOHzANvmZk4aRU7BOQ1IJY6naXG5RcN300o1qc3yaSiEFDQxKDPQ+2j210lp4ae67Lg+XgyX2u8pL1eEYh2Md+161HhbyZtd1/H+Lk4IUbT+pibFcFmaExkHDIzv2GVDeauN8pK9HGpKv7eLWFNK1+Ha30lbgFm6SIqMmG1DUcO229uAMKsIqUpKO2sTOrsv8MxJVY4jlJFOq5qh/4ZIxjIZ66VGxQviKKfyVbVcvt7r1vIRCLpFu0Slmj8mYenPnm6Qx0bxDAzrqEDvrdFnEMmMhSdwqqKBMTk91epj0GagoNmc2Ks+knIX1kL/6uAzzZ9JIYYdx7RyOil6ZVQpUfnVGvMZmta3LIWvsI07QWoHv+msuVDBk+HFExIScNT0pDYzlzcqX67LXeS5zZOVuQNCE2v+FNhrwbyeEfGDMGG/Ng/4Klvhbk0BtnP3/JnU73S9X0/aHgBFtaP+oMUKmLHVzItqs1Nt9iRETuNbULyLeUI4A0g9vi+Xg1RxNHNhEH8y7MpWpG5tGMxvjGw6nYPn8p2a5GgiWkjtWZTP1Ky51s6LUbezw4NWM3f1mREy+xRs57pM67jC2J7+wyQynB+rWzXHacHKmPB9CNT5wc6bxVz1HrNZZRnpewJr0dHoMaV1uzwDs05nu73KtxsFnoG22gREbQvJ+6SUsP51UkTdrk96d61vFRZ1z2sZVPsNUHlT3wP8kZ1U83MmQTGrKWxvFTzT+or7RYqeTLLQ1J0j9PXOkS4SbGN+XMVTkNJ/M6ywqVWJ4o5uKC3inP7Wugt/UwFSa84QrvD/FStwxNYAQzpYidIhsVZhGMZCxVv4A8OHDg/qxflwxbhFaZOed4lFmxWi5R7xkxNvgoyGJJExGgjGtirk9aokuXKYHOSG7G4jlzEGnVwo85ZJ5zdJISlJHkNF3f7HtFDPP+7yOdu3vGtV4p9sJjXrAHhFxHu7BSUM2eWNSsaZ8+QQW1P5zo9wMmb0FZZq2Byh12vduZm4egV0gctzW5ccAccDcy20mXtJb8xtKiav09Zsm7gYze2SsH5m2ijhHxvBRInDq0ACZAA5VpTOp+yKThhCCVMcdI/CEzdqfRBwhT0Wc3V1LrsoYPSoHbcp2mCHBy0nabHXytZFi9Q X-Microsoft-Antispam-Message-Info: Ab9HoM0vLltdVq2AiLC7TFNrSaNOLrgEdh74mR/M+B8ST7MFZO2BFXOaVIVo0/O1/PBmeWgBaI3UYb3m/noVj/c0XUP3y/JImRr9er7vWLvH5JvbiRxgPfPr6hKvxVH3xBAcFZLqqV9vVJcBmgN82Amcf7OGqp0beVvcUBQ3KK3sU7vjziNtjGDxTtnTiCXpTgtDilpdPYrJN3RyU+YtDykV2k+KRQZrea6gnln/91bJoZtOzV4r9m8hbWKianex7bZf+eqwkLrLh2pBRC4EVwdLAtTo0N+ugiRLQIAy5wqEjZm0i3A1kwb1pWI5/g7oNsRMUkqm81zPnVmYH6nXTNkGHLKq4w23D/WGvjkc5Nk= X-Microsoft-Exchange-Diagnostics: 1; AM4PR0501MB2322; 6:Ej7isFV4fpgUSAuEvriPQJq9n3HxXhSp+0xieWniJa1/WXeL4JTDPH3IGNzAx8VonYexvhMCKs9UkhpHxaePRCQwTad4mqwd0c/+IKdFGHi287rd/7O5qsdrZm3+KFLd7+sFU8LjQg+T5fFUo1ukML+Bin85zTtcV/Wo+69nC3A5MbVDdMcOVuXst4XYJha0NEP8PkOk0CHloBo4pg2MdXsbC8gNpbOhWsRJr7BKzBgAbeMzZrjspYcPZTpnsHwFmw/akh3z/tBPNbzVyVy+wFP1q7qS0S2TSSQ41v85t8a5Znfji/GmtccW8zamNf3xCnkL414M/APaCQS9Uxlf2TKpZ+bX6MpEmQ9tb2vBJkPfOt3joPazl7pOXm/mt/CcgfkHhZXsuTIHoR60Ex2qR3Cp0F+tRlThihRZA8sL5IdxZyqe40DRIuU7dih2iaGvXPCOX/cw+QS5g6T353/wGA==; 5:teMlFdcz3q5XB6MJrUAXo17VhwlGyPowsrMUegEOTKp8Boa1GZGSs2+cb9nPUOMkjCU5k50f8pqnXNA0jkOGf9REK3afZSLPzJUOJ6gzBpjVY/hvf/h6FebykY7d60k1KSLD9TxgRhxzkBJdIDSemhWFWvkqQYFFfDPyzwRsvxs=; 7:sm8kPUPOwZ87pXYBQQuqCnfrrN4YimBOCg3DQBFZyDL5FegNrR8XgxZ0MzQrKKeYeAGI9/r11aX1m8Pk0ZCkuLBeN6OUxWcbudiLTYQrmJcFzQMq04e/J2AyYIU4cU6Lr4iGS/I7NQBVYbtt8+4QUdSJ7Q+k8OBzlQavjVEFWRgmjiTPNnXrEFGTpW63zoW/EHsKupNFWhJwuEIr2k3adnL2Hl31ZjVgpdk9SVm7slNvqNOcePx6z7CbGkHHYyHi SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Jul 2018 14:30:01.4425 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 0bd263d7-1a4e-490b-1928-08d5f171f10a 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 The number of eRPs that can be used by a single A-TCAM region is limited to 16. When more eRPs are needed, an ordinary circuit TCAM (C-TCAM) can be used to hold the extra eRPs. Unlike the A-TCAM, only a single (last) lookup is performed in the C-TCAM and not a lookup per-eRP. However, modeling the C-TCAM as extra eRPs will allow us to easily introduce support for pruning in a follow-up patch set and is also logically correct. The following diagram depicts the relation between both TCAMs: C-TCAM +-------------------+ +--------------------+ +-----------+ | | | | | | | eRP #1 (A-TCAM) +----> ... +----+ eRP #16 (A-TCAM) +----+ eRP #17 | | | | | | ... | +-------------------+ +--------------------+ | eRP #N | | | +-----------+ Lookup order is from left to right. Extend the eRP core APIs with a C-TCAM parameter which indicates whether the requested eRP is to be used with the C-TCAM or not. Since the C-TCAM is only meant to absorb rules that can't fit in the A-TCAM due to exceeded number of eRPs or key collision, an error is returned when a C-TCAM eRP needs to be created when the eRP state machine is in its initial state (i.e., 'no masks'). This should only happen in the face of very unlikely errors when trying to push rules into the A-TCAM. In order not to perform unnecessary lookups, the eRP core will only enable a C-TCAM lookup for a given region if it knows there are C-TCAM eRPs present. Signed-off-by: Ido Schimmel Reviewed-by: Jiri Pirko --- Notes: v2: * Cast to 'u32 *' instead of 'void *' .../mellanox/mlxsw/spectrum_acl_erp.c | 202 ++++++++++++++++-- .../mellanox/mlxsw/spectrum_acl_tcam.h | 2 +- 2 files changed, 191 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c index 86600c780c95..e26efa451d4a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c @@ -60,6 +60,7 @@ struct mlxsw_sp_acl_erp_core { struct mlxsw_sp_acl_erp_key { char mask[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; + bool ctcam; }; struct mlxsw_sp_acl_erp { @@ -90,6 +91,7 @@ struct mlxsw_sp_acl_erp_table { unsigned long base_index; unsigned int num_atcam_erps; unsigned int num_max_atcam_erps; + unsigned int num_ctcam_erps; }; static const struct rhashtable_params mlxsw_sp_acl_erp_ht_params = { @@ -448,13 +450,14 @@ static void mlxsw_sp_acl_erp_table_erp_del(struct mlxsw_sp_acl_erp *erp) } static int -mlxsw_sp_acl_erp_table_enable(struct mlxsw_sp_acl_erp_table *erp_table) +mlxsw_sp_acl_erp_table_enable(struct mlxsw_sp_acl_erp_table *erp_table, + bool ctcam_le) { struct mlxsw_sp_acl_tcam_region *region = erp_table->aregion->region; struct mlxsw_sp *mlxsw_sp = erp_table->erp_core->mlxsw_sp; char pererp_pl[MLXSW_REG_PERERP_LEN]; - mlxsw_reg_pererp_pack(pererp_pl, region->id, false, true, 0, + mlxsw_reg_pererp_pack(pererp_pl, region->id, ctcam_le, true, 0, erp_table->base_index, 0); mlxsw_reg_pererp_erp_vector_pack(pererp_pl, erp_table->erp_index_bitmap, MLXSW_SP_ACL_ERP_MAX_PER_REGION); @@ -471,11 +474,12 @@ mlxsw_sp_acl_erp_table_disable(struct mlxsw_sp_acl_erp_table *erp_table) struct mlxsw_sp_acl_erp *master_rp; master_rp = mlxsw_sp_acl_erp_table_master_rp(erp_table); - if (!master_rp) - return; - + /* It is possible we do not have a master RP when we disable the + * table when there are no rules in the A-TCAM and the last C-TCAM + * rule is deleted + */ mlxsw_reg_pererp_pack(pererp_pl, region->id, false, false, 0, 0, - master_rp->id); + master_rp ? master_rp->id : 0); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pererp), pererp_pl); } @@ -506,6 +510,7 @@ mlxsw_sp_acl_erp_table_expand(struct mlxsw_sp_acl_erp_table *erp_table) unsigned int num_erps, old_num_erps = erp_table->num_max_atcam_erps; struct mlxsw_sp_acl_erp_core *erp_core = erp_table->erp_core; unsigned long old_base_index = erp_table->base_index; + bool ctcam_le = erp_table->num_ctcam_erps > 0; int err; if (erp_table->num_atcam_erps < erp_table->num_max_atcam_erps) @@ -526,7 +531,7 @@ mlxsw_sp_acl_erp_table_expand(struct mlxsw_sp_acl_erp_table *erp_table) if (err) goto err_table_relocate; - err = mlxsw_sp_acl_erp_table_enable(erp_table); + err = mlxsw_sp_acl_erp_table_enable(erp_table, ctcam_le); if (err) goto err_table_enable; @@ -579,7 +584,7 @@ mlxsw_sp_acl_erp_region_table_trans(struct mlxsw_sp_acl_erp_table *erp_table) if (err) goto err_table_master_rp_add; - err = mlxsw_sp_acl_erp_table_enable(erp_table); + err = mlxsw_sp_acl_erp_table_enable(erp_table, false); if (err) goto err_table_enable; @@ -619,9 +624,10 @@ mlxsw_sp_acl_erp_region_erp_add(struct mlxsw_sp_acl_erp_table *erp_table, { struct mlxsw_sp_acl_tcam_region *region = erp_table->aregion->region; struct mlxsw_sp *mlxsw_sp = erp_table->erp_core->mlxsw_sp; + bool ctcam_le = erp_table->num_ctcam_erps > 0; char pererp_pl[MLXSW_REG_PERERP_LEN]; - mlxsw_reg_pererp_pack(pererp_pl, region->id, false, true, 0, + mlxsw_reg_pererp_pack(pererp_pl, region->id, ctcam_le, true, 0, erp_table->base_index, 0); mlxsw_reg_pererp_erp_vector_pack(pererp_pl, erp_table->erp_index_bitmap, MLXSW_SP_ACL_ERP_MAX_PER_REGION); @@ -635,9 +641,10 @@ static void mlxsw_sp_acl_erp_region_erp_del(struct mlxsw_sp_acl_erp *erp) struct mlxsw_sp_acl_erp_table *erp_table = erp->erp_table; struct mlxsw_sp_acl_tcam_region *region = erp_table->aregion->region; struct mlxsw_sp *mlxsw_sp = erp_table->erp_core->mlxsw_sp; + bool ctcam_le = erp_table->num_ctcam_erps > 0; char pererp_pl[MLXSW_REG_PERERP_LEN]; - mlxsw_reg_pererp_pack(pererp_pl, region->id, false, true, 0, + mlxsw_reg_pererp_pack(pererp_pl, region->id, ctcam_le, true, 0, erp_table->base_index, 0); mlxsw_reg_pererp_erp_vector_pack(pererp_pl, erp_table->erp_index_bitmap, MLXSW_SP_ACL_ERP_MAX_PER_REGION); @@ -646,6 +653,161 @@ static void mlxsw_sp_acl_erp_region_erp_del(struct mlxsw_sp_acl_erp *erp) mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pererp), pererp_pl); } +static int +mlxsw_sp_acl_erp_region_ctcam_enable(struct mlxsw_sp_acl_erp_table *erp_table) +{ + /* No need to re-enable lookup in the C-TCAM */ + if (erp_table->num_ctcam_erps > 1) + return 0; + + return mlxsw_sp_acl_erp_table_enable(erp_table, true); +} + +static void +mlxsw_sp_acl_erp_region_ctcam_disable(struct mlxsw_sp_acl_erp_table *erp_table) +{ + /* Only disable C-TCAM lookup when last C-TCAM eRP is deleted */ + if (erp_table->num_ctcam_erps > 1) + return; + + mlxsw_sp_acl_erp_table_enable(erp_table, false); +} + +static void +mlxsw_sp_acl_erp_ctcam_table_ops_set(struct mlxsw_sp_acl_erp_table *erp_table) +{ + switch (erp_table->num_atcam_erps) { + case 2: + /* Keep using the eRP table, but correctly set the + * operations pointer so that when an A-TCAM eRP is + * deleted we will transition to use the master mask + */ + erp_table->ops = &erp_two_masks_ops; + break; + case 1: + /* We only kept the eRP table because we had C-TCAM + * eRPs in use. Now that the last C-TCAM eRP is gone we + * can stop using the table and transition to use the + * master mask + */ + mlxsw_sp_acl_erp_region_master_mask_trans(erp_table); + erp_table->ops = &erp_single_mask_ops; + break; + case 0: + /* There are no more eRPs of any kind used by the region + * so free its eRP table and transition to initial state + */ + mlxsw_sp_acl_erp_table_disable(erp_table); + mlxsw_sp_acl_erp_table_free(erp_table->erp_core, + erp_table->num_max_atcam_erps, + erp_table->aregion->type, + erp_table->base_index); + erp_table->ops = &erp_no_mask_ops; + break; + default: + break; + } +} + +static struct mlxsw_sp_acl_erp * +__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; + int err; + + erp = kzalloc(sizeof(*erp), GFP_KERNEL); + if (!erp) + return ERR_PTR(-ENOMEM); + + memcpy(&erp->key, key, sizeof(*key)); + bitmap_from_arr32(erp->mask_bitmap, (u32 *) key->mask, + MLXSW_SP_ACL_TCAM_MASK_LEN); + refcount_set(&erp->refcnt, 1); + erp_table->num_ctcam_erps++; + erp->erp_table = erp_table; + + err = mlxsw_sp_acl_erp_master_mask_set(erp_table, erp); + if (err) + goto err_master_mask_set; + + err = rhashtable_insert_fast(&erp_table->erp_ht, &erp->ht_node, + mlxsw_sp_acl_erp_ht_params); + if (err) + goto err_rhashtable_insert; + + err = mlxsw_sp_acl_erp_region_ctcam_enable(erp_table); + if (err) + goto err_erp_region_ctcam_enable; + + /* When C-TCAM is used, the eRP table must be used */ + erp_table->ops = &erp_multiple_masks_ops; + + return erp; + +err_erp_region_ctcam_enable: + 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: + erp_table->num_ctcam_erps--; + kfree(erp); + return ERR_PTR(err); +} + +static struct mlxsw_sp_acl_erp * +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; + int err; + + /* There is a special situation where we need to spill rules + * into the C-TCAM, yet the region is still using a master + * mask and thus not performing a lookup in the C-TCAM. This + * can happen when two rules that only differ in priority - and + * thus sharing the same key - are programmed. In this case + * we transition the region to use an eRP table + */ + err = mlxsw_sp_acl_erp_region_table_trans(erp_table); + if (err) + return ERR_PTR(err); + + erp = __mlxsw_sp_acl_erp_ctcam_mask_create(erp_table, key); + if (IS_ERR(erp)) { + err = PTR_ERR(erp); + goto err_erp_create; + } + + return erp; + +err_erp_create: + mlxsw_sp_acl_erp_region_master_mask_trans(erp_table); + return ERR_PTR(err); +} + +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; + + mlxsw_sp_acl_erp_region_ctcam_disable(erp_table); + 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); + erp_table->num_ctcam_erps--; + kfree(erp); + + /* Once the last C-TCAM eRP was destroyed, the state we + * transition to depends on the number of A-TCAM eRPs currently + * in use + */ + if (erp_table->num_ctcam_erps > 0) + return; + mlxsw_sp_acl_erp_ctcam_table_ops_set(erp_table); +} + static struct mlxsw_sp_acl_erp * mlxsw_sp_acl_erp_mask_create(struct mlxsw_sp_acl_erp_table *erp_table, struct mlxsw_sp_acl_erp_key *key) @@ -653,6 +815,9 @@ mlxsw_sp_acl_erp_mask_create(struct mlxsw_sp_acl_erp_table *erp_table, struct mlxsw_sp_acl_erp *erp; int err; + if (key->ctcam) + return __mlxsw_sp_acl_erp_ctcam_mask_create(erp_table, key); + /* Expand the eRP table for the new eRP, if needed */ err = mlxsw_sp_acl_erp_table_expand(erp_table); if (err) @@ -691,12 +856,15 @@ static void mlxsw_sp_acl_erp_mask_destroy(struct mlxsw_sp_acl_erp_table *erp_table, struct mlxsw_sp_acl_erp *erp) { + if (erp->key.ctcam) + return mlxsw_sp_acl_erp_ctcam_mask_destroy(erp); + mlxsw_sp_acl_erp_region_erp_del(erp); mlxsw_sp_acl_erp_table_erp_del(erp); mlxsw_sp_acl_erp_index_put(erp_table, erp->index); mlxsw_sp_acl_erp_generic_destroy(erp); - if (erp_table->num_atcam_erps == 2) + if (erp_table->num_atcam_erps == 2 && erp_table->num_ctcam_erps == 0) erp_table->ops = &erp_two_masks_ops; } @@ -707,6 +875,9 @@ mlxsw_sp_acl_erp_second_mask_create(struct mlxsw_sp_acl_erp_table *erp_table, struct mlxsw_sp_acl_erp *erp; int err; + if (key->ctcam) + return mlxsw_sp_acl_erp_ctcam_mask_create(erp_table, key); + /* Transition to use eRP table instead of master mask */ err = mlxsw_sp_acl_erp_region_table_trans(erp_table); if (err) @@ -749,6 +920,9 @@ static void mlxsw_sp_acl_erp_second_mask_destroy(struct mlxsw_sp_acl_erp_table *erp_table, struct mlxsw_sp_acl_erp *erp) { + if (erp->key.ctcam) + return mlxsw_sp_acl_erp_ctcam_mask_destroy(erp); + mlxsw_sp_acl_erp_region_erp_del(erp); mlxsw_sp_acl_erp_table_erp_del(erp); mlxsw_sp_acl_erp_index_put(erp_table, erp->index); @@ -765,6 +939,9 @@ mlxsw_sp_acl_erp_first_mask_create(struct mlxsw_sp_acl_erp_table *erp_table, { struct mlxsw_sp_acl_erp *erp; + if (key->ctcam) + return ERR_PTR(-EINVAL); + erp = mlxsw_sp_acl_erp_generic_create(erp_table, key); if (IS_ERR(erp)) return erp; @@ -791,7 +968,7 @@ mlxsw_sp_acl_erp_no_mask_destroy(struct mlxsw_sp_acl_erp_table *erp_table, struct mlxsw_sp_acl_erp * mlxsw_sp_acl_erp_get(struct mlxsw_sp_acl_atcam_region *aregion, - const char *mask) + const char *mask, bool ctcam) { struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table; struct mlxsw_sp_acl_erp_key key; @@ -803,6 +980,7 @@ mlxsw_sp_acl_erp_get(struct mlxsw_sp_acl_atcam_region *aregion, ASSERT_RTNL(); memcpy(key.mask, mask, MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN); + key.ctcam = ctcam; erp = rhashtable_lookup_fast(&erp_table->erp_ht, &key, mlxsw_sp_acl_erp_ht_params); if (erp) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index af21f7c6c6df..70094936ca43 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -179,7 +179,7 @@ struct mlxsw_sp_acl_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, - const char *mask); + const char *mask, bool ctcam); void mlxsw_sp_acl_erp_put(struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_erp *erp); int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion);