From patchwork Mon Jul 31 15:09:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= X-Patchwork-Id: 9872055 X-Patchwork-Delegate: kvalo@adurom.com 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 B87C3602F0 for ; Mon, 31 Jul 2017 15:12:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9C39A26E3A for ; Mon, 31 Jul 2017 15:12:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 90B39285F5; Mon, 31 Jul 2017 15:12:12 +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.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM 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 1E92526E3A for ; Mon, 31 Jul 2017 15:12:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752517AbdGaPMA (ORCPT ); Mon, 31 Jul 2017 11:12:00 -0400 Received: from mail-lf0-f65.google.com ([209.85.215.65]:35121 "EHLO mail-lf0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752045AbdGaPLV (ORCPT ); Mon, 31 Jul 2017 11:11:21 -0400 Received: by mail-lf0-f65.google.com with SMTP id w199so12507227lff.2; Mon, 31 Jul 2017 08:11:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=R3Pfw13Bdk/6sg6mNxYdNi8zsP95tNR83ufl229yj5I=; b=Ys5QC/JOQghJ79LhaOC9XSrwaASYj/jLYeorLjpUaYkPnWoEdxTB2OqTPc25QLLTha cn+yX8EEMGEeqzpCeDGcTMkM+NJK9oUIZUkHYPhFgHnZzxxuC1AF8OM6k8b0BEeGzLzZ Majd6mCLeiXTmth9MlUp6+PFUyX0kwmVbcgsuDhHqaVTNRDy7MW8WpCB6Cb72E1h/mHT O7LAY5djWP6+0KIBwI88Up5kqyXkfy2AtsxYFGlS4t826O7VMxZCBDXXQodcmJvqRpSI sEHe/mnEZLpAjc0e/MLlZf9BzclEN3zI8hXccUBZOgXgTZuvxgMynltCBZi0niRDH28t rMZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=R3Pfw13Bdk/6sg6mNxYdNi8zsP95tNR83ufl229yj5I=; b=kI3MqSqgfCoje37fulFKaqJ7ALYZ4A95wIMcm0TgrRA6GtS+Z9Xut/ZIu4UtVuJEpE 88KmVJs2Py3iljDNWgRo13pFot9Ak+0U4tlukC0Wiotb+c+RdXEH33esa+5wSFD5cJgZ DomwDou73Uw3+K/QcGcfMZZPIuEkbvu0ZXWOOWbS+Koo2QTDQs5iZ2ZaIZZ1FmWuYptV paXRo6JeSgWq2Dt5VWIQXUVgG4biaum5VoGQqcQFgHtlhxvCglU2plCSXdkTExVxZjlC vxCiIftg77BbOOvIUbEuz6fUt94dUhmTty0cD2vSIftQcFv0JEBlI1BOxmMRaOkR14+P VkDQ== X-Gm-Message-State: AIVw111sefCb7+bpaxYfTpVsAGNPef9HEoUY29Ux4cubjgl2ZbSaPH94 AiyRrUuD/9Vjrw== X-Received: by 10.46.22.88 with SMTP id 24mr6389061ljw.9.1501513879263; Mon, 31 Jul 2017 08:11:19 -0700 (PDT) Received: from linux-samsung.lan (ip-194-187-74-233.konfederacka.maverick.com.pl. [194.187.74.233]) by smtp.gmail.com with ESMTPSA id b126sm5440328lfe.39.2017.07.31.08.11.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 31 Jul 2017 08:11:18 -0700 (PDT) From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= To: "Luis R . Rodriguez" , Greg Kroah-Hartman Cc: Bjorn Andersson , Daniel Wagner , David Woodhouse , Arend van Spriel , "Rafael J . Wysocki" , yi1.li@linux.intel.com, atull@kernel.org, Moritz Fischer , pmladek@suse.com, Johannes Berg , emmanuel.grumbach@intel.com, luciano.coelho@intel.com, Kalle Valo , luto@kernel.org, Linus Torvalds , Kees Cook , AKASHI Takahiro , David Howells , pjones@redhat.com, Hans de Goede , alan@linux.intel.com, tytso@mit.edu, lkml , Franky Lin , Hante Meuleman , Chi-Hsien Lin , Wright Feng , Pieter-Paul Giesberts , linux-wireless@vger.kernel.org, netdev@vger.kernel.org, =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Subject: [PATCH V5 1/2] firmware: add more flexible request_firmware_async function Date: Mon, 31 Jul 2017 17:09:44 +0200 Message-Id: <20170731150945.8925-1-zajec5@gmail.com> X-Mailer: git-send-email 2.11.0 MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- V3: Don't expose all FW_OPT_* flags. As Luis noted we want a struct so add struct firmware_opts for real flexibility. Thank you Luis for your review! V5: Rebase, update commit message, resend after drvdata discussion --- drivers/base/firmware_class.c | 43 ++++++++++++++++++++++++++++++++++--------- include/linux/firmware.h | 15 ++++++++++++++- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index b9f907eedbf7..cde85b05e4cb 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -1375,7 +1375,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); @@ -1383,10 +1383,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 - * @uevent: sends uevent to copy the firmware image if this flag - * is non-zero else the firmware copy must be done manually. + * @opt_flags: flags that control firmware loading process, see FW_OPT_* * @name: name of firmware file * @device: device for which firmware is being loaded * @gfp: allocation flags @@ -1405,9 +1404,9 @@ 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)) { @@ -1426,8 +1425,7 @@ request_firmware_nowait( fw_work->device = device; fw_work->context = context; fw_work->cont = cont; - fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK | - (uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER); + fw_work->opt_flags = FW_OPT_NOWAIT | opt_flags; if (!try_module_get(module)) { kfree_const(fw_work->name); @@ -1440,8 +1438,35 @@ 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 = FW_OPT_FALLBACK | + (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 b1f9f0ccb8ac..a32b6e67462d 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -82,6 +82,19 @@ static inline int request_firmware_into_buf(const struct firmware **firmware_p, { return -EINVAL; } - #endif + +struct firmware_opts { + bool optional; +}; + +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)); + +#define request_firmware_async(name, fw_opts, dev, context, cont) \ + __request_firmware_async(THIS_MODULE, name, fw_opts, dev, \ + context, cont) + #endif