Received: by 2002:ac0:a581:0:0:0:0:0 with SMTP id m1-v6csp941700imm; Fri, 22 Jun 2018 07:51:20 -0700 (PDT) X-Google-Smtp-Source: ADUXVKLps2ALIQ96lYJ8HZd2ucQhODXg8cHfkG8A6MiwW1hyboAgcPexY4/mdq1zbilNKRJlSLjU X-Received: by 2002:a63:6807:: with SMTP id d7-v6mr1653371pgc.7.1529679080686; Fri, 22 Jun 2018 07:51:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529679080; cv=none; d=google.com; s=arc-20160816; b=ArtdcOeuhEENYHS5G3ziSycmz4I2FGNayGRsPq5CcZSFrP/RuVTWzf6n/obgMvjrPl wHL926LnvJ804FwRIxsmNUmFwQustiTkxlShHOSO/J7JZf4Kd2hOsCm020Bwhn+/djos EYj23yM75oYskCxqlcWemtjx3V/bGy1Hx6b6mO9pL+lqFdwX67RxFJhEWqRE4Gz0iTJF /CgFW+LwevPuSwmWxltGEhBcySSLzf7q1u8TlXeD7Bv5X5jEu3SgdnMoVIdFobUBx9jv owJO62CTNaoTnEFzncteoqV98j6rOibXpdACb85KY5VsjTZvdcQRK0Wm1HxEvjrqlMNG sUHQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=RiF+/qx7MNjiOwr6uGnjwI59QTrQWdt5syNh4mdVPds=; b=HBDhLaK9SY/S5lMJPmu6k9d0FhUxXuYAJWbV+D2e9EBOARWF+6bTVdtdlpxPhup033 pNUXc0hes9CcBTe+ncrJjc6Nq06z7ypRl6bduV9hUGeYqeQiJ+IEIbPKUZRUPeGuP6Pq Sj3cMb1rntVcbH1BcUspWhgpI/mMdARC5H4xml3yElhs2BDkH10kuc2ZajiOa9Upyy8i hy4dRUTiLtDmwVdxuY6Bs6Gk74jTVbSJKNcpAhY5xLi0q+0JUTbjtbWxmL1su1OMKzuk fg0cHGNBB7OGf6o7DhhSx7Fg5fUepOAjtdz1Ipee366ZvL8oX1bGoD8vnr4S8H2evIss O+/Q== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=collabora.co.uk Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j66-v6si7592635pfc.243.2018.06.22.07.51.06; Fri, 22 Jun 2018 07:51:20 -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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=collabora.co.uk Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933664AbeFVOuD (ORCPT + 99 others); Fri, 22 Jun 2018 10:50:03 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:54326 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932264AbeFVOuA (ORCPT ); Fri, 22 Jun 2018 10:50:00 -0400 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: sre) with ESMTPSA id D8D09288FB4 From: Sebastian Reichel To: "Luis R. Rodriguez" , Greg Kroah-Hartman , Dan Williams , Vinod Koul Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org, =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= , Sebastian Reichel Subject: [PATCH 1/2] firmware: add more flexible request_firmware_async function Date: Fri, 22 Jun 2018 16:49:50 +0200 Message-Id: <20180622144951.17464-2-sebastian.reichel@collabora.co.uk> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180622144951.17464-1-sebastian.reichel@collabora.co.uk> References: <20180622144951.17464-1-sebastian.reichel@collabora.co.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Rafał Miłecki So far we got only one function for loading firmware asynchronously: request_firmware_nowait. It didn't allow much customization of firmware loading process - there is only one bool uevent argument. Moreover this bool also controls user helper in an unclear way. Some drivers need more flexible helper providing more options. This includes control over uevent or warning for the missing firmware. Of course this list may grow up in the future. To handle this easily this patch adds a generic request_firmware_async function. It takes struct with options as an argument which will allow extending it in the future without massive changes. This is a really cheap change (no new independent API) which works nicely with the existing code. The old request_firmware_nowait is kept as a simple helper calling new helper. Signed-off-by: Rafał Miłecki [rebased to v4.18-rc1] Signed-off-by: Sebastian Reichel --- drivers/base/firmware_loader/main.c | 41 ++++++++++++++++++++++++----- include/linux/firmware.h | 20 ++++++++++++++ 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index 0943e7065e0e..e1d2ba570ea3 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -774,7 +774,7 @@ static void request_firmware_work_func(struct work_struct *work) _request_firmware(&fw, fw_work->name, fw_work->device, NULL, 0, fw_work->opt_flags); fw_work->cont(fw, fw_work->context); - put_device(fw_work->device); /* taken in request_firmware_nowait() */ + put_device(fw_work->device); /* taken in __request_firmware_nowait() */ module_put(fw_work->module); kfree_const(fw_work->name); @@ -782,8 +782,9 @@ static void request_firmware_work_func(struct work_struct *work) } /** - * request_firmware_nowait() - asynchronous version of request_firmware + * __request_firmware_nowait() - asynchronous version of request_firmware * @module: module requesting the firmware + * @opt_flags: flags that control firmware loading process, see FW_OPT_* * @uevent: sends uevent to copy the firmware image if this flag * is non-zero else the firmware copy must be done manually. * @name: name of firmware file @@ -804,13 +805,14 @@ static void request_firmware_work_func(struct work_struct *work) * * - can't sleep at all if @gfp is GFP_ATOMIC. **/ -int -request_firmware_nowait( - struct module *module, bool uevent, +static int +__request_firmware_nowait( + struct module *module, unsigned int opt_flags, const char *name, struct device *device, gfp_t gfp, void *context, void (*cont)(const struct firmware *fw, void *context)) { struct firmware_work *fw_work; + bool uevent = !!(opt_flags & FW_OPT_UEVENT); fw_work = kzalloc(sizeof(struct firmware_work), gfp); if (!fw_work) @@ -825,8 +827,7 @@ request_firmware_nowait( fw_work->device = device; fw_work->context = context; fw_work->cont = cont; - fw_work->opt_flags = FW_OPT_NOWAIT | - (uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER); + fw_work->opt_flags = FW_OPT_NOWAIT | opt_flags; if (!uevent && fw_cache_is_setup(device, name)) { kfree_const(fw_work->name); @@ -845,8 +846,34 @@ request_firmware_nowait( schedule_work(&fw_work->work); return 0; } + +int request_firmware_nowait(struct module *module, bool uevent, + const char *name, struct device *device, gfp_t gfp, + void *context, + void (*cont)(const struct firmware *fw, void *context)) +{ + unsigned int opt_flags = (uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER); + + return __request_firmware_nowait(module, opt_flags, name, device, gfp, + context, cont); +} EXPORT_SYMBOL(request_firmware_nowait); +int __request_firmware_async(struct module *module, const char *name, + struct firmware_opts *fw_opts, struct device *dev, + void *context, + void (*cont)(const struct firmware *fw, void *context)) +{ + unsigned int opt_flags = FW_OPT_UEVENT; + + if (fw_opts->optional) + opt_flags |= FW_OPT_NO_WARN; + + return __request_firmware_nowait(module, opt_flags, name, dev, + GFP_KERNEL, context, cont); +} +EXPORT_SYMBOL(__request_firmware_async); + #ifdef CONFIG_PM_SLEEP static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); diff --git a/include/linux/firmware.h b/include/linux/firmware.h index 2dd566c91d44..ad2fc6e7fee7 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -27,6 +27,10 @@ struct builtin_fw { unsigned long size; }; +struct firmware_opts { + bool optional; +}; + /* We have to play tricks here much like stringify() to get the __COUNTER__ macro to be expanded as we want it */ #define __fw_concat1(x, y) x##y @@ -52,6 +56,10 @@ int request_firmware_direct(const struct firmware **fw, const char *name, struct device *device); int request_firmware_into_buf(const struct firmware **firmware_p, const char *name, struct device *device, void *buf, size_t size); +int __request_firmware_async(struct module *module, const char *name, + struct firmware_opts *fw_opts, struct device *dev, + void *context, + void (*cont)(const struct firmware *fw, void *context)); void release_firmware(const struct firmware *fw); #else @@ -94,8 +102,20 @@ static inline int request_firmware_into_buf(const struct firmware **firmware_p, return -EINVAL; } +int __request_firmware_async(struct module *module, const char *name, + struct firmware_opts *fw_opts, struct device *dev, + void *context, + void (*cont)(const struct firmware *fw, void *context)) +{ + return -EINVAL; +} + #endif int firmware_request_cache(struct device *device, const char *name); +#define request_firmware_async(name, fw_opts, dev, context, cont) \ + __request_firmware_async(THIS_MODULE, name, fw_opts, dev, \ + context, cont) + #endif -- 2.17.1