mirror of
https://github.com/adulau/aha.git
synced 2025-01-01 13:46:24 +00:00
[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: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
63f4f9e128
commit
6ab4879a0d
5 changed files with 29 additions and 7 deletions
|
@ -519,6 +519,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
|
|||
memset(sch, 0, sizeof(struct subchannel));
|
||||
|
||||
spin_lock_init(&sch->lock);
|
||||
mutex_init(&sch->reg_mutex);
|
||||
|
||||
/* Set a name for the subchannel */
|
||||
snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define S390_CIO_H
|
||||
|
||||
#include "schid.h"
|
||||
#include <linux/mutex.h>
|
||||
|
||||
/*
|
||||
* where we put the ssd info
|
||||
|
@ -87,7 +88,7 @@ struct orb {
|
|||
struct subchannel {
|
||||
struct subchannel_id schid;
|
||||
spinlock_t lock; /* subchannel lock */
|
||||
|
||||
struct mutex reg_mutex;
|
||||
enum {
|
||||
SUBCHANNEL_TYPE_IO = 0,
|
||||
SUBCHANNEL_TYPE_CHSC = 1,
|
||||
|
|
|
@ -108,6 +108,24 @@ css_subchannel_release(struct device *dev)
|
|||
|
||||
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
|
||||
css_register_subchannel(struct subchannel *sch)
|
||||
{
|
||||
|
@ -119,7 +137,7 @@ css_register_subchannel(struct subchannel *sch)
|
|||
sch->dev.release = &css_subchannel_release;
|
||||
|
||||
/* make it known to the system */
|
||||
ret = device_register(&sch->dev);
|
||||
ret = css_sch_device_register(sch);
|
||||
if (ret)
|
||||
printk (KERN_WARNING "%s: could not register %s\n",
|
||||
__func__, sch->dev.bus_id);
|
||||
|
@ -250,7 +268,7 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow)
|
|||
* The device will be killed automatically.
|
||||
*/
|
||||
cio_disable_subchannel(sch);
|
||||
device_unregister(&sch->dev);
|
||||
css_sch_device_unregister(sch);
|
||||
/* Reset intparm to zeroes. */
|
||||
sch->schib.pmcw.intparm = 0;
|
||||
cio_modify(sch);
|
||||
|
@ -264,7 +282,7 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow)
|
|||
* away in any case.
|
||||
*/
|
||||
if (!disc) {
|
||||
device_unregister(&sch->dev);
|
||||
css_sch_device_unregister(sch);
|
||||
/* Reset intparm to zeroes. */
|
||||
sch->schib.pmcw.intparm = 0;
|
||||
cio_modify(sch);
|
||||
|
|
|
@ -136,6 +136,8 @@ extern struct bus_type css_bus_type;
|
|||
extern struct css_driver io_subchannel_driver;
|
||||
|
||||
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 int css_init_done;
|
||||
extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
|
||||
|
|
|
@ -280,7 +280,7 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
|
|||
* 'throw away device'.
|
||||
*/
|
||||
sch = to_subchannel(cdev->dev.parent);
|
||||
device_unregister(&sch->dev);
|
||||
css_sch_device_unregister(sch);
|
||||
/* Reset intparm to zeroes. */
|
||||
sch->schib.pmcw.intparm = 0;
|
||||
cio_modify(sch);
|
||||
|
@ -625,7 +625,7 @@ ccw_device_do_unreg_rereg(void *data)
|
|||
other_sch->schib.pmcw.intparm = 0;
|
||||
cio_modify(other_sch);
|
||||
}
|
||||
device_unregister(&other_sch->dev);
|
||||
css_sch_device_unregister(other_sch);
|
||||
}
|
||||
}
|
||||
/* Update ssd info here. */
|
||||
|
@ -709,7 +709,7 @@ ccw_device_call_sch_unregister(void *data)
|
|||
struct subchannel *sch;
|
||||
|
||||
sch = to_subchannel(cdev->dev.parent);
|
||||
device_unregister(&sch->dev);
|
||||
css_sch_device_unregister(sch);
|
||||
/* Reset intparm to zeroes. */
|
||||
sch->schib.pmcw.intparm = 0;
|
||||
cio_modify(sch);
|
||||
|
|
Loading…
Reference in a new issue