From patchwork Tue Oct 11 13:39:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Redfearn X-Patchwork-Id: 9371029 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D5E9960865 for ; Tue, 11 Oct 2016 13:41:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C857029B20 for ; Tue, 11 Oct 2016 13:41:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BC50429C26; Tue, 11 Oct 2016 13:41:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 56B0A29BE7 for ; Tue, 11 Oct 2016 13:41:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753088AbcJKNkM (ORCPT ); Tue, 11 Oct 2016 09:40:12 -0400 Received: from mailapp02.imgtec.com ([217.156.133.132]:63576 "EHLO mailapp01.imgtec.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752618AbcJKNkJ (ORCPT ); Tue, 11 Oct 2016 09:40:09 -0400 Received: from HHMAIL03.hh.imgtec.org (unknown [10.44.0.21]) by Forcepoint Email with ESMTPS id AA83512A4C815; Tue, 11 Oct 2016 14:39:47 +0100 (IST) Received: from HHMAIL01.hh.imgtec.org (10.100.10.19) by HHMAIL03.hh.imgtec.org (10.44.0.21) with Microsoft SMTP Server (TLS) id 14.3.294.0; Tue, 11 Oct 2016 14:39:50 +0100 Received: from mredfearn-linux.le.imgtec.org (10.150.130.83) by HHMAIL01.hh.imgtec.org (10.100.10.21) with Microsoft SMTP Server (TLS) id 14.3.294.0; Tue, 11 Oct 2016 14:39:49 +0100 From: Matt Redfearn To: Bjorn Andersson , Ohad Ben-Cohen CC: , , "Matt Redfearn" Subject: [PATCH 1/4] remoteproc: Use fixed length field for firmware name Date: Tue, 11 Oct 2016 14:39:42 +0100 Message-ID: <1476193185-32107-2-git-send-email-matt.redfearn@imgtec.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1476193185-32107-1-git-send-email-matt.redfearn@imgtec.com> References: <1476193185-32107-1-git-send-email-matt.redfearn@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [10.150.130.83] Sender: linux-remoteproc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-remoteproc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Storage of the firmware name was inconsistent, either storing a pointer to a name stored with unknown ownership, or a variable length tacked onto the end of the struct proc allocated in rproc_alloc. In preparation for allowing the firmware of an already allocated struct rproc to be changed, the easiest way to allow reallocation of the name is to switch to a fixed length buffer held as part of the struct rproc. That way we can either copy the provided firmware name into it, or print into it based on a name template. A new function, rproc_set_firmware_name() is introduced for this purpose, and that logic removed from rproc_alloc(). Signed-off-by: Matt Redfearn --- drivers/remoteproc/remoteproc_core.c | 64 +++++++++++++++++++++++------------- include/linux/remoteproc.h | 4 ++- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index fe0539ed9cb5..48cd9d5afb69 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1309,6 +1309,42 @@ static void rproc_type_release(struct device *dev) kfree(rproc); } +/** + * rproc_set_firmware_name() - helper to create a valid firmare name + * @rproc: remote processor + * @firmware: name of firmware file, can be NULL + * + * If the caller didn't pass in a firmware name then construct a default name, + * otherwise the provided name is copied into the firmware field of struct + * rproc. If the name is too long to fit, -EINVAL is returned. + * + * Returns 0 on success and an appropriate error code otherwise. + */ +static int rproc_set_firmware_name(struct rproc *rproc, const char *firmware) +{ + char *cp, *template = "rproc-%s-fw"; + int name_len; + + if (firmware) { + name_len = strlen(firmware); + cp = memchr(firmware, '\n', name_len); + if (cp) + name_len = cp - firmware; + + if (name_len > RPROC_MAX_FIRMWARE_NAME_LEN) + return -EINVAL; + + strncpy(rproc->firmware, firmware, name_len); + rproc->firmware[name_len] = '\0'; + } else { + snprintf(rproc->firmware, RPROC_MAX_FIRMWARE_NAME_LEN, + template, rproc->name); + } + + dev_dbg(&rproc->dev, "Using firmware %s\n", rproc->firmware); + return 0; +} + static struct device_type rproc_type = { .name = "remoteproc", .release = rproc_type_release, @@ -1342,35 +1378,14 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, const char *firmware, int len) { struct rproc *rproc; - char *p, *template = "rproc-%s-fw"; - int name_len = 0; if (!dev || !name || !ops) return NULL; - if (!firmware) - /* - * Make room for default firmware name (minus %s plus '\0'). - * If the caller didn't pass in a firmware name then - * construct a default name. We're already glomming 'len' - * bytes onto the end of the struct rproc allocation, so do - * a few more for the default firmware name (but only if - * the caller doesn't pass one). - */ - name_len = strlen(name) + strlen(template) - 2 + 1; - - rproc = kzalloc(sizeof(struct rproc) + len + name_len, GFP_KERNEL); + rproc = kzalloc(sizeof(struct rproc) + len, GFP_KERNEL); if (!rproc) return NULL; - if (!firmware) { - p = (char *)rproc + sizeof(struct rproc) + len; - snprintf(p, name_len, template, name); - } else { - p = (char *)firmware; - } - - rproc->firmware = p; rproc->name = name; rproc->ops = ops; rproc->priv = &rproc[1]; @@ -1389,6 +1404,11 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, dev_set_name(&rproc->dev, "remoteproc%d", rproc->index); + if (rproc_set_firmware_name(rproc, firmware)) { + put_device(&rproc->dev); + return NULL; + } + atomic_set(&rproc->power, 0); /* Set ELF as the default fw_ops handler */ diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index 1c457a8dd5a6..7a6f9ad55011 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -42,6 +42,8 @@ #include #include +#define RPROC_MAX_FIRMWARE_NAME_LEN 128 + /** * struct resource_table - firmware resource table header * @ver: version number @@ -416,7 +418,7 @@ struct rproc { struct list_head node; struct iommu_domain *domain; const char *name; - const char *firmware; + char firmware[RPROC_MAX_FIRMWARE_NAME_LEN]; void *priv; const struct rproc_ops *ops; struct device dev;