From: Cornelia Huck <coh...@redhat.com>

[ Upstream commit 05ce3e53f375295c2940390b2b429e506e07655c ]

The common I/O layer delays the ADD uevent for subchannels and
delegates generating this uevent to the individual subchannel
drivers. The io_subchannel driver will do so when the associated
ccw_device has been registered -- but unconditionally, so more
ADD uevents will be generated if a subchannel has been unbound
from the io_subchannel driver and later rebound.

To fix this, only generate the ADD event if uevents were still
suppressed for the device.

Fixes: fa1a8c23eb7d ("s390: cio: Delay uevents for subchannels")
Message-Id: <20200327124503.9794-2-coh...@redhat.com>
Reported-by: Boris Fiuczynski <fiu...@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <ober...@linux.ibm.com>
Reviewed-by: Boris Fiuczynski <fiu...@linux.ibm.com>
Signed-off-by: Cornelia Huck <coh...@redhat.com>
Signed-off-by: Vasily Gorbik <g...@linux.ibm.com>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 drivers/s390/cio/device.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 0c6245fc77069..983f9c9e08deb 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -849,8 +849,10 @@ static void io_subchannel_register(struct ccw_device *cdev)
         * Now we know this subchannel will stay, we can throw
         * our delayed uevent.
         */
-       dev_set_uevent_suppress(&sch->dev, 0);
-       kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
+       if (dev_get_uevent_suppress(&sch->dev)) {
+               dev_set_uevent_suppress(&sch->dev, 0);
+               kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
+       }
        /* make it known to the system */
        ret = ccw_device_add(cdev);
        if (ret) {
@@ -1058,8 +1060,11 @@ static int io_subchannel_probe(struct subchannel *sch)
                 * Throw the delayed uevent for the subchannel, register
                 * the ccw_device and exit.
                 */
-               dev_set_uevent_suppress(&sch->dev, 0);
-               kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
+               if (dev_get_uevent_suppress(&sch->dev)) {
+                       /* should always be the case for the console */
+                       dev_set_uevent_suppress(&sch->dev, 0);
+                       kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
+               }
                cdev = sch_get_cdev(sch);
                rc = ccw_device_add(cdev);
                if (rc) {
-- 
2.20.1



Reply via email to