summaryrefslogtreecommitdiff
path: root/drivers/s390
diff options
context:
space:
mode:
authorVineeth Vijayan <vneethv@linux.ibm.com>2021-06-09 09:21:08 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-07-20 16:22:31 +0200
commit4be1fa6d2d193087ba9cda454ec3399e24b6c08d (patch)
treee0c5c9c6339f07e90e2aa3cac039337cf2418f92 /drivers/s390
parent3954583f4464c698e4d88317b3984004f66eb5ba (diff)
s390/cio: dont call css_wait_for_slow_path() inside a lock
commit c749d8c018daf5fba6dfac7b6c5c78b27efd7d65 upstream. Currently css_wait_for_slow_path() gets called inside the chp->lock. The path-verification-loop of slowpath inside this lock could lead to deadlock as reported by the lockdep validator. The ccw_device_get_chp_desc() during the instance of a device-set-online would try to acquire the same 'chp->lock' to read the chp->desc. The instance of this function can get called from multiple scenario, like probing or setting-device online manually. This could, in some corner-cases lead to the deadlock. lockdep validator reported this as, CPU0 CPU1 ---- ---- lock(&chp->lock); lock(kn->active#43); lock(&chp->lock); lock((wq_completion)cio); The chp->lock was introduced to serialize the access of struct channel_path. This lock is not needed for the css_wait_for_slow_path() function, so invoke the slow-path function outside this lock. Fixes: b730f3a93395 ("[S390] cio: add lock to struct channel_path") Cc: <stable@vger.kernel.org> Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com> Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/chp.c3
-rw-r--r--drivers/s390/cio/chsc.c2
2 files changed, 3 insertions, 2 deletions
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index 50597f9522fe..151c8df394a8 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -257,6 +257,9 @@ static ssize_t chp_status_write(struct device *dev,
if (!num_args)
return count;
+ /* Wait until previous actions have settled. */
+ css_wait_for_slow_path();
+
if (!strncasecmp(cmd, "on", 2) || !strcmp(cmd, "1")) {
mutex_lock(&cp->lock);
error = s390_vary_chpid(cp->chpid, 1);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index f9d6a9f00640..276b2034cbda 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -769,8 +769,6 @@ int chsc_chp_vary(struct chp_id chpid, int on)
{
struct channel_path *chp = chpid_to_chp(chpid);
- /* Wait until previous actions have settled. */
- css_wait_for_slow_path();
/*
* Redo PathVerification on the devices the chpid connects to
*/