Commit 6ab4879a authored by Cornelia Huck's avatar Cornelia Huck Committed by Martin Schwidefsky

[S390] subchannel register/unregister mutex.

Add a reg_mutex to prevent unregistering a subchannel before it has been
registered. Since 2.6.17, we've seen oopses in kslowcrw when a device is
found to be not operational during sense id when doing initial device
recognition; it is not clear yet why that particular problem was not (yet)
observed with earlier kernels...
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 63f4f9e1
...@@ -519,6 +519,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) ...@@ -519,6 +519,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
memset(sch, 0, sizeof(struct subchannel)); memset(sch, 0, sizeof(struct subchannel));
spin_lock_init(&sch->lock); spin_lock_init(&sch->lock);
mutex_init(&sch->reg_mutex);
/* Set a name for the subchannel */ /* Set a name for the subchannel */
snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid, snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define S390_CIO_H #define S390_CIO_H
#include "schid.h" #include "schid.h"
#include <linux/mutex.h>
/* /*
* where we put the ssd info * where we put the ssd info
...@@ -87,7 +88,7 @@ struct orb { ...@@ -87,7 +88,7 @@ struct orb {
struct subchannel { struct subchannel {
struct subchannel_id schid; struct subchannel_id schid;
spinlock_t lock; /* subchannel lock */ spinlock_t lock; /* subchannel lock */
struct mutex reg_mutex;
enum { enum {
SUBCHANNEL_TYPE_IO = 0, SUBCHANNEL_TYPE_IO = 0,
SUBCHANNEL_TYPE_CHSC = 1, SUBCHANNEL_TYPE_CHSC = 1,
......
...@@ -108,6 +108,24 @@ css_subchannel_release(struct device *dev) ...@@ -108,6 +108,24 @@ css_subchannel_release(struct device *dev)
extern int css_get_ssd_info(struct subchannel *sch); extern int css_get_ssd_info(struct subchannel *sch);
int css_sch_device_register(struct subchannel *sch)
{
int ret;
mutex_lock(&sch->reg_mutex);
ret = device_register(&sch->dev);
mutex_unlock(&sch->reg_mutex);
return ret;
}
void css_sch_device_unregister(struct subchannel *sch)
{
mutex_lock(&sch->reg_mutex);
device_unregister(&sch->dev);
mutex_unlock(&sch->reg_mutex);
}
static int static int
css_register_subchannel(struct subchannel *sch) css_register_subchannel(struct subchannel *sch)
{ {
...@@ -119,7 +137,7 @@ css_register_subchannel(struct subchannel *sch) ...@@ -119,7 +137,7 @@ css_register_subchannel(struct subchannel *sch)
sch->dev.release = &css_subchannel_release; sch->dev.release = &css_subchannel_release;
/* make it known to the system */ /* make it known to the system */
ret = device_register(&sch->dev); ret = css_sch_device_register(sch);
if (ret) if (ret)
printk (KERN_WARNING "%s: could not register %s\n", printk (KERN_WARNING "%s: could not register %s\n",
__func__, sch->dev.bus_id); __func__, sch->dev.bus_id);
...@@ -250,7 +268,7 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow) ...@@ -250,7 +268,7 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow)
* The device will be killed automatically. * The device will be killed automatically.
*/ */
cio_disable_subchannel(sch); cio_disable_subchannel(sch);
device_unregister(&sch->dev); css_sch_device_unregister(sch);
/* Reset intparm to zeroes. */ /* Reset intparm to zeroes. */
sch->schib.pmcw.intparm = 0; sch->schib.pmcw.intparm = 0;
cio_modify(sch); cio_modify(sch);
...@@ -264,7 +282,7 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow) ...@@ -264,7 +282,7 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow)
* away in any case. * away in any case.
*/ */
if (!disc) { if (!disc) {
device_unregister(&sch->dev); css_sch_device_unregister(sch);
/* Reset intparm to zeroes. */ /* Reset intparm to zeroes. */
sch->schib.pmcw.intparm = 0; sch->schib.pmcw.intparm = 0;
cio_modify(sch); cio_modify(sch);
......
...@@ -136,6 +136,8 @@ extern struct bus_type css_bus_type; ...@@ -136,6 +136,8 @@ extern struct bus_type css_bus_type;
extern struct css_driver io_subchannel_driver; extern struct css_driver io_subchannel_driver;
extern int css_probe_device(struct subchannel_id); extern int css_probe_device(struct subchannel_id);
extern int css_sch_device_register(struct subchannel *);
extern void css_sch_device_unregister(struct subchannel *);
extern struct subchannel * get_subchannel_by_schid(struct subchannel_id); extern struct subchannel * get_subchannel_by_schid(struct subchannel_id);
extern int css_init_done; extern int css_init_done;
extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
......
...@@ -280,7 +280,7 @@ ccw_device_remove_disconnected(struct ccw_device *cdev) ...@@ -280,7 +280,7 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
* 'throw away device'. * 'throw away device'.
*/ */
sch = to_subchannel(cdev->dev.parent); sch = to_subchannel(cdev->dev.parent);
device_unregister(&sch->dev); css_sch_device_unregister(sch);
/* Reset intparm to zeroes. */ /* Reset intparm to zeroes. */
sch->schib.pmcw.intparm = 0; sch->schib.pmcw.intparm = 0;
cio_modify(sch); cio_modify(sch);
...@@ -625,7 +625,7 @@ ccw_device_do_unreg_rereg(void *data) ...@@ -625,7 +625,7 @@ ccw_device_do_unreg_rereg(void *data)
other_sch->schib.pmcw.intparm = 0; other_sch->schib.pmcw.intparm = 0;
cio_modify(other_sch); cio_modify(other_sch);
} }
device_unregister(&other_sch->dev); css_sch_device_unregister(other_sch);
} }
} }
/* Update ssd info here. */ /* Update ssd info here. */
...@@ -709,7 +709,7 @@ ccw_device_call_sch_unregister(void *data) ...@@ -709,7 +709,7 @@ ccw_device_call_sch_unregister(void *data)
struct subchannel *sch; struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent); sch = to_subchannel(cdev->dev.parent);
device_unregister(&sch->dev); css_sch_device_unregister(sch);
/* Reset intparm to zeroes. */ /* Reset intparm to zeroes. */
sch->schib.pmcw.intparm = 0; sch->schib.pmcw.intparm = 0;
cio_modify(sch); cio_modify(sch);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment