From patchwork Thu Nov 9 23:38:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 10052097 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 D0EC76032D for ; Thu, 9 Nov 2017 23:40:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C3E072B1CF for ; Thu, 9 Nov 2017 23:40:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B86542B1CD; Thu, 9 Nov 2017 23:40:35 +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=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, 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 4F7C52B1CB for ; Thu, 9 Nov 2017 23:40:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755228AbdKIXjn (ORCPT ); Thu, 9 Nov 2017 18:39:43 -0500 Received: from mail-wm0-f66.google.com ([74.125.82.66]:52437 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755327AbdKIXi5 (ORCPT ); Thu, 9 Nov 2017 18:38:57 -0500 Received: by mail-wm0-f66.google.com with SMTP id t139so20954057wmt.1; Thu, 09 Nov 2017 15:38:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3S+b2d92L3en/XmtCvLLNsqQ3W4ErCZ+uwIt94oAOn4=; b=Rzb3xTLDwrendymFKFKI66TegQuD7SipkyAyebH4nW3joeelx2QinXISj/uNK0Z9Bb UsMyGo1ARlZBC4SWRwpwuvXI2ydZBADilyxgrHdiOs5ueyWs41J8yfntexHgyq4Wi1go KN8GsOQn1haInUCxTltpkBqku0ZiqbHVpW6KJyjFlQ0wb++kKZjYiFjbcxw+bMmGz4tq JHIwdP+KGDP0y7yri7IalfqORulZJ5QNsHCMoxd0ZaLphklHJ1M7EZ6ak5VRLln3UXqC 3j1bYQoYgvWKrwhzD+sEGcFv/t/U0Vg1crnHpajBYOvrqhJuclRnBGb+OTGktIKe2xIZ wasg== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=3S+b2d92L3en/XmtCvLLNsqQ3W4ErCZ+uwIt94oAOn4=; b=tR8OtHGwql2/NBF4UFUV2j1MDFe2s3hz3X66CRd3OctI0f+l7G4lsk85rq4JqNw1hB ACrT1O5/vnjpr5rBPuf0sEp0zpHF1O4/vQt0yetIyckrjGCfTMcQJNlxu4/bFsseOZIw FcFkCkNfGPnh+KXurnYEsnzm7Q/pCHnxTYExPf3Lkx08tFfUIS7J5RRL4nZ+0nOj8MHh YyU1CUjfUY5tfmi00nFojwHvyKwQszWna8QnY2qxtgE5UpnxisTQoeoMkC9G5Othe+ZI 3J3ZbfeY94RDMLEieD9CZRGvQTfT5zGfKn/6eBY4tcmk4a5c9Ecbll74mkOWfoApeXNY t11Q== X-Gm-Message-State: AJaThX4w/9xGgp8Ybqo8dwRlEQ/WbrAq8kSTW5i2iXM5fVWUG65JaPw5 +gGF/nmM3ukMz1B4xg29Fyk= X-Google-Smtp-Source: ABhQp+QWtjqKAEDojJfm/gnl3acY5PUh9DiCsEn34AFaV24laq/DZOTJngYar9tpeOgc+nrtBbjqvA== X-Received: by 10.28.138.12 with SMTP id m12mr1200471wmd.134.1510270735590; Thu, 09 Nov 2017 15:38:55 -0800 (PST) Received: from Pali-Latitude.lan (pali.kolej.mff.cuni.cz. [78.128.193.202]) by smtp.gmail.com with ESMTPSA id 55sm9578181wrw.60.2017.11.09.15.38.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 09 Nov 2017 15:38:55 -0800 (PST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Ming Lei , "Luis R. Rodriguez" , Greg Kroah-Hartman , Kalle Valo , David Gnedt , Michal Kazior , Daniel Wagner , Tony Lindgren , Sebastian Reichel , Pavel Machek , Ivaylo Dimitrov , Aaro Koskinen , Grazvydas Ignotas Cc: linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org, =?UTF-8?q?Pali=20Roh=C3=A1r?= Subject: [PATCH v2 5/6] firmware: Add request_firmware_prefer_user() function Date: Fri, 10 Nov 2017 00:38:27 +0100 Message-Id: <1510270708-14377-6-git-send-email-pali.rohar@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1510270708-14377-1-git-send-email-pali.rohar@gmail.com> References: <1482598381-16513-1-git-send-email-pali.rohar@gmail.com> <1510270708-14377-1-git-send-email-pali.rohar@gmail.com> 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 This function works pretty much like request_firmware(), but it prefer usermode helper. If usermode helper fails then it fallback to direct access. Useful for dynamic or model specific firmware data. Signed-off-by: Pali Rohár --- drivers/base/firmware_class.c | 45 +++++++++++++++++++++++++++++++++++++++-- include/linux/firmware.h | 9 +++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 4b57cf5..c3a9fe5 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -195,6 +195,11 @@ static int __fw_state_check(struct fw_state *fw_st, enum fw_status status) #endif #define FW_OPT_NO_WARN (1U << 3) #define FW_OPT_NOCACHE (1U << 4) +#ifdef CONFIG_FW_LOADER_USER_HELPER +#define FW_OPT_PREFER_USER (1U << 5) +#else +#define FW_OPT_PREFER_USER 0 +#endif struct firmware_cache { /* firmware_buf instance will be added into the below list */ @@ -1214,13 +1219,26 @@ static void fw_abort_batch_reqs(struct firmware *fw) if (ret <= 0) /* error or already assigned */ goto out; - ret = fw_get_filesystem_firmware(device, fw->priv); + if (opt_flags & FW_OPT_PREFER_USER) { + ret = fw_load_from_user_helper(fw, name, device, opt_flags, timeout); + if (ret && !(opt_flags & FW_OPT_NO_WARN)) { + dev_warn(device, + "User helper firmware load for %s failed with error %d\n", + name, ret); + dev_warn(device, "Falling back to direct firmware load\n"); + } + } else { + ret = -EINVAL; + } + + if (ret) + ret = fw_get_filesystem_firmware(device, fw->priv); if (ret) { if (!(opt_flags & FW_OPT_NO_WARN)) dev_warn(device, "Direct firmware load for %s failed with error %d\n", name, ret); - if (opt_flags & FW_OPT_USERHELPER) { + if ((opt_flags & FW_OPT_USERHELPER) && !(opt_flags & FW_OPT_PREFER_USER)) { dev_warn(device, "Falling back to user helper\n"); ret = fw_load_from_user_helper(fw, name, device, opt_flags); @@ -1329,6 +1347,29 @@ int request_firmware_direct(const struct firmware **firmware_p, EXPORT_SYMBOL(request_firmware_into_buf); /** + * request_firmware_prefer_user: - prefer usermode helper for loading firmware + * @firmware_p: pointer to firmware image + * @name: name of firmware file + * @device: device for which firmware is being loaded + * + * This function works pretty much like request_firmware(), but it prefer + * usermode helper. If usermode helper fails then it fallback to direct access. + * Useful for dynamic or model specific firmware data. + **/ +int request_firmware_prefer_user(const struct firmware **firmware_p, + const char *name, struct device *device) +{ + int ret; + + __module_get(THIS_MODULE); + ret = _request_firmware(firmware_p, name, device, NULL, 0, + FW_OPT_UEVENT | FW_OPT_PREFER_USER); + module_put(THIS_MODULE); + return ret; +} +EXPORT_SYMBOL_GPL(request_firmware_prefer_user); + +/** * release_firmware: - release the resource associated with a firmware image * @fw: firmware resource to release **/ diff --git a/include/linux/firmware.h b/include/linux/firmware.h index d450808..8584528 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -48,6 +48,8 @@ int request_firmware_nowait( void (*cont)(const struct firmware *fw, void *context)); int request_firmware_direct(const struct firmware **fw, const char *name, struct device *device); +int request_firmware_prefer_user(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); @@ -78,6 +80,13 @@ static inline int request_firmware_direct(const struct firmware **fw, return -EINVAL; } +static inline int request_firmware_prefer_user(const struct firmware **fw, + const char *name, + struct device *device) +{ + return -EINVAL; +} + static inline int request_firmware_into_buf(const struct firmware **firmware_p, const char *name, struct device *device, void *buf, size_t size) {