From patchwork Mon May 10 05:41:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476067 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=2404:9400:2:0:216:3eff:fee1:b9f1; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=rGQNWhcS; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=jPMeHoC6; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2404:9400:2:0:216:3eff:fee1:b9f1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fdqjt5Hqfz9vG0 for ; Mon, 10 May 2021 15:44:02 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4Fdqjt4z8wz2yxN for ; Mon, 10 May 2021 15:44:02 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=rGQNWhcS; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=jPMeHoC6; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=rGQNWhcS; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=jPMeHoC6; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4Fdqj26DWxz2yXj; Mon, 10 May 2021 15:43:18 +1000 (AEST) Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailnew.nyi.internal (Postfix) with ESMTP id A78405803EE; Mon, 10 May 2021 01:43:16 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Mon, 10 May 2021 01:43:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=zeMjTxXMNLvgc rRh47QEf17e/Pjyznlid4yZDXfrvgI=; b=rGQNWhcSpwG/qdsT1nuTHhjgEojB9 8tj3hTg/pMsfK4al46/EZQeNj+94PfzjkOqI8O+UsDkssX7l8z4FgjR7tc05A6ta QmgSUYO2rkNGhIy02Hn0o0BsKIKIMDpdhBM8tPsql/BI/BGkSbzQBCLMmhMTZ1J2 f/28Sh0Goz9uNffxsmC6inxDrFrNmWlSU5Sj/DugljEZqpukU4Fp3+ElwB0f138K CK/4R+lmMRB2cQUhSUDBPT4c5NPWhl23KUXtni1NEHgMJ4pkuzaCq+otjVfYmOo/ PNl9Noy/uQ1Py2B+JObS5vle+Gfa9QzUGJHIt1zJgkvTfjpjDnx+GHftA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=zeMjTxXMNLvgcrRh47QEf17e/Pjyznlid4yZDXfrvgI=; b=jPMeHoC6 o8wExzoIVeSYjJhheujf7J915eW981hIKEQsSPIelrWZM22DVIlWZQJM+Z4AFirx lpHHGMh0NwwTgOTCKEVyZ8hhnc66m+ibtg5CUXRlSmeMevHKf6Od+8Mh3qi6D5eY G0ZnrpVkEmC9hcFqJ8lpVt60Z2Cnyq3MKoz27UMYM+jCnYMKTa1AervT4CH9a5HI cz6GIk4LigdvNMXNc5qHAFKJGjTSL0y8sAP6t5IHMR5Hz02dwIGY0ZhW1aIsLR2Z xpANEKV+qC7bTaFvVIiYs0ats+pdU/JuwV8dUq3Zdqe/XS3PGAuaJd9hjq5Ic1Q+ /CyyHX07/t8yPQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:43:10 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 01/16] ipmi: kcs_bmc_aspeed: Use of match data to extract KCS properties Date: Mon, 10 May 2021 15:11:58 +0930 Message-Id: <20210510054213.1610760-2-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Unpack and remove the aspeed_kcs_probe_of_v[12]() functions to aid rearranging how the private device-driver memory is allocated. Signed-off-by: Andrew Jeffery --- drivers/char/ipmi/kcs_bmc_aspeed.c | 154 ++++++++++++++--------------- 1 file changed, 76 insertions(+), 78 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index eefe362f65f0..c94d36e195be 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,10 @@ struct aspeed_kcs_bmc { struct regmap *map; }; +struct aspeed_kcs_of_ops { + int (*get_channel)(struct platform_device *pdev); + int (*get_io_address)(struct platform_device *pdev); +}; static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) { @@ -231,13 +236,10 @@ static const struct kcs_ioreg ast_kcs_bmc_ioregs[KCS_CHANNEL_MAX] = { { .idr = LPC_IDR4, .odr = LPC_ODR4, .str = LPC_STR4 }, }; -static struct kcs_bmc *aspeed_kcs_probe_of_v1(struct platform_device *pdev) +static int aspeed_kcs_of_v1_get_channel(struct platform_device *pdev) { - struct aspeed_kcs_bmc *priv; struct device_node *np; - struct kcs_bmc *kcs; u32 channel; - u32 slave; int rc; np = pdev->dev.of_node; @@ -245,105 +247,79 @@ static struct kcs_bmc *aspeed_kcs_probe_of_v1(struct platform_device *pdev) rc = of_property_read_u32(np, "kcs_chan", &channel); if ((rc != 0) || (channel == 0 || channel > KCS_CHANNEL_MAX)) { dev_err(&pdev->dev, "no valid 'kcs_chan' configured\n"); - return ERR_PTR(-EINVAL); + return -EINVAL; } - kcs = kcs_bmc_alloc(&pdev->dev, sizeof(struct aspeed_kcs_bmc), channel); - if (!kcs) - return ERR_PTR(-ENOMEM); + return channel; +} - priv = kcs_bmc_priv(kcs); - priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node); - if (IS_ERR(priv->map)) { - dev_err(&pdev->dev, "Couldn't get regmap\n"); - return ERR_PTR(-ENODEV); - } +static int aspeed_kcs_of_v1_get_io_address(struct platform_device *pdev) +{ + u32 slave; + int rc; - rc = of_property_read_u32(np, "kcs_addr", &slave); - if (rc) { + rc = of_property_read_u32(pdev->dev.of_node, "kcs_addr", &slave); + if (rc || slave > 0xffff) { dev_err(&pdev->dev, "no valid 'kcs_addr' configured\n"); - return ERR_PTR(-EINVAL); + return -EINVAL; } - kcs->ioreg = ast_kcs_bmc_ioregs[channel - 1]; - aspeed_kcs_set_address(kcs, slave); - - return kcs; -} - -static int aspeed_kcs_calculate_channel(const struct kcs_ioreg *regs) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ast_kcs_bmc_ioregs); i++) { - if (!memcmp(&ast_kcs_bmc_ioregs[i], regs, sizeof(*regs))) - return i + 1; - } - - return -EINVAL; + return slave; } -static struct kcs_bmc *aspeed_kcs_probe_of_v2(struct platform_device *pdev) +static int aspeed_kcs_of_v2_get_channel(struct platform_device *pdev) { - struct aspeed_kcs_bmc *priv; struct device_node *np; struct kcs_ioreg ioreg; - struct kcs_bmc *kcs; const __be32 *reg; - int channel; - u32 slave; - int rc; + int i; np = pdev->dev.of_node; /* Don't translate addresses, we want offsets for the regmaps */ reg = of_get_address(np, 0, NULL, NULL); if (!reg) - return ERR_PTR(-EINVAL); + return -EINVAL; ioreg.idr = be32_to_cpup(reg); reg = of_get_address(np, 1, NULL, NULL); if (!reg) - return ERR_PTR(-EINVAL); + return -EINVAL; ioreg.odr = be32_to_cpup(reg); reg = of_get_address(np, 2, NULL, NULL); if (!reg) - return ERR_PTR(-EINVAL); + return -EINVAL; ioreg.str = be32_to_cpup(reg); - channel = aspeed_kcs_calculate_channel(&ioreg); - if (channel < 0) - return ERR_PTR(channel); - - kcs = kcs_bmc_alloc(&pdev->dev, sizeof(struct aspeed_kcs_bmc), channel); - if (!kcs) - return ERR_PTR(-ENOMEM); - - kcs->ioreg = ioreg; - - priv = kcs_bmc_priv(kcs); - priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node); - if (IS_ERR(priv->map)) { - dev_err(&pdev->dev, "Couldn't get regmap\n"); - return ERR_PTR(-ENODEV); + for (i = 0; i < ARRAY_SIZE(ast_kcs_bmc_ioregs); i++) { + if (!memcmp(&ast_kcs_bmc_ioregs[i], &ioreg, sizeof(ioreg))) + return i + 1; } - rc = of_property_read_u32(np, "aspeed,lpc-io-reg", &slave); - if (rc) - return ERR_PTR(rc); + return -EINVAL; +} - aspeed_kcs_set_address(kcs, slave); +static int aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev) +{ + uint32_t slave; + int rc; - return kcs; + rc = of_property_read_u32(pdev->dev.of_node, "aspeed,lpc-io-reg", &slave); + if (rc || slave > 0xffff) + return -EINVAL; + + return slave; } static int aspeed_kcs_probe(struct platform_device *pdev) { + const struct aspeed_kcs_of_ops *ops; struct device *dev = &pdev->dev; + struct aspeed_kcs_bmc *priv; struct kcs_bmc *kcs_bmc; struct device_node *np; - int rc; + int rc, channel, addr; np = dev->of_node->parent; if (!of_device_is_compatible(np, "aspeed,ast2400-lpc-v2") && @@ -352,23 +328,35 @@ static int aspeed_kcs_probe(struct platform_device *pdev) dev_err(dev, "unsupported LPC device binding\n"); return -ENODEV; } - - np = dev->of_node; - if (of_device_is_compatible(np, "aspeed,ast2400-kcs-bmc") || - of_device_is_compatible(np, "aspeed,ast2500-kcs-bmc")) - kcs_bmc = aspeed_kcs_probe_of_v1(pdev); - else if (of_device_is_compatible(np, "aspeed,ast2400-kcs-bmc-v2") || - of_device_is_compatible(np, "aspeed,ast2500-kcs-bmc-v2")) - kcs_bmc = aspeed_kcs_probe_of_v2(pdev); - else + ops = of_device_get_match_data(&pdev->dev); + if (!ops) return -EINVAL; - if (IS_ERR(kcs_bmc)) - return PTR_ERR(kcs_bmc); + channel = ops->get_channel(pdev); + if (channel < 0) + return channel; + kcs_bmc = kcs_bmc_alloc(&pdev->dev, sizeof(struct aspeed_kcs_bmc), channel); + if (!kcs_bmc) + return -ENOMEM; + + kcs_bmc->ioreg = ast_kcs_bmc_ioregs[channel - 1]; kcs_bmc->io_inputb = aspeed_kcs_inb; kcs_bmc->io_outputb = aspeed_kcs_outb; + addr = ops->get_io_address(pdev); + if (addr < 0) + return addr; + + priv = kcs_bmc_priv(kcs_bmc); + priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node); + if (IS_ERR(priv->map)) { + dev_err(&pdev->dev, "Couldn't get regmap\n"); + return -ENODEV; + } + + aspeed_kcs_set_address(kcs_bmc, addr); + rc = aspeed_kcs_config_irq(kcs_bmc, pdev); if (rc) return rc; @@ -400,11 +388,21 @@ static int aspeed_kcs_remove(struct platform_device *pdev) return 0; } +static const struct aspeed_kcs_of_ops of_v1_ops = { + .get_channel = aspeed_kcs_of_v1_get_channel, + .get_io_address = aspeed_kcs_of_v1_get_io_address, +}; + +static const struct aspeed_kcs_of_ops of_v2_ops = { + .get_channel = aspeed_kcs_of_v2_get_channel, + .get_io_address = aspeed_kcs_of_v2_get_io_address, +}; + static const struct of_device_id ast_kcs_bmc_match[] = { - { .compatible = "aspeed,ast2400-kcs-bmc" }, - { .compatible = "aspeed,ast2500-kcs-bmc" }, - { .compatible = "aspeed,ast2400-kcs-bmc-v2" }, - { .compatible = "aspeed,ast2500-kcs-bmc-v2" }, + { .compatible = "aspeed,ast2400-kcs-bmc", .data = &of_v1_ops }, + { .compatible = "aspeed,ast2500-kcs-bmc", .data = &of_v1_ops }, + { .compatible = "aspeed,ast2400-kcs-bmc-v2", .data = &of_v2_ops }, + { .compatible = "aspeed,ast2500-kcs-bmc-v2", .data = &of_v2_ops }, { } }; MODULE_DEVICE_TABLE(of, ast_kcs_bmc_match); From patchwork Mon May 10 05:41:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476071 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=2404:9400:2:0:216:3eff:fee1:b9f1; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=lsYMSosf; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=dIANDsRT; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2404:9400:2:0:216:3eff:fee1:b9f1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FdqkQ3YxCz9vFs for ; Mon, 10 May 2021 15:44:30 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4FdqkQ3B0vz2yYV for ; Mon, 10 May 2021 15:44:30 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=lsYMSosf; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=dIANDsRT; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=lsYMSosf; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=dIANDsRT; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4Fdqj907Fnz302H; Mon, 10 May 2021 15:43:25 +1000 (AEST) Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailnew.nyi.internal (Postfix) with ESMTP id 0522D5804C8; Mon, 10 May 2021 01:43:23 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Mon, 10 May 2021 01:43:23 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=2oYWU/9OjPkLQ kQfeH4LDKNvXAEFhmY5/iusfzNu4d8=; b=lsYMSosfFphbDwbgqJJP2ppfXRwFY 1238abm2R1wp5Inp0sU7TetlW1RIGoxamPJysn39+m9nj0uM0RekhIBwpJdfuaGP fGFrSHMX4ndINANMz5y1uIido+3LfgvLwQEeXiWaRPwwUdyouFxb7rnwtkvLfAU3 g7YKdmQeBYawDA+iqvafNSX3B+lx8oTo+NNWXMTklgrRMX4RjBsojJzVPAkL6KC7 q1iM1mqmtb4nJFF+iCCeMzO94WWz8LkLf6Nzbf1SUlmFqOFTDrZBQDZt/H/FcUDL iuiOctHk0sL9LiNq6m1Hc4DCzCNSEHiPdz49Y5zofSpnABW06pSCQ70mA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=2oYWU/9OjPkLQkQfeH4LDKNvXAEFhmY5/iusfzNu4d8=; b=dIANDsRT KVlRdtLfnQP8Gj2uMHIrM9TRbEbmL/I0M+YBXpkOk+kZwX7q/Qk+eUceffr+UDLd sEkrZTDKLM7BjZouJUj3eDEjTjo0DAaX0y2yS21CUPvNZoP7ZD96tNoS16gITETA KgQydTF9q2czYLVbLKjRB0vNHvxYaIvXi1Jcf3sMUAX/q70yiprdbKkuoDj+pM2X 5aje9Y+k03IDFqqXw9ZAqtf19lbrCkJ9VlEDgrA7OkfZa4SKKE0anPXAqT+dKXdX U+YtOPmrPReln3f6jFa9HEerOqGoWgBLuN6gB3L4W9XEaCt/mQl7JRAJYStc+zJ2 lbNmWkmgqqRmqA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:43:16 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 02/16] ipmi: kcs_bmc: Make status update atomic Date: Mon, 10 May 2021 15:11:59 +0930 Message-Id: <20210510054213.1610760-3-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Enable more efficient implementation of read-modify-write sequences. Both device drivers for the KCS BMC stack use regmaps. The new callback allows us to exploit regmap_update_bits(). Signed-off-by: Andrew Jeffery Reviewed-by: Zev Weiss --- drivers/char/ipmi/kcs_bmc.c | 7 +------ drivers/char/ipmi/kcs_bmc.h | 1 + drivers/char/ipmi/kcs_bmc_aspeed.c | 9 +++++++++ drivers/char/ipmi/kcs_bmc_npcm7xx.c | 10 ++++++++++ 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index f292e74bd4a5..58fb1a7bd50d 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -67,12 +67,7 @@ static inline void write_status(struct kcs_bmc *kcs_bmc, u8 data) static void update_status_bits(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) { - u8 tmp = read_status(kcs_bmc); - - tmp &= ~mask; - tmp |= val & mask; - - write_status(kcs_bmc, tmp); + kcs_bmc->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val); } static inline void set_state(struct kcs_bmc *kcs_bmc, u8 state) diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index eb9ea4ce78b8..970f53892f2d 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -76,6 +76,7 @@ struct kcs_bmc { struct kcs_ioreg ioreg; u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg); void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b); + void (*io_updateb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val); enum kcs_phases phase; enum kcs_errors error; diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index c94d36e195be..06628ca69750 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -90,6 +90,14 @@ static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) WARN(rc != 0, "regmap_write() failed: %d\n", rc); } +static void aspeed_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val) +{ + struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + int rc; + + rc = regmap_update_bits(priv->map, reg, mask, val); + WARN(rc != 0, "regmap_update_bits() failed: %d\n", rc); +} /* * AST_usrGuide_KCS.pdf @@ -343,6 +351,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev) kcs_bmc->ioreg = ast_kcs_bmc_ioregs[channel - 1]; kcs_bmc->io_inputb = aspeed_kcs_inb; kcs_bmc->io_outputb = aspeed_kcs_outb; + kcs_bmc->io_updateb = aspeed_kcs_updateb; addr = ops->get_io_address(pdev); if (addr < 0) diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c index 722f7391fe1f..1f44aadec9e8 100644 --- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c +++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c @@ -97,6 +97,15 @@ static void npcm7xx_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) WARN(rc != 0, "regmap_write() failed: %d\n", rc); } +static void npcm7xx_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 data) +{ + struct npcm7xx_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + int rc; + + rc = regmap_update_bits(priv->map, reg, mask, data); + WARN(rc != 0, "regmap_update_bits() failed: %d\n", rc); +} + static void npcm7xx_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) { struct npcm7xx_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); @@ -163,6 +172,7 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) kcs_bmc->ioreg.str = priv->reg->sts; kcs_bmc->io_inputb = npcm7xx_kcs_inb; kcs_bmc->io_outputb = npcm7xx_kcs_outb; + kcs_bmc->io_updateb = npcm7xx_kcs_updateb; dev_set_drvdata(dev, kcs_bmc); From patchwork Mon May 10 05:42:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476073 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=112.213.38.117; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=oYMy0bFp; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=ovXUI8qf; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FdqlJ01Kfz9vFL for ; Mon, 10 May 2021 15:45:15 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4FdqlH6mQNz307G for ; Mon, 10 May 2021 15:45:15 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=oYMy0bFp; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=ovXUI8qf; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=oYMy0bFp; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=ovXUI8qf; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4FdqjG5H4Fz2yxx; Mon, 10 May 2021 15:43:30 +1000 (AEST) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailnew.nyi.internal (Postfix) with ESMTP id B2C075804CB; Mon, 10 May 2021 01:43:28 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Mon, 10 May 2021 01:43:28 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=NRoX+CkOTTxsb n+R9nzd3/V2P1lI8thbzzsb3SjJ4xo=; b=oYMy0bFp1m5RFIXpWKlYJvg4dikID ubyUXLxr/0JZnIXBl77Xo6tavaVSbn829I0EQrMbN3E44kb0LldM6vagIpulO79M EgaHtC17S837wo0d3U/FP+4EUyptFO1UuXUR/+wrTgpIPdhT80x9gYXaSeiqmK3v oFbV2SHMn2GcykaU67k75O35CuL6MM9WBJBFukF8sL0YGjXhug2w07OlZEgKjD49 XAOR/GRQ28DlbPqfl3WAecCKofuhkyHQGA4ibpHhPz9cDdtV21CKVeQeGs7tEwOp i5DBDfJ/px9Uq8vh88MHrOSybJzP+Kwq/Jx7LH9EssiDSSx3pX9hcjHeg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=NRoX+CkOTTxsbn+R9nzd3/V2P1lI8thbzzsb3SjJ4xo=; b=ovXUI8qf QqRM3hk6gJ74FXBdq9jh4Y7xtyNC0qe84MSkVXrmhkxBtB6AYIqs1gpLjulwuh7X wGy07ytZHBvPO9/PqPq595mOZuKEtCAuE3HuFQh9Aq4WomaK82Fu2WuaU3VazhKI A9pfnRzLtx7w7D6aHHaiplCNIMIoxmbxBh1IK51Brm1Phy7qVdG+mzrHWB2FmSl0 2Gu6L5fBwnaIESseYZ2jcL8MiFoPieWVyuTRGq6UfuSqAiQX8slPEpQlLe+WWWG2 Jg5rjGOnr0lpIEodUXVsZD5Ci18X2i6fBBv/Z7thc/Nfst+AMIzOprpNaeX9347c ghONPs9tbpcnlw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:43:23 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 03/16] ipmi: kcs_bmc: Rename {read, write}_{status, data}() functions Date: Mon, 10 May 2021 15:12:00 +0930 Message-Id: <20210510054213.1610760-4-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Rename the functions in preparation for separating the IPMI chardev out from the KCS BMC core. Signed-off-by: Andrew Jeffery Reviewed-by: Zev Weiss --- drivers/char/ipmi/kcs_bmc.c | 52 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index 58fb1a7bd50d..c4336c1f2d6d 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -45,42 +45,42 @@ enum kcs_states { #define KCS_CMD_WRITE_END 0x62 #define KCS_CMD_READ_BYTE 0x68 -static inline u8 read_data(struct kcs_bmc *kcs_bmc) +static inline u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc) { return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr); } -static inline void write_data(struct kcs_bmc *kcs_bmc, u8 data) +static inline void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data) { kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data); } -static inline u8 read_status(struct kcs_bmc *kcs_bmc) +static inline u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc) { return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.str); } -static inline void write_status(struct kcs_bmc *kcs_bmc, u8 data) +static inline void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data) { kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data); } -static void update_status_bits(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) +static void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) { kcs_bmc->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val); } static inline void set_state(struct kcs_bmc *kcs_bmc, u8 state) { - update_status_bits(kcs_bmc, KCS_STATUS_STATE_MASK, + kcs_bmc_update_status(kcs_bmc, KCS_STATUS_STATE_MASK, KCS_STATUS_STATE(state)); } static void kcs_force_abort(struct kcs_bmc *kcs_bmc) { set_state(kcs_bmc, ERROR_STATE); - read_data(kcs_bmc); - write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc_read_data(kcs_bmc); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); kcs_bmc->phase = KCS_PHASE_ERROR; kcs_bmc->data_in_avail = false; @@ -99,9 +99,9 @@ static void kcs_bmc_handle_data(struct kcs_bmc *kcs_bmc) case KCS_PHASE_WRITE_DATA: if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { set_state(kcs_bmc, WRITE_STATE); - write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); kcs_bmc->data_in[kcs_bmc->data_in_idx++] = - read_data(kcs_bmc); + kcs_bmc_read_data(kcs_bmc); } else { kcs_force_abort(kcs_bmc); kcs_bmc->error = KCS_LENGTH_ERROR; @@ -112,7 +112,7 @@ static void kcs_bmc_handle_data(struct kcs_bmc *kcs_bmc) if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { set_state(kcs_bmc, READ_STATE); kcs_bmc->data_in[kcs_bmc->data_in_idx++] = - read_data(kcs_bmc); + kcs_bmc_read_data(kcs_bmc); kcs_bmc->phase = KCS_PHASE_WRITE_DONE; kcs_bmc->data_in_avail = true; wake_up_interruptible(&kcs_bmc->queue); @@ -126,34 +126,34 @@ static void kcs_bmc_handle_data(struct kcs_bmc *kcs_bmc) if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) set_state(kcs_bmc, IDLE_STATE); - data = read_data(kcs_bmc); + data = kcs_bmc_read_data(kcs_bmc); if (data != KCS_CMD_READ_BYTE) { set_state(kcs_bmc, ERROR_STATE); - write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); break; } if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) { - write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); kcs_bmc->phase = KCS_PHASE_IDLE; break; } - write_data(kcs_bmc, + kcs_bmc_write_data(kcs_bmc, kcs_bmc->data_out[kcs_bmc->data_out_idx++]); break; case KCS_PHASE_ABORT_ERROR1: set_state(kcs_bmc, READ_STATE); - read_data(kcs_bmc); - write_data(kcs_bmc, kcs_bmc->error); + kcs_bmc_read_data(kcs_bmc); + kcs_bmc_write_data(kcs_bmc, kcs_bmc->error); kcs_bmc->phase = KCS_PHASE_ABORT_ERROR2; break; case KCS_PHASE_ABORT_ERROR2: set_state(kcs_bmc, IDLE_STATE); - read_data(kcs_bmc); - write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc_read_data(kcs_bmc); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); kcs_bmc->phase = KCS_PHASE_IDLE; break; @@ -168,9 +168,9 @@ static void kcs_bmc_handle_cmd(struct kcs_bmc *kcs_bmc) u8 cmd; set_state(kcs_bmc, WRITE_STATE); - write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - cmd = read_data(kcs_bmc); + cmd = kcs_bmc_read_data(kcs_bmc); switch (cmd) { case KCS_CMD_WRITE_START: kcs_bmc->phase = KCS_PHASE_WRITE_START; @@ -212,7 +212,7 @@ int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) spin_lock_irqsave(&kcs_bmc->lock, flags); - status = read_status(kcs_bmc); + status = kcs_bmc_read_status(kcs_bmc); if (status & KCS_STATUS_IBF) { if (!kcs_bmc->running) kcs_force_abort(kcs_bmc); @@ -350,7 +350,7 @@ static ssize_t kcs_bmc_write(struct file *filp, const char __user *buf, kcs_bmc->data_out_idx = 1; kcs_bmc->data_out_len = count; memcpy(kcs_bmc->data_out, kcs_bmc->kbuffer, count); - write_data(kcs_bmc, kcs_bmc->data_out[0]); + kcs_bmc_write_data(kcs_bmc, kcs_bmc->data_out[0]); ret = count; } else { ret = -EINVAL; @@ -373,13 +373,11 @@ static long kcs_bmc_ioctl(struct file *filp, unsigned int cmd, switch (cmd) { case IPMI_BMC_IOCTL_SET_SMS_ATN: - update_status_bits(kcs_bmc, KCS_STATUS_SMS_ATN, - KCS_STATUS_SMS_ATN); + kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, KCS_STATUS_SMS_ATN); break; case IPMI_BMC_IOCTL_CLEAR_SMS_ATN: - update_status_bits(kcs_bmc, KCS_STATUS_SMS_ATN, - 0); + kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, 0); break; case IPMI_BMC_IOCTL_FORCE_ABORT: From patchwork Mon May 10 05:42:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476076 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=112.213.38.117; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=Lpj3BEeU; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=Ih1U+wE5; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fdqlr6YMtz9vFL for ; Mon, 10 May 2021 15:45:44 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4Fdqlr6Dr4z300b for ; Mon, 10 May 2021 15:45:44 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=Lpj3BEeU; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=Ih1U+wE5; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=Lpj3BEeU; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=Ih1U+wE5; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4FdqjN4ljkz305v; Mon, 10 May 2021 15:43:36 +1000 (AEST) Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailnew.nyi.internal (Postfix) with ESMTP id A27EF5803ED; Mon, 10 May 2021 01:43:34 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Mon, 10 May 2021 01:43:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=AGY1Obu/JHy/i Qm9onvFNxW29x0bpj0BoK1Nr879xuU=; b=Lpj3BEeUH9+bEKVFc71BD+9RYY4ET 7+nhaGdT3E4cJxbCvTxVrP1523OO/zRfSpIWU4MA9VaFbUHr6WhaA4tCPKv60hej 2ExSePxRNhYSx8ChNdQk65y+lOIks7h+zOExX088P5gfXzh/W5HgwkeVwLOUMVVf ilswUuUy2yI6G6Cf33V7lRknqWHDgEH6e8i9PYfaODiXdVMBla2zxyB+n3RIrGFl 5f4rNbfGGftfWo8sVCcNFJByIzu+s5PBW72y3YpKldG2Aui227Nc4UCpEr/WMURy MYHprQ2l6fLyT5dC+mqjeNEMFpyW4KxF6VsmFxOP7FndOZWknmYxGhesg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=AGY1Obu/JHy/iQm9onvFNxW29x0bpj0BoK1Nr879xuU=; b=Ih1U+wE5 QqOIkcQi1z1FcVazYS1fC9ljGiRc0JMa9yoUemV3iq4xkUWXPiVqaljtfSazbjqW l4qRMgO2A2gkSSO0BHQDJ+K8ELwB/KScbzkRiJ9WuraOeOSDyOB5QDyxBhC7fiHG axsjGyc1fspgoGhKy1xWVBGUteaX3UZi+qb3bDm769o5GWP9laLKoyfpl2VIHekz Iiqdt18ed91+byDhDQMFOUoUa6ZLth8lPRUnFo5KfYx6fs1mPTwydV9nwKL4OyJm aEajhVcFQIXFQYUURjVN8UxJTuIox8TBw4DJutDvBMwfGWp9VMINUoBTyQhtKChF B35C03mlaASRfA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedvnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:43:29 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 04/16] ipmi: kcs_bmc: Split out kcs_bmc_cdev_ipmi Date: Mon, 10 May 2021 15:12:01 +0930 Message-Id: <20210510054213.1610760-5-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Take steps towards defining a coherent API to separate the KCS device drivers from the userspace interface. Decreasing the coupling will improve the separation of concerns and enable the introduction of alternative userspace interfaces. For now, simply split the chardev logic out to a separate file. The code continues to build into the same module. Signed-off-by: Andrew Jeffery Reviewed-by: Zev Weiss --- drivers/char/ipmi/Makefile | 2 +- drivers/char/ipmi/kcs_bmc.c | 423 +------------------------ drivers/char/ipmi/kcs_bmc.h | 10 +- drivers/char/ipmi/kcs_bmc_cdev_ipmi.c | 428 ++++++++++++++++++++++++++ 4 files changed, 451 insertions(+), 412 deletions(-) create mode 100644 drivers/char/ipmi/kcs_bmc_cdev_ipmi.c diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile index 0822adc2ec41..a302bc865370 100644 --- a/drivers/char/ipmi/Makefile +++ b/drivers/char/ipmi/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_IPMI_SSIF) += ipmi_ssif.o obj-$(CONFIG_IPMI_POWERNV) += ipmi_powernv.o obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o -obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o +obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o kcs_bmc_cdev_ipmi.o obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index c4336c1f2d6d..ef5c48ffe74a 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -3,446 +3,51 @@ * Copyright (c) 2015-2018, Intel Corporation. */ -#define pr_fmt(fmt) "kcs-bmc: " fmt - -#include -#include -#include #include -#include -#include -#include -#include #include "kcs_bmc.h" -#define DEVICE_NAME "ipmi-kcs" - -#define KCS_MSG_BUFSIZ 1000 - -#define KCS_ZERO_DATA 0 - - -/* IPMI 2.0 - Table 9-1, KCS Interface Status Register Bits */ -#define KCS_STATUS_STATE(state) (state << 6) -#define KCS_STATUS_STATE_MASK GENMASK(7, 6) -#define KCS_STATUS_CMD_DAT BIT(3) -#define KCS_STATUS_SMS_ATN BIT(2) -#define KCS_STATUS_IBF BIT(1) -#define KCS_STATUS_OBF BIT(0) - -/* IPMI 2.0 - Table 9-2, KCS Interface State Bits */ -enum kcs_states { - IDLE_STATE = 0, - READ_STATE = 1, - WRITE_STATE = 2, - ERROR_STATE = 3, -}; - -/* IPMI 2.0 - Table 9-3, KCS Interface Control Codes */ -#define KCS_CMD_GET_STATUS_ABORT 0x60 -#define KCS_CMD_WRITE_START 0x61 -#define KCS_CMD_WRITE_END 0x62 -#define KCS_CMD_READ_BYTE 0x68 - -static inline u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc) +u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc) { return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr); } +EXPORT_SYMBOL(kcs_bmc_read_data); -static inline void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data) +void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data) { kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data); } +EXPORT_SYMBOL(kcs_bmc_write_data); -static inline u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc) +u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc) { return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.str); } +EXPORT_SYMBOL(kcs_bmc_read_status); -static inline void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data) +void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data) { kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data); } +EXPORT_SYMBOL(kcs_bmc_write_status); -static void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) +void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) { kcs_bmc->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val); } +EXPORT_SYMBOL(kcs_bmc_update_status); -static inline void set_state(struct kcs_bmc *kcs_bmc, u8 state) -{ - kcs_bmc_update_status(kcs_bmc, KCS_STATUS_STATE_MASK, - KCS_STATUS_STATE(state)); -} - -static void kcs_force_abort(struct kcs_bmc *kcs_bmc) -{ - set_state(kcs_bmc, ERROR_STATE); - kcs_bmc_read_data(kcs_bmc); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - - kcs_bmc->phase = KCS_PHASE_ERROR; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; -} - -static void kcs_bmc_handle_data(struct kcs_bmc *kcs_bmc) -{ - u8 data; - - switch (kcs_bmc->phase) { - case KCS_PHASE_WRITE_START: - kcs_bmc->phase = KCS_PHASE_WRITE_DATA; - fallthrough; - - case KCS_PHASE_WRITE_DATA: - if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { - set_state(kcs_bmc, WRITE_STATE); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - kcs_bmc->data_in[kcs_bmc->data_in_idx++] = - kcs_bmc_read_data(kcs_bmc); - } else { - kcs_force_abort(kcs_bmc); - kcs_bmc->error = KCS_LENGTH_ERROR; - } - break; - - case KCS_PHASE_WRITE_END_CMD: - if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { - set_state(kcs_bmc, READ_STATE); - kcs_bmc->data_in[kcs_bmc->data_in_idx++] = - kcs_bmc_read_data(kcs_bmc); - kcs_bmc->phase = KCS_PHASE_WRITE_DONE; - kcs_bmc->data_in_avail = true; - wake_up_interruptible(&kcs_bmc->queue); - } else { - kcs_force_abort(kcs_bmc); - kcs_bmc->error = KCS_LENGTH_ERROR; - } - break; - - case KCS_PHASE_READ: - if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) - set_state(kcs_bmc, IDLE_STATE); - - data = kcs_bmc_read_data(kcs_bmc); - if (data != KCS_CMD_READ_BYTE) { - set_state(kcs_bmc, ERROR_STATE); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - break; - } - - if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) { - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - kcs_bmc->phase = KCS_PHASE_IDLE; - break; - } - - kcs_bmc_write_data(kcs_bmc, - kcs_bmc->data_out[kcs_bmc->data_out_idx++]); - break; - - case KCS_PHASE_ABORT_ERROR1: - set_state(kcs_bmc, READ_STATE); - kcs_bmc_read_data(kcs_bmc); - kcs_bmc_write_data(kcs_bmc, kcs_bmc->error); - kcs_bmc->phase = KCS_PHASE_ABORT_ERROR2; - break; - - case KCS_PHASE_ABORT_ERROR2: - set_state(kcs_bmc, IDLE_STATE); - kcs_bmc_read_data(kcs_bmc); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - kcs_bmc->phase = KCS_PHASE_IDLE; - break; - - default: - kcs_force_abort(kcs_bmc); - break; - } -} - -static void kcs_bmc_handle_cmd(struct kcs_bmc *kcs_bmc) -{ - u8 cmd; - - set_state(kcs_bmc, WRITE_STATE); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - - cmd = kcs_bmc_read_data(kcs_bmc); - switch (cmd) { - case KCS_CMD_WRITE_START: - kcs_bmc->phase = KCS_PHASE_WRITE_START; - kcs_bmc->error = KCS_NO_ERROR; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; - break; - - case KCS_CMD_WRITE_END: - if (kcs_bmc->phase != KCS_PHASE_WRITE_DATA) { - kcs_force_abort(kcs_bmc); - break; - } - - kcs_bmc->phase = KCS_PHASE_WRITE_END_CMD; - break; - - case KCS_CMD_GET_STATUS_ABORT: - if (kcs_bmc->error == KCS_NO_ERROR) - kcs_bmc->error = KCS_ABORTED_BY_COMMAND; - - kcs_bmc->phase = KCS_PHASE_ABORT_ERROR1; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; - break; - - default: - kcs_force_abort(kcs_bmc); - kcs_bmc->error = KCS_ILLEGAL_CONTROL_CODE; - break; - } -} - +int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc); int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) { - unsigned long flags; - int ret = -ENODATA; - u8 status; - - spin_lock_irqsave(&kcs_bmc->lock, flags); - - status = kcs_bmc_read_status(kcs_bmc); - if (status & KCS_STATUS_IBF) { - if (!kcs_bmc->running) - kcs_force_abort(kcs_bmc); - else if (status & KCS_STATUS_CMD_DAT) - kcs_bmc_handle_cmd(kcs_bmc); - else - kcs_bmc_handle_data(kcs_bmc); - - ret = 0; - } - - spin_unlock_irqrestore(&kcs_bmc->lock, flags); - - return ret; + return kcs_bmc_ipmi_event(kcs_bmc); } EXPORT_SYMBOL(kcs_bmc_handle_event); -static inline struct kcs_bmc *to_kcs_bmc(struct file *filp) -{ - return container_of(filp->private_data, struct kcs_bmc, miscdev); -} - -static int kcs_bmc_open(struct inode *inode, struct file *filp) -{ - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); - int ret = 0; - - spin_lock_irq(&kcs_bmc->lock); - if (!kcs_bmc->running) - kcs_bmc->running = 1; - else - ret = -EBUSY; - spin_unlock_irq(&kcs_bmc->lock); - - return ret; -} - -static __poll_t kcs_bmc_poll(struct file *filp, poll_table *wait) -{ - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); - __poll_t mask = 0; - - poll_wait(filp, &kcs_bmc->queue, wait); - - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->data_in_avail) - mask |= EPOLLIN; - spin_unlock_irq(&kcs_bmc->lock); - - return mask; -} - -static ssize_t kcs_bmc_read(struct file *filp, char __user *buf, - size_t count, loff_t *ppos) -{ - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); - bool data_avail; - size_t data_len; - ssize_t ret; - - if (!(filp->f_flags & O_NONBLOCK)) - wait_event_interruptible(kcs_bmc->queue, - kcs_bmc->data_in_avail); - - mutex_lock(&kcs_bmc->mutex); - - spin_lock_irq(&kcs_bmc->lock); - data_avail = kcs_bmc->data_in_avail; - if (data_avail) { - data_len = kcs_bmc->data_in_idx; - memcpy(kcs_bmc->kbuffer, kcs_bmc->data_in, data_len); - } - spin_unlock_irq(&kcs_bmc->lock); - - if (!data_avail) { - ret = -EAGAIN; - goto out_unlock; - } - - if (count < data_len) { - pr_err("channel=%u with too large data : %zu\n", - kcs_bmc->channel, data_len); - - spin_lock_irq(&kcs_bmc->lock); - kcs_force_abort(kcs_bmc); - spin_unlock_irq(&kcs_bmc->lock); - - ret = -EOVERFLOW; - goto out_unlock; - } - - if (copy_to_user(buf, kcs_bmc->kbuffer, data_len)) { - ret = -EFAULT; - goto out_unlock; - } - - ret = data_len; - - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->phase == KCS_PHASE_WRITE_DONE) { - kcs_bmc->phase = KCS_PHASE_WAIT_READ; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; - } else { - ret = -EAGAIN; - } - spin_unlock_irq(&kcs_bmc->lock); - -out_unlock: - mutex_unlock(&kcs_bmc->mutex); - - return ret; -} - -static ssize_t kcs_bmc_write(struct file *filp, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); - ssize_t ret; - - /* a minimum response size '3' : netfn + cmd + ccode */ - if (count < 3 || count > KCS_MSG_BUFSIZ) - return -EINVAL; - - mutex_lock(&kcs_bmc->mutex); - - if (copy_from_user(kcs_bmc->kbuffer, buf, count)) { - ret = -EFAULT; - goto out_unlock; - } - - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->phase == KCS_PHASE_WAIT_READ) { - kcs_bmc->phase = KCS_PHASE_READ; - kcs_bmc->data_out_idx = 1; - kcs_bmc->data_out_len = count; - memcpy(kcs_bmc->data_out, kcs_bmc->kbuffer, count); - kcs_bmc_write_data(kcs_bmc, kcs_bmc->data_out[0]); - ret = count; - } else { - ret = -EINVAL; - } - spin_unlock_irq(&kcs_bmc->lock); - -out_unlock: - mutex_unlock(&kcs_bmc->mutex); - - return ret; -} - -static long kcs_bmc_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); - long ret = 0; - - spin_lock_irq(&kcs_bmc->lock); - - switch (cmd) { - case IPMI_BMC_IOCTL_SET_SMS_ATN: - kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, KCS_STATUS_SMS_ATN); - break; - - case IPMI_BMC_IOCTL_CLEAR_SMS_ATN: - kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, 0); - break; - - case IPMI_BMC_IOCTL_FORCE_ABORT: - kcs_force_abort(kcs_bmc); - break; - - default: - ret = -EINVAL; - break; - } - - spin_unlock_irq(&kcs_bmc->lock); - - return ret; -} - -static int kcs_bmc_release(struct inode *inode, struct file *filp) -{ - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); - - spin_lock_irq(&kcs_bmc->lock); - kcs_bmc->running = 0; - kcs_force_abort(kcs_bmc); - spin_unlock_irq(&kcs_bmc->lock); - - return 0; -} - -static const struct file_operations kcs_bmc_fops = { - .owner = THIS_MODULE, - .open = kcs_bmc_open, - .read = kcs_bmc_read, - .write = kcs_bmc_write, - .release = kcs_bmc_release, - .poll = kcs_bmc_poll, - .unlocked_ioctl = kcs_bmc_ioctl, -}; - +struct kcs_bmc *kcs_bmc_ipmi_alloc(struct device *dev, int sizeof_priv, u32 channel); struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, u32 channel) { - struct kcs_bmc *kcs_bmc; - - kcs_bmc = devm_kzalloc(dev, sizeof(*kcs_bmc) + sizeof_priv, GFP_KERNEL); - if (!kcs_bmc) - return NULL; - - spin_lock_init(&kcs_bmc->lock); - kcs_bmc->channel = channel; - - mutex_init(&kcs_bmc->mutex); - init_waitqueue_head(&kcs_bmc->queue); - - kcs_bmc->data_in = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - kcs_bmc->data_out = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - kcs_bmc->kbuffer = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - - kcs_bmc->miscdev.minor = MISC_DYNAMIC_MINOR; - kcs_bmc->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%u", - DEVICE_NAME, channel); - if (!kcs_bmc->data_in || !kcs_bmc->data_out || !kcs_bmc->kbuffer || - !kcs_bmc->miscdev.name) - return NULL; - kcs_bmc->miscdev.fops = &kcs_bmc_fops; - - return kcs_bmc; + return kcs_bmc_ipmi_alloc(dev, sizeof_priv, channel); } EXPORT_SYMBOL(kcs_bmc_alloc); diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index 970f53892f2d..febea0c8deb4 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -104,6 +104,12 @@ static inline void *kcs_bmc_priv(struct kcs_bmc *kcs_bmc) } int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); -struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, - u32 channel); +struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, u32 channel); + +u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc); +void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data); +u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc); +void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data); +void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val); + #endif /* __KCS_BMC_H__ */ diff --git a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c new file mode 100644 index 000000000000..82c77994e481 --- /dev/null +++ b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2018, Intel Corporation. + */ + +#define pr_fmt(fmt) "kcs-bmc: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kcs_bmc.h" + +#define DEVICE_NAME "ipmi-kcs" + +#define KCS_MSG_BUFSIZ 1000 + +#define KCS_ZERO_DATA 0 + + +/* IPMI 2.0 - Table 9-1, KCS Interface Status Register Bits */ +#define KCS_STATUS_STATE(state) (state << 6) +#define KCS_STATUS_STATE_MASK GENMASK(7, 6) +#define KCS_STATUS_CMD_DAT BIT(3) +#define KCS_STATUS_SMS_ATN BIT(2) +#define KCS_STATUS_IBF BIT(1) +#define KCS_STATUS_OBF BIT(0) + +/* IPMI 2.0 - Table 9-2, KCS Interface State Bits */ +enum kcs_states { + IDLE_STATE = 0, + READ_STATE = 1, + WRITE_STATE = 2, + ERROR_STATE = 3, +}; + +/* IPMI 2.0 - Table 9-3, KCS Interface Control Codes */ +#define KCS_CMD_GET_STATUS_ABORT 0x60 +#define KCS_CMD_WRITE_START 0x61 +#define KCS_CMD_WRITE_END 0x62 +#define KCS_CMD_READ_BYTE 0x68 + +static inline void set_state(struct kcs_bmc *kcs_bmc, u8 state) +{ + kcs_bmc_update_status(kcs_bmc, KCS_STATUS_STATE_MASK, + KCS_STATUS_STATE(state)); +} + +static void kcs_bmc_ipmi_force_abort(struct kcs_bmc *kcs_bmc) +{ + set_state(kcs_bmc, ERROR_STATE); + kcs_bmc_read_data(kcs_bmc); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + + kcs_bmc->phase = KCS_PHASE_ERROR; + kcs_bmc->data_in_avail = false; + kcs_bmc->data_in_idx = 0; +} + +static void kcs_bmc_ipmi_handle_data(struct kcs_bmc *kcs_bmc) +{ + u8 data; + + switch (kcs_bmc->phase) { + case KCS_PHASE_WRITE_START: + kcs_bmc->phase = KCS_PHASE_WRITE_DATA; + fallthrough; + + case KCS_PHASE_WRITE_DATA: + if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { + set_state(kcs_bmc, WRITE_STATE); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc->data_in[kcs_bmc->data_in_idx++] = + kcs_bmc_read_data(kcs_bmc); + } else { + kcs_bmc_ipmi_force_abort(kcs_bmc); + kcs_bmc->error = KCS_LENGTH_ERROR; + } + break; + + case KCS_PHASE_WRITE_END_CMD: + if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { + set_state(kcs_bmc, READ_STATE); + kcs_bmc->data_in[kcs_bmc->data_in_idx++] = + kcs_bmc_read_data(kcs_bmc); + kcs_bmc->phase = KCS_PHASE_WRITE_DONE; + kcs_bmc->data_in_avail = true; + wake_up_interruptible(&kcs_bmc->queue); + } else { + kcs_bmc_ipmi_force_abort(kcs_bmc); + kcs_bmc->error = KCS_LENGTH_ERROR; + } + break; + + case KCS_PHASE_READ: + if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) + set_state(kcs_bmc, IDLE_STATE); + + data = kcs_bmc_read_data(kcs_bmc); + if (data != KCS_CMD_READ_BYTE) { + set_state(kcs_bmc, ERROR_STATE); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + break; + } + + if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) { + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc->phase = KCS_PHASE_IDLE; + break; + } + + kcs_bmc_write_data(kcs_bmc, + kcs_bmc->data_out[kcs_bmc->data_out_idx++]); + break; + + case KCS_PHASE_ABORT_ERROR1: + set_state(kcs_bmc, READ_STATE); + kcs_bmc_read_data(kcs_bmc); + kcs_bmc_write_data(kcs_bmc, kcs_bmc->error); + kcs_bmc->phase = KCS_PHASE_ABORT_ERROR2; + break; + + case KCS_PHASE_ABORT_ERROR2: + set_state(kcs_bmc, IDLE_STATE); + kcs_bmc_read_data(kcs_bmc); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc->phase = KCS_PHASE_IDLE; + break; + + default: + kcs_bmc_ipmi_force_abort(kcs_bmc); + break; + } +} + +static void kcs_bmc_ipmi_handle_cmd(struct kcs_bmc *kcs_bmc) +{ + u8 cmd; + + set_state(kcs_bmc, WRITE_STATE); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + + cmd = kcs_bmc_read_data(kcs_bmc); + switch (cmd) { + case KCS_CMD_WRITE_START: + kcs_bmc->phase = KCS_PHASE_WRITE_START; + kcs_bmc->error = KCS_NO_ERROR; + kcs_bmc->data_in_avail = false; + kcs_bmc->data_in_idx = 0; + break; + + case KCS_CMD_WRITE_END: + if (kcs_bmc->phase != KCS_PHASE_WRITE_DATA) { + kcs_bmc_ipmi_force_abort(kcs_bmc); + break; + } + + kcs_bmc->phase = KCS_PHASE_WRITE_END_CMD; + break; + + case KCS_CMD_GET_STATUS_ABORT: + if (kcs_bmc->error == KCS_NO_ERROR) + kcs_bmc->error = KCS_ABORTED_BY_COMMAND; + + kcs_bmc->phase = KCS_PHASE_ABORT_ERROR1; + kcs_bmc->data_in_avail = false; + kcs_bmc->data_in_idx = 0; + break; + + default: + kcs_bmc_ipmi_force_abort(kcs_bmc); + kcs_bmc->error = KCS_ILLEGAL_CONTROL_CODE; + break; + } +} + +int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc); +int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc) +{ + unsigned long flags; + int ret = -ENODATA; + u8 status; + + spin_lock_irqsave(&kcs_bmc->lock, flags); + + status = kcs_bmc_read_status(kcs_bmc); + if (status & KCS_STATUS_IBF) { + if (!kcs_bmc->running) + kcs_bmc_ipmi_force_abort(kcs_bmc); + else if (status & KCS_STATUS_CMD_DAT) + kcs_bmc_ipmi_handle_cmd(kcs_bmc); + else + kcs_bmc_ipmi_handle_data(kcs_bmc); + + ret = 0; + } + + spin_unlock_irqrestore(&kcs_bmc->lock, flags); + + return ret; +} +EXPORT_SYMBOL(kcs_bmc_ipmi_event); + +static inline struct kcs_bmc *to_kcs_bmc(struct file *filp) +{ + return container_of(filp->private_data, struct kcs_bmc, miscdev); +} + +static int kcs_bmc_ipmi_open(struct inode *inode, struct file *filp) +{ + struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + int ret = 0; + + spin_lock_irq(&kcs_bmc->lock); + if (!kcs_bmc->running) + kcs_bmc->running = 1; + else + ret = -EBUSY; + spin_unlock_irq(&kcs_bmc->lock); + + return ret; +} + +static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait) +{ + struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + __poll_t mask = 0; + + poll_wait(filp, &kcs_bmc->queue, wait); + + spin_lock_irq(&kcs_bmc->lock); + if (kcs_bmc->data_in_avail) + mask |= EPOLLIN; + spin_unlock_irq(&kcs_bmc->lock); + + return mask; +} + +static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) +{ + struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + bool data_avail; + size_t data_len; + ssize_t ret; + + if (!(filp->f_flags & O_NONBLOCK)) + wait_event_interruptible(kcs_bmc->queue, + kcs_bmc->data_in_avail); + + mutex_lock(&kcs_bmc->mutex); + + spin_lock_irq(&kcs_bmc->lock); + data_avail = kcs_bmc->data_in_avail; + if (data_avail) { + data_len = kcs_bmc->data_in_idx; + memcpy(kcs_bmc->kbuffer, kcs_bmc->data_in, data_len); + } + spin_unlock_irq(&kcs_bmc->lock); + + if (!data_avail) { + ret = -EAGAIN; + goto out_unlock; + } + + if (count < data_len) { + pr_err("channel=%u with too large data : %zu\n", + kcs_bmc->channel, data_len); + + spin_lock_irq(&kcs_bmc->lock); + kcs_bmc_ipmi_force_abort(kcs_bmc); + spin_unlock_irq(&kcs_bmc->lock); + + ret = -EOVERFLOW; + goto out_unlock; + } + + if (copy_to_user(buf, kcs_bmc->kbuffer, data_len)) { + ret = -EFAULT; + goto out_unlock; + } + + ret = data_len; + + spin_lock_irq(&kcs_bmc->lock); + if (kcs_bmc->phase == KCS_PHASE_WRITE_DONE) { + kcs_bmc->phase = KCS_PHASE_WAIT_READ; + kcs_bmc->data_in_avail = false; + kcs_bmc->data_in_idx = 0; + } else { + ret = -EAGAIN; + } + spin_unlock_irq(&kcs_bmc->lock); + +out_unlock: + mutex_unlock(&kcs_bmc->mutex); + + return ret; +} + +static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + ssize_t ret; + + /* a minimum response size '3' : netfn + cmd + ccode */ + if (count < 3 || count > KCS_MSG_BUFSIZ) + return -EINVAL; + + mutex_lock(&kcs_bmc->mutex); + + if (copy_from_user(kcs_bmc->kbuffer, buf, count)) { + ret = -EFAULT; + goto out_unlock; + } + + spin_lock_irq(&kcs_bmc->lock); + if (kcs_bmc->phase == KCS_PHASE_WAIT_READ) { + kcs_bmc->phase = KCS_PHASE_READ; + kcs_bmc->data_out_idx = 1; + kcs_bmc->data_out_len = count; + memcpy(kcs_bmc->data_out, kcs_bmc->kbuffer, count); + kcs_bmc_write_data(kcs_bmc, kcs_bmc->data_out[0]); + ret = count; + } else { + ret = -EINVAL; + } + spin_unlock_irq(&kcs_bmc->lock); + +out_unlock: + mutex_unlock(&kcs_bmc->mutex); + + return ret; +} + +static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + long ret = 0; + + spin_lock_irq(&kcs_bmc->lock); + + switch (cmd) { + case IPMI_BMC_IOCTL_SET_SMS_ATN: + kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, KCS_STATUS_SMS_ATN); + break; + + case IPMI_BMC_IOCTL_CLEAR_SMS_ATN: + kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, 0); + break; + + case IPMI_BMC_IOCTL_FORCE_ABORT: + kcs_bmc_ipmi_force_abort(kcs_bmc); + break; + + default: + ret = -EINVAL; + break; + } + + spin_unlock_irq(&kcs_bmc->lock); + + return ret; +} + +static int kcs_bmc_ipmi_release(struct inode *inode, struct file *filp) +{ + struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + + spin_lock_irq(&kcs_bmc->lock); + kcs_bmc->running = 0; + kcs_bmc_ipmi_force_abort(kcs_bmc); + spin_unlock_irq(&kcs_bmc->lock); + + return 0; +} + +static const struct file_operations kcs_bmc_fops = { + .owner = THIS_MODULE, + .open = kcs_bmc_ipmi_open, + .read = kcs_bmc_ipmi_read, + .write = kcs_bmc_ipmi_write, + .release = kcs_bmc_ipmi_release, + .poll = kcs_bmc_ipmi_poll, + .unlocked_ioctl = kcs_bmc_ipmi_ioctl, +}; + +struct kcs_bmc *kcs_bmc_ipmi_alloc(struct device *dev, int sizeof_priv, u32 channel); +struct kcs_bmc *kcs_bmc_ipmi_alloc(struct device *dev, int sizeof_priv, u32 channel) +{ + struct kcs_bmc *kcs_bmc; + + kcs_bmc = devm_kzalloc(dev, sizeof(*kcs_bmc) + sizeof_priv, GFP_KERNEL); + if (!kcs_bmc) + return NULL; + + spin_lock_init(&kcs_bmc->lock); + kcs_bmc->channel = channel; + + mutex_init(&kcs_bmc->mutex); + init_waitqueue_head(&kcs_bmc->queue); + + kcs_bmc->data_in = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + kcs_bmc->data_out = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + kcs_bmc->kbuffer = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + + kcs_bmc->miscdev.minor = MISC_DYNAMIC_MINOR; + kcs_bmc->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%u", + DEVICE_NAME, channel); + if (!kcs_bmc->data_in || !kcs_bmc->data_out || !kcs_bmc->kbuffer || + !kcs_bmc->miscdev.name) + return NULL; + kcs_bmc->miscdev.fops = &kcs_bmc_fops; + + return kcs_bmc; +} +EXPORT_SYMBOL(kcs_bmc_ipmi_alloc); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Haiyue Wang "); +MODULE_DESCRIPTION("KCS BMC to handle the IPMI request from system software"); From patchwork Mon May 10 05:42:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476078 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=2404:9400:2:0:216:3eff:fee1:b9f1; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=lSqphjYa; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=t9ZaiqQ3; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2404:9400:2:0:216:3eff:fee1:b9f1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fdqmh6NmKz9vFL for ; Mon, 10 May 2021 15:46:28 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4Fdqmh61Swz308j for ; Mon, 10 May 2021 15:46:28 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=lSqphjYa; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=t9ZaiqQ3; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=lSqphjYa; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=t9ZaiqQ3; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4FdqjV4tKVz300T; Mon, 10 May 2021 15:43:42 +1000 (AEST) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.nyi.internal (Postfix) with ESMTP id A6CBE5803EE; Mon, 10 May 2021 01:43:40 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 10 May 2021 01:43:40 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=jq/W0zRfJ6LNz i3X60ygkiAkjMX53KRk+X0yjwKcDto=; b=lSqphjYaj17c/jXPEdSpdM+8RQyYH kYcHW6PhOfus8VzR+se7MB5e0J6gxBXAL16aJFi62jP7YLVDC77Z1GQSZWonuNIM n6qNIB7yXxquWsmHVxfLT5dRuOFivE6pV/x86XmrOKfyO5fl4R0P3W5s1kI44L34 JE61S6gLN+JZ2pG9bRen8acK7THmfqZO2zWi/tbSojeebcqpzfAZlQXIOxz2sj6W RJbWtaBPNwRTfiIpAU8YYE8PUBZWyY2u8sFJ3mv0ZOkDKTBhrja+NRjM9N0P1T+D 4AWfLE0upRSNiUpwh2Jf2qxijr7XxRJsn0RIiWk5yi9REuyw2afohYDQQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=jq/W0zRfJ6LNzi3X60ygkiAkjMX53KRk+X0yjwKcDto=; b=t9ZaiqQ3 VP7FwXIRmnfM7AoMQrCg/LeepTOIuzQI1Fjc/4umpc2kiVtMyTcxnq/qwbOlqs2e Z6umlX6aaFumYUtmJiIZsGtbwWEcQQE7kwYerFau5YYAoN860v5zVOZx2W+hvWwE vvAqvUX4rsCuLWP8e41lcyDDMbuG+RwD/c7cIlwkHZmAtNV3zhWj9IaadinrULLt 4TrSAqo3vGmuws/499j59t60+G6dPsQiAgv5FI0DrmJvS9nJNYj+hAlqeowFesFm EoVNrxqUq43Hamxb6RvDjc82Yia2Xlb2Y+0Z5SlFQUTtej9bRi4/EifVxGIkiDuH lCmCLSaRfr7U2g== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:43:34 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 05/16] ipmi: kcs_bmc: Turn the driver data-structures inside-out Date: Mon, 10 May 2021 15:12:02 +0930 Message-Id: <20210510054213.1610760-6-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Make the KCS device drivers responsible for allocating their own memory. Until now the private data for the device driver was allocated internal to the private data for the chardev interface. This coupling required the slightly awkward API of passing through the struct size for the driver private data to the chardev constructor, and then retrieving a pointer to the driver private data from the allocated chardev memory. In addition to being awkward, the arrangement prevents the implementation of alternative userspace interfaces as the device driver private data is not independent. Peel a layer off the onion and turn the data-structures inside out by exploiting container_of() and embedding `struct kcs_device` in the driver private data. Signed-off-by: Andrew Jeffery Reviewed-by: Zev Weiss --- drivers/char/ipmi/kcs_bmc.c | 19 +++++++-- drivers/char/ipmi/kcs_bmc.h | 12 ++---- drivers/char/ipmi/kcs_bmc_aspeed.c | 56 +++++++++++++------------ drivers/char/ipmi/kcs_bmc_cdev_ipmi.c | 60 ++++++++++++++++++--------- drivers/char/ipmi/kcs_bmc_npcm7xx.c | 37 ++++++++++------- 5 files changed, 111 insertions(+), 73 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index ef5c48ffe74a..83da681bf49e 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -44,12 +44,23 @@ int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) } EXPORT_SYMBOL(kcs_bmc_handle_event); -struct kcs_bmc *kcs_bmc_ipmi_alloc(struct device *dev, int sizeof_priv, u32 channel); -struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, u32 channel) +int kcs_bmc_ipmi_add_device(struct kcs_bmc *kcs_bmc); +void kcs_bmc_add_device(struct kcs_bmc *kcs_bmc) { - return kcs_bmc_ipmi_alloc(dev, sizeof_priv, channel); + if (kcs_bmc_ipmi_add_device(kcs_bmc)) + pr_warn("Failed to add device for KCS channel %d\n", + kcs_bmc->channel); } -EXPORT_SYMBOL(kcs_bmc_alloc); +EXPORT_SYMBOL(kcs_bmc_add_device); + +int kcs_bmc_ipmi_remove_device(struct kcs_bmc *kcs_bmc); +void kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc) +{ + if (kcs_bmc_ipmi_remove_device(kcs_bmc)) + pr_warn("Failed to remove device for KCS channel %d\n", + kcs_bmc->channel); +} +EXPORT_SYMBOL(kcs_bmc_remove_device); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index febea0c8deb4..b2e6b7a7fe62 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -67,6 +67,8 @@ struct kcs_ioreg { }; struct kcs_bmc { + struct device *dev; + spinlock_t lock; u32 channel; @@ -94,17 +96,11 @@ struct kcs_bmc { u8 *kbuffer; struct miscdevice miscdev; - - unsigned long priv[]; }; -static inline void *kcs_bmc_priv(struct kcs_bmc *kcs_bmc) -{ - return kcs_bmc->priv; -} - int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); -struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, u32 channel); +void kcs_bmc_add_device(struct kcs_bmc *kcs_bmc); +void kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc); u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc); void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data); diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 06628ca69750..5d433dea5714 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -61,6 +61,8 @@ #define LPC_STR4 0x11C struct aspeed_kcs_bmc { + struct kcs_bmc kcs_bmc; + struct regmap *map; }; @@ -69,9 +71,14 @@ struct aspeed_kcs_of_ops { int (*get_io_address)(struct platform_device *pdev); }; +static inline struct aspeed_kcs_bmc *to_aspeed_kcs_bmc(struct kcs_bmc *kcs_bmc) +{ + return container_of(kcs_bmc, struct aspeed_kcs_bmc, kcs_bmc); +} + static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) { - struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); u32 val = 0; int rc; @@ -83,7 +90,7 @@ static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) { - struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); int rc; rc = regmap_write(priv->map, reg, data); @@ -92,7 +99,7 @@ static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) static void aspeed_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val) { - struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); int rc; rc = regmap_update_bits(priv->map, reg, mask, val); @@ -114,7 +121,7 @@ static void aspeed_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val */ static void aspeed_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr) { - struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); switch (kcs_bmc->channel) { case 1: @@ -148,7 +155,7 @@ static void aspeed_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr) static void aspeed_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) { - struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); switch (kcs_bmc->channel) { case 1: @@ -323,17 +330,16 @@ static int aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev) static int aspeed_kcs_probe(struct platform_device *pdev) { const struct aspeed_kcs_of_ops *ops; - struct device *dev = &pdev->dev; struct aspeed_kcs_bmc *priv; struct kcs_bmc *kcs_bmc; struct device_node *np; int rc, channel, addr; - np = dev->of_node->parent; + np = pdev->dev.of_node->parent; if (!of_device_is_compatible(np, "aspeed,ast2400-lpc-v2") && !of_device_is_compatible(np, "aspeed,ast2500-lpc-v2") && !of_device_is_compatible(np, "aspeed,ast2600-lpc-v2")) { - dev_err(dev, "unsupported LPC device binding\n"); + dev_err(&pdev->dev, "unsupported LPC device binding\n"); return -ENODEV; } ops = of_device_get_match_data(&pdev->dev); @@ -344,20 +350,22 @@ static int aspeed_kcs_probe(struct platform_device *pdev) if (channel < 0) return channel; - kcs_bmc = kcs_bmc_alloc(&pdev->dev, sizeof(struct aspeed_kcs_bmc), channel); - if (!kcs_bmc) + addr = ops->get_io_address(pdev); + if (addr < 0) + return addr; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; + kcs_bmc = &priv->kcs_bmc; + kcs_bmc->dev = &pdev->dev; + kcs_bmc->channel = channel; kcs_bmc->ioreg = ast_kcs_bmc_ioregs[channel - 1]; kcs_bmc->io_inputb = aspeed_kcs_inb; kcs_bmc->io_outputb = aspeed_kcs_outb; kcs_bmc->io_updateb = aspeed_kcs_updateb; - addr = ops->get_io_address(pdev); - if (addr < 0) - return addr; - - priv = kcs_bmc_priv(kcs_bmc); priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node); if (IS_ERR(priv->map)) { dev_err(&pdev->dev, "Couldn't get regmap\n"); @@ -370,29 +378,23 @@ static int aspeed_kcs_probe(struct platform_device *pdev) if (rc) return rc; - dev_set_drvdata(dev, kcs_bmc); + platform_set_drvdata(pdev, priv); aspeed_kcs_enable_channel(kcs_bmc, true); - rc = misc_register(&kcs_bmc->miscdev); - if (rc) { - dev_err(dev, "Unable to register device\n"); - return rc; - } + kcs_bmc_add_device(&priv->kcs_bmc); - dev_dbg(&pdev->dev, - "Probed KCS device %d (IDR=0x%x, ODR=0x%x, STR=0x%x)\n", - kcs_bmc->channel, kcs_bmc->ioreg.idr, kcs_bmc->ioreg.odr, - kcs_bmc->ioreg.str); + dev_info(&pdev->dev, "Initialised channel %d at 0x%x\n", kcs_bmc->channel, addr); return 0; } static int aspeed_kcs_remove(struct platform_device *pdev) { - struct kcs_bmc *kcs_bmc = dev_get_drvdata(&pdev->dev); + struct aspeed_kcs_bmc *priv = platform_get_drvdata(pdev); + struct kcs_bmc *kcs_bmc = &priv->kcs_bmc; - misc_deregister(&kcs_bmc->miscdev); + kcs_bmc_remove_device(kcs_bmc); return 0; } diff --git a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c index 82c77994e481..5060643bf530 100644 --- a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c +++ b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c @@ -382,7 +382,7 @@ static int kcs_bmc_ipmi_release(struct inode *inode, struct file *filp) return 0; } -static const struct file_operations kcs_bmc_fops = { +static const struct file_operations kcs_bmc_ipmi_fops = { .owner = THIS_MODULE, .open = kcs_bmc_ipmi_open, .read = kcs_bmc_ipmi_read, @@ -392,36 +392,58 @@ static const struct file_operations kcs_bmc_fops = { .unlocked_ioctl = kcs_bmc_ipmi_ioctl, }; -struct kcs_bmc *kcs_bmc_ipmi_alloc(struct device *dev, int sizeof_priv, u32 channel); -struct kcs_bmc *kcs_bmc_ipmi_alloc(struct device *dev, int sizeof_priv, u32 channel) +int kcs_bmc_ipmi_add_device(struct kcs_bmc *kcs_bmc); +int kcs_bmc_ipmi_add_device(struct kcs_bmc *kcs_bmc) { - struct kcs_bmc *kcs_bmc; - - kcs_bmc = devm_kzalloc(dev, sizeof(*kcs_bmc) + sizeof_priv, GFP_KERNEL); - if (!kcs_bmc) - return NULL; + int rc; spin_lock_init(&kcs_bmc->lock); - kcs_bmc->channel = channel; - mutex_init(&kcs_bmc->mutex); init_waitqueue_head(&kcs_bmc->queue); - kcs_bmc->data_in = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - kcs_bmc->data_out = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - kcs_bmc->kbuffer = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + kcs_bmc->data_in = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + kcs_bmc->data_out = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + kcs_bmc->kbuffer = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); kcs_bmc->miscdev.minor = MISC_DYNAMIC_MINOR; - kcs_bmc->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%u", - DEVICE_NAME, channel); + kcs_bmc->miscdev.name = devm_kasprintf(kcs_bmc->dev, GFP_KERNEL, "%s%u", + DEVICE_NAME, kcs_bmc->channel); if (!kcs_bmc->data_in || !kcs_bmc->data_out || !kcs_bmc->kbuffer || !kcs_bmc->miscdev.name) - return NULL; - kcs_bmc->miscdev.fops = &kcs_bmc_fops; + return -ENOMEM; - return kcs_bmc; + kcs_bmc->miscdev.fops = &kcs_bmc_ipmi_fops; + + rc = misc_register(&kcs_bmc->miscdev); + if (rc) { + dev_err(kcs_bmc->dev, "Unable to register device: %d\n", rc); + return rc; + } + + dev_info(kcs_bmc->dev, "Initialised IPMI client for channel %d", kcs_bmc->channel); + + return 0; +} +EXPORT_SYMBOL(kcs_bmc_ipmi_add_device); + +int kcs_bmc_ipmi_remove_device(struct kcs_bmc *kcs_bmc); +int kcs_bmc_ipmi_remove_device(struct kcs_bmc *kcs_bmc) +{ + misc_deregister(&kcs_bmc->miscdev); + + spin_lock_irq(&kcs_bmc->lock); + kcs_bmc->running = 0; + kcs_bmc_ipmi_force_abort(kcs_bmc); + spin_unlock_irq(&kcs_bmc->lock); + + devm_kfree(kcs_bmc->dev, kcs_bmc->kbuffer); + devm_kfree(kcs_bmc->dev, kcs_bmc->data_out); + devm_kfree(kcs_bmc->dev, kcs_bmc->data_in); + devm_kfree(kcs_bmc->dev, kcs_bmc); + + return 0; } -EXPORT_SYMBOL(kcs_bmc_ipmi_alloc); +EXPORT_SYMBOL(kcs_bmc_ipmi_remove_device); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c index 1f44aadec9e8..f7b4e866f86e 100644 --- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c +++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c @@ -65,6 +65,8 @@ struct npcm7xx_kcs_reg { }; struct npcm7xx_kcs_bmc { + struct kcs_bmc kcs_bmc; + struct regmap *map; const struct npcm7xx_kcs_reg *reg; @@ -76,9 +78,14 @@ static const struct npcm7xx_kcs_reg npcm7xx_kcs_reg_tbl[KCS_CHANNEL_MAX] = { { .sts = KCS3ST, .dob = KCS3DO, .dib = KCS3DI, .ctl = KCS3CTL, .ie = KCS3IE }, }; +static inline struct npcm7xx_kcs_bmc *to_npcm7xx_kcs_bmc(struct kcs_bmc *kcs_bmc) +{ + return container_of(kcs_bmc, struct npcm7xx_kcs_bmc, kcs_bmc); +} + static u8 npcm7xx_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) { - struct npcm7xx_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); u32 val = 0; int rc; @@ -90,7 +97,7 @@ static u8 npcm7xx_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) static void npcm7xx_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) { - struct npcm7xx_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); int rc; rc = regmap_write(priv->map, reg, data); @@ -99,7 +106,7 @@ static void npcm7xx_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) static void npcm7xx_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 data) { - struct npcm7xx_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); int rc; rc = regmap_update_bits(priv->map, reg, mask, data); @@ -108,7 +115,7 @@ static void npcm7xx_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 da static void npcm7xx_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) { - struct npcm7xx_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); regmap_update_bits(priv->map, priv->reg->ctl, KCS_CTL_IBFIE, enable ? KCS_CTL_IBFIE : 0); @@ -155,11 +162,10 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) return -ENODEV; } - kcs_bmc = kcs_bmc_alloc(dev, sizeof(*priv), chan); - if (!kcs_bmc) + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; - priv = kcs_bmc_priv(kcs_bmc); priv->map = syscon_node_to_regmap(dev->parent->of_node); if (IS_ERR(priv->map)) { dev_err(dev, "Couldn't get regmap\n"); @@ -167,6 +173,9 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) } priv->reg = &npcm7xx_kcs_reg_tbl[chan - 1]; + kcs_bmc = &priv->kcs_bmc; + kcs_bmc->dev = &pdev->dev; + kcs_bmc->channel = chan; kcs_bmc->ioreg.idr = priv->reg->dib; kcs_bmc->ioreg.odr = priv->reg->dob; kcs_bmc->ioreg.str = priv->reg->sts; @@ -174,31 +183,29 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) kcs_bmc->io_outputb = npcm7xx_kcs_outb; kcs_bmc->io_updateb = npcm7xx_kcs_updateb; - dev_set_drvdata(dev, kcs_bmc); + platform_set_drvdata(pdev, priv); npcm7xx_kcs_enable_channel(kcs_bmc, true); rc = npcm7xx_kcs_config_irq(kcs_bmc, pdev); if (rc) return rc; - rc = misc_register(&kcs_bmc->miscdev); - if (rc) { - dev_err(dev, "Unable to register device\n"); - return rc; - } pr_info("channel=%u idr=0x%x odr=0x%x str=0x%x\n", chan, kcs_bmc->ioreg.idr, kcs_bmc->ioreg.odr, kcs_bmc->ioreg.str); + kcs_bmc_add_device(kcs_bmc); + return 0; } static int npcm7xx_kcs_remove(struct platform_device *pdev) { - struct kcs_bmc *kcs_bmc = dev_get_drvdata(&pdev->dev); + struct npcm7xx_kcs_bmc *priv = platform_get_drvdata(pdev); + struct kcs_bmc *kcs_bmc = &priv->kcs_bmc; - misc_deregister(&kcs_bmc->miscdev); + kcs_bmc_remove_device(kcs_bmc); return 0; } From patchwork Mon May 10 05:42:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476080 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=112.213.38.117; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=BrrA0u6z; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=dFC3IAG+; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FdqnC5VqQz9sXH for ; Mon, 10 May 2021 15:46:55 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4FdqnC59VDz3bsy for ; Mon, 10 May 2021 15:46:55 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=BrrA0u6z; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=dFC3IAG+; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=BrrA0u6z; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=dFC3IAG+; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4Fdqjc1smKz3014; Mon, 10 May 2021 15:43:48 +1000 (AEST) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.nyi.internal (Postfix) with ESMTP id 3E48E5803ED; Mon, 10 May 2021 01:43:46 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 10 May 2021 01:43:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=rt5YVCPcQGKRY AxrqP7h6kBxTmjOLd9w68WfhTQZg8s=; b=BrrA0u6z+U4LalsDakW3V+RFmX3lF 3mkm9BrEaSdsr80Pyney+IaObCeuIbFWZ8gpwnzkFBlNfKp9qJOFPRpRwESDCfnr igVwM5kJHDm2zKorM1TtQcl89asdEH83pJytQTQK4HEvUWmFAwdWcklB2bqA3ZrC FEPlL0N0OgC2VoFKZsUO9fVJK+ZHW2VLZiCLjVCNIU6FfQjNkvwkqDiZS8Fu6Zrv uwORjNR4MrUd2PeOBotIbvgQ76LcgM/Yx5uevkXp1WeWyHDlWCVycqAxuE89Fjp+ J5BEWXKlZBLERL2asYG0YEsYcf53aM8SXlqHlSOdNJsnxyBTS8neXx3KQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=rt5YVCPcQGKRYAxrqP7h6kBxTmjOLd9w68WfhTQZg8s=; b=dFC3IAG+ FDZkeWPxv9oRgnJPm7Fn9ZC7lGQEIEaOrXdJuVLM1TfzvVA8EJmkSe1MsmayQl8O Cc3DPjOum55V1qL+UFS1E58QYJWl3O2TaBR7agLA8LT/GcpwMlve5dpGKkWGKlGu 7ZoPyiSmehuwnwjV7ft9RagCmWI2Ly2lC/ovqrNGdi/8++oZEOlt0su/N1j8RMr0 3vzY/ifX8XwMhzrbCJMA6/1KIRQiR/RZ/mWwyJ+vjyuyfRrFEMSGJbugucKlarAR hz9sCvhUzzO9eG7HN9vKUyL0gLhUJWpYQUDKuhbOJpGABMxbvFkg0qohboKfv/PZ dKS0pm43YLwgnw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:43:40 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 06/16] ipmi: kcs_bmc: Split headers into device and client Date: Mon, 10 May 2021 15:12:03 +0930 Message-Id: <20210510054213.1610760-7-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Strengthen the distinction between code that abstracts the implementation of the KCS behaviours (device drivers) and code that exploits KCS behaviours (clients). Neither needs to know about the APIs required by the other, so provide separate headers. Signed-off-by: Andrew Jeffery --- drivers/char/ipmi/kcs_bmc.c | 23 ++++++++++------ drivers/char/ipmi/kcs_bmc.h | 27 +++++++++---------- drivers/char/ipmi/kcs_bmc_aspeed.c | 17 ++++++------ drivers/char/ipmi/kcs_bmc_cdev_ipmi.c | 39 ++++++++++++++++++--------- drivers/char/ipmi/kcs_bmc_client.h | 30 +++++++++++++++++++++ drivers/char/ipmi/kcs_bmc_device.h | 19 +++++++++++++ drivers/char/ipmi/kcs_bmc_npcm7xx.c | 17 ++++++------ 7 files changed, 120 insertions(+), 52 deletions(-) create mode 100644 drivers/char/ipmi/kcs_bmc_client.h create mode 100644 drivers/char/ipmi/kcs_bmc_device.h diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index 83da681bf49e..d3c11a46bca2 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -1,46 +1,52 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2015-2018, Intel Corporation. + * Copyright (c) 2021, IBM Corp. */ #include #include "kcs_bmc.h" +/* Implement both the device and client interfaces here */ +#include "kcs_bmc_device.h" +#include "kcs_bmc_client.h" + +/* Consumer data access */ + u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc) { - return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr); + return kcs_bmc->ops->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr); } EXPORT_SYMBOL(kcs_bmc_read_data); void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data) { - kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data); + kcs_bmc->ops->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data); } EXPORT_SYMBOL(kcs_bmc_write_data); u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc) { - return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.str); + return kcs_bmc->ops->io_inputb(kcs_bmc, kcs_bmc->ioreg.str); } EXPORT_SYMBOL(kcs_bmc_read_status); void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data) { - kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data); + kcs_bmc->ops->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data); } EXPORT_SYMBOL(kcs_bmc_write_status); void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) { - kcs_bmc->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val); + kcs_bmc->ops->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val); } EXPORT_SYMBOL(kcs_bmc_update_status); -int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc); -int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) +irqreturn_t kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) { - return kcs_bmc_ipmi_event(kcs_bmc); + return kcs_bmc->client.ops->event(&kcs_bmc->client); } EXPORT_SYMBOL(kcs_bmc_handle_event); @@ -64,4 +70,5 @@ EXPORT_SYMBOL(kcs_bmc_remove_device); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); +MODULE_AUTHOR("Andrew Jeffery "); MODULE_DESCRIPTION("KCS BMC to handle the IPMI request from system software"); diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index b2e6b7a7fe62..f42843d240ed 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -8,6 +8,12 @@ #include +#include "kcs_bmc_client.h" + +#define KCS_BMC_STR_OBF BIT(0) +#define KCS_BMC_STR_IBF BIT(1) +#define KCS_BMC_STR_CMD_DAT BIT(3) + /* Different phases of the KCS BMC module. * KCS_PHASE_IDLE: * BMC should not be expecting nor sending any data. @@ -66,19 +72,21 @@ struct kcs_ioreg { u32 str; }; +struct kcs_bmc_device_ops; + struct kcs_bmc { struct device *dev; + const struct kcs_bmc_device_ops *ops; + + struct kcs_bmc_client client; + spinlock_t lock; u32 channel; int running; - /* Setup by BMC KCS controller driver */ struct kcs_ioreg ioreg; - u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg); - void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b); - void (*io_updateb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val); enum kcs_phases phase; enum kcs_errors error; @@ -97,15 +105,4 @@ struct kcs_bmc { struct miscdevice miscdev; }; - -int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); -void kcs_bmc_add_device(struct kcs_bmc *kcs_bmc); -void kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc); - -u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc); -void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data); -u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc); -void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data); -void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val); - #endif /* __KCS_BMC_H__ */ diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 5d433dea5714..337b69cea1da 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -21,7 +21,7 @@ #include #include -#include "kcs_bmc.h" +#include "kcs_bmc_device.h" #define DEVICE_NAME "ast-kcs-bmc" @@ -220,14 +220,17 @@ static void aspeed_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) } } +static const struct kcs_bmc_device_ops aspeed_kcs_ops = { + .io_inputb = aspeed_kcs_inb, + .io_outputb = aspeed_kcs_outb, + .io_updateb = aspeed_kcs_updateb, +}; + static irqreturn_t aspeed_kcs_irq(int irq, void *arg) { struct kcs_bmc *kcs_bmc = arg; - if (!kcs_bmc_handle_event(kcs_bmc)) - return IRQ_HANDLED; - - return IRQ_NONE; + return kcs_bmc_handle_event(kcs_bmc); } static int aspeed_kcs_config_irq(struct kcs_bmc *kcs_bmc, @@ -362,9 +365,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev) kcs_bmc->dev = &pdev->dev; kcs_bmc->channel = channel; kcs_bmc->ioreg = ast_kcs_bmc_ioregs[channel - 1]; - kcs_bmc->io_inputb = aspeed_kcs_inb; - kcs_bmc->io_outputb = aspeed_kcs_outb; - kcs_bmc->io_updateb = aspeed_kcs_updateb; + kcs_bmc->ops = &aspeed_kcs_ops; priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node); if (IS_ERR(priv->map)) { diff --git a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c index 5060643bf530..476ad6d541d5 100644 --- a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c +++ b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c @@ -22,7 +22,6 @@ #define KCS_ZERO_DATA 0 - /* IPMI 2.0 - Table 9-1, KCS Interface Status Register Bits */ #define KCS_STATUS_STATE(state) (state << 6) #define KCS_STATUS_STATE_MASK GENMASK(7, 6) @@ -179,12 +178,19 @@ static void kcs_bmc_ipmi_handle_cmd(struct kcs_bmc *kcs_bmc) } } -int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc); -int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc) +static inline struct kcs_bmc *client_to_kcs_bmc(struct kcs_bmc_client *client) { + return container_of(client, struct kcs_bmc, client); +} + +static irqreturn_t kcs_bmc_ipmi_event(struct kcs_bmc_client *client) +{ + struct kcs_bmc *kcs_bmc; unsigned long flags; - int ret = -ENODATA; u8 status; + int ret; + + kcs_bmc = client_to_kcs_bmc(client); spin_lock_irqsave(&kcs_bmc->lock, flags); @@ -197,23 +203,28 @@ int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc) else kcs_bmc_ipmi_handle_data(kcs_bmc); - ret = 0; + ret = IRQ_HANDLED; + } else { + ret = IRQ_NONE; } spin_unlock_irqrestore(&kcs_bmc->lock, flags); return ret; } -EXPORT_SYMBOL(kcs_bmc_ipmi_event); -static inline struct kcs_bmc *to_kcs_bmc(struct file *filp) +static const struct kcs_bmc_client_ops kcs_bmc_ipmi_client_ops = { + .event = kcs_bmc_ipmi_event, +}; + +static inline struct kcs_bmc *file_to_kcs_bmc(struct file *filp) { return container_of(filp->private_data, struct kcs_bmc, miscdev); } static int kcs_bmc_ipmi_open(struct inode *inode, struct file *filp) { - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); int ret = 0; spin_lock_irq(&kcs_bmc->lock); @@ -228,7 +239,7 @@ static int kcs_bmc_ipmi_open(struct inode *inode, struct file *filp) static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait) { - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); __poll_t mask = 0; poll_wait(filp, &kcs_bmc->queue, wait); @@ -244,7 +255,7 @@ static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait) static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); bool data_avail; size_t data_len; ssize_t ret; @@ -306,7 +317,7 @@ static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf, static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ssize_t ret; /* a minimum response size '3' : netfn + cmd + ccode */ @@ -342,7 +353,7 @@ static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf, static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); long ret = 0; spin_lock_irq(&kcs_bmc->lock); @@ -372,7 +383,7 @@ static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd, static int kcs_bmc_ipmi_release(struct inode *inode, struct file *filp) { - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); spin_lock_irq(&kcs_bmc->lock); kcs_bmc->running = 0; @@ -401,6 +412,8 @@ int kcs_bmc_ipmi_add_device(struct kcs_bmc *kcs_bmc) mutex_init(&kcs_bmc->mutex); init_waitqueue_head(&kcs_bmc->queue); + kcs_bmc->client.dev = kcs_bmc; + kcs_bmc->client.ops = &kcs_bmc_ipmi_client_ops; kcs_bmc->data_in = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); kcs_bmc->data_out = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); kcs_bmc->kbuffer = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); diff --git a/drivers/char/ipmi/kcs_bmc_client.h b/drivers/char/ipmi/kcs_bmc_client.h new file mode 100644 index 000000000000..b19a7ff64b80 --- /dev/null +++ b/drivers/char/ipmi/kcs_bmc_client.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021, IBM Corp. */ + +#ifndef __KCS_BMC_CONSUMER_H__ +#define __KCS_BMC_CONSUMER_H__ + +#include +#include +#include +#include + +struct kcs_bmc; +struct kcs_bmc_client_ops; + +struct kcs_bmc_client { + const struct kcs_bmc_client_ops *ops; + + struct kcs_bmc *dev; +}; + +struct kcs_bmc_client_ops { + irqreturn_t (*event)(struct kcs_bmc_client *client); +}; + +u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc); +void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data); +u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc); +void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data); +void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val); +#endif diff --git a/drivers/char/ipmi/kcs_bmc_device.h b/drivers/char/ipmi/kcs_bmc_device.h new file mode 100644 index 000000000000..14f8d700a3d8 --- /dev/null +++ b/drivers/char/ipmi/kcs_bmc_device.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021, IBM Corp. */ + +#ifndef __KCS_BMC_DEVICE_H__ +#define __KCS_BMC_DEVICE_H__ + +#include "kcs_bmc.h" + +struct kcs_bmc_device_ops { + u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg); + void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b); + void (*io_updateb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 b); +}; + +irqreturn_t kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); +void kcs_bmc_add_device(struct kcs_bmc *kcs_bmc); +void kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc); + +#endif diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c index f7b4e866f86e..203258b24708 100644 --- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c +++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c @@ -17,7 +17,7 @@ #include #include -#include "kcs_bmc.h" +#include "kcs_bmc_device.h" #define DEVICE_NAME "npcm-kcs-bmc" #define KCS_CHANNEL_MAX 3 @@ -128,10 +128,7 @@ static irqreturn_t npcm7xx_kcs_irq(int irq, void *arg) { struct kcs_bmc *kcs_bmc = arg; - if (!kcs_bmc_handle_event(kcs_bmc)) - return IRQ_HANDLED; - - return IRQ_NONE; + return kcs_bmc_handle_event(kcs_bmc); } static int npcm7xx_kcs_config_irq(struct kcs_bmc *kcs_bmc, @@ -148,6 +145,12 @@ static int npcm7xx_kcs_config_irq(struct kcs_bmc *kcs_bmc, dev_name(dev), kcs_bmc); } +static const struct kcs_bmc_device_ops npcm7xx_kcs_ops = { + .io_inputb = npcm7xx_kcs_inb, + .io_outputb = npcm7xx_kcs_outb, + .io_updateb = npcm7xx_kcs_updateb, +}; + static int npcm7xx_kcs_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -179,9 +182,7 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) kcs_bmc->ioreg.idr = priv->reg->dib; kcs_bmc->ioreg.odr = priv->reg->dob; kcs_bmc->ioreg.str = priv->reg->sts; - kcs_bmc->io_inputb = npcm7xx_kcs_inb; - kcs_bmc->io_outputb = npcm7xx_kcs_outb; - kcs_bmc->io_updateb = npcm7xx_kcs_updateb; + kcs_bmc->ops = &npcm7xx_kcs_ops; platform_set_drvdata(pdev, priv); From patchwork Mon May 10 05:42:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476082 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=2404:9400:2:0:216:3eff:fee1:b9f1; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=ml826hA0; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=nOuoQS42; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2404:9400:2:0:216:3eff:fee1:b9f1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fdqp30vmKz9vFY for ; Mon, 10 May 2021 15:47:39 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4Fdqp30SPZz2yys for ; Mon, 10 May 2021 15:47:39 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=ml826hA0; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=nOuoQS42; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=ml826hA0; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=nOuoQS42; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4Fdqjk44J4z306K; Mon, 10 May 2021 15:43:54 +1000 (AEST) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailnew.nyi.internal (Postfix) with ESMTP id 8B3DB5804C8; Mon, 10 May 2021 01:43:52 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Mon, 10 May 2021 01:43:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=Mv+XkRS9PP5hP 3oK9kDXhFUkS4C7zSR8x/YUsonQA5A=; b=ml826hA0pFi4998z5N92w/2wyEfeO PaXUIrY5V0PPxbIGiOqZJN8bxoCUhP5fwbrZd7CK3X3kw0kb7oMLJazsf0PfmD4D UAHXAddCLEy7/4pvWJQotgEZndiOQ08QX66umTPtFs/Qo2usTEuoKs9/FXphu/Si zVLge3MALeZN9Med3Vmrlhw7qsMDyCiSl8eoO0I2RTWaGtg9Pea5ys0P9fUGoTcH WH/036lg6jRarB5mvunyK28xSNNWWNN/ONl2RpGgmH86TSzljQlyb+mYIRZBcKV2 TtzkjAUJlpiFuKyJ51zQWiBwGQTh8MSF1RC4ZYJK/UeueudEENUaWA8sQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=Mv+XkRS9PP5hP3oK9kDXhFUkS4C7zSR8x/YUsonQA5A=; b=nOuoQS42 AWLJu3Yl8LkYV85jgOdFCt4c02Wh9me2M2NkH9+VgvfjKYbGdsvn3WNoip9ByS4S McQ8I4v5xlzpEhU/bx79gso19NsFH2m/oaoUiyyIiseVlg3FttnZPYpQUuorANiR 5iYqcv/rBWfa9Qhpd/rDul4rKQ/GTnxpjQSEOLvni1ci56k1I1fw5F3I86G4fiug m2Dnb97hNwN7D1lb7IHqN8ivPQ4OA+jCMkk9GvT4yPDtoQw1oI0iTIFnOxsPUx0O SG/c1k4wPWqGL62JQE0lXIa0Tel9pdwtkP9Nqm+Gy6ybng6Mzhm1oPY6BpqIHGXY khIl5dbjA9ArRA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:43:46 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 07/16] ipmi: kcs_bmc: Strip private client data from struct kcs_bmc Date: Mon, 10 May 2021 15:12:04 +0930 Message-Id: <20210510054213.1610760-8-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Move all client-private data out of `struct kcs_bmc` into the KCS client implementation. With this change the KCS BMC core code now only concerns itself with abstract `struct kcs_bmc` and `struct kcs_bmc_client` types, achieving expected separation of concerns. Further, the change clears the path for implementation of alternative userspace interfaces. The chardev data-structures are rearranged in the same manner applied to the KCS device driver data-structures in an earlier patch - `struct kcs_bmc_client` is embedded in the client's private data and we exploit container_of() to translate as required. Finally, now that it is free of client data, `struct kcs_bmc` is renamed to `struct kcs_bmc_device` to contrast `struct kcs_bmc_client`. Signed-off-by: Andrew Jeffery Reviewed-by: Zev Weiss --- drivers/char/ipmi/kcs_bmc.c | 70 ++++- drivers/char/ipmi/kcs_bmc.h | 83 +---- drivers/char/ipmi/kcs_bmc_aspeed.c | 22 +- drivers/char/ipmi/kcs_bmc_cdev_ipmi.c | 428 ++++++++++++++++---------- drivers/char/ipmi/kcs_bmc_client.h | 28 +- drivers/char/ipmi/kcs_bmc_device.h | 14 +- drivers/char/ipmi/kcs_bmc_npcm7xx.c | 20 +- 7 files changed, 369 insertions(+), 296 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index d3c11a46bca2..70bfeb72c3c7 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -4,6 +4,7 @@ * Copyright (c) 2021, IBM Corp. */ +#include #include #include "kcs_bmc.h" @@ -14,44 +15,91 @@ /* Consumer data access */ -u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc) +u8 kcs_bmc_read_data(struct kcs_bmc_device *kcs_bmc) { return kcs_bmc->ops->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr); } EXPORT_SYMBOL(kcs_bmc_read_data); -void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data) +void kcs_bmc_write_data(struct kcs_bmc_device *kcs_bmc, u8 data) { kcs_bmc->ops->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data); } EXPORT_SYMBOL(kcs_bmc_write_data); -u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc) +u8 kcs_bmc_read_status(struct kcs_bmc_device *kcs_bmc) { return kcs_bmc->ops->io_inputb(kcs_bmc, kcs_bmc->ioreg.str); } EXPORT_SYMBOL(kcs_bmc_read_status); -void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data) +void kcs_bmc_write_status(struct kcs_bmc_device *kcs_bmc, u8 data) { kcs_bmc->ops->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data); } EXPORT_SYMBOL(kcs_bmc_write_status); -void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) +void kcs_bmc_update_status(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 val) { kcs_bmc->ops->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val); } EXPORT_SYMBOL(kcs_bmc_update_status); -irqreturn_t kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) +irqreturn_t kcs_bmc_handle_event(struct kcs_bmc_device *kcs_bmc) { - return kcs_bmc->client.ops->event(&kcs_bmc->client); + struct kcs_bmc_client *client; + irqreturn_t rc; + + spin_lock(&kcs_bmc->lock); + client = kcs_bmc->client; + if (client) { + rc = client->ops->event(client); + } else { + u8 status; + + status = kcs_bmc_read_status(kcs_bmc); + if (status & KCS_BMC_STR_IBF) { + /* Ack the event by reading the data */ + kcs_bmc_read_data(kcs_bmc); + rc = IRQ_HANDLED; + } else { + rc = IRQ_NONE; + } + } + spin_unlock(&kcs_bmc->lock); + + return rc; } EXPORT_SYMBOL(kcs_bmc_handle_event); -int kcs_bmc_ipmi_add_device(struct kcs_bmc *kcs_bmc); -void kcs_bmc_add_device(struct kcs_bmc *kcs_bmc) +int kcs_bmc_enable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client) +{ + int rc; + + spin_lock_irq(&kcs_bmc->lock); + if (kcs_bmc->client) { + rc = -EBUSY; + } else { + kcs_bmc->client = client; + rc = 0; + } + spin_unlock_irq(&kcs_bmc->lock); + + return rc; +} +EXPORT_SYMBOL(kcs_bmc_enable_device); + +void kcs_bmc_disable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client) +{ + spin_lock_irq(&kcs_bmc->lock); + if (client == kcs_bmc->client) + kcs_bmc->client = NULL; + spin_unlock_irq(&kcs_bmc->lock); +} +EXPORT_SYMBOL(kcs_bmc_disable_device); + +int kcs_bmc_ipmi_add_device(struct kcs_bmc_device *kcs_bmc); +void kcs_bmc_add_device(struct kcs_bmc_device *kcs_bmc) { if (kcs_bmc_ipmi_add_device(kcs_bmc)) pr_warn("Failed to add device for KCS channel %d\n", @@ -59,8 +107,8 @@ void kcs_bmc_add_device(struct kcs_bmc *kcs_bmc) } EXPORT_SYMBOL(kcs_bmc_add_device); -int kcs_bmc_ipmi_remove_device(struct kcs_bmc *kcs_bmc); -void kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc) +int kcs_bmc_ipmi_remove_device(struct kcs_bmc_device *kcs_bmc); +void kcs_bmc_remove_device(struct kcs_bmc_device *kcs_bmc) { if (kcs_bmc_ipmi_remove_device(kcs_bmc)) pr_warn("Failed to remove device for KCS channel %d\n", diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index f42843d240ed..3f0cce315b4f 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -6,61 +6,12 @@ #ifndef __KCS_BMC_H__ #define __KCS_BMC_H__ -#include - -#include "kcs_bmc_client.h" +#include #define KCS_BMC_STR_OBF BIT(0) #define KCS_BMC_STR_IBF BIT(1) #define KCS_BMC_STR_CMD_DAT BIT(3) -/* Different phases of the KCS BMC module. - * KCS_PHASE_IDLE: - * BMC should not be expecting nor sending any data. - * KCS_PHASE_WRITE_START: - * BMC is receiving a WRITE_START command from system software. - * KCS_PHASE_WRITE_DATA: - * BMC is receiving a data byte from system software. - * KCS_PHASE_WRITE_END_CMD: - * BMC is waiting a last data byte from system software. - * KCS_PHASE_WRITE_DONE: - * BMC has received the whole request from system software. - * KCS_PHASE_WAIT_READ: - * BMC is waiting the response from the upper IPMI service. - * KCS_PHASE_READ: - * BMC is transferring the response to system software. - * KCS_PHASE_ABORT_ERROR1: - * BMC is waiting error status request from system software. - * KCS_PHASE_ABORT_ERROR2: - * BMC is waiting for idle status afer error from system software. - * KCS_PHASE_ERROR: - * BMC has detected a protocol violation at the interface level. - */ -enum kcs_phases { - KCS_PHASE_IDLE, - - KCS_PHASE_WRITE_START, - KCS_PHASE_WRITE_DATA, - KCS_PHASE_WRITE_END_CMD, - KCS_PHASE_WRITE_DONE, - - KCS_PHASE_WAIT_READ, - KCS_PHASE_READ, - - KCS_PHASE_ABORT_ERROR1, - KCS_PHASE_ABORT_ERROR2, - KCS_PHASE_ERROR -}; - -/* IPMI 2.0 - Table 9-4, KCS Interface Status Codes */ -enum kcs_errors { - KCS_NO_ERROR = 0x00, - KCS_ABORTED_BY_COMMAND = 0x01, - KCS_ILLEGAL_CONTROL_CODE = 0x02, - KCS_LENGTH_ERROR = 0x06, - KCS_UNSPECIFIED_ERROR = 0xFF -}; - /* IPMI 2.0 - 9.5, KCS Interface Registers * @idr: Input Data Register * @odr: Output Data Register @@ -73,36 +24,20 @@ struct kcs_ioreg { }; struct kcs_bmc_device_ops; +struct kcs_bmc_client; + +struct kcs_bmc_device { + struct list_head entry; -struct kcs_bmc { struct device *dev; - - const struct kcs_bmc_device_ops *ops; - - struct kcs_bmc_client client; - - spinlock_t lock; - u32 channel; - int running; struct kcs_ioreg ioreg; - enum kcs_phases phase; - enum kcs_errors error; + const struct kcs_bmc_device_ops *ops; - wait_queue_head_t queue; - bool data_in_avail; - int data_in_idx; - u8 *data_in; - - int data_out_idx; - int data_out_len; - u8 *data_out; - - struct mutex mutex; - u8 *kbuffer; - - struct miscdevice miscdev; + spinlock_t lock; + struct kcs_bmc_client *client; }; + #endif /* __KCS_BMC_H__ */ diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 337b69cea1da..8e00675d1019 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -61,7 +61,7 @@ #define LPC_STR4 0x11C struct aspeed_kcs_bmc { - struct kcs_bmc kcs_bmc; + struct kcs_bmc_device kcs_bmc; struct regmap *map; }; @@ -71,12 +71,12 @@ struct aspeed_kcs_of_ops { int (*get_io_address)(struct platform_device *pdev); }; -static inline struct aspeed_kcs_bmc *to_aspeed_kcs_bmc(struct kcs_bmc *kcs_bmc) +static inline struct aspeed_kcs_bmc *to_aspeed_kcs_bmc(struct kcs_bmc_device *kcs_bmc) { return container_of(kcs_bmc, struct aspeed_kcs_bmc, kcs_bmc); } -static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) +static u8 aspeed_kcs_inb(struct kcs_bmc_device *kcs_bmc, u32 reg) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); u32 val = 0; @@ -88,7 +88,7 @@ static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) return rc == 0 ? (u8) val : 0; } -static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) +static void aspeed_kcs_outb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 data) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); int rc; @@ -97,7 +97,7 @@ static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) WARN(rc != 0, "regmap_write() failed: %d\n", rc); } -static void aspeed_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val) +static void aspeed_kcs_updateb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, u8 val) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); int rc; @@ -119,7 +119,7 @@ static void aspeed_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val * C. KCS4 * D / C : CA4h / CA5h */ -static void aspeed_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr) +static void aspeed_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u16 addr) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); @@ -153,7 +153,7 @@ static void aspeed_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr) } } -static void aspeed_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) +static void aspeed_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enable) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); @@ -228,12 +228,12 @@ static const struct kcs_bmc_device_ops aspeed_kcs_ops = { static irqreturn_t aspeed_kcs_irq(int irq, void *arg) { - struct kcs_bmc *kcs_bmc = arg; + struct kcs_bmc_device *kcs_bmc = arg; return kcs_bmc_handle_event(kcs_bmc); } -static int aspeed_kcs_config_irq(struct kcs_bmc *kcs_bmc, +static int aspeed_kcs_config_irq(struct kcs_bmc_device *kcs_bmc, struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -333,8 +333,8 @@ static int aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev) static int aspeed_kcs_probe(struct platform_device *pdev) { const struct aspeed_kcs_of_ops *ops; + struct kcs_bmc_device *kcs_bmc; struct aspeed_kcs_bmc *priv; - struct kcs_bmc *kcs_bmc; struct device_node *np; int rc, channel, addr; @@ -393,7 +393,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev) static int aspeed_kcs_remove(struct platform_device *pdev) { struct aspeed_kcs_bmc *priv = platform_get_drvdata(pdev); - struct kcs_bmc *kcs_bmc = &priv->kcs_bmc; + struct kcs_bmc_device *kcs_bmc = &priv->kcs_bmc; kcs_bmc_remove_device(kcs_bmc); diff --git a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c index 476ad6d541d5..865d8b93f3b7 100644 --- a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c +++ b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c @@ -8,13 +8,88 @@ #include #include #include +#include +#include #include +#include #include #include #include #include -#include "kcs_bmc.h" +#include "kcs_bmc_client.h" + +/* Different phases of the KCS BMC module. + * KCS_PHASE_IDLE: + * BMC should not be expecting nor sending any data. + * KCS_PHASE_WRITE_START: + * BMC is receiving a WRITE_START command from system software. + * KCS_PHASE_WRITE_DATA: + * BMC is receiving a data byte from system software. + * KCS_PHASE_WRITE_END_CMD: + * BMC is waiting a last data byte from system software. + * KCS_PHASE_WRITE_DONE: + * BMC has received the whole request from system software. + * KCS_PHASE_WAIT_READ: + * BMC is waiting the response from the upper IPMI service. + * KCS_PHASE_READ: + * BMC is transferring the response to system software. + * KCS_PHASE_ABORT_ERROR1: + * BMC is waiting error status request from system software. + * KCS_PHASE_ABORT_ERROR2: + * BMC is waiting for idle status afer error from system software. + * KCS_PHASE_ERROR: + * BMC has detected a protocol violation at the interface level. + */ +enum kcs_ipmi_phases { + KCS_PHASE_IDLE, + + KCS_PHASE_WRITE_START, + KCS_PHASE_WRITE_DATA, + KCS_PHASE_WRITE_END_CMD, + KCS_PHASE_WRITE_DONE, + + KCS_PHASE_WAIT_READ, + KCS_PHASE_READ, + + KCS_PHASE_ABORT_ERROR1, + KCS_PHASE_ABORT_ERROR2, + KCS_PHASE_ERROR +}; + +/* IPMI 2.0 - Table 9-4, KCS Interface Status Codes */ +enum kcs_ipmi_errors { + KCS_NO_ERROR = 0x00, + KCS_ABORTED_BY_COMMAND = 0x01, + KCS_ILLEGAL_CONTROL_CODE = 0x02, + KCS_LENGTH_ERROR = 0x06, + KCS_UNSPECIFIED_ERROR = 0xFF +}; + +struct kcs_bmc_ipmi { + struct list_head entry; + + struct kcs_bmc_client client; + + spinlock_t lock; + + enum kcs_ipmi_phases phase; + enum kcs_ipmi_errors error; + + wait_queue_head_t queue; + bool data_in_avail; + int data_in_idx; + u8 *data_in; + + int data_out_idx; + int data_out_len; + u8 *data_out; + + struct mutex mutex; + u8 *kbuffer; + + struct miscdevice miscdev; +}; #define DEVICE_NAME "ipmi-kcs" @@ -44,171 +119,169 @@ enum kcs_states { #define KCS_CMD_WRITE_END 0x62 #define KCS_CMD_READ_BYTE 0x68 -static inline void set_state(struct kcs_bmc *kcs_bmc, u8 state) +static inline void set_state(struct kcs_bmc_ipmi *priv, u8 state) { - kcs_bmc_update_status(kcs_bmc, KCS_STATUS_STATE_MASK, - KCS_STATUS_STATE(state)); + kcs_bmc_update_status(priv->client.dev, KCS_STATUS_STATE_MASK, KCS_STATUS_STATE(state)); } -static void kcs_bmc_ipmi_force_abort(struct kcs_bmc *kcs_bmc) +static void kcs_bmc_ipmi_force_abort(struct kcs_bmc_ipmi *priv) { - set_state(kcs_bmc, ERROR_STATE); - kcs_bmc_read_data(kcs_bmc); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + set_state(priv, ERROR_STATE); + kcs_bmc_read_data(priv->client.dev); + kcs_bmc_write_data(priv->client.dev, KCS_ZERO_DATA); - kcs_bmc->phase = KCS_PHASE_ERROR; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; + priv->phase = KCS_PHASE_ERROR; + priv->data_in_avail = false; + priv->data_in_idx = 0; } -static void kcs_bmc_ipmi_handle_data(struct kcs_bmc *kcs_bmc) +static void kcs_bmc_ipmi_handle_data(struct kcs_bmc_ipmi *priv) { + struct kcs_bmc_device *dev; u8 data; - switch (kcs_bmc->phase) { + dev = priv->client.dev; + + switch (priv->phase) { case KCS_PHASE_WRITE_START: - kcs_bmc->phase = KCS_PHASE_WRITE_DATA; + priv->phase = KCS_PHASE_WRITE_DATA; fallthrough; case KCS_PHASE_WRITE_DATA: - if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { - set_state(kcs_bmc, WRITE_STATE); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - kcs_bmc->data_in[kcs_bmc->data_in_idx++] = - kcs_bmc_read_data(kcs_bmc); + if (priv->data_in_idx < KCS_MSG_BUFSIZ) { + set_state(priv, WRITE_STATE); + kcs_bmc_write_data(dev, KCS_ZERO_DATA); + priv->data_in[priv->data_in_idx++] = kcs_bmc_read_data(dev); } else { - kcs_bmc_ipmi_force_abort(kcs_bmc); - kcs_bmc->error = KCS_LENGTH_ERROR; + kcs_bmc_ipmi_force_abort(priv); + priv->error = KCS_LENGTH_ERROR; } break; case KCS_PHASE_WRITE_END_CMD: - if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { - set_state(kcs_bmc, READ_STATE); - kcs_bmc->data_in[kcs_bmc->data_in_idx++] = - kcs_bmc_read_data(kcs_bmc); - kcs_bmc->phase = KCS_PHASE_WRITE_DONE; - kcs_bmc->data_in_avail = true; - wake_up_interruptible(&kcs_bmc->queue); + if (priv->data_in_idx < KCS_MSG_BUFSIZ) { + set_state(priv, READ_STATE); + priv->data_in[priv->data_in_idx++] = kcs_bmc_read_data(dev); + priv->phase = KCS_PHASE_WRITE_DONE; + priv->data_in_avail = true; + wake_up_interruptible(&priv->queue); } else { - kcs_bmc_ipmi_force_abort(kcs_bmc); - kcs_bmc->error = KCS_LENGTH_ERROR; + kcs_bmc_ipmi_force_abort(priv); + priv->error = KCS_LENGTH_ERROR; } break; case KCS_PHASE_READ: - if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) - set_state(kcs_bmc, IDLE_STATE); + if (priv->data_out_idx == priv->data_out_len) + set_state(priv, IDLE_STATE); - data = kcs_bmc_read_data(kcs_bmc); + data = kcs_bmc_read_data(dev); if (data != KCS_CMD_READ_BYTE) { - set_state(kcs_bmc, ERROR_STATE); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + set_state(priv, ERROR_STATE); + kcs_bmc_write_data(dev, KCS_ZERO_DATA); break; } - if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) { - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - kcs_bmc->phase = KCS_PHASE_IDLE; + if (priv->data_out_idx == priv->data_out_len) { + kcs_bmc_write_data(dev, KCS_ZERO_DATA); + priv->phase = KCS_PHASE_IDLE; break; } - kcs_bmc_write_data(kcs_bmc, - kcs_bmc->data_out[kcs_bmc->data_out_idx++]); + kcs_bmc_write_data(dev, priv->data_out[priv->data_out_idx++]); break; case KCS_PHASE_ABORT_ERROR1: - set_state(kcs_bmc, READ_STATE); - kcs_bmc_read_data(kcs_bmc); - kcs_bmc_write_data(kcs_bmc, kcs_bmc->error); - kcs_bmc->phase = KCS_PHASE_ABORT_ERROR2; + set_state(priv, READ_STATE); + kcs_bmc_read_data(dev); + kcs_bmc_write_data(dev, priv->error); + priv->phase = KCS_PHASE_ABORT_ERROR2; break; case KCS_PHASE_ABORT_ERROR2: - set_state(kcs_bmc, IDLE_STATE); - kcs_bmc_read_data(kcs_bmc); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - kcs_bmc->phase = KCS_PHASE_IDLE; + set_state(priv, IDLE_STATE); + kcs_bmc_read_data(dev); + kcs_bmc_write_data(dev, KCS_ZERO_DATA); + priv->phase = KCS_PHASE_IDLE; break; default: - kcs_bmc_ipmi_force_abort(kcs_bmc); + kcs_bmc_ipmi_force_abort(priv); break; } } -static void kcs_bmc_ipmi_handle_cmd(struct kcs_bmc *kcs_bmc) +static void kcs_bmc_ipmi_handle_cmd(struct kcs_bmc_ipmi *priv) { u8 cmd; - set_state(kcs_bmc, WRITE_STATE); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + set_state(priv, WRITE_STATE); + kcs_bmc_write_data(priv->client.dev, KCS_ZERO_DATA); - cmd = kcs_bmc_read_data(kcs_bmc); + cmd = kcs_bmc_read_data(priv->client.dev); switch (cmd) { case KCS_CMD_WRITE_START: - kcs_bmc->phase = KCS_PHASE_WRITE_START; - kcs_bmc->error = KCS_NO_ERROR; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; + priv->phase = KCS_PHASE_WRITE_START; + priv->error = KCS_NO_ERROR; + priv->data_in_avail = false; + priv->data_in_idx = 0; break; case KCS_CMD_WRITE_END: - if (kcs_bmc->phase != KCS_PHASE_WRITE_DATA) { - kcs_bmc_ipmi_force_abort(kcs_bmc); + if (priv->phase != KCS_PHASE_WRITE_DATA) { + kcs_bmc_ipmi_force_abort(priv); break; } - kcs_bmc->phase = KCS_PHASE_WRITE_END_CMD; + priv->phase = KCS_PHASE_WRITE_END_CMD; break; case KCS_CMD_GET_STATUS_ABORT: - if (kcs_bmc->error == KCS_NO_ERROR) - kcs_bmc->error = KCS_ABORTED_BY_COMMAND; + if (priv->error == KCS_NO_ERROR) + priv->error = KCS_ABORTED_BY_COMMAND; - kcs_bmc->phase = KCS_PHASE_ABORT_ERROR1; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; + priv->phase = KCS_PHASE_ABORT_ERROR1; + priv->data_in_avail = false; + priv->data_in_idx = 0; break; default: - kcs_bmc_ipmi_force_abort(kcs_bmc); - kcs_bmc->error = KCS_ILLEGAL_CONTROL_CODE; + kcs_bmc_ipmi_force_abort(priv); + priv->error = KCS_ILLEGAL_CONTROL_CODE; break; } } -static inline struct kcs_bmc *client_to_kcs_bmc(struct kcs_bmc_client *client) +static inline struct kcs_bmc_ipmi *client_to_kcs_bmc_ipmi(struct kcs_bmc_client *client) { - return container_of(client, struct kcs_bmc, client); + return container_of(client, struct kcs_bmc_ipmi, client); } static irqreturn_t kcs_bmc_ipmi_event(struct kcs_bmc_client *client) { - struct kcs_bmc *kcs_bmc; - unsigned long flags; + struct kcs_bmc_ipmi *priv; u8 status; int ret; - kcs_bmc = client_to_kcs_bmc(client); + priv = client_to_kcs_bmc_ipmi(client); + if (!priv) + return IRQ_NONE; - spin_lock_irqsave(&kcs_bmc->lock, flags); + spin_lock(&priv->lock); - status = kcs_bmc_read_status(kcs_bmc); + status = kcs_bmc_read_status(client->dev); if (status & KCS_STATUS_IBF) { - if (!kcs_bmc->running) - kcs_bmc_ipmi_force_abort(kcs_bmc); - else if (status & KCS_STATUS_CMD_DAT) - kcs_bmc_ipmi_handle_cmd(kcs_bmc); + if (status & KCS_STATUS_CMD_DAT) + kcs_bmc_ipmi_handle_cmd(priv); else - kcs_bmc_ipmi_handle_data(kcs_bmc); + kcs_bmc_ipmi_handle_data(priv); ret = IRQ_HANDLED; } else { ret = IRQ_NONE; } - spin_unlock_irqrestore(&kcs_bmc->lock, flags); + spin_unlock(&priv->lock); return ret; } @@ -217,37 +290,29 @@ static const struct kcs_bmc_client_ops kcs_bmc_ipmi_client_ops = { .event = kcs_bmc_ipmi_event, }; -static inline struct kcs_bmc *file_to_kcs_bmc(struct file *filp) +static inline struct kcs_bmc_ipmi *to_kcs_bmc(struct file *filp) { - return container_of(filp->private_data, struct kcs_bmc, miscdev); + return container_of(filp->private_data, struct kcs_bmc_ipmi, miscdev); } static int kcs_bmc_ipmi_open(struct inode *inode, struct file *filp) { - struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); - int ret = 0; + struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp); - spin_lock_irq(&kcs_bmc->lock); - if (!kcs_bmc->running) - kcs_bmc->running = 1; - else - ret = -EBUSY; - spin_unlock_irq(&kcs_bmc->lock); - - return ret; + return kcs_bmc_enable_device(priv->client.dev, &priv->client); } static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait) { - struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); + struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp); __poll_t mask = 0; - poll_wait(filp, &kcs_bmc->queue, wait); + poll_wait(filp, &priv->queue, wait); - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->data_in_avail) + spin_lock_irq(&priv->lock); + if (priv->data_in_avail) mask |= EPOLLIN; - spin_unlock_irq(&kcs_bmc->lock); + spin_unlock_irq(&priv->lock); return mask; } @@ -255,24 +320,24 @@ static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait) static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { - struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); + struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp); bool data_avail; size_t data_len; ssize_t ret; if (!(filp->f_flags & O_NONBLOCK)) - wait_event_interruptible(kcs_bmc->queue, - kcs_bmc->data_in_avail); + wait_event_interruptible(priv->queue, + priv->data_in_avail); - mutex_lock(&kcs_bmc->mutex); + mutex_lock(&priv->mutex); - spin_lock_irq(&kcs_bmc->lock); - data_avail = kcs_bmc->data_in_avail; + spin_lock_irq(&priv->lock); + data_avail = priv->data_in_avail; if (data_avail) { - data_len = kcs_bmc->data_in_idx; - memcpy(kcs_bmc->kbuffer, kcs_bmc->data_in, data_len); + data_len = priv->data_in_idx; + memcpy(priv->kbuffer, priv->data_in, data_len); } - spin_unlock_irq(&kcs_bmc->lock); + spin_unlock_irq(&priv->lock); if (!data_avail) { ret = -EAGAIN; @@ -281,35 +346,35 @@ static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf, if (count < data_len) { pr_err("channel=%u with too large data : %zu\n", - kcs_bmc->channel, data_len); + priv->client.dev->channel, data_len); - spin_lock_irq(&kcs_bmc->lock); - kcs_bmc_ipmi_force_abort(kcs_bmc); - spin_unlock_irq(&kcs_bmc->lock); + spin_lock_irq(&priv->lock); + kcs_bmc_ipmi_force_abort(priv); + spin_unlock_irq(&priv->lock); ret = -EOVERFLOW; goto out_unlock; } - if (copy_to_user(buf, kcs_bmc->kbuffer, data_len)) { + if (copy_to_user(buf, priv->kbuffer, data_len)) { ret = -EFAULT; goto out_unlock; } ret = data_len; - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->phase == KCS_PHASE_WRITE_DONE) { - kcs_bmc->phase = KCS_PHASE_WAIT_READ; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; + spin_lock_irq(&priv->lock); + if (priv->phase == KCS_PHASE_WRITE_DONE) { + priv->phase = KCS_PHASE_WAIT_READ; + priv->data_in_avail = false; + priv->data_in_idx = 0; } else { ret = -EAGAIN; } - spin_unlock_irq(&kcs_bmc->lock); + spin_unlock_irq(&priv->lock); out_unlock: - mutex_unlock(&kcs_bmc->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -317,35 +382,35 @@ static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf, static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { - struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); + struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp); ssize_t ret; /* a minimum response size '3' : netfn + cmd + ccode */ if (count < 3 || count > KCS_MSG_BUFSIZ) return -EINVAL; - mutex_lock(&kcs_bmc->mutex); + mutex_lock(&priv->mutex); - if (copy_from_user(kcs_bmc->kbuffer, buf, count)) { + if (copy_from_user(priv->kbuffer, buf, count)) { ret = -EFAULT; goto out_unlock; } - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->phase == KCS_PHASE_WAIT_READ) { - kcs_bmc->phase = KCS_PHASE_READ; - kcs_bmc->data_out_idx = 1; - kcs_bmc->data_out_len = count; - memcpy(kcs_bmc->data_out, kcs_bmc->kbuffer, count); - kcs_bmc_write_data(kcs_bmc, kcs_bmc->data_out[0]); + spin_lock_irq(&priv->lock); + if (priv->phase == KCS_PHASE_WAIT_READ) { + priv->phase = KCS_PHASE_READ; + priv->data_out_idx = 1; + priv->data_out_len = count; + memcpy(priv->data_out, priv->kbuffer, count); + kcs_bmc_write_data(priv->client.dev, priv->data_out[0]); ret = count; } else { ret = -EINVAL; } - spin_unlock_irq(&kcs_bmc->lock); + spin_unlock_irq(&priv->lock); out_unlock: - mutex_unlock(&kcs_bmc->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -353,22 +418,22 @@ static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf, static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); + struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp); long ret = 0; - spin_lock_irq(&kcs_bmc->lock); + spin_lock_irq(&priv->lock); switch (cmd) { case IPMI_BMC_IOCTL_SET_SMS_ATN: - kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, KCS_STATUS_SMS_ATN); + kcs_bmc_update_status(priv->client.dev, KCS_STATUS_SMS_ATN, KCS_STATUS_SMS_ATN); break; case IPMI_BMC_IOCTL_CLEAR_SMS_ATN: - kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, 0); + kcs_bmc_update_status(priv->client.dev, KCS_STATUS_SMS_ATN, 0); break; case IPMI_BMC_IOCTL_FORCE_ABORT: - kcs_bmc_ipmi_force_abort(kcs_bmc); + kcs_bmc_ipmi_force_abort(priv); break; default: @@ -376,19 +441,17 @@ static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd, break; } - spin_unlock_irq(&kcs_bmc->lock); + spin_unlock_irq(&priv->lock); return ret; } static int kcs_bmc_ipmi_release(struct inode *inode, struct file *filp) { - struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); + struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp); - spin_lock_irq(&kcs_bmc->lock); - kcs_bmc->running = 0; - kcs_bmc_ipmi_force_abort(kcs_bmc); - spin_unlock_irq(&kcs_bmc->lock); + kcs_bmc_ipmi_force_abort(priv); + kcs_bmc_disable_device(priv->client.dev, &priv->client); return 0; } @@ -403,56 +466,78 @@ static const struct file_operations kcs_bmc_ipmi_fops = { .unlocked_ioctl = kcs_bmc_ipmi_ioctl, }; -int kcs_bmc_ipmi_add_device(struct kcs_bmc *kcs_bmc); -int kcs_bmc_ipmi_add_device(struct kcs_bmc *kcs_bmc) +static DEFINE_SPINLOCK(kcs_bmc_ipmi_instances_lock); +static LIST_HEAD(kcs_bmc_ipmi_instances); + +int kcs_bmc_ipmi_add_device(struct kcs_bmc_device *kcs_bmc); +int kcs_bmc_ipmi_add_device(struct kcs_bmc_device *kcs_bmc) { + struct kcs_bmc_ipmi *priv; int rc; - spin_lock_init(&kcs_bmc->lock); - mutex_init(&kcs_bmc->mutex); - init_waitqueue_head(&kcs_bmc->queue); - - kcs_bmc->client.dev = kcs_bmc; - kcs_bmc->client.ops = &kcs_bmc_ipmi_client_ops; - kcs_bmc->data_in = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - kcs_bmc->data_out = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - kcs_bmc->kbuffer = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - - kcs_bmc->miscdev.minor = MISC_DYNAMIC_MINOR; - kcs_bmc->miscdev.name = devm_kasprintf(kcs_bmc->dev, GFP_KERNEL, "%s%u", - DEVICE_NAME, kcs_bmc->channel); - if (!kcs_bmc->data_in || !kcs_bmc->data_out || !kcs_bmc->kbuffer || - !kcs_bmc->miscdev.name) + priv = devm_kzalloc(kcs_bmc->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; - kcs_bmc->miscdev.fops = &kcs_bmc_ipmi_fops; + spin_lock_init(&priv->lock); + mutex_init(&priv->mutex); - rc = misc_register(&kcs_bmc->miscdev); + init_waitqueue_head(&priv->queue); + + priv->client.dev = kcs_bmc; + priv->client.ops = &kcs_bmc_ipmi_client_ops; + priv->data_in = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + priv->data_out = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + priv->kbuffer = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + + priv->miscdev.minor = MISC_DYNAMIC_MINOR; + priv->miscdev.name = devm_kasprintf(kcs_bmc->dev, GFP_KERNEL, "%s%u", DEVICE_NAME, + kcs_bmc->channel); + if (!priv->data_in || !priv->data_out || !priv->kbuffer || !priv->miscdev.name) + return -EINVAL; + + priv->miscdev.fops = &kcs_bmc_ipmi_fops; + + rc = misc_register(&priv->miscdev); if (rc) { dev_err(kcs_bmc->dev, "Unable to register device: %d\n", rc); return rc; } + spin_lock_irq(&kcs_bmc_ipmi_instances_lock); + list_add(&priv->entry, &kcs_bmc_ipmi_instances); + spin_unlock_irq(&kcs_bmc_ipmi_instances_lock); + dev_info(kcs_bmc->dev, "Initialised IPMI client for channel %d", kcs_bmc->channel); return 0; } EXPORT_SYMBOL(kcs_bmc_ipmi_add_device); -int kcs_bmc_ipmi_remove_device(struct kcs_bmc *kcs_bmc); -int kcs_bmc_ipmi_remove_device(struct kcs_bmc *kcs_bmc) +int kcs_bmc_ipmi_remove_device(struct kcs_bmc_device *kcs_bmc); +int kcs_bmc_ipmi_remove_device(struct kcs_bmc_device *kcs_bmc) { - misc_deregister(&kcs_bmc->miscdev); + struct kcs_bmc_ipmi *priv = NULL, *pos; - spin_lock_irq(&kcs_bmc->lock); - kcs_bmc->running = 0; - kcs_bmc_ipmi_force_abort(kcs_bmc); - spin_unlock_irq(&kcs_bmc->lock); + spin_lock_irq(&kcs_bmc_ipmi_instances_lock); + list_for_each_entry(pos, &kcs_bmc_ipmi_instances, entry) { + if (pos->client.dev == kcs_bmc) { + priv = pos; + list_del(&pos->entry); + break; + } + } + spin_unlock_irq(&kcs_bmc_ipmi_instances_lock); - devm_kfree(kcs_bmc->dev, kcs_bmc->kbuffer); - devm_kfree(kcs_bmc->dev, kcs_bmc->data_out); - devm_kfree(kcs_bmc->dev, kcs_bmc->data_in); - devm_kfree(kcs_bmc->dev, kcs_bmc); + if (!priv) + return -ENODEV; + + misc_deregister(&priv->miscdev); + kcs_bmc_disable_device(priv->client.dev, &priv->client); + devm_kfree(kcs_bmc->dev, priv->kbuffer); + devm_kfree(kcs_bmc->dev, priv->data_out); + devm_kfree(kcs_bmc->dev, priv->data_in); + devm_kfree(kcs_bmc->dev, priv); return 0; } @@ -460,4 +545,5 @@ EXPORT_SYMBOL(kcs_bmc_ipmi_remove_device); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); +MODULE_AUTHOR("Andrew Jeffery "); MODULE_DESCRIPTION("KCS BMC to handle the IPMI request from system software"); diff --git a/drivers/char/ipmi/kcs_bmc_client.h b/drivers/char/ipmi/kcs_bmc_client.h index b19a7ff64b80..c0f85c5bdf5c 100644 --- a/drivers/char/ipmi/kcs_bmc_client.h +++ b/drivers/char/ipmi/kcs_bmc_client.h @@ -9,22 +9,24 @@ #include #include -struct kcs_bmc; -struct kcs_bmc_client_ops; - -struct kcs_bmc_client { - const struct kcs_bmc_client_ops *ops; - - struct kcs_bmc *dev; -}; +#include "kcs_bmc.h" struct kcs_bmc_client_ops { irqreturn_t (*event)(struct kcs_bmc_client *client); }; -u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc); -void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data); -u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc); -void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data); -void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val); +struct kcs_bmc_client { + const struct kcs_bmc_client_ops *ops; + + struct kcs_bmc_device *dev; +}; + +int kcs_bmc_enable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client); +void kcs_bmc_disable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client); + +u8 kcs_bmc_read_data(struct kcs_bmc_device *kcs_bmc); +void kcs_bmc_write_data(struct kcs_bmc_device *kcs_bmc, u8 data); +u8 kcs_bmc_read_status(struct kcs_bmc_device *kcs_bmc); +void kcs_bmc_write_status(struct kcs_bmc_device *kcs_bmc, u8 data); +void kcs_bmc_update_status(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 val); #endif diff --git a/drivers/char/ipmi/kcs_bmc_device.h b/drivers/char/ipmi/kcs_bmc_device.h index 14f8d700a3d8..dd90f8c2ebd6 100644 --- a/drivers/char/ipmi/kcs_bmc_device.h +++ b/drivers/char/ipmi/kcs_bmc_device.h @@ -4,16 +4,18 @@ #ifndef __KCS_BMC_DEVICE_H__ #define __KCS_BMC_DEVICE_H__ +#include + #include "kcs_bmc.h" struct kcs_bmc_device_ops { - u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg); - void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b); - void (*io_updateb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 b); + u8 (*io_inputb)(struct kcs_bmc_device *kcs_bmc, u32 reg); + void (*io_outputb)(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 b); + void (*io_updateb)(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, u8 b); }; -irqreturn_t kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); -void kcs_bmc_add_device(struct kcs_bmc *kcs_bmc); -void kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc); +irqreturn_t kcs_bmc_handle_event(struct kcs_bmc_device *kcs_bmc); +void kcs_bmc_add_device(struct kcs_bmc_device *kcs_bmc); +void kcs_bmc_remove_device(struct kcs_bmc_device *kcs_bmc); #endif diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c index 203258b24708..9f0b168e487c 100644 --- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c +++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c @@ -65,7 +65,7 @@ struct npcm7xx_kcs_reg { }; struct npcm7xx_kcs_bmc { - struct kcs_bmc kcs_bmc; + struct kcs_bmc_device kcs_bmc; struct regmap *map; @@ -78,12 +78,12 @@ static const struct npcm7xx_kcs_reg npcm7xx_kcs_reg_tbl[KCS_CHANNEL_MAX] = { { .sts = KCS3ST, .dob = KCS3DO, .dib = KCS3DI, .ctl = KCS3CTL, .ie = KCS3IE }, }; -static inline struct npcm7xx_kcs_bmc *to_npcm7xx_kcs_bmc(struct kcs_bmc *kcs_bmc) +static inline struct npcm7xx_kcs_bmc *to_npcm7xx_kcs_bmc(struct kcs_bmc_device *kcs_bmc) { return container_of(kcs_bmc, struct npcm7xx_kcs_bmc, kcs_bmc); } -static u8 npcm7xx_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) +static u8 npcm7xx_kcs_inb(struct kcs_bmc_device *kcs_bmc, u32 reg) { struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); u32 val = 0; @@ -95,7 +95,7 @@ static u8 npcm7xx_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) return rc == 0 ? (u8)val : 0; } -static void npcm7xx_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) +static void npcm7xx_kcs_outb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 data) { struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); int rc; @@ -104,7 +104,7 @@ static void npcm7xx_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) WARN(rc != 0, "regmap_write() failed: %d\n", rc); } -static void npcm7xx_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 data) +static void npcm7xx_kcs_updateb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, u8 data) { struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); int rc; @@ -113,7 +113,7 @@ static void npcm7xx_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 da WARN(rc != 0, "regmap_update_bits() failed: %d\n", rc); } -static void npcm7xx_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) +static void npcm7xx_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enable) { struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); @@ -126,12 +126,12 @@ static void npcm7xx_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) static irqreturn_t npcm7xx_kcs_irq(int irq, void *arg) { - struct kcs_bmc *kcs_bmc = arg; + struct kcs_bmc_device *kcs_bmc = arg; return kcs_bmc_handle_event(kcs_bmc); } -static int npcm7xx_kcs_config_irq(struct kcs_bmc *kcs_bmc, +static int npcm7xx_kcs_config_irq(struct kcs_bmc_device *kcs_bmc, struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -155,7 +155,7 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct npcm7xx_kcs_bmc *priv; - struct kcs_bmc *kcs_bmc; + struct kcs_bmc_device *kcs_bmc; u32 chan; int rc; @@ -204,7 +204,7 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) static int npcm7xx_kcs_remove(struct platform_device *pdev) { struct npcm7xx_kcs_bmc *priv = platform_get_drvdata(pdev); - struct kcs_bmc *kcs_bmc = &priv->kcs_bmc; + struct kcs_bmc_device *kcs_bmc = &priv->kcs_bmc; kcs_bmc_remove_device(kcs_bmc); From patchwork Mon May 10 05:42:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476085 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=112.213.38.117; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=jAAXUp5D; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=FtCxL4lY; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fdqpx2V2Mz9vFs for ; Mon, 10 May 2021 15:48:25 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4Fdqpx2JmBz2yx3 for ; Mon, 10 May 2021 15:48:25 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=jAAXUp5D; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=FtCxL4lY; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=jAAXUp5D; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=FtCxL4lY; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4Fdqjr3Ww3z307W; Mon, 10 May 2021 15:44:00 +1000 (AEST) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.nyi.internal (Postfix) with ESMTP id 79C3C5803ED; Mon, 10 May 2021 01:43:58 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 10 May 2021 01:43:58 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=InrPZqVE3HCO6 TAKccZenE663hE0xm5RBvgu+bsgDEw=; b=jAAXUp5Dqa76i0rGRavmtAD2Xc11D w1STNY/sDZZ/PJ6n74q9ZZ+liaRr8Mb8ohwinZw1EwlKbdenL6G7/YkFv/oJaoh5 sCEtI2KFlPGtTIykmhvMuFdndL4Xa18LC6X3ua5SPeCcRX3ZqmmMV3AGwbR6lkvm PnKDfv8TczzGn4eWlRlaQJQryANRMDjZpfQLWDJhS+wkSXfp1k25r7L/MXQI+/4T qUHOnrUEa1lOh8dKjkm1EUhjivjuAHEI+EIikwnGNtWb+2i1nK2r/s+hWXB8x7Fg P0wFugR42AJXgOnlXWYXivamXwINIDGaIpyn9QRXU8/leZDDW1/9mlFHQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=InrPZqVE3HCO6TAKccZenE663hE0xm5RBvgu+bsgDEw=; b=FtCxL4lY b25dXUeBpdn0iRs28Q2YKDEBDSu6ZAnbuC0xJVO3NoU+GoV8x9i28tdS+l4Ei3t8 PLQeOZHAfHjWsUiweK3zaKp/mIX4SpCWzN/2+4x36S4TIwBXTWi8RjtBRVQpbyPY b4M9F0xGUOFEqXblUbCe5M9iRM2TQW6GM4hPrO4cDxjPRVcxfjNMwuBdNbVuz37w lEN2ar0S5GECdRX9+++wflz0+ocbIfBDnEgzrCeT1rF6aLZ73SXjg4eYh5obASTc DX9qrSU9d//PGtzqW26KfU9cx3fsy09hvxFTExJJVYF3+sjhg5DrN76TjFYwLEwj pBfaNKLaArclng== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:43:52 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 08/16] ipmi: kcs_bmc: Decouple the IPMI chardev from the core Date: Mon, 10 May 2021 15:12:05 +0930 Message-Id: <20210510054213.1610760-9-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Now that we have untangled the data-structures, split the userspace interface out into its own module. Userspace interfaces and drivers are registered to the KCS BMC core to support arbitrary binding of either. Signed-off-by: Andrew Jeffery --- drivers/char/ipmi/Kconfig | 13 +++++ drivers/char/ipmi/Makefile | 3 +- drivers/char/ipmi/kcs_bmc.c | 76 ++++++++++++++++++++++++--- drivers/char/ipmi/kcs_bmc_cdev_ipmi.c | 31 ++++++++--- drivers/char/ipmi/kcs_bmc_client.h | 14 +++++ 5 files changed, 122 insertions(+), 15 deletions(-) diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig index 07847d9a459a..bc5f81899b62 100644 --- a/drivers/char/ipmi/Kconfig +++ b/drivers/char/ipmi/Kconfig @@ -124,6 +124,19 @@ config NPCM7XX_KCS_IPMI_BMC This support is also available as a module. If so, the module will be called kcs_bmc_npcm7xx. +config IPMI_KCS_BMC_CDEV_IPMI + depends on IPMI_KCS_BMC + tristate "IPMI character device interface for BMC KCS devices" + help + Provides a BMC-side character device implementing IPMI + semantics for KCS IPMI devices. + + Say YES if you wish to expose KCS devices on the BMC for IPMI + purposes. + + This support is also available as a module. The module will be + called kcs_bmc_cdev_ipmi. + config ASPEED_BT_IPMI_BMC depends on ARCH_ASPEED || COMPILE_TEST depends on REGMAP && REGMAP_MMIO && MFD_SYSCON diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile index a302bc865370..fcfa676afddb 100644 --- a/drivers/char/ipmi/Makefile +++ b/drivers/char/ipmi/Makefile @@ -22,7 +22,8 @@ obj-$(CONFIG_IPMI_SSIF) += ipmi_ssif.o obj-$(CONFIG_IPMI_POWERNV) += ipmi_powernv.o obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o -obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o kcs_bmc_cdev_ipmi.o +obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o +obj-$(CONFIG_IPMI_KCS_BMC_CDEV_IPMI) += kcs_bmc_cdev_ipmi.o obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index 70bfeb72c3c7..2ec8312ce766 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -5,7 +5,9 @@ */ #include +#include #include +#include #include "kcs_bmc.h" @@ -13,6 +15,11 @@ #include "kcs_bmc_device.h" #include "kcs_bmc_client.h" +/* Record registered devices and drivers */ +static DEFINE_MUTEX(kcs_bmc_lock); +static LIST_HEAD(kcs_bmc_devices); +static LIST_HEAD(kcs_bmc_drivers); + /* Consumer data access */ u8 kcs_bmc_read_data(struct kcs_bmc_device *kcs_bmc) @@ -98,24 +105,77 @@ void kcs_bmc_disable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_clien } EXPORT_SYMBOL(kcs_bmc_disable_device); -int kcs_bmc_ipmi_add_device(struct kcs_bmc_device *kcs_bmc); void kcs_bmc_add_device(struct kcs_bmc_device *kcs_bmc) { - if (kcs_bmc_ipmi_add_device(kcs_bmc)) - pr_warn("Failed to add device for KCS channel %d\n", - kcs_bmc->channel); + struct kcs_bmc_driver *drv; + int rc; + + spin_lock_init(&kcs_bmc->lock); + kcs_bmc->client = NULL; + + mutex_lock(&kcs_bmc_lock); + list_add(&kcs_bmc->entry, &kcs_bmc_devices); + list_for_each_entry(drv, &kcs_bmc_drivers, entry) { + rc = drv->ops->add_device(kcs_bmc); + if (rc) + dev_err(kcs_bmc->dev, "Failed to add chardev for KCS channel %d: %d", + kcs_bmc->channel, rc); + } + mutex_unlock(&kcs_bmc_lock); } EXPORT_SYMBOL(kcs_bmc_add_device); -int kcs_bmc_ipmi_remove_device(struct kcs_bmc_device *kcs_bmc); void kcs_bmc_remove_device(struct kcs_bmc_device *kcs_bmc) { - if (kcs_bmc_ipmi_remove_device(kcs_bmc)) - pr_warn("Failed to remove device for KCS channel %d\n", - kcs_bmc->channel); + struct kcs_bmc_driver *drv; + int rc; + + mutex_lock(&kcs_bmc_lock); + list_del(&kcs_bmc->entry); + list_for_each_entry(drv, &kcs_bmc_drivers, entry) { + rc = drv->ops->remove_device(kcs_bmc); + if (rc) + dev_err(kcs_bmc->dev, "Failed to remove chardev for KCS channel %d: %d", + kcs_bmc->channel, rc); + } + mutex_unlock(&kcs_bmc_lock); } EXPORT_SYMBOL(kcs_bmc_remove_device); +void kcs_bmc_register_driver(struct kcs_bmc_driver *drv) +{ + struct kcs_bmc_device *kcs_bmc; + int rc; + + mutex_lock(&kcs_bmc_lock); + list_add(&drv->entry, &kcs_bmc_drivers); + list_for_each_entry(kcs_bmc, &kcs_bmc_devices, entry) { + rc = drv->ops->add_device(kcs_bmc); + if (rc) + dev_err(kcs_bmc->dev, "Failed to add chardev for KCS channel %d: %d", + kcs_bmc->channel, rc); + } + mutex_unlock(&kcs_bmc_lock); +} +EXPORT_SYMBOL(kcs_bmc_register_driver); + +void kcs_bmc_unregister_driver(struct kcs_bmc_driver *drv) +{ + struct kcs_bmc_device *kcs_bmc; + int rc; + + mutex_lock(&kcs_bmc_lock); + list_del(&drv->entry); + list_for_each_entry(kcs_bmc, &kcs_bmc_devices, entry) { + rc = drv->ops->remove_device(kcs_bmc); + if (rc) + dev_err(kcs_bmc->dev, "Failed to add chardev for KCS channel %d: %d", + kcs_bmc->channel, rc); + } + mutex_unlock(&kcs_bmc_lock); +} +EXPORT_SYMBOL(kcs_bmc_unregister_driver); + MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); MODULE_AUTHOR("Andrew Jeffery "); diff --git a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c index 865d8b93f3b7..486834a962c3 100644 --- a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c +++ b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c @@ -469,8 +469,7 @@ static const struct file_operations kcs_bmc_ipmi_fops = { static DEFINE_SPINLOCK(kcs_bmc_ipmi_instances_lock); static LIST_HEAD(kcs_bmc_ipmi_instances); -int kcs_bmc_ipmi_add_device(struct kcs_bmc_device *kcs_bmc); -int kcs_bmc_ipmi_add_device(struct kcs_bmc_device *kcs_bmc) +static int kcs_bmc_ipmi_add_device(struct kcs_bmc_device *kcs_bmc) { struct kcs_bmc_ipmi *priv; int rc; @@ -512,10 +511,8 @@ int kcs_bmc_ipmi_add_device(struct kcs_bmc_device *kcs_bmc) return 0; } -EXPORT_SYMBOL(kcs_bmc_ipmi_add_device); -int kcs_bmc_ipmi_remove_device(struct kcs_bmc_device *kcs_bmc); -int kcs_bmc_ipmi_remove_device(struct kcs_bmc_device *kcs_bmc) +static int kcs_bmc_ipmi_remove_device(struct kcs_bmc_device *kcs_bmc) { struct kcs_bmc_ipmi *priv = NULL, *pos; @@ -541,7 +538,29 @@ int kcs_bmc_ipmi_remove_device(struct kcs_bmc_device *kcs_bmc) return 0; } -EXPORT_SYMBOL(kcs_bmc_ipmi_remove_device); + +static const struct kcs_bmc_driver_ops kcs_bmc_ipmi_driver_ops = { + .add_device = kcs_bmc_ipmi_add_device, + .remove_device = kcs_bmc_ipmi_remove_device, +}; + +static struct kcs_bmc_driver kcs_bmc_ipmi_driver = { + .ops = &kcs_bmc_ipmi_driver_ops, +}; + +static int kcs_bmc_ipmi_init(void) +{ + kcs_bmc_register_driver(&kcs_bmc_ipmi_driver); + + return 0; +} +module_init(kcs_bmc_ipmi_init); + +static void kcs_bmc_ipmi_exit(void) +{ + kcs_bmc_unregister_driver(&kcs_bmc_ipmi_driver); +} +module_exit(kcs_bmc_ipmi_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); diff --git a/drivers/char/ipmi/kcs_bmc_client.h b/drivers/char/ipmi/kcs_bmc_client.h index c0f85c5bdf5c..cb38b56cda85 100644 --- a/drivers/char/ipmi/kcs_bmc_client.h +++ b/drivers/char/ipmi/kcs_bmc_client.h @@ -11,6 +11,17 @@ #include "kcs_bmc.h" +struct kcs_bmc_driver_ops { + int (*add_device)(struct kcs_bmc_device *kcs_bmc); + int (*remove_device)(struct kcs_bmc_device *kcs_bmc); +}; + +struct kcs_bmc_driver { + struct list_head entry; + + const struct kcs_bmc_driver_ops *ops; +}; + struct kcs_bmc_client_ops { irqreturn_t (*event)(struct kcs_bmc_client *client); }; @@ -21,6 +32,9 @@ struct kcs_bmc_client { struct kcs_bmc_device *dev; }; +void kcs_bmc_register_driver(struct kcs_bmc_driver *drv); +void kcs_bmc_unregister_driver(struct kcs_bmc_driver *drv); + int kcs_bmc_enable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client); void kcs_bmc_disable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client); From patchwork Mon May 10 05:42:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476087 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=112.213.38.117; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=C+soS976; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=XlLbOuvx; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FdqqQ2wHkz9vFw for ; Mon, 10 May 2021 15:48:50 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4FdqqQ2Brqz306k for ; Mon, 10 May 2021 15:48:50 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=C+soS976; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=XlLbOuvx; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=C+soS976; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=XlLbOuvx; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4Fdqjy5Nkvz3071; Mon, 10 May 2021 15:44:06 +1000 (AEST) Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailnew.nyi.internal (Postfix) with ESMTP id B65BF5803EE; Mon, 10 May 2021 01:44:04 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Mon, 10 May 2021 01:44:04 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=E0UnERwk5jiqV 0/qRRyEl8PacMyhOcRKLUTOtqwa6T0=; b=C+soS976MudPq2EjIz8LsG3y/he/y YLJAo2Rt2ufLZ7bfjiYR1tZQR0KAhYFj0edkzqfCYxITGegRNEBQBxIqFAcCFz28 OGXgJEyZPdIB2CeioSzF6ZtI4lnkg3NyNvYG23SFRmQWgdJkuxc78ds1F+jCNMmw NSlIgg79BCzlj0vL1pjasz9IdV8BpArt4TME15AFAmk11yQldR6rPgvgPOjbsbU3 oeUY7OZFIRs/2lMp3Ou2WVT3iKfQhBxQk3BScCa+lPRHCgbDW9yQaMvSbZVcGahu 7iPGtTcRtIuJnWpss5veqNNkvvbIaDd5yV+u/8ZOZN6bw0o0DIzpR4ayA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=E0UnERwk5jiqV0/qRRyEl8PacMyhOcRKLUTOtqwa6T0=; b=XlLbOuvx UXg59jWScC9JGvFrTMROD+VdqjVWjz7zmfwKlyZBH6udmPGtu/TBcMA5d4ZenZww bl719vb1YymyzvrFx2VPpsyZA2wMP6VhJxD9Cz5bdu3TpXP/qGZlMlJMGfG+g3sE 5DkcUgpf+iUguz+j6LS/9O85Un+ADSLJ+WzZ27BIDkGLz7RGFF6/4Fe05whSpvV2 RvgtvSpsiYc0tCJwqvZ1rWlcSeUi+uWKmLXupqi/Man11UOTMnTYtD3I3DXzamIe O0fwaDV5eI2xeKEbj120DTv0SMLLd0s/I2Xq+HxgGZMFSpPoXDm7LFEgf3MQVxiB wfZX4k7k2PsBmg== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:43:58 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 09/16] ipmi: kcs_bmc: Allow clients to control KCS IRQ state Date: Mon, 10 May 2021 15:12:06 +0930 Message-Id: <20210510054213.1610760-10-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Add a mechanism for controlling whether the client associated with a KCS device will receive Input Buffer Full (IBF) and Output Buffer Empty (OBE) events. This enables an abstract implementation of poll() for KCS devices. A wart in the implementation is that the ASPEED KCS devices don't support an OBE interrupt for the BMC. Instead we pretend it has one by polling the status register waiting for the Output Buffer Full (OBF) bit to clear, and generating an event when OBE is observed. Signed-off-by: Andrew Jeffery Reviewed-by: Zev Weiss --- drivers/char/ipmi/kcs_bmc.c | 6 ++ drivers/char/ipmi/kcs_bmc.h | 3 + drivers/char/ipmi/kcs_bmc_aspeed.c | 150 ++++++++++++++++++---------- drivers/char/ipmi/kcs_bmc_client.h | 2 + drivers/char/ipmi/kcs_bmc_device.h | 1 + drivers/char/ipmi/kcs_bmc_npcm7xx.c | 25 ++++- 6 files changed, 130 insertions(+), 57 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index 2ec8312ce766..7081541bb6ce 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -176,6 +176,12 @@ void kcs_bmc_unregister_driver(struct kcs_bmc_driver *drv) } EXPORT_SYMBOL(kcs_bmc_unregister_driver); +void kcs_bmc_update_event_mask(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 events) +{ + kcs_bmc->ops->irq_mask_update(kcs_bmc, mask, events); +} +EXPORT_SYMBOL(kcs_bmc_update_event_mask); + MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); MODULE_AUTHOR("Andrew Jeffery "); diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index 3f0cce315b4f..fa408b802c79 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -8,6 +8,9 @@ #include +#define KCS_BMC_EVENT_TYPE_OBE BIT(0) +#define KCS_BMC_EVENT_TYPE_IBF BIT(1) + #define KCS_BMC_STR_OBF BIT(0) #define KCS_BMC_STR_IBF BIT(1) #define KCS_BMC_STR_CMD_DAT BIT(3) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 8e00675d1019..8b223e58d900 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -60,10 +60,18 @@ #define LPC_ODR4 0x118 #define LPC_STR4 0x11C +#define OBE_POLL_PERIOD (HZ / 2) + struct aspeed_kcs_bmc { struct kcs_bmc_device kcs_bmc; struct regmap *map; + + struct { + spinlock_t lock; + bool remove; + struct timer_list timer; + } obe; }; struct aspeed_kcs_of_ops { @@ -159,68 +167,89 @@ static void aspeed_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enabl switch (kcs_bmc->channel) { case 1: - if (enable) { - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF1, LPC_HICR2_IBFIF1); - regmap_update_bits(priv->map, LPC_HICR0, - LPC_HICR0_LPC1E, LPC_HICR0_LPC1E); - } else { - regmap_update_bits(priv->map, LPC_HICR0, - LPC_HICR0_LPC1E, 0); - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF1, 0); - } - break; - + regmap_update_bits(priv->map, LPC_HICR0, LPC_HICR0_LPC1E, enable * LPC_HICR0_LPC1E); + return; case 2: - if (enable) { - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF2, LPC_HICR2_IBFIF2); - regmap_update_bits(priv->map, LPC_HICR0, - LPC_HICR0_LPC2E, LPC_HICR0_LPC2E); - } else { - regmap_update_bits(priv->map, LPC_HICR0, - LPC_HICR0_LPC2E, 0); - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF2, 0); - } - break; - + regmap_update_bits(priv->map, LPC_HICR0, LPC_HICR0_LPC2E, enable * LPC_HICR0_LPC2E); + return; case 3: - if (enable) { - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF3, LPC_HICR2_IBFIF3); - regmap_update_bits(priv->map, LPC_HICR0, - LPC_HICR0_LPC3E, LPC_HICR0_LPC3E); - regmap_update_bits(priv->map, LPC_HICR4, - LPC_HICR4_KCSENBL, LPC_HICR4_KCSENBL); - } else { - regmap_update_bits(priv->map, LPC_HICR0, - LPC_HICR0_LPC3E, 0); - regmap_update_bits(priv->map, LPC_HICR4, - LPC_HICR4_KCSENBL, 0); - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF3, 0); - } - break; - + regmap_update_bits(priv->map, LPC_HICR0, LPC_HICR0_LPC3E, enable * LPC_HICR0_LPC3E); + regmap_update_bits(priv->map, LPC_HICR4, + LPC_HICR4_KCSENBL, enable * LPC_HICR4_KCSENBL); + return; case 4: - if (enable) - regmap_update_bits(priv->map, LPC_HICRB, - LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E, - LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E); + regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_LPC4E, enable * LPC_HICRB_LPC4E); + return; + default: + pr_warn("%s: Unsupported channel: %d", __func__, kcs_bmc->channel); + return; + } +} + +static void aspeed_kcs_check_obe(struct timer_list *timer) +{ + struct aspeed_kcs_bmc *priv = container_of(timer, struct aspeed_kcs_bmc, obe.timer); + unsigned long flags; + u8 str; + + spin_lock_irqsave(&priv->obe.lock, flags); + if (priv->obe.remove) { + spin_unlock_irqrestore(&priv->obe.lock, flags); + return; + } + + str = aspeed_kcs_inb(&priv->kcs_bmc, priv->kcs_bmc.ioreg.str); + if (str & KCS_BMC_STR_OBF) { + mod_timer(timer, jiffies + OBE_POLL_PERIOD); + spin_unlock_irqrestore(&priv->obe.lock, flags); + return; + } + spin_unlock_irqrestore(&priv->obe.lock, flags); + + kcs_bmc_handle_event(&priv->kcs_bmc); +} + +static void aspeed_kcs_irq_mask_update(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 state) +{ + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); + + /* We don't have an OBE IRQ, emulate it */ + if (mask & KCS_BMC_EVENT_TYPE_OBE) { + if (KCS_BMC_EVENT_TYPE_OBE & state) + mod_timer(&priv->obe.timer, jiffies + OBE_POLL_PERIOD); else - regmap_update_bits(priv->map, LPC_HICRB, - LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E, - 0); - break; + del_timer(&priv->obe.timer); + } - default: - break; + if (mask & KCS_BMC_EVENT_TYPE_IBF) { + const bool enable = !!(state & KCS_BMC_EVENT_TYPE_IBF); + + switch (kcs_bmc->channel) { + case 1: + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF1, + enable * LPC_HICR2_IBFIF1); + return; + case 2: + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF2, + enable * LPC_HICR2_IBFIF2); + return; + case 3: + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF3, + enable * LPC_HICR2_IBFIF3); + return; + case 4: + regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_IBFIF4, + enable * LPC_HICRB_IBFIF4); + return; + default: + pr_warn("%s: Unsupported channel: %d", __func__, kcs_bmc->channel); + return; + } } } static const struct kcs_bmc_device_ops aspeed_kcs_ops = { + .irq_mask_update = aspeed_kcs_irq_mask_update, .io_inputb = aspeed_kcs_inb, .io_outputb = aspeed_kcs_outb, .io_updateb = aspeed_kcs_updateb, @@ -373,6 +402,10 @@ static int aspeed_kcs_probe(struct platform_device *pdev) return -ENODEV; } + spin_lock_init(&priv->obe.lock); + priv->obe.remove = false; + timer_setup(&priv->obe.timer, aspeed_kcs_check_obe, 0); + aspeed_kcs_set_address(kcs_bmc, addr); rc = aspeed_kcs_config_irq(kcs_bmc, pdev); @@ -381,6 +414,8 @@ static int aspeed_kcs_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); + aspeed_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), + KCS_BMC_EVENT_TYPE_IBF); aspeed_kcs_enable_channel(kcs_bmc, true); kcs_bmc_add_device(&priv->kcs_bmc); @@ -397,6 +432,15 @@ static int aspeed_kcs_remove(struct platform_device *pdev) kcs_bmc_remove_device(kcs_bmc); + aspeed_kcs_enable_channel(kcs_bmc, false); + aspeed_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0); + + /* Make sure it's proper dead */ + spin_lock_irq(&priv->obe.lock); + priv->obe.remove = true; + spin_unlock_irq(&priv->obe.lock); + del_timer_sync(&priv->obe.timer); + return 0; } diff --git a/drivers/char/ipmi/kcs_bmc_client.h b/drivers/char/ipmi/kcs_bmc_client.h index cb38b56cda85..d14e8e0fa230 100644 --- a/drivers/char/ipmi/kcs_bmc_client.h +++ b/drivers/char/ipmi/kcs_bmc_client.h @@ -38,6 +38,8 @@ void kcs_bmc_unregister_driver(struct kcs_bmc_driver *drv); int kcs_bmc_enable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client); void kcs_bmc_disable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client); +void kcs_bmc_update_event_mask(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 events); + u8 kcs_bmc_read_data(struct kcs_bmc_device *kcs_bmc); void kcs_bmc_write_data(struct kcs_bmc_device *kcs_bmc, u8 data); u8 kcs_bmc_read_status(struct kcs_bmc_device *kcs_bmc); diff --git a/drivers/char/ipmi/kcs_bmc_device.h b/drivers/char/ipmi/kcs_bmc_device.h index dd90f8c2ebd6..a1410eb16308 100644 --- a/drivers/char/ipmi/kcs_bmc_device.h +++ b/drivers/char/ipmi/kcs_bmc_device.h @@ -9,6 +9,7 @@ #include "kcs_bmc.h" struct kcs_bmc_device_ops { + void (*irq_mask_update)(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 enable); u8 (*io_inputb)(struct kcs_bmc_device *kcs_bmc, u32 reg); void (*io_outputb)(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 b); void (*io_updateb)(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, u8 b); diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c index 9f0b168e487c..f8b7162fb830 100644 --- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c +++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c @@ -38,6 +38,7 @@ #define KCS2CTL 0x2A #define KCS3CTL 0x3C #define KCS_CTL_IBFIE BIT(0) +#define KCS_CTL_OBEIE BIT(0) #define KCS1IE 0x1C #define KCS2IE 0x2E @@ -117,13 +118,23 @@ static void npcm7xx_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enab { struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); - regmap_update_bits(priv->map, priv->reg->ctl, KCS_CTL_IBFIE, - enable ? KCS_CTL_IBFIE : 0); - regmap_update_bits(priv->map, priv->reg->ie, KCS_IE_IRQE | KCS_IE_HIRQE, enable ? KCS_IE_IRQE | KCS_IE_HIRQE : 0); } +static void npcm7xx_kcs_irq_mask_update(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 state) +{ + struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); + + if (KCS_BMC_EVENT_TYPE_OBE & mask) + regmap_update_bits(priv->map, priv->reg->ctl, KCS_CTL_OBEIE, + !!(KCS_BMC_EVENT_TYPE_OBE & state) * KCS_CTL_OBEIE); + + if (KCS_BMC_EVENT_TYPE_IBF & mask) + regmap_update_bits(priv->map, priv->reg->ctl, KCS_CTL_IBFIE, + !!(state & KCS_BMC_EVENT_TYPE_IBF) * KCS_CTL_IBFIE); +} + static irqreturn_t npcm7xx_kcs_irq(int irq, void *arg) { struct kcs_bmc_device *kcs_bmc = arg; @@ -146,6 +157,7 @@ static int npcm7xx_kcs_config_irq(struct kcs_bmc_device *kcs_bmc, } static const struct kcs_bmc_device_ops npcm7xx_kcs_ops = { + .irq_mask_update = npcm7xx_kcs_irq_mask_update, .io_inputb = npcm7xx_kcs_inb, .io_outputb = npcm7xx_kcs_outb, .io_updateb = npcm7xx_kcs_updateb, @@ -186,11 +198,13 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); - npcm7xx_kcs_enable_channel(kcs_bmc, true); rc = npcm7xx_kcs_config_irq(kcs_bmc, pdev); if (rc) return rc; + npcm7xx_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), + KCS_BMC_EVENT_TYPE_IBF); + npcm7xx_kcs_enable_channel(kcs_bmc, true); pr_info("channel=%u idr=0x%x odr=0x%x str=0x%x\n", chan, @@ -208,6 +222,9 @@ static int npcm7xx_kcs_remove(struct platform_device *pdev) kcs_bmc_remove_device(kcs_bmc); + npcm7xx_kcs_enable_channel(kcs_bmc, false); + npcm7xx_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0); + return 0; } From patchwork Mon May 10 05:42:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476089 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=112.213.38.117; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=QRGlL/x+; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=PVqFb2kn; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fdqqw6pykz9vFY for ; Mon, 10 May 2021 15:49:16 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4Fdqqw6kSqz309K for ; Mon, 10 May 2021 15:49:16 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=QRGlL/x+; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=PVqFb2kn; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=QRGlL/x+; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=PVqFb2kn; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4Fdqk46glsz2ykL; Mon, 10 May 2021 15:44:12 +1000 (AEST) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.nyi.internal (Postfix) with ESMTP id E584A5803ED; Mon, 10 May 2021 01:44:10 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 10 May 2021 01:44:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=kLchKO/0VbbO8 bzomJ3GZBmNt8twxEL+g7L03VtxT00=; b=QRGlL/x+llnwU9mRhh4ueMkzfIqDw sJFPZeKGAymRduKhB/mevwvmbMgLEqr+jPcUiN4not6iv8CZ+9tL+TendR8sHB59 n+C6PZbrGNA7QrPaXlJTWuCpvraM8rt0qKeEGu8J7E3E78/YFaf2o3iMQpwXo1ij OffdIIVwmtWS6K9D4KEMUEunxGS4hYM1EAV/CSi+mi4DSlq8tA+M/gY8/k75FpFb MlW++NUkthX5Zw+F8kYYx0n/S9zNAG/jSeyjPLtckdi37spWHKb5oSqlKntxGrb1 yhrErYdUGei05rVrh/LLFLTKG9pARiVVjBpYEzVcOCXbLbsHT4Vb+41gw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=kLchKO/0VbbO8bzomJ3GZBmNt8twxEL+g7L03VtxT00=; b=PVqFb2kn WRS1BqQ9xcDiKDcyKK3L7aGHDNnP1UlQBiaFlEIx2hQ5MQkn8lGeQlf5cJgQUvEQ Y97RUUuNQXPA66LtS+7KmKB2lKwDBTMauDfo90QWQ5IVUMc6RfAiv0lEWsPdU+rq A5eertsy6krp4cQW+AsXsvCsCBh3foA0oNwVmupyJY20lvtympM7ONKbIpK2tR85 iN7cyaQaRqeublvtimkTMZ4baV6Gcwth3QCuR+am+hZXN4JyhZyyqw3IiW8zZidO 8wqjJs/Zu/PuDBSp7vOO6XJlIIzT+QHKWDFD2Qt3jeKrN738iy7GmyA0nXCLC2cp 6+f0dDUFtWk9eA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:44:05 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 10/16] ipmi: kcs_bmc: Don't enforce single-open policy in the kernel Date: Mon, 10 May 2021 15:12:07 +0930 Message-Id: <20210510054213.1610760-11-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Soon it will be possible for one KCS device to have multiple associated chardevs exposed to userspace (for IPMI and raw-style access). However, don't prevent userspace from: 1. Opening more than one chardev at a time, or 2. Opening the same chardev more than once. System behaviour is undefined for both classes of multiple access, so userspace must manage itself accordingly. The implementation delivers IBF and OBF events to the first chardev client to associate with the KCS device. An open on a related chardev cannot associate its client with the KCS device and so will not receive notification of events. However, any fd on any chardev may race their accesses to the data and status registers. Signed-off-by: Andrew Jeffery --- drivers/char/ipmi/kcs_bmc.c | 34 ++++++++++------------------- drivers/char/ipmi/kcs_bmc_aspeed.c | 3 +-- drivers/char/ipmi/kcs_bmc_npcm7xx.c | 3 +-- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index 7081541bb6ce..ad9ff13ba831 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -55,24 +55,12 @@ EXPORT_SYMBOL(kcs_bmc_update_status); irqreturn_t kcs_bmc_handle_event(struct kcs_bmc_device *kcs_bmc) { struct kcs_bmc_client *client; - irqreturn_t rc; + irqreturn_t rc = IRQ_NONE; spin_lock(&kcs_bmc->lock); client = kcs_bmc->client; - if (client) { + if (client) rc = client->ops->event(client); - } else { - u8 status; - - status = kcs_bmc_read_status(kcs_bmc); - if (status & KCS_BMC_STR_IBF) { - /* Ack the event by reading the data */ - kcs_bmc_read_data(kcs_bmc); - rc = IRQ_HANDLED; - } else { - rc = IRQ_NONE; - } - } spin_unlock(&kcs_bmc->lock); return rc; @@ -81,26 +69,28 @@ EXPORT_SYMBOL(kcs_bmc_handle_event); int kcs_bmc_enable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client) { - int rc; - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->client) { - rc = -EBUSY; - } else { + if (!kcs_bmc->client) { + u8 mask = KCS_BMC_EVENT_TYPE_IBF; + kcs_bmc->client = client; - rc = 0; + kcs_bmc_update_event_mask(kcs_bmc, mask, mask); } spin_unlock_irq(&kcs_bmc->lock); - return rc; + return 0; } EXPORT_SYMBOL(kcs_bmc_enable_device); void kcs_bmc_disable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client) { spin_lock_irq(&kcs_bmc->lock); - if (client == kcs_bmc->client) + if (client == kcs_bmc->client) { + u8 mask = KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE; + + kcs_bmc_update_event_mask(kcs_bmc, mask, 0); kcs_bmc->client = NULL; + } spin_unlock_irq(&kcs_bmc->lock); } EXPORT_SYMBOL(kcs_bmc_disable_device); diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 8b223e58d900..8a0b1e18e945 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -414,8 +414,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); - aspeed_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), - KCS_BMC_EVENT_TYPE_IBF); + aspeed_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0); aspeed_kcs_enable_channel(kcs_bmc, true); kcs_bmc_add_device(&priv->kcs_bmc); diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c index f8b7162fb830..ab4a8caf1270 100644 --- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c +++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c @@ -202,8 +202,7 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) if (rc) return rc; - npcm7xx_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), - KCS_BMC_EVENT_TYPE_IBF); + npcm7xx_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0); npcm7xx_kcs_enable_channel(kcs_bmc, true); pr_info("channel=%u idr=0x%x odr=0x%x str=0x%x\n", From patchwork Mon May 10 05:42:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476090 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=2404:9400:2:0:216:3eff:fee1:b9f1; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=rqlrfsQV; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=wkhXf+0p; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2404:9400:2:0:216:3eff:fee1:b9f1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fdqrh3Q9Rz9vFY for ; Mon, 10 May 2021 15:49:56 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4Fdqrh39BXz3bsq for ; Mon, 10 May 2021 15:49:56 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=rqlrfsQV; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=wkhXf+0p; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=rqlrfsQV; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=wkhXf+0p; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4FdqkB4jTJz2ymX; Mon, 10 May 2021 15:44:18 +1000 (AEST) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailnew.nyi.internal (Postfix) with ESMTP id 9D8B35804C8; Mon, 10 May 2021 01:44:16 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Mon, 10 May 2021 01:44:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=nsLAALaBsNKVR j4KauJmqDuvdmIxsmXV7ge30R1+IA8=; b=rqlrfsQVqSMd2VDxkjpqwdyxA7+ty RRbxbnA12lRdLdGu3GSYHZZ/DzXCF0JdarWdNg7Q2PbqYHwYrYpo+Q9vRvVwUAzo rvwHAd+ZRfVT8VVdP4a8clLrna+5XL4f5AtRwjfUVn/1USeQe6Ij6e9AupVqfS/n SUoNy6MSWCL5BI1qJdYlZ2n+APNJ0MPMQxiLHBEOKOQeSA7D9kd9jqcItye13R3r sa/lx8LN9rvvYpgKf5qdlota4sn/Lo7OzgnbJtmKObQKpq+6ufLc34P/ZWdTSl7Y wWE5sU5UOD8pFk4pyV1gEY3PejnHi8DbvW3VpeQsCUGvgKy+Ko2yOpqGw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=nsLAALaBsNKVRj4KauJmqDuvdmIxsmXV7ge30R1+IA8=; b=wkhXf+0p P/964dAXRZWJFxPnw7opcdZUhwYSscNU74PXh7l5plEY8oTqitvlKt8Wlilych2O rWBi7u768nZKWvxDtA5HS0Op2jMrj8rfi3pzPWTuqF9Wwf3RHOBZCxAtNqxX099m UknZnizZXC93SoPg63udUKJD3t+ClRpqSJxw2Tdn1aR0Wgh+BAnRcCLIBR+YoMmU B42CSX1paF/ZdHBga4Be1TNEgWKJGc6N18zkXgLW1v4ELYpGOSQxWSuDGaSU5+CB 0j8I8GirdjsOKGdd0M24Xw+APQXaLMmBPwx1Qw7EkNWu6PmniRXLWNnnFm+Cspn+ Oz8VMvxoVI/R5Q== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:44:11 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 11/16] ipmi: kcs_bmc: Add serio adaptor Date: Mon, 10 May 2021 15:12:08 +0930 Message-Id: <20210510054213.1610760-12-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" kcs_bmc_serio acts as a bridge between the KCS drivers in the IPMI subsystem and the existing userspace interfaces available through the serio subsystem. This is useful when userspace would like to make use of the BMC KCS devices for purposes that aren't IPMI. Signed-off-by: Andrew Jeffery --- drivers/char/ipmi/Kconfig | 14 +++ drivers/char/ipmi/Makefile | 1 + drivers/char/ipmi/kcs_bmc_serio.c | 151 ++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 drivers/char/ipmi/kcs_bmc_serio.c diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig index bc5f81899b62..249b31197eea 100644 --- a/drivers/char/ipmi/Kconfig +++ b/drivers/char/ipmi/Kconfig @@ -137,6 +137,20 @@ config IPMI_KCS_BMC_CDEV_IPMI This support is also available as a module. The module will be called kcs_bmc_cdev_ipmi. +config IPMI_KCS_BMC_SERIO + depends on IPMI_KCS_BMC && SERIO + tristate "SerIO adaptor for BMC KCS devices" + help + Adapts the BMC KCS device for the SerIO subsystem. This allows users + to take advantage of userspace interfaces provided by SerIO where + appropriate. + + Say YES if you wish to expose KCS devices on the BMC via SerIO + interfaces. + + This support is also available as a module. The module will be + called kcs_bmc_serio. + config ASPEED_BT_IPMI_BMC depends on ARCH_ASPEED || COMPILE_TEST depends on REGMAP && REGMAP_MMIO && MFD_SYSCON diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile index fcfa676afddb..84f47d18007f 100644 --- a/drivers/char/ipmi/Makefile +++ b/drivers/char/ipmi/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_IPMI_POWERNV) += ipmi_powernv.o obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o +obj-$(CONFIG_IPMI_KCS_BMC_SERIO) += kcs_bmc_serio.o obj-$(CONFIG_IPMI_KCS_BMC_CDEV_IPMI) += kcs_bmc_cdev_ipmi.o obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o diff --git a/drivers/char/ipmi/kcs_bmc_serio.c b/drivers/char/ipmi/kcs_bmc_serio.c new file mode 100644 index 000000000000..30a2b7ab464b --- /dev/null +++ b/drivers/char/ipmi/kcs_bmc_serio.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Copyright (c) 2021 IBM Corp. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kcs_bmc_client.h" + +struct kcs_bmc_serio { + struct list_head entry; + + struct kcs_bmc_client client; + struct serio *port; + + spinlock_t lock; +}; + +static inline struct kcs_bmc_serio *client_to_kcs_bmc_serio(struct kcs_bmc_client *client) +{ + return container_of(client, struct kcs_bmc_serio, client); +} + +static irqreturn_t kcs_bmc_serio_event(struct kcs_bmc_client *client) +{ + struct kcs_bmc_serio *priv; + u8 handled = IRQ_NONE; + u8 status; + + priv = client_to_kcs_bmc_serio(client); + + spin_lock(&priv->lock); + + status = kcs_bmc_read_status(client->dev); + + if (status & KCS_BMC_STR_IBF) + handled = serio_interrupt(priv->port, kcs_bmc_read_data(client->dev), 0); + + spin_unlock(&priv->lock); + + return handled; +} + +static const struct kcs_bmc_client_ops kcs_bmc_serio_client_ops = { + .event = kcs_bmc_serio_event, +}; + +static int kcs_bmc_serio_open(struct serio *port) +{ + struct kcs_bmc_serio *priv = port->port_data; + + return kcs_bmc_enable_device(priv->client.dev, &priv->client); +} + +static void kcs_bmc_serio_close(struct serio *port) +{ + struct kcs_bmc_serio *priv = port->port_data; + + kcs_bmc_disable_device(priv->client.dev, &priv->client); +} + +static DEFINE_SPINLOCK(kcs_bmc_serio_instances_lock); +static LIST_HEAD(kcs_bmc_serio_instances); + +static int kcs_bmc_serio_add_device(struct kcs_bmc_device *kcs_bmc) +{ + struct kcs_bmc_serio *priv; + struct serio *port; + + priv = devm_kzalloc(kcs_bmc->dev, sizeof(*priv), GFP_KERNEL); + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!(priv && port)) + return -ENOMEM; + + port->id.type = SERIO_8042; + port->open = kcs_bmc_serio_open; + port->close = kcs_bmc_serio_close; + port->port_data = priv; + port->dev.parent = kcs_bmc->dev; + + spin_lock_init(&priv->lock); + priv->port = port; + priv->client.dev = kcs_bmc; + priv->client.ops = &kcs_bmc_serio_client_ops; + + spin_lock_irq(&kcs_bmc_serio_instances_lock); + list_add(&priv->entry, &kcs_bmc_serio_instances); + spin_unlock_irq(&kcs_bmc_serio_instances_lock); + + serio_register_port(port); + + dev_info(kcs_bmc->dev, "Initialised serio client for channel %d", kcs_bmc->channel); + + return 0; +} + +static int kcs_bmc_serio_remove_device(struct kcs_bmc_device *kcs_bmc) +{ + struct kcs_bmc_serio *priv = NULL, *pos; + + spin_lock_irq(&kcs_bmc_serio_instances_lock); + list_for_each_entry(pos, &kcs_bmc_serio_instances, entry) { + if (pos->client.dev == kcs_bmc) { + priv = pos; + list_del(&pos->entry); + break; + } + } + spin_unlock_irq(&kcs_bmc_serio_instances_lock); + + if (!priv) + return -ENODEV; + + serio_unregister_port(priv->port); + kcs_bmc_disable_device(kcs_bmc, &priv->client); + devm_kfree(priv->client.dev->dev, priv); + + return 0; +} + +static const struct kcs_bmc_driver_ops kcs_bmc_serio_driver_ops = { + .add_device = kcs_bmc_serio_add_device, + .remove_device = kcs_bmc_serio_remove_device, +}; + +static struct kcs_bmc_driver kcs_bmc_serio_driver = { + .ops = &kcs_bmc_serio_driver_ops, +}; + +static int kcs_bmc_serio_init(void) +{ + kcs_bmc_register_driver(&kcs_bmc_serio_driver); + + return 0; +} +module_init(kcs_bmc_serio_init); + +static void kcs_bmc_serio_exit(void) +{ + kcs_bmc_unregister_driver(&kcs_bmc_serio_driver); +} +module_exit(kcs_bmc_serio_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Andrew Jeffery "); +MODULE_DESCRIPTION("Adapter driver for serio access to BMC KCS devices"); From patchwork Mon May 10 05:42:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476093 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=2404:9400:2:0:216:3eff:fee1:b9f1; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=e5nklvh4; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=Cirz+97x; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2404:9400:2:0:216:3eff:fee1:b9f1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FdqsK4zf1z9vFY for ; Mon, 10 May 2021 15:50:29 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4FdqsK4gfjz3bxp for ; Mon, 10 May 2021 15:50:29 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=e5nklvh4; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=Cirz+97x; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=e5nklvh4; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=Cirz+97x; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4FdqkJ6Lbcz308M; Mon, 10 May 2021 15:44:24 +1000 (AEST) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.nyi.internal (Postfix) with ESMTP id DA1A85803EE; Mon, 10 May 2021 01:44:22 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 10 May 2021 01:44:22 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=cnao/xXDBi5Ut isNNxs5pmuioumkhfUO3U6beHJwaRg=; b=e5nklvh4SQ4zz8l9uTze8tyOci7DB eUXY4h43tR+/ZsmfQ30jJg9np4SCLUSgCRKSUOfvBU7Od8yXTEZQ1sDu+L2R8C+h f7wrwy964O7rDooG/h1vboXRS7rHw67w3qHFUIX19tMMo7jyzznFj7NBbbdseJTg idBwerMitl0fXc/OZQk45D3bnGZeDVXtuAmlDWnACfwMbAqyUqqKXQbYWVT4wyDN 7L3PgYBsj82lta3P4Ac5vA7QzmzRak4kdGM8SLHLLYYKNiyMvdIs1QSmPDQKUw+Q iOf0FXr4NkwR6EIAY1NjMYKBruly69c/Ud1EV5d6oJg56sRxCx5evyGgQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=cnao/xXDBi5UtisNNxs5pmuioumkhfUO3U6beHJwaRg=; b=Cirz+97x R4YGgjnQZ9/WWXFqWUVWzD/y1eDzp1To7E4wAjat3cjmhZM4XOkhWdzEbFj40atQ 61LJ+ZU/k0uMnmAUOXQHu97/Mo3V0v8vIXJ2F7mvVbYVj8aSi2OfEeGomaG7hLaH s0kpmVriEKLYIVLdUqArHqfyQ+vii/hEpGEDMzT75Jm/v+8AHrPo8M9zOtOg82nU J6LOHBYdCsbi8BZxdq3jSLXks54zqTnl0XOd1aqOfYyn1TDsADsO9FTMrGdC+HIb vhWsU7Ri7gHQWO0sBL+9tzRs71OVwziDbTd/Tj3HRDjI4jB3bLpHii2Pwx0tg7C5 LICKFhH+cI1y3Q== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpeetnhgurhgv ficulfgvfhhfvghrhicuoegrnhgurhgvfiesrghjrdhiugdrrghuqeenucggtffrrghtth gvrhhnpeeluedvvedtgffggefggfeugeevgffhjeefiedtvdehvdfhtefftefffeeihfev vdenucffohhmrghinhepuggvvhhitggvthhrvggvrdhorhhgnecukfhppedvtdefrdehje drvdduhedrkeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhr ohhmpegrnhgurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:44:16 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 12/16] dt-bindings: ipmi: Convert ASPEED KCS binding to schema Date: Mon, 10 May 2021 15:12:09 +0930 Message-Id: <20210510054213.1610760-13-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, Rob Herring , avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Given the deprecated binding, improve the ability to detect issues in the platform devicetrees. Further, a subsequent patch will introduce a new interrupts property for specifying SerIRQ behaviour, so convert before we do any further additions. Signed-off-by: Andrew Jeffery Reviewed-by: Rob Herring Reviewed-by: Zev Weiss --- .../bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml | 92 +++++++++++++++++++ .../bindings/ipmi/aspeed-kcs-bmc.txt | 33 ------- 2 files changed, 92 insertions(+), 33 deletions(-) create mode 100644 Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml delete mode 100644 Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt diff --git a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml new file mode 100644 index 000000000000..697ca575454f --- /dev/null +++ b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ASPEED BMC KCS Devices + +maintainers: + - Andrew Jeffery + +description: | + The Aspeed BMC SoCs typically use the Keyboard-Controller-Style (KCS) + interfaces on the LPC bus for in-band IPMI communication with their host. + +properties: + compatible: + oneOf: + - description: Channel ID derived from reg + items: + enum: + - aspeed,ast2400-kcs-bmc-v2 + - aspeed,ast2500-kcs-bmc-v2 + - aspeed,ast2600-kcs-bmc + + - description: Old-style with explicit channel ID, no reg + deprecated: true + items: + enum: + - aspeed,ast2400-kcs-bmc + - aspeed,ast2500-kcs-bmc + + interrupts: + maxItems: 1 + + reg: + # maxItems: 3 + items: + - description: IDR register + - description: ODR register + - description: STR register + + aspeed,lpc-io-reg: + $ref: '/schemas/types.yaml#/definitions/uint32-array' + minItems: 1 + maxItems: 2 + description: | + The host CPU LPC IO data and status addresses for the device. For most + channels the status address is derived from the data address, but the + status address may be optionally provided. + + kcs_chan: + deprecated: true + $ref: '/schemas/types.yaml#/definitions/uint32' + description: The LPC channel number in the controller + + kcs_addr: + deprecated: true + $ref: '/schemas/types.yaml#/definitions/uint32' + description: The host CPU IO map address + +required: + - compatible + - interrupts + +additionalProperties: false + +allOf: + - if: + properties: + compatible: + contains: + enum: + - aspeed,ast2400-kcs-bmc + - aspeed,ast2500-kcs-bmc + then: + required: + - kcs_chan + - kcs_addr + else: + required: + - reg + - aspeed,lpc-io-reg + +examples: + - | + kcs3: kcs@24 { + compatible = "aspeed,ast2600-kcs-bmc"; + reg = <0x24 0x1>, <0x30 0x1>, <0x3c 0x1>; + aspeed,lpc-io-reg = <0xca2>; + interrupts = <8>; + }; diff --git a/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt b/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt deleted file mode 100644 index 193e71ca96b0..000000000000 --- a/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt +++ /dev/null @@ -1,33 +0,0 @@ -# Aspeed KCS (Keyboard Controller Style) IPMI interface - -The Aspeed SOCs (AST2400 and AST2500) are commonly used as BMCs -(Baseboard Management Controllers) and the KCS interface can be -used to perform in-band IPMI communication with their host. - -## v1 -Required properties: -- compatible : should be one of - "aspeed,ast2400-kcs-bmc" - "aspeed,ast2500-kcs-bmc" -- interrupts : interrupt generated by the controller -- kcs_chan : The LPC channel number in the controller -- kcs_addr : The host CPU IO map address - -## v2 -Required properties: -- compatible : should be one of - "aspeed,ast2400-kcs-bmc-v2" - "aspeed,ast2500-kcs-bmc-v2" -- reg : The address and size of the IDR, ODR and STR registers -- interrupts : interrupt generated by the controller -- aspeed,lpc-io-reg : The host CPU LPC IO address for the device - -Example: - - kcs3: kcs@24 { - compatible = "aspeed,ast2500-kcs-bmc-v2"; - reg = <0x24 0x1>, <0x30 0x1>, <0x3c 0x1>; - aspeed,lpc-reg = <0xca2>; - interrupts = <8>; - status = "okay"; - }; From patchwork Mon May 10 05:42:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476095 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=2404:9400:2:0:216:3eff:fee1:b9f1; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=ci1Usrf1; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=klEKiaei; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2404:9400:2:0:216:3eff:fee1:b9f1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fdqsr4Wchz9vFY for ; Mon, 10 May 2021 15:50:56 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4Fdqsr3d8Jz2yYM for ; Mon, 10 May 2021 15:50:56 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=ci1Usrf1; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=klEKiaei; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=ci1Usrf1; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=klEKiaei; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4FdqkR4TM6z308m; Mon, 10 May 2021 15:44:31 +1000 (AEST) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id 98D865803ED; Mon, 10 May 2021 01:44:29 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Mon, 10 May 2021 01:44:29 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=E8QunPh9AaMnR gR+ENPZuJJI09F8EPSuDjGchklbXy8=; b=ci1Usrf1jf2DBeAn6MFtJNhve1NwA gjTe1jVG0rdmByllTmNu7H0U+K8RSlcKwR0UD4nJcT7Gkuai219yAj5jgSMm6DYd HUYP1/0T6hhMBdWREGIafGmh4R52A8yVQTW8N17fTxMnBIsVkJ8v29tHVUUGNFOB XtmH0j/NF+hlA6XGv/+j6Fx0G9E8wZv/aKNY25R4w0iU+Op+1OzOnM+snepW+0Jf VfnklXDjwnGuoPZbrzN6IpxfpEAamj+RSrFB2JjSumPCM1EfaYzbDGLjDJBAA7rA fhKpZzb4LpsemG764keME44qjZshs7/KZtwr+8ZOyBSV6EDafsC9l8ueQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=E8QunPh9AaMnRgR+ENPZuJJI09F8EPSuDjGchklbXy8=; b=klEKiaei SrE0ckKtCFdFf+eEJ2WCv8u+m+5LNs09+rl5UX4c+aJiYNtqxTcHvBYUIc/p2bxv RQSUjH74K+tRrjy+YRlDLJ1opjp1uwCpHg+Ql95+pkdVceUUE74hhUY/ajzoY9mK oXbxlnyMT/4kN7V6+4pHFznXQV9if9+2BHvezaBQp2SV7Z8yF3NtboJYoFKYIHFK DJrJmZvuafoNNEjHp36LKgVUMdOLN6b39IunkluKbwiBlO07YH3iL4PlwiuKqChY h2ShAYsJRXPBIOvbhwSHRXPGUWQ9iXOn+KKSXXEOrJBMdELu+FzFordDDLdiX/HF I6pK2OIHb4c0bA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpeetnhgurhgv ficulfgvfhhfvghrhicuoegrnhgurhgvfiesrghjrdhiugdrrghuqeenucggtffrrghtth gvrhhnpeejgfdvveehteekveeggeellefgleetteejffelffdvudduveeiffegteelvefh teenucfkphepvddtfedrheejrddvudehrdeknecuvehluhhsthgvrhfuihiivgeptdenuc frrghrrghmpehmrghilhhfrhhomheprghnughrvgifsegrjhdrihgurdgruh X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:44:23 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 13/16] dt-bindings: ipmi: Add optional SerIRQ property to ASPEED KCS devices Date: Mon, 10 May 2021 15:12:10 +0930 Message-Id: <20210510054213.1610760-14-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, Rob Herring , avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Allocating IO and IRQ resources to LPC devices is in-theory an operation for the host, however ASPEED don't appear to expose this capability outside the BMC (e.g. SuperIO). Instead, we are left with BMC-internal registers for managing these resources, so introduce a devicetree property for KCS devices to describe SerIRQ properties. Signed-off-by: Andrew Jeffery Reviewed-by: Rob Herring --- .../bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml index 697ca575454f..4ff6fabfcb30 100644 --- a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml +++ b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml @@ -49,6 +49,18 @@ properties: channels the status address is derived from the data address, but the status address may be optionally provided. + aspeed,lpc-interrupts: + $ref: "/schemas/types.yaml#/definitions/uint32-array" + minItems: 2 + maxItems: 2 + description: | + A 2-cell property expressing the LPC SerIRQ number and the interrupt + level/sense encoding (specified in the standard fashion). + + Note that the generated interrupt is issued from the BMC to the host, and + thus the target interrupt controller is not captured by the BMC's + devicetree. + kcs_chan: deprecated: true $ref: '/schemas/types.yaml#/definitions/uint32' @@ -84,9 +96,11 @@ allOf: examples: - | + #include kcs3: kcs@24 { compatible = "aspeed,ast2600-kcs-bmc"; reg = <0x24 0x1>, <0x30 0x1>, <0x3c 0x1>; aspeed,lpc-io-reg = <0xca2>; + aspeed,lpc-interrupts = <11 IRQ_TYPE_LEVEL_LOW>; interrupts = <8>; }; From patchwork Mon May 10 05:42:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476097 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=112.213.38.117; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=Ta5ou68u; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=Vt+E/FTA; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FdqtM4Bqwz9vFY for ; Mon, 10 May 2021 15:51:23 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4FdqtM3vbTz3c0R for ; Mon, 10 May 2021 15:51:23 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=Ta5ou68u; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=Vt+E/FTA; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=Ta5ou68u; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=Vt+E/FTA; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4FdqkY2459z305y; Mon, 10 May 2021 15:44:37 +1000 (AEST) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.nyi.internal (Postfix) with ESMTP id 45CBE5804C8; Mon, 10 May 2021 01:44:35 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 10 May 2021 01:44:35 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=wvBJFdrBDSIRZ jWHn1pIyGhXpCM1v/80obO94jVCjH8=; b=Ta5ou68uHIR14upmOchQt7CVMvQgA l7Yo8ghXHXkkQgCvwGZplZR2kiDLEHZ5McJFL2Tk1CrnIqZVpHzDfBibUkcAF2ic sw8d2YM8bhaOJx38l6Q6hfOhttB6DbAvw4AqruOjg+eQo8ef7N/xpk2L4yv1NDSj YJjejqhZG6jST8CKVhJer4+TyOTSAw+88PKJX+o5CAAWEHNw6bQ6L+dLtWOSaGCm c/lKMPXT1c64mCAnMnUhGUPTPcvb8RRxdDF7Yv9hDK0MAkKTxsherqEHWTsPRTEj RwGlXYzxNIjj7xQC+WNo1jGQikySWEY9eQz1uRBq04uZ14/PjXDEKA32g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=wvBJFdrBDSIRZjWHn1pIyGhXpCM1v/80obO94jVCjH8=; b=Vt+E/FTA scdA8Dqif4KEiFBzQxTCsKkDzFO0woHC37xkmcZMNBA6gBbr0Inc1Ko4wjMuEHku opqlENlMVnaGKCt9IHouXl4gwSzr8USJqPnFnRxJilknJV7PUmsroJZeC19y681H V4SQASJ2WCCqiGAAIckZ16P3hnPqekZtVBpU1Ls/VrO6sazP4PSojhfgs1TFsCot NpOk468EsrPxRwX7maqQgGTxwc3cxRb5H3QAyiKY2g2MgIQw6AGad6FQOOGmrCwN De6kYPS3mksm796AVUOAt9TVuNRzSNeKFv026lMXLsLay4hG+okfLZmQC384cTxQ vOxoE/qwOjq/rw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedvnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:44:29 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 14/16] ipmi: kcs_bmc_aspeed: Implement KCS SerIRQ configuration Date: Mon, 10 May 2021 15:12:11 +0930 Message-Id: <20210510054213.1610760-15-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Apply the SerIRQ ID and level/sense behaviours from the devicetree if provided. Signed-off-by: Andrew Jeffery --- drivers/char/ipmi/kcs_bmc_aspeed.c | 182 ++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 2 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 8a0b1e18e945..9b81806b4dcb 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,22 @@ #define KCS_CHANNEL_MAX 4 +/* + * Field class descriptions + * + * LPCyE Enable LPC channel y + * IBFIEy Input Buffer Full IRQ Enable for LPC channel y + * IRQxEy Assert SerIRQ x for LPC channel y (Deprecated, use IDyIRQX, IRQXEy) + * IDyIRQX Use the specified 4-bit SerIRQ for LPC channel y + * SELyIRQX SerIRQ polarity for LPC channel y (low: 0, high: 1) + * IRQXEy Assert the SerIRQ specified in IDyIRQX for LPC channel y + */ + +#define LPC_TYIRQX_LOW 0b00 +#define LPC_TYIRQX_HIGH 0b01 +#define LPC_TYIRQX_RSVD 0b10 +#define LPC_TYIRQX_RISING 0b11 + #define LPC_HICR0 0x000 #define LPC_HICR0_LPC3E BIT(7) #define LPC_HICR0_LPC2E BIT(6) @@ -39,6 +56,19 @@ #define LPC_HICR4 0x010 #define LPC_HICR4_LADR12AS BIT(7) #define LPC_HICR4_KCSENBL BIT(2) +#define LPC_SIRQCR0 0x070 +/* IRQ{12,1}E1 are deprecated as of AST2600 A3 but necessary for prior chips */ +#define LPC_SIRQCR0_IRQ12E1 BIT(1) +#define LPC_SIRQCR0_IRQ1E1 BIT(0) +#define LPC_HICR5 0x080 +#define LPC_HICR5_ID3IRQX_MASK GENMASK(23, 20) +#define LPC_HICR5_ID3IRQX_SHIFT 20 +#define LPC_HICR5_ID2IRQX_MASK GENMASK(19, 16) +#define LPC_HICR5_ID2IRQX_SHIFT 16 +#define LPC_HICR5_SEL3IRQX BIT(15) +#define LPC_HICR5_IRQXE3 BIT(14) +#define LPC_HICR5_SEL2IRQX BIT(13) +#define LPC_HICR5_IRQXE2 BIT(12) #define LPC_LADR3H 0x014 #define LPC_LADR3L 0x018 #define LPC_LADR12H 0x01C @@ -55,6 +85,13 @@ #define LPC_HICRB 0x100 #define LPC_HICRB_IBFIF4 BIT(1) #define LPC_HICRB_LPC4E BIT(0) +#define LPC_HICRC 0x104 +#define LPC_HICRC_ID4IRQX_MASK GENMASK(7, 4) +#define LPC_HICRC_ID4IRQX_SHIFT 4 +#define LPC_HICRC_TY4IRQX_MASK GENMASK(3, 2) +#define LPC_HICRC_TY4IRQX_SHIFT 2 +#define LPC_HICRC_OBF4_AUTO_CLR BIT(1) +#define LPC_HICRC_IRQXE4 BIT(0) #define LPC_LADR4 0x110 #define LPC_IDR4 0x114 #define LPC_ODR4 0x118 @@ -62,11 +99,21 @@ #define OBE_POLL_PERIOD (HZ / 2) +enum aspeed_kcs_irq_mode { + aspeed_kcs_irq_none, + aspeed_kcs_irq_serirq, +}; + struct aspeed_kcs_bmc { struct kcs_bmc_device kcs_bmc; struct regmap *map; + struct { + enum aspeed_kcs_irq_mode mode; + int id; + } upstream_irq; + struct { spinlock_t lock; bool remove; @@ -103,6 +150,49 @@ static void aspeed_kcs_outb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 data) rc = regmap_write(priv->map, reg, data); WARN(rc != 0, "regmap_write() failed: %d\n", rc); + + /* Trigger the upstream IRQ on ODR writes, if enabled */ + + switch (reg) { + case LPC_ODR1: + case LPC_ODR2: + case LPC_ODR3: + case LPC_ODR4: + break; + default: + return; + } + + if (priv->upstream_irq.mode != aspeed_kcs_irq_serirq) + return; + + switch (kcs_bmc->channel) { + case 1: + switch (priv->upstream_irq.id) { + case 12: + regmap_update_bits(priv->map, LPC_SIRQCR0, LPC_SIRQCR0_IRQ12E1, + LPC_SIRQCR0_IRQ12E1); + break; + case 1: + regmap_update_bits(priv->map, LPC_SIRQCR0, LPC_SIRQCR0_IRQ1E1, + LPC_SIRQCR0_IRQ1E1); + break; + default: + break; + } + break; + case 2: + regmap_update_bits(priv->map, LPC_HICR5, LPC_HICR5_IRQXE2, LPC_HICR5_IRQXE2); + break; + case 3: + regmap_update_bits(priv->map, LPC_HICR5, LPC_HICR5_IRQXE3, LPC_HICR5_IRQXE3); + break; + case 4: + regmap_update_bits(priv->map, LPC_HICRC, LPC_HICRC_IRQXE4, LPC_HICRC_IRQXE4); + break; + default: + break; + } } static void aspeed_kcs_updateb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, u8 val) @@ -161,6 +251,73 @@ static void aspeed_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u16 addr) } } +static inline int aspeed_kcs_map_serirq_type(u32 dt_type) +{ + switch (dt_type) { + case IRQ_TYPE_EDGE_RISING: + return LPC_TYIRQX_RISING; + case IRQ_TYPE_LEVEL_HIGH: + return LPC_TYIRQX_HIGH; + case IRQ_TYPE_LEVEL_LOW: + return LPC_TYIRQX_LOW; + default: + return -EINVAL; + } +} + +static int aspeed_kcs_config_upstream_irq(struct aspeed_kcs_bmc *priv, u32 id, u32 dt_type) +{ + unsigned int mask, val, hw_type; + + if (id > 15) + return -EINVAL; + + hw_type = aspeed_kcs_map_serirq_type(dt_type); + if (hw_type < 0) + return hw_type; + + priv->upstream_irq.mode = aspeed_kcs_irq_serirq; + priv->upstream_irq.id = id; + + switch (priv->kcs_bmc.channel) { + case 1: + /* Needs IRQxE1 rather than (ID1IRQX, SEL1IRQX, IRQXE1) before AST2600 A3 */ + break; + case 2: + if (!(hw_type == LPC_TYIRQX_LOW || hw_type == LPC_TYIRQX_HIGH)) + return -EINVAL; + + mask = LPC_HICR5_SEL2IRQX | LPC_HICR5_ID2IRQX_MASK; + val = (id << LPC_HICR5_ID2IRQX_SHIFT); + val |= (hw_type == LPC_TYIRQX_HIGH) ? LPC_HICR5_SEL2IRQX : 0; + regmap_update_bits(priv->map, LPC_HICR5, mask, val); + + break; + case 3: + if (!(hw_type == LPC_TYIRQX_LOW || hw_type == LPC_TYIRQX_HIGH)) + return -EINVAL; + + mask = LPC_HICR5_SEL3IRQX | LPC_HICR5_ID3IRQX_MASK; + val = (id << LPC_HICR5_ID3IRQX_SHIFT); + val |= (hw_type == LPC_TYIRQX_HIGH) ? LPC_HICR5_SEL3IRQX : 0; + regmap_update_bits(priv->map, LPC_HICR5, mask, val); + + break; + case 4: + mask = LPC_HICRC_ID4IRQX_MASK | LPC_HICRC_TY4IRQX_MASK | LPC_HICRC_OBF4_AUTO_CLR; + val = (id << LPC_HICRC_ID4IRQX_SHIFT) | (hw_type << LPC_HICRC_TY4IRQX_SHIFT); + regmap_update_bits(priv->map, LPC_HICRC, mask, val); + break; + default: + dev_warn(priv->kcs_bmc.dev, + "SerIRQ configuration not supported on KCS channel %d\n", + priv->kcs_bmc.channel); + return -EINVAL; + } + + return 0; +} + static void aspeed_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enable) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); @@ -262,7 +419,7 @@ static irqreturn_t aspeed_kcs_irq(int irq, void *arg) return kcs_bmc_handle_event(kcs_bmc); } -static int aspeed_kcs_config_irq(struct kcs_bmc_device *kcs_bmc, +static int aspeed_kcs_config_downstream_irq(struct kcs_bmc_device *kcs_bmc, struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -366,6 +523,8 @@ static int aspeed_kcs_probe(struct platform_device *pdev) struct aspeed_kcs_bmc *priv; struct device_node *np; int rc, channel, addr; + bool have_upstream_irq; + u32 upstream_irq[2]; np = pdev->dev.of_node->parent; if (!of_device_is_compatible(np, "aspeed,ast2400-lpc-v2") && @@ -374,6 +533,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev) dev_err(&pdev->dev, "unsupported LPC device binding\n"); return -ENODEV; } + ops = of_device_get_match_data(&pdev->dev); if (!ops) return -EINVAL; @@ -386,6 +546,13 @@ static int aspeed_kcs_probe(struct platform_device *pdev) if (addr < 0) return addr; + np = pdev->dev.of_node; + rc = of_property_read_u32_array(np, "aspeed,lpc-interrupts", upstream_irq, 2); + if ((rc && rc != -EINVAL)) + return -EINVAL; + + have_upstream_irq = !rc; + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -408,10 +575,20 @@ static int aspeed_kcs_probe(struct platform_device *pdev) aspeed_kcs_set_address(kcs_bmc, addr); - rc = aspeed_kcs_config_irq(kcs_bmc, pdev); + /* Host to BMC IRQ */ + rc = aspeed_kcs_config_downstream_irq(kcs_bmc, pdev); if (rc) return rc; + /* BMC to Host IRQ */ + if (have_upstream_irq) { + rc = aspeed_kcs_config_upstream_irq(priv, upstream_irq[0], upstream_irq[1]); + if (rc < 0) + return rc; + } else { + priv->upstream_irq.mode = aspeed_kcs_irq_none; + } + platform_set_drvdata(pdev, priv); aspeed_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0); @@ -474,4 +651,5 @@ module_platform_driver(ast_kcs_bmc_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); +MODULE_AUTHOR("Andrew Jeffery "); MODULE_DESCRIPTION("Aspeed device interface to the KCS BMC device"); From patchwork Mon May 10 05:42:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476098 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=112.213.38.117; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=O7r5u+Pb; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=thpxnPm1; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fdqv94sZxz9vFY for ; Mon, 10 May 2021 15:52:05 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4Fdqv94HY6z3c25 for ; Mon, 10 May 2021 15:52:05 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=O7r5u+Pb; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=thpxnPm1; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=O7r5u+Pb; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=thpxnPm1; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4Fdqkg2xxXz3079; Mon, 10 May 2021 15:44:43 +1000 (AEST) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.nyi.internal (Postfix) with ESMTP id 643455803ED; Mon, 10 May 2021 01:44:41 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 10 May 2021 01:44:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=Cf8vcTHTFHQGR l2fPzXB+QwMHUhRpgEuhayhDdGSR0o=; b=O7r5u+Pb8GS2Q1DY2IQJlcY3a6mOh dZeDbnqS2KxWPDEfwjx84Eh5A2MB2vJWrVy+5qxJCHYvfQheNJEAYlCzn+O18q7V XMREvbWCgMAkbo4RKMAu0UroNFALk2mcXmItY8IFPZVC1bixpfvBUonD36TJv2e+ fOsw/nibpqiLgt9CZ+jPZ8XmFx8AxXfSczg74i6gXLQDc2Bxp/SyT2oKAOHR1h43 f88Jzv9ddWZTBt1fhpVwHz0Df7kO7kAru0wc6L/8pU9oMCJzrulZlDldmVedgWkU IrU/O6Oe9xkZklJ+w16Okl4GJBDRvtFp2Zz33UnX0JZ1Ph5Bd9omohZQQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=Cf8vcTHTFHQGRl2fPzXB+QwMHUhRpgEuhayhDdGSR0o=; b=thpxnPm1 spFbmLH4SZdrghRKsDpRnTdgYoXjaWEnjRwvKmsa0W1//uuqFmlDQk7mOS21qEEz jOJ9rc4FLVxdfsQnQOs6sO5her+Ex8DN3gtDRMIIDL4PuVDAtm12xnFZ7sx7zFM4 5mIpV9wa3K5PJMwkkzGd4FPiwimfdxgvRqfE+rVdCtvisHYZaOV/z+L7UjXZiCJY ak8LlgOpinhORA+rSRW0xWnr9FGUo2un/If0SA1AdWQJMaFecIbwcXl2RcVOnzLZ +pnc7M+eU5ODgVpYSIT3S7vUdZgbrQiag8Ls4kU78Pz0qRdMMLqrCsNT9BpiafRZ F3zS+on2wVHAzA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpeefnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:44:35 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 15/16] ipmi: kcs_bmc_aspeed: Fix IBFIE typo from datasheet Date: Mon, 10 May 2021 15:12:12 +0930 Message-Id: <20210510054213.1610760-16-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Input Buffer Full Interrupt Enable (IBFIE) is typoed as IBFIF for some registers in the datasheet. Fix the driver to use the sensible acronym. Signed-off-by: Andrew Jeffery Reviewed-by: Zev Weiss --- drivers/char/ipmi/kcs_bmc_aspeed.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 9b81806b4dcb..558132b2b9f7 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -50,9 +50,9 @@ #define LPC_HICR0_LPC2E BIT(6) #define LPC_HICR0_LPC1E BIT(5) #define LPC_HICR2 0x008 -#define LPC_HICR2_IBFIF3 BIT(3) -#define LPC_HICR2_IBFIF2 BIT(2) -#define LPC_HICR2_IBFIF1 BIT(1) +#define LPC_HICR2_IBFIE3 BIT(3) +#define LPC_HICR2_IBFIE2 BIT(2) +#define LPC_HICR2_IBFIE1 BIT(1) #define LPC_HICR4 0x010 #define LPC_HICR4_LADR12AS BIT(7) #define LPC_HICR4_KCSENBL BIT(2) @@ -83,7 +83,7 @@ #define LPC_STR2 0x040 #define LPC_STR3 0x044 #define LPC_HICRB 0x100 -#define LPC_HICRB_IBFIF4 BIT(1) +#define LPC_HICRB_IBFIE4 BIT(1) #define LPC_HICRB_LPC4E BIT(0) #define LPC_HICRC 0x104 #define LPC_HICRC_ID4IRQX_MASK GENMASK(7, 4) @@ -383,20 +383,20 @@ static void aspeed_kcs_irq_mask_update(struct kcs_bmc_device *kcs_bmc, u8 mask, switch (kcs_bmc->channel) { case 1: - regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF1, - enable * LPC_HICR2_IBFIF1); + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIE1, + enable * LPC_HICR2_IBFIE1); return; case 2: - regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF2, - enable * LPC_HICR2_IBFIF2); + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIE2, + enable * LPC_HICR2_IBFIE2); return; case 3: - regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF3, - enable * LPC_HICR2_IBFIF3); + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIE3, + enable * LPC_HICR2_IBFIE3); return; case 4: - regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_IBFIF4, - enable * LPC_HICRB_IBFIF4); + regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_IBFIE4, + enable * LPC_HICRB_IBFIE4); return; default: pr_warn("%s: Unsupported channel: %d", __func__, kcs_bmc->channel); From patchwork Mon May 10 05:42:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1476101 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=2404:9400:2:0:216:3eff:fee1:b9f1; helo=lists.ozlabs.org; envelope-from=openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=aAyZNcO1; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=FrmDWdZO; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2404:9400:2:0:216:3eff:fee1:b9f1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fdqvj5y4mz9vFY for ; Mon, 10 May 2021 15:52:33 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4Fdqvj5dbqz301q for ; Mon, 10 May 2021 15:52:33 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=aAyZNcO1; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=FrmDWdZO; dkim-atps=neutral X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.221; helo=new1-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=aAyZNcO1; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=FrmDWdZO; dkim-atps=neutral Received: from new1-smtp.messagingengine.com (new1-smtp.messagingengine.com [66.111.4.221]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4Fdqkn4SwYz307Q; Mon, 10 May 2021 15:44:49 +1000 (AEST) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id 5B78B5803EE; Mon, 10 May 2021 01:44:47 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Mon, 10 May 2021 01:44:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=WcWLsIVd7FBaV pMfmIuuKOIgK8kxwBSDHbabyxefQ2A=; b=aAyZNcO12+sQBN9IYuW333tWOLpYD ivdpU6xr9pkGxiSoJ3/ERzB7rxJDEihLIwL17hU55Im1u46uDZij3Qn59oVW0l1h TtCOlDC2JNtJsPleZj1E8pgvfMkivkMaFnRDTQvQyRJG/4PPNV8x/SCB7tQm6f74 KYTjGMMqSJE2Ydfi+4LZqfTeMVi3/8gqRTB4igWRZ1L/XW2DoTlZfzPWRKrhe50a RSTytmerxBrSsink7S2Hv6xdOo0O79C03EXioPHmM+Y35JpvZJICjCxQI6STuYoq ksr61f/5q/q1H6cgSqfgJSvmBxzRiMIAvemiYKzIRozoa0MoEUEcqXAXw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=WcWLsIVd7FBaVpMfmIuuKOIgK8kxwBSDHbabyxefQ2A=; b=FrmDWdZO xfFL021Yrm8QBWfY5wI6rI4hTj23Hiy4XBUTX0QjccAUBmwuzx4K95Eu+FybileB 5ZXWiAiOFTuz32MLrJVOYAjXjWSIBttbt2IYW0qt01RW8ZOuz0n87ztLeqofzP/k CdkEQI9ozU+k3AhNfoUIlKP8YPjyrIWxFUFTzcPPAHjy2zV07mf01/zrHE4jo0R+ Z8KFnf60RgCGr/1rQiARxoyMrOsJ6uiBlrlww+ryBLph80mxVX1TTCXKwAmr0lT2 zNNvKOyCccojgXrFKp9blklECwEqis/pMXWhMVHEo3WJNFFttIcrsPJEQkxWo8xK kBb1QTzTiRj/Ww== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrvdegjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppedvtdefrdehjedrvdduhedrkeen ucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (unknown [203.57.215.8]) by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 10 May 2021 01:44:41 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Subject: [PATCH v3 16/16] ipmi: kcs_bmc_aspeed: Optionally apply status address Date: Mon, 10 May 2021 15:12:13 +0930 Message-Id: <20210510054213.1610760-17-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210510054213.1610760-1-andrew@aj.id.au> References: <20210510054213.1610760-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, avifishman70@gmail.com, venture@google.com, chiawei_wang@aspeedtech.com, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, arnd@arndb.de, zweiss@equinix.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Some Aspeed KCS devices can derive the status register address from the address of the data register. As such, the address of the status register can be implicit in the configuration if desired. On the other hand, sometimes address schemes might be requested that are incompatible with the default addressing scheme. Allow these requests where possible if the devicetree specifies the status register address. Signed-off-by: Andrew Jeffery Reviewed-by: Chia-Wei Wang --- drivers/char/ipmi/kcs_bmc_aspeed.c | 110 ++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 32 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 558132b2b9f7..f6c58eb2883e 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -83,6 +83,8 @@ #define LPC_STR2 0x040 #define LPC_STR3 0x044 #define LPC_HICRB 0x100 +#define LPC_HICRB_EN16LADR2 BIT(5) +#define LPC_HICRB_EN16LADR1 BIT(4) #define LPC_HICRB_IBFIE4 BIT(1) #define LPC_HICRB_LPC4E BIT(0) #define LPC_HICRC 0x104 @@ -96,6 +98,11 @@ #define LPC_IDR4 0x114 #define LPC_ODR4 0x118 #define LPC_STR4 0x11C +#define LPC_LSADR12 0x120 +#define LPC_LSADR12_LSADR2_MASK GENMASK(31, 16) +#define LPC_LSADR12_LSADR2_SHIFT 16 +#define LPC_LSADR12_LSADR1_MASK GENMASK(15, 0) +#define LPC_LSADR12_LSADR1_SHIFT 0 #define OBE_POLL_PERIOD (HZ / 2) @@ -123,7 +130,7 @@ struct aspeed_kcs_bmc { struct aspeed_kcs_of_ops { int (*get_channel)(struct platform_device *pdev); - int (*get_io_address)(struct platform_device *pdev); + int (*get_io_address)(struct platform_device *pdev, u32 addrs[2]); }; static inline struct aspeed_kcs_bmc *to_aspeed_kcs_bmc(struct kcs_bmc_device *kcs_bmc) @@ -217,38 +224,64 @@ static void aspeed_kcs_updateb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, * C. KCS4 * D / C : CA4h / CA5h */ -static void aspeed_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u16 addr) +static int aspeed_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u32 addrs[2], int nr_addrs) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); - switch (kcs_bmc->channel) { + if (WARN_ON(nr_addrs < 1 || nr_addrs > 2)) + return -EINVAL; + + switch (priv->kcs_bmc.channel) { case 1: - regmap_update_bits(priv->map, LPC_HICR4, - LPC_HICR4_LADR12AS, 0); - regmap_write(priv->map, LPC_LADR12H, addr >> 8); - regmap_write(priv->map, LPC_LADR12L, addr & 0xFF); + regmap_update_bits(priv->map, LPC_HICR4, LPC_HICR4_LADR12AS, 0); + regmap_write(priv->map, LPC_LADR12H, addrs[0] >> 8); + regmap_write(priv->map, LPC_LADR12L, addrs[0] & 0xFF); + if (nr_addrs == 2) { + regmap_update_bits(priv->map, LPC_LSADR12, LPC_LSADR12_LSADR1_MASK, + addrs[1] << LPC_LSADR12_LSADR1_SHIFT); + + regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_EN16LADR1, + LPC_HICRB_EN16LADR1); + } break; case 2: - regmap_update_bits(priv->map, LPC_HICR4, - LPC_HICR4_LADR12AS, LPC_HICR4_LADR12AS); - regmap_write(priv->map, LPC_LADR12H, addr >> 8); - regmap_write(priv->map, LPC_LADR12L, addr & 0xFF); + regmap_update_bits(priv->map, LPC_HICR4, LPC_HICR4_LADR12AS, LPC_HICR4_LADR12AS); + regmap_write(priv->map, LPC_LADR12H, addrs[0] >> 8); + regmap_write(priv->map, LPC_LADR12L, addrs[0] & 0xFF); + if (nr_addrs == 2) { + regmap_update_bits(priv->map, LPC_LSADR12, LPC_LSADR12_LSADR2_MASK, + addrs[1] << LPC_LSADR12_LSADR2_SHIFT); + + regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_EN16LADR2, + LPC_HICRB_EN16LADR2); + } break; case 3: - regmap_write(priv->map, LPC_LADR3H, addr >> 8); - regmap_write(priv->map, LPC_LADR3L, addr & 0xFF); + if (nr_addrs == 2) { + dev_err(priv->kcs_bmc.dev, + "Channel 3 only supports inferred status IO address\n"); + return -EINVAL; + } + + regmap_write(priv->map, LPC_LADR3H, addrs[0] >> 8); + regmap_write(priv->map, LPC_LADR3L, addrs[0] & 0xFF); break; case 4: - regmap_write(priv->map, LPC_LADR4, ((addr + 1) << 16) | - addr); + if (nr_addrs == 1) + regmap_write(priv->map, LPC_LADR4, ((addrs[0] + 1) << 16) | addrs[0]); + else + regmap_write(priv->map, LPC_LADR4, (addrs[1] << 16) | addrs[0]); + break; default: - break; + return -EINVAL; } + + return 0; } static inline int aspeed_kcs_map_serirq_type(u32 dt_type) @@ -457,18 +490,18 @@ static int aspeed_kcs_of_v1_get_channel(struct platform_device *pdev) return channel; } -static int aspeed_kcs_of_v1_get_io_address(struct platform_device *pdev) +static int +aspeed_kcs_of_v1_get_io_address(struct platform_device *pdev, u32 addrs[2]) { - u32 slave; int rc; - rc = of_property_read_u32(pdev->dev.of_node, "kcs_addr", &slave); - if (rc || slave > 0xffff) { + rc = of_property_read_u32(pdev->dev.of_node, "kcs_addr", addrs); + if (rc || addrs[0] > 0xffff) { dev_err(&pdev->dev, "no valid 'kcs_addr' configured\n"); return -EINVAL; } - return slave; + return 1; } static int aspeed_kcs_of_v2_get_channel(struct platform_device *pdev) @@ -504,16 +537,24 @@ static int aspeed_kcs_of_v2_get_channel(struct platform_device *pdev) return -EINVAL; } -static int aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev) +static int +aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev, u32 addrs[2]) { - uint32_t slave; int rc; - rc = of_property_read_u32(pdev->dev.of_node, "aspeed,lpc-io-reg", &slave); - if (rc || slave > 0xffff) + rc = of_property_read_variable_u32_array(pdev->dev.of_node, + "aspeed,lpc-io-reg", + addrs, 1, 2); + if (rc < 0) + return rc; + + if (addrs[0] > 0xffff) + return -EINVAL; + + if (rc == 2 && addrs[1] > 0xffff) return -EINVAL; - return slave; + return rc; } static int aspeed_kcs_probe(struct platform_device *pdev) @@ -522,9 +563,11 @@ static int aspeed_kcs_probe(struct platform_device *pdev) struct kcs_bmc_device *kcs_bmc; struct aspeed_kcs_bmc *priv; struct device_node *np; - int rc, channel, addr; bool have_upstream_irq; u32 upstream_irq[2]; + int rc, channel; + int nr_addrs; + u32 addrs[2]; np = pdev->dev.of_node->parent; if (!of_device_is_compatible(np, "aspeed,ast2400-lpc-v2") && @@ -542,9 +585,9 @@ static int aspeed_kcs_probe(struct platform_device *pdev) if (channel < 0) return channel; - addr = ops->get_io_address(pdev); - if (addr < 0) - return addr; + nr_addrs = ops->get_io_address(pdev, addrs); + if (nr_addrs < 0) + return nr_addrs; np = pdev->dev.of_node; rc = of_property_read_u32_array(np, "aspeed,lpc-interrupts", upstream_irq, 2); @@ -573,7 +616,9 @@ static int aspeed_kcs_probe(struct platform_device *pdev) priv->obe.remove = false; timer_setup(&priv->obe.timer, aspeed_kcs_check_obe, 0); - aspeed_kcs_set_address(kcs_bmc, addr); + rc = aspeed_kcs_set_address(kcs_bmc, addrs, nr_addrs); + if (rc) + return rc; /* Host to BMC IRQ */ rc = aspeed_kcs_config_downstream_irq(kcs_bmc, pdev); @@ -596,7 +641,8 @@ static int aspeed_kcs_probe(struct platform_device *pdev) kcs_bmc_add_device(&priv->kcs_bmc); - dev_info(&pdev->dev, "Initialised channel %d at 0x%x\n", kcs_bmc->channel, addr); + dev_info(&pdev->dev, "Initialised channel %d at 0x%x\n", + kcs_bmc->channel, addrs[0]); return 0; }