[S390] Some preparations for the dynamic subchannel mapping patch.
- Move adding subchannel attributes to css_register_subchannel(). - Don't call device_trigger_reprobe() for non-operational devices. - Introduce io_subchannel_create_ccwdev(). Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
34249d0f92
commit
7674da77cb
|
@ -135,14 +135,19 @@ css_register_subchannel(struct subchannel *sch)
|
||||||
sch->dev.parent = &css[0]->device;
|
sch->dev.parent = &css[0]->device;
|
||||||
sch->dev.bus = &css_bus_type;
|
sch->dev.bus = &css_bus_type;
|
||||||
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 = css_sch_device_register(sch);
|
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);
|
||||||
else
|
return ret;
|
||||||
css_get_ssd_info(sch);
|
}
|
||||||
|
css_get_ssd_info(sch);
|
||||||
|
ret = subchannel_add_files(&sch->dev);
|
||||||
|
if (ret)
|
||||||
|
printk(KERN_WARNING "%s: could not add attributes to %s\n",
|
||||||
|
__func__, sch->dev.bus_id);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,4 +189,6 @@ extern int need_rescan;
|
||||||
|
|
||||||
extern struct workqueue_struct *slow_path_wq;
|
extern struct workqueue_struct *slow_path_wq;
|
||||||
extern struct work_struct slow_path_work;
|
extern struct work_struct slow_path_work;
|
||||||
|
|
||||||
|
int subchannel_add_files (struct device *);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -294,6 +294,18 @@ online_show (struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
return sprintf(buf, cdev->online ? "1\n" : "0\n");
|
return sprintf(buf, cdev->online ? "1\n" : "0\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ccw_device_unregister(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct ccw_device_private *priv;
|
||||||
|
struct ccw_device *cdev;
|
||||||
|
|
||||||
|
priv = container_of(work, struct ccw_device_private, kick_work);
|
||||||
|
cdev = priv->cdev;
|
||||||
|
if (test_and_clear_bit(1, &cdev->private->registered))
|
||||||
|
device_unregister(&cdev->dev);
|
||||||
|
put_device(&cdev->dev);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ccw_device_remove_disconnected(struct ccw_device *cdev)
|
ccw_device_remove_disconnected(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
|
@ -498,8 +510,7 @@ static struct attribute_group subch_attr_group = {
|
||||||
.attrs = subch_attrs,
|
.attrs = subch_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int
|
int subchannel_add_files (struct device *dev)
|
||||||
subchannel_add_files (struct device *dev)
|
|
||||||
{
|
{
|
||||||
return sysfs_create_group(&dev->kobj, &subch_attr_group);
|
return sysfs_create_group(&dev->kobj, &subch_attr_group);
|
||||||
}
|
}
|
||||||
|
@ -676,6 +687,55 @@ ccw_device_release(struct device *dev)
|
||||||
kfree(cdev);
|
kfree(cdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct ccw_device * io_subchannel_allocate_dev(struct subchannel *sch)
|
||||||
|
{
|
||||||
|
struct ccw_device *cdev;
|
||||||
|
|
||||||
|
cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
|
||||||
|
if (cdev) {
|
||||||
|
cdev->private = kzalloc(sizeof(struct ccw_device_private),
|
||||||
|
GFP_KERNEL | GFP_DMA);
|
||||||
|
if (cdev->private)
|
||||||
|
return cdev;
|
||||||
|
}
|
||||||
|
kfree(cdev);
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int io_subchannel_initialize_dev(struct subchannel *sch,
|
||||||
|
struct ccw_device *cdev)
|
||||||
|
{
|
||||||
|
cdev->private->cdev = cdev;
|
||||||
|
atomic_set(&cdev->private->onoff, 0);
|
||||||
|
cdev->dev.parent = &sch->dev;
|
||||||
|
cdev->dev.release = ccw_device_release;
|
||||||
|
INIT_LIST_HEAD(&cdev->private->kick_work.entry);
|
||||||
|
/* Do first half of device_register. */
|
||||||
|
device_initialize(&cdev->dev);
|
||||||
|
if (!get_device(&sch->dev)) {
|
||||||
|
if (cdev->dev.release)
|
||||||
|
cdev->dev.release(&cdev->dev);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ccw_device * io_subchannel_create_ccwdev(struct subchannel *sch)
|
||||||
|
{
|
||||||
|
struct ccw_device *cdev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
cdev = io_subchannel_allocate_dev(sch);
|
||||||
|
if (!IS_ERR(cdev)) {
|
||||||
|
ret = io_subchannel_initialize_dev(sch, cdev);
|
||||||
|
if (ret) {
|
||||||
|
kfree(cdev);
|
||||||
|
cdev = ERR_PTR(ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cdev;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register recognized device.
|
* Register recognized device.
|
||||||
*/
|
*/
|
||||||
|
@ -724,11 +784,6 @@ io_subchannel_register(struct work_struct *work)
|
||||||
wake_up(&ccw_device_init_wq);
|
wake_up(&ccw_device_init_wq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = subchannel_add_files(cdev->dev.parent);
|
|
||||||
if (ret)
|
|
||||||
printk(KERN_WARNING "%s: could not add attributes to %s\n",
|
|
||||||
__func__, sch->dev.bus_id);
|
|
||||||
put_device(&cdev->dev);
|
put_device(&cdev->dev);
|
||||||
out:
|
out:
|
||||||
cdev->private->flags.recog_done = 1;
|
cdev->private->flags.recog_done = 1;
|
||||||
|
@ -851,7 +906,6 @@ io_subchannel_probe (struct subchannel *sch)
|
||||||
cdev = sch->dev.driver_data;
|
cdev = sch->dev.driver_data;
|
||||||
device_initialize(&cdev->dev);
|
device_initialize(&cdev->dev);
|
||||||
ccw_device_register(cdev);
|
ccw_device_register(cdev);
|
||||||
subchannel_add_files(&sch->dev);
|
|
||||||
/*
|
/*
|
||||||
* Check if the device is already online. If it is
|
* Check if the device is already online. If it is
|
||||||
* the reference count needs to be corrected
|
* the reference count needs to be corrected
|
||||||
|
@ -864,28 +918,9 @@ io_subchannel_probe (struct subchannel *sch)
|
||||||
get_device(&cdev->dev);
|
get_device(&cdev->dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
cdev = kzalloc (sizeof(*cdev), GFP_KERNEL);
|
cdev = io_subchannel_create_ccwdev(sch);
|
||||||
if (!cdev)
|
if (IS_ERR(cdev))
|
||||||
return -ENOMEM;
|
return PTR_ERR(cdev);
|
||||||
cdev->private = kzalloc(sizeof(struct ccw_device_private),
|
|
||||||
GFP_KERNEL | GFP_DMA);
|
|
||||||
if (!cdev->private) {
|
|
||||||
kfree(cdev);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
cdev->private->cdev = cdev;
|
|
||||||
atomic_set(&cdev->private->onoff, 0);
|
|
||||||
cdev->dev.parent = &sch->dev;
|
|
||||||
cdev->dev.release = ccw_device_release;
|
|
||||||
INIT_LIST_HEAD(&cdev->private->kick_work.entry);
|
|
||||||
/* Do first half of device_register. */
|
|
||||||
device_initialize(&cdev->dev);
|
|
||||||
|
|
||||||
if (!get_device(&sch->dev)) {
|
|
||||||
if (cdev->dev.release)
|
|
||||||
cdev->dev.release(&cdev->dev);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = io_subchannel_recog(cdev, sch);
|
rc = io_subchannel_recog(cdev, sch);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@ -899,18 +934,6 @@ io_subchannel_probe (struct subchannel *sch)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ccw_device_unregister(struct work_struct *work)
|
|
||||||
{
|
|
||||||
struct ccw_device_private *priv;
|
|
||||||
struct ccw_device *cdev;
|
|
||||||
|
|
||||||
priv = container_of(work, struct ccw_device_private, kick_work);
|
|
||||||
cdev = priv->cdev;
|
|
||||||
if (test_and_clear_bit(1, &cdev->private->registered))
|
|
||||||
device_unregister(&cdev->dev);
|
|
||||||
put_device(&cdev->dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
io_subchannel_remove (struct subchannel *sch)
|
io_subchannel_remove (struct subchannel *sch)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1106,7 +1106,8 @@ device_trigger_reprobe(struct subchannel *sch)
|
||||||
/* Update some values. */
|
/* Update some values. */
|
||||||
if (stsch(sch->schid, &sch->schib))
|
if (stsch(sch->schid, &sch->schib))
|
||||||
return;
|
return;
|
||||||
|
if (!sch->schib.pmcw.dnv)
|
||||||
|
return;
|
||||||
/*
|
/*
|
||||||
* The pim, pam, pom values may not be accurate, but they are the best
|
* The pim, pam, pom values may not be accurate, but they are the best
|
||||||
* we have before performing device selection :/
|
* we have before performing device selection :/
|
||||||
|
|
Loading…
Reference in New Issue