From patchwork Thu May 5 13:29:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 67204 Delivered-To: patch@linaro.org Received: by 10.140.92.199 with SMTP id b65csp751788qge; Thu, 5 May 2016 06:31:54 -0700 (PDT) X-Received: by 10.66.54.35 with SMTP id g3mr20837992pap.30.1462455114308; Thu, 05 May 2016 06:31:54 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t88si11122105pfj.44.2016.05.05.06.31.53; Thu, 05 May 2016 06:31:54 -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; dkim=pass header.i=@linaro.org; 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; dmarc=pass (p=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757316AbcEENbu (ORCPT + 29 others); Thu, 5 May 2016 09:31:50 -0400 Received: from mail-wm0-f50.google.com ([74.125.82.50]:38606 "EHLO mail-wm0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756765AbcEENbq (ORCPT ); Thu, 5 May 2016 09:31:46 -0400 Received: by mail-wm0-f50.google.com with SMTP id g17so28021095wme.1 for ; Thu, 05 May 2016 06:31:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=cjyjpaSWthJ/Zre6Byte9c0SHP2isXYoJ26xAy9tjT8=; b=BdVsHjD0jO92ny6r97B2lIBE7zifqdyqwNtBmweBJJs/fnCq1ZXifqNMhqRwbvrqZl csaIWQDuOMcYDz9s4F1Q5fC2sS7t+jaKXgP7iNx0mwYv1Avsgv+YjOVJjzDm2w599Gt4 2dlLqQtAwHqgMLzWv0mTas+o9Mn6Y6PqxB3qs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=cjyjpaSWthJ/Zre6Byte9c0SHP2isXYoJ26xAy9tjT8=; b=a8zAoigF6GGPaPoxRo+KhETHFtRYSGwCxFLe5FNJgGUL9jWJPFbHB+ut86ezLyWZQB We2yyWaWq1ez3ghbkYwbcbOtqJxzJLA8ttL/PUo1XA+gF1NkUlOa+G11aso/mAea7wyn OFzwk0/6skcT7Z25O0aVopuufUxuLChlbjZ9Umkk4v1M+dxdImuWFqt+5mX+ZNvr/77m 3bPwxuNvLMzWbUEKOsq4Wwk8qsOmtx3FeknpNRqS3PWga33I37rFFXBqKC3Y95qW5qSW 14Iy+jVj1uKoUYwegtTFYZBEx7oTv7GFlDHSzMnNS1s9IWNk1IDRLFpIcmzAjdEsWfS2 O7WA== X-Gm-Message-State: AOPr4FWaT+yzwgvaTrvRLa3j96PfhY8Skj2x3OGePp/JsHsd18kK1Xq7z9ZaK1hJOib86iX0 X-Received: by 10.194.203.138 with SMTP id kq10mr14352066wjc.155.1462455105063; Thu, 05 May 2016 06:31:45 -0700 (PDT) Received: from localhost.localdomain (host81-129-173-198.range81-129.btcentralplus.com. [81.129.173.198]) by smtp.gmail.com with ESMTPSA id lf9sm9776868wjc.44.2016.05.05.06.31.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 05 May 2016 06:31:44 -0700 (PDT) From: Lee Jones To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: kernel@stlinux.com, maxime.coquelin@st.com, ohad@wizery.com, bjorn.andersson@linaro.org, linux-remoteproc@vger.kernel.org, Lee Jones Subject: [PATCH 4/5] remoteproc: core: Supply framework to request, declare and fetch shared memory Date: Thu, 5 May 2016 14:29:42 +0100 Message-Id: <1462454983-13168-5-git-send-email-lee.jones@linaro.org> X-Mailer: git-send-email 2.8.0 In-Reply-To: <1462454983-13168-1-git-send-email-lee.jones@linaro.org> References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Normally used for management of; carveout, devmem and trace memory. Signed-off-by: Lee Jones --- drivers/remoteproc/remoteproc_core.c | 174 +++++++++++++++++++++++++++++++++-- 1 file changed, 167 insertions(+), 7 deletions(-) -- 2.8.0 diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 03720c0..3d9798c 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -209,6 +209,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) { struct rproc *rproc = rvdev->rproc; struct device *dev = &rproc->dev; + struct device *dma_dev; struct rproc_vring *rvring = &rvdev->vring[i]; struct fw_rsc_vdev *rsc; dma_addr_t dma; @@ -222,7 +223,8 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) * Allocate non-cacheable memory for the vring. In the future * this call will also configure the IOMMU for us */ - va = dma_alloc_coherent(dev->parent, size, &dma, GFP_KERNEL); + dma_dev = rproc_subdev_lookup(rproc, "vring"); + va = dma_alloc_coherent(dma_dev, size, &dma, GFP_KERNEL); if (!va) { dev_err(dev->parent, "dma_alloc_coherent failed\n"); return -EINVAL; @@ -236,7 +238,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) ret = idr_alloc(&rproc->notifyids, rvring, 0, 0, GFP_KERNEL); if (ret < 0) { dev_err(dev, "idr_alloc failed: %d\n", ret); - dma_free_coherent(dev->parent, size, va, dma); + dma_free_coherent(dma_dev, size, va, dma); return ret; } notifyid = ret; @@ -297,8 +299,10 @@ void rproc_free_vring(struct rproc_vring *rvring) struct rproc *rproc = rvring->rvdev->rproc; int idx = rvring->rvdev->vring - rvring; struct fw_rsc_vdev *rsc; + struct device *dma_dev; - dma_free_coherent(rproc->dev.parent, size, rvring->va, rvring->dma); + dma_dev = rproc_subdev_lookup(rproc, "vring"); + dma_free_coherent(dma_dev, size, rvring->va, rvring->dma); idr_remove(&rproc->notifyids, rvring->notifyid); /* reset resource entry info */ @@ -572,6 +576,7 @@ static int rproc_handle_carveout(struct rproc *rproc, { struct rproc_mem_entry *carveout, *mapping; struct device *dev = &rproc->dev; + struct device *dma_dev; dma_addr_t dma; void *va; int ret; @@ -594,7 +599,8 @@ static int rproc_handle_carveout(struct rproc *rproc, if (!carveout) return -ENOMEM; - va = dma_alloc_coherent(dev->parent, rsc->len, &dma, GFP_KERNEL); + dma_dev = rproc_subdev_lookup(rproc, "carveout"); + va = dma_alloc_coherent(dma_dev, rsc->len, &dma, GFP_KERNEL); if (!va) { dev_err(dev->parent, "dma_alloc_coherent err: %d\n", rsc->len); ret = -ENOMEM; @@ -682,7 +688,7 @@ static int rproc_handle_carveout(struct rproc *rproc, free_mapping: kfree(mapping); dma_free: - dma_free_coherent(dev->parent, rsc->len, va, dma); + dma_free_coherent(dma_dev, rsc->len, va, dma); free_carv: kfree(carveout); return ret; @@ -766,6 +772,7 @@ static void rproc_resource_cleanup(struct rproc *rproc) { struct rproc_mem_entry *entry, *tmp; struct device *dev = &rproc->dev; + struct device *dma_dev; /* clean up debugfs trace entries */ list_for_each_entry_safe(entry, tmp, &rproc->traces, node) { @@ -791,9 +798,9 @@ static void rproc_resource_cleanup(struct rproc *rproc) } /* clean up carveout allocations */ + dma_dev = rproc_subdev_lookup(rproc, "carveout"); list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) { - dma_free_coherent(dev->parent, entry->len, entry->va, - entry->dma); + dma_free_coherent(dma_dev, entry->len, entry->va, entry->dma); list_del(&entry->node); kfree(entry); } @@ -1329,6 +1336,156 @@ struct rproc *rproc_get_by_phandle(phandle phandle) #endif EXPORT_SYMBOL(rproc_get_by_phandle); +/* + * resource structure of rproc_subdev is used for identify the right subdevice + * that has the dma coherent memory. + */ +static int rproc_subdev_match(struct device *dev, void *data) +{ + char *sub_name; + + if (!dev_name(dev)) + return 0; + + sub_name = strpbrk(dev_name(dev), "#"); + if (!sub_name) + return 0; + + return !strcmp(++sub_name, (char *)data); +} + +/* + * find the subdevice child dma coherent memory that match with name region + * the rproc parent is the default device, if there is no match + */ +struct device *rproc_subdev_lookup(struct rproc *rproc, const char *name) +{ + struct device *dev; + + dev = device_find_child(rproc->dev.parent, (void *)name, + rproc_subdev_match); + if (dev) { + /* decrement the matched device's refcount back */ + put_device(dev); + return dev; + } + + return rproc->dev.parent; +} +EXPORT_SYMBOL(rproc_subdev_lookup); + +/** + * rproc_subdev_release() - release the existence of a subdevice + * + * @dev: the subdevice's dev + */ +static void rproc_subdev_release(struct device *dev) +{ + struct rproc_subdev *sub = to_subdevice(dev); + + kfree(sub); +} + +/** + * rproc_subdev_unregister() - unregister sub-device of remote processor + * + * @dev: rproc sub-device + * @data: Not use (just to be compliant with device_for_each_child) + * + * This function is called by device_for_each_child function when unregister + * remote processor. + */ +static int rproc_subdev_unregister(struct device *dev, void *data) +{ + struct rproc_subdev *sub = to_subdevice(dev); + struct rproc *rproc = data; + + if (dev != &(rproc->dev)) + rproc_subdev_del(sub); + return 0; +} + +/** + * rproc_subdev_add() - add a sub-device on remote processor + * + * @rproc: the parent remote processor + * @res: resource allow to define the dma coherent memory of sub-device + * + * This function add a sub-device child on rproc parent. This sub-device allow + * to define a new dma coherent memory area. when the rproc would alloc a + * dma coherent memory it's find the subdevice that match with physical memory + * asked (if there is no children that match, the rproc is the default device) + * + * Returns the sub-device handle on success, and error on failure. + */ +struct rproc_subdev *rproc_subdev_add(struct rproc *rproc, struct resource *res) +{ + struct rproc_subdev *sub; + int ret; + + if (!res || res->flags != IORESOURCE_MEM || res->name == NULL) { + ret = -EINVAL; + goto err; + } + + sub = kzalloc(sizeof(*sub), GFP_KERNEL); + if (!sub) { + ret = -ENOMEM; + goto err; + } + + sub->rproc = rproc; + sub->res = res; + sub->dev.parent = rproc->dev.parent; + sub->dev.release = rproc_subdev_release; + dev_set_name(&sub->dev, "%s#%s", dev_name(sub->dev.parent), res->name); + dev_set_drvdata(&sub->dev, sub); + + ret = device_register(&sub->dev); + if (ret) + goto err_dev; + + if (!devm_request_mem_region(&sub->dev, res->start, + resource_size(res), + dev_name(&sub->dev))) { + dev_err(&rproc->dev, "failed to get memory region\n"); + ret = -EINVAL; + goto err_dev; + } + + ret = dmam_declare_coherent_memory(&sub->dev, + res->start, res->start, + resource_size(res), + DMA_MEMORY_MAP | + DMA_MEMORY_EXCLUSIVE); + if (ret < 0) + goto err_dev; + + return sub; + +err_dev: + put_device(&sub->dev); +err: + dev_err(&rproc->dev, "unable to register subdev %s, err = %d\n", + (res && res->name) ? res->name : "unnamed", ret); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(rproc_subdev_add); + +/** + * rproc_subdev_del() - delete a sub-device of remote processor + * + * @subdev: rproc sub-device + */ +void rproc_subdev_del(struct rproc_subdev *subdev) +{ + if (get_device(&subdev->dev)) { + device_unregister(&subdev->dev); + put_device(&subdev->dev); + } +} +EXPORT_SYMBOL(rproc_subdev_del); + /** * rproc_set_fw_name() - change rproc fw name * @rproc: rproc handle @@ -1618,6 +1775,9 @@ int rproc_del(struct rproc *rproc) kfree(rproc->cached_table); rproc->cached_table = NULL; + device_for_each_child(rproc->dev.parent, rproc, + rproc_subdev_unregister); + /* the rproc is downref'ed as soon as it's removed from the klist */ mutex_lock(&rproc_list_mutex); list_del(&rproc->node);