From: Daniel Wagner <wagi@monom.org>
To: linux-kernel@vger.kernel.org
Cc: Ming Lei <ming.lei@canonical.com>,
"Luis R . Rodriguez" <mcgrof@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Srivatsa S . Bhat" <srivatsa.bhat@linux.vnet.ibm.com>,
"Rafael J . Wysocki" <rjw@sisk.pl>,
Daniel Vetter <daniel.vetter@intel.com>,
Takashi Iwai <tiwai@suse.com>,
Bjorn Andersson <bjorn.andersson@linaro.org>,
Arend van Spriel <arend.vanspriel@broadcom.com>,
Daniel Wagner <daniel.wagner@bmw-carit.de>
Subject: [PATCH v5 5/5] firmware: do not use fw_lock for fw_umh protection
Date: Fri, 9 Sep 2016 14:12:24 +0200 [thread overview]
Message-ID: <1473423144-21734-6-git-send-email-wagi@monom.org> (raw)
In-Reply-To: <1473423144-21734-1-git-send-email-wagi@monom.org>
From: Daniel Wagner <daniel.wagner@bmw-carit.de>
fw_lock is to use to protect 'corner cases' inside firmware_class. It
is not exactly clear what those corner cases are nor what it exactly
protects. fw_umh can be used without needing the fw_lock to protect
its state transition and wake ups.
fw_umh is holds the state in status and the completion is used to
wake up all waiters (in this case that is the user land helper so only
one). This operation has to be 'atomic' to avoid races. We can do this
by using swait which takes care we don't miss any wake up.
We use also swait instead of wait because don't need all the additional
features wait provides.
Cc: Ming Lei <ming.lei@canonical.com>
Cc: Luis R. Rodriguez <mcgrof@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Daniel Wagner <daniel.wagner@bmw-carit.de>
---
drivers/base/firmware_class.c | 50 +++++++++++++------------------------------
1 file changed, 15 insertions(+), 35 deletions(-)
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8f5838c..1a28070 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -30,6 +30,7 @@
#include <linux/syscore_ops.h>
#include <linux/reboot.h>
#include <linux/security.h>
+#include <linux/swait.h>
#include <generated/utsrelease.h>
@@ -108,13 +109,13 @@ enum {
};
struct fw_umh {
- struct completion completion;
+ struct swait_queue_head wq;
u8 status;
};
static void fw_umh_init(struct fw_umh *fw_umh)
{
- init_completion(&fw_umh->completion);
+ init_swait_queue_head(&fw_umh->wq);
fw_umh->status = FW_UMH_UNKNOWN;
}
@@ -123,13 +124,19 @@ static int __fw_umh_check(struct fw_umh *fw_umh, unsigned long status)
return fw_umh->status == status;
}
+static inline bool __fw_umh_is_done(unsigned long status)
+{
+ return status == FW_UMH_DONE || status == FW_UMH_ABORTED;
+}
+
static int fw_umh_wait_timeout(struct fw_umh *fw_umh, long timeout)
{
int ret;
- ret = wait_for_completion_interruptible_timeout(&fw_umh->completion,
- timeout);
- if (ret != 0 && READ_ONCE(fw_umh->status) == FW_UMH_ABORTED)
+ ret = swait_event_interruptible_timeout(fw_umh->wq,
+ __fw_umh_is_done(READ_ONCE(fw_umh->status)),
+ timeout);
+ if (ret != 0 && fw_umh->status == FW_UMH_ABORTED)
return -ENOENT;
return ret;
@@ -141,7 +148,7 @@ static void __fw_umh_set(struct fw_umh *fw_umh,
WRITE_ONCE(fw_umh->status, status);
if (status == FW_UMH_DONE || status == FW_UMH_ABORTED)
- complete_all(&fw_umh->completion);
+ swake_up(&fw_umh->wq);
}
#define fw_umh_start(fw_umh) \
@@ -367,14 +374,6 @@ static const char * const fw_path[] = {
module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
-static void fw_finish_direct_load(struct device *device,
- struct firmware_buf *buf)
-{
- mutex_lock(&fw_lock);
- fw_umh_done(&buf->fw_umh);
- mutex_unlock(&fw_lock);
-}
-
static int
fw_get_filesystem_firmware(struct device *device, struct firmware_buf *buf)
{
@@ -421,7 +420,7 @@ fw_get_filesystem_firmware(struct device *device, struct firmware_buf *buf)
}
dev_dbg(device, "direct-loading %s\n", buf->fw_id);
buf->size = size;
- fw_finish_direct_load(device, buf);
+ fw_umh_done(&buf->fw_umh);
break;
}
__putname(path);
@@ -1074,25 +1073,6 @@ static inline void kill_requests_without_uevent(void) { }
#endif /* CONFIG_FW_LOADER_USER_HELPER */
-/* wait until the shared firmware_buf becomes ready (or error) */
-static int sync_cached_firmware_buf(struct firmware_buf *buf)
-{
- int ret = 0;
-
- mutex_lock(&fw_lock);
- while (!fw_umh_is_done(&buf->fw_umh)) {
- if (fw_umh_is_aborted(&buf->fw_umh)) {
- ret = -ENOENT;
- break;
- }
- mutex_unlock(&fw_lock);
- ret = fw_umh_wait_timeout(&buf->fw_umh, 0);
- mutex_lock(&fw_lock);
- }
- mutex_unlock(&fw_lock);
- return ret;
-}
-
/* prepare firmware and firmware_buf structs;
* return 0 if a firmware is already assigned, 1 if need to load one,
* or a negative error code
@@ -1126,7 +1106,7 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name,
firmware->priv = buf;
if (ret > 0) {
- ret = sync_cached_firmware_buf(buf);
+ ret = fw_umh_wait_timeout(&buf->fw_umh, 0);
if (!ret) {
fw_set_page_data(buf, firmware);
return 0; /* assigned */
--
2.7.4
next prev parent reply other threads:[~2016-09-09 12:13 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-09 12:12 [PATCH v5 0/5] firmware: encapsulate firmware loading status Daniel Wagner
2016-09-09 12:12 ` [PATCH v5 1/5] firmware: document user mode helper lock usage Daniel Wagner
2016-09-09 22:14 ` Luis R. Rodriguez
2016-09-22 2:36 ` Ming Lei
2016-10-05 20:41 ` Luis R. Rodriguez
[not found] ` <ab544ba0-2128-055f-3190-6a1a24e879e1@bmw-carit.de>
2016-10-05 20:46 ` Luis R. Rodriguez
[not found] ` <2ec51622-f727-e884-1a09-a595a31f4b21@bmw-carit.de>
2016-10-10 18:40 ` Luis R. Rodriguez
2016-09-09 12:12 ` [PATCH v5 2/5] firmware: encapsulate firmware loading status Daniel Wagner
2016-09-09 22:19 ` Luis R. Rodriguez
2016-09-09 22:24 ` Luis R. Rodriguez
2016-09-13 9:47 ` Daniel Wagner
2016-10-05 20:27 ` Luis R. Rodriguez
2016-10-07 11:41 ` Daniel Wagner
2016-10-10 20:37 ` Luis R. Rodriguez
2016-10-18 13:30 ` Daniel Wagner
2016-10-18 21:54 ` Luis R. Rodriguez
2016-10-19 8:05 ` Daniel Wagner
2016-09-09 12:12 ` [PATCH v5 3/5] firmware: rename fw_load_from_user_helper() and _request_firmware_load() Daniel Wagner
2016-09-09 22:17 ` Luis R. Rodriguez
2016-09-09 12:12 ` [PATCH v5 4/5] firmware: drop bit ops in favor of simple state machine Daniel Wagner
2016-09-09 22:30 ` Luis R. Rodriguez
2016-09-09 12:12 ` Daniel Wagner [this message]
2016-09-09 17:38 ` [PATCH v5 0/5] firmware: encapsulate firmware loading status Luis R. Rodriguez
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1473423144-21734-6-git-send-email-wagi@monom.org \
--to=wagi@monom.org \
--cc=arend.vanspriel@broadcom.com \
--cc=bjorn.andersson@linaro.org \
--cc=daniel.vetter@intel.com \
--cc=daniel.wagner@bmw-carit.de \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mcgrof@kernel.org \
--cc=ming.lei@canonical.com \
--cc=rjw@sisk.pl \
--cc=srivatsa.bhat@linux.vnet.ibm.com \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®