From patchwork Fri Aug 4 14:31:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sudeep Holla X-Patchwork-Id: 109415 Delivered-To: patch@linaro.org Received: by 10.140.101.6 with SMTP id t6csp2236542qge; Fri, 4 Aug 2017 07:34:01 -0700 (PDT) X-Received: by 10.84.231.203 with SMTP id g11mr3094423pln.199.1501857241311; Fri, 04 Aug 2017 07:34:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1501857241; cv=none; d=google.com; s=arc-20160816; b=cUUmSGxvgbXEY14bG6NQq5hMp1JIeRIDG9s6CiZ9Y+WrtVy+edRM95H9d60PWQXllK 1l+gqru+MN/+5xIcSzNrOq/P2NjoVteRUE8I4Tq4hdJz2FbAmD+sScAaHV1LFCwiRP1u NJlm3HkDQ20W9Rh0BqEcTyDChgfhLTm5FxLrESyeXzjmBifFyMWdd3J6chZ6NPyg+dGE eA69pTbwZByyMOChPReK/vDnMnOgNyOMgZJLO1E52MHK6IwnMvgyAURP3mFCJ7w5YEl3 ohme7Pwy7oD9MCaBYnaaN+9b3hcoY8MHlS+ly13dxZcPr6QjWmt0uAKGq5IZT+xMD1kD NZPQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=W2TCXnrsm1vkNKiSNDIX8rfbn6w/N7sjuYsGlCOGqQw=; b=DMSGf6Ut/kU8kBHucpBhLpiiI4g/Oh2L0cXnXKcqZE6A/IgfqzQVkb0tAFw6qlU7aV eUDsUqLI2VGanImn7u+Yyp2StXF8j68OzrDrvKWc3MT5FIZRF0HancuYGFYzooXqgRP4 DNMikMUxQUdQzwt+ZZxiN84WKpcCcM2UcMS6pYD5IGVyH1DpX+jT3Y43CbkRn2CGEDU6 iQSuw3PUSf33+EI6rRuUOr7Iu59yJppNnSvYUjAtE2tg7PwJXYBpWyGqnrC9/NQeS41a cakYXcG5n/EC7yAuwzhMQup8TVZGi4XvnsrkoBA/Jw/NI24nG9Z4IuSazfxZV0/omPR5 M7Kg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o19si1106526pfj.166.2017.08.04.07.34.01; Fri, 04 Aug 2017 07:34:01 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753050AbdHDOd7 (ORCPT + 25 others); Fri, 4 Aug 2017 10:33:59 -0400 Received: from foss.arm.com ([217.140.101.70]:54392 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752519AbdHDOcg (ORCPT ); Fri, 4 Aug 2017 10:32:36 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id AE5FC16A0; Fri, 4 Aug 2017 07:32:35 -0700 (PDT) Received: from e107155-lin.cambridge.arm.com (unknown [10.1.210.28]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 915523F3E1; Fri, 4 Aug 2017 07:32:33 -0700 (PDT) From: Sudeep Holla To: ALKML , LKML , DTML Cc: Sudeep Holla , Roy Franz , Harb Abdulhamid , Nishanth Menon , Arnd Bergmann , Loc Ho , Alexey Klimov , Ryan Harkin , Jassi Brar Subject: [PATCH v2 13/18] firmware: arm_scmi: add per-protocol channels support using idr objects Date: Fri, 4 Aug 2017 15:31:39 +0100 Message-Id: <1501857104-11279-14-git-send-email-sudeep.holla@arm.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1501857104-11279-1-git-send-email-sudeep.holla@arm.com> References: <1501857104-11279-1-git-send-email-sudeep.holla@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In order to maintain the channel information per protocol, we need some sort of list or hashtable to hold all this information. IDR provides sparse array mapping of small integer ID numbers onto arbitrary pointers. In this case the arbitrary pointers can be pointers to the channel information. This patch adds support for per-protocol channels using those idr objects. Cc: Arnd Bergmann Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 50 +++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 11 deletions(-) -- 2.7.4 diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 3eaf619858bb..b59cbdde0237 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -112,6 +112,8 @@ struct scmi_desc { * @tx_payload: Transmit mailbox channel payload area * @rx_payload: Receive mailbox channel payload area * @info: Reference to SCMI instance corresponding to this channel + * @dev: Reference to device in the SCMI hierarchy corresponding to this + * channel */ struct scmi_chan_info { struct mbox_client cl; @@ -120,6 +122,7 @@ struct scmi_chan_info { void __iomem *tx_payload; void __iomem *rx_payload; struct scmi_info *info; + struct device *dev; }; /** @@ -131,7 +134,7 @@ struct scmi_chan_info { * @version: SCMI revision information containing protocol version, * implementation version and (sub-)vendor identification. * @minfo: Message info - * @cinfo: Reference to SCMI channel information + * @idr: IDR object to map protocol id to channel info pointer * @protocols_imp: list of protocols implemented * @node: list head * @users: Number of users of this instance @@ -142,7 +145,7 @@ struct scmi_info { struct scmi_revision_info version; struct scmi_handle handle; struct scmi_xfers_info minfo; - struct scmi_chan_info *cinfo; + struct idr idr; u8 *protocols_imp; struct list_head node; int users; @@ -412,7 +415,11 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) int timeout; struct scmi_info *info = handle_to_scmi_info(handle); struct device *dev = info->dev; - struct scmi_chan_info *cinfo = info->cinfo; + struct scmi_chan_info *cinfo; + + cinfo = idr_find(&info->idr, xfer->hdr.protocol_id); + if (unlikely(!cinfo)) + return -EINVAL; ret = mbox_send_message(cinfo->tx_chan, xfer); if (ret < 0) { @@ -772,8 +779,11 @@ static int scmi_mailbox_check(struct device_node *np) return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg); } -static int scmi_mbox_free_channel(struct scmi_chan_info *cinfo) +static int scmi_mbox_free_channel(int id, void *p, void *data) { + struct scmi_chan_info *cinfo = p; + struct idr *idr = data; + if (!IS_ERR_OR_NULL(cinfo->tx_chan)) { mbox_free_channel(cinfo->tx_chan); cinfo->tx_chan = NULL; @@ -783,6 +793,8 @@ static int scmi_mbox_free_channel(struct scmi_chan_info *cinfo) cinfo->rx_chan = NULL; } + idr_remove(idr, id); + return 0; } @@ -790,6 +802,7 @@ static int scmi_remove(struct platform_device *pdev) { int ret = 0; struct scmi_info *info = platform_get_drvdata(pdev); + struct idr *idr = &info->idr; of_platform_depopulate(&pdev->dev); @@ -800,28 +813,34 @@ static int scmi_remove(struct platform_device *pdev) list_del(&info->node); mutex_unlock(&scmi_list_mutex); - if (!ret) + if (!ret) { /* Safe to free channels since no more users */ - return scmi_mbox_free_channel(info->cinfo); + ret = idr_for_each(idr, scmi_mbox_free_channel, idr); + idr_destroy(&info->idr); + } return ret; } -static inline int scmi_mbox_chan_setup(struct scmi_info *info) +static inline int +scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id) { int ret; struct resource res; resource_size_t size; - struct device *dev = info->dev; struct device_node *shmem, *np = dev->of_node; struct scmi_chan_info *cinfo; struct mbox_client *cl; + if (scmi_mailbox_check(np)) { + cinfo = idr_find(&info->idr, SCMI_PROTOCOL_BASE); + goto idr_alloc; + } + cinfo = devm_kzalloc(info->dev, sizeof(*cinfo), GFP_KERNEL); if (!cinfo) return -ENOMEM; - info->cinfo = cinfo; cinfo->info = info; cl = &cinfo->cl; @@ -854,6 +873,13 @@ static inline int scmi_mbox_chan_setup(struct scmi_info *info) return ret; } +idr_alloc: + ret = idr_alloc(&info->idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL); + if (ret != prot_id) { + dev_err(dev, "unable to allocate SCMI idr slot err %d\n", ret); + return ret; + } + return 0; } @@ -887,19 +913,19 @@ static int scmi_probe(struct platform_device *pdev) return ret; platform_set_drvdata(pdev, info); + idr_init(&info->idr); handle = &info->handle; handle->dev = info->dev; handle->version = &info->version; - ret = scmi_mbox_chan_setup(info); + ret = scmi_mbox_chan_setup(info, dev, SCMI_PROTOCOL_BASE); if (ret) return ret; ret = scmi_base_protocol_init(handle); if (ret) { dev_err(dev, "unable to communicate with SCMI(%d)\n", ret); - scmi_mbox_free_channel(info->cinfo); return ret; } @@ -931,6 +957,8 @@ static int scmi_probe(struct platform_device *pdev) continue; } + scmi_mbox_chan_setup(info, &cdev->dev, prot_id); + init_ret = match->fn(handle); if (init_ret) { dev_err(dev, "SCMI protocol %d init error %d\n",