aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/cio/ccwgroup.c30
-rw-r--r--drivers/s390/cio/css.c34
-rw-r--r--drivers/s390/cio/device.c84
3 files changed, 66 insertions, 82 deletions
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 306525acb9f8..91ea8e4777f3 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -403,34 +403,22 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
403 return driver_register(&cdriver->driver); 403 return driver_register(&cdriver->driver);
404} 404}
405 405
406static inline struct device * 406static int
407__get_next_ccwgroup_device(struct device_driver *drv) 407__ccwgroup_driver_unregister_device(struct device *dev, void *data)
408{ 408{
409 struct device *dev, *d; 409 __ccwgroup_remove_symlinks(to_ccwgroupdev(dev));
410 410 device_unregister(dev);
411 down_read(&drv->bus->subsys.rwsem); 411 put_device(dev);
412 dev = NULL; 412 return 0;
413 list_for_each_entry(d, &drv->devices, driver_list) {
414 dev = get_device(d);
415 if (dev)
416 break;
417 }
418 up_read(&drv->bus->subsys.rwsem);
419 return dev;
420} 413}
421 414
422void 415void
423ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) 416ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver)
424{ 417{
425 struct device *dev;
426
427 /* We don't want ccwgroup devices to live longer than their driver. */ 418 /* We don't want ccwgroup devices to live longer than their driver. */
428 get_driver(&cdriver->driver); 419 get_driver(&cdriver->driver);
429 while ((dev = __get_next_ccwgroup_device(&cdriver->driver))) { 420 driver_for_each_device(&cdriver->driver, NULL, NULL,
430 __ccwgroup_remove_symlinks(to_ccwgroupdev(dev)); 421 __ccwgroup_driver_unregister_device);
431 device_unregister(dev);
432 put_device(dev);
433 };
434 put_driver(&cdriver->driver); 422 put_driver(&cdriver->driver);
435 driver_unregister(&cdriver->driver); 423 driver_unregister(&cdriver->driver);
436} 424}
@@ -449,7 +437,7 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
449 if (cdev->dev.driver_data) { 437 if (cdev->dev.driver_data) {
450 gdev = (struct ccwgroup_device *)cdev->dev.driver_data; 438 gdev = (struct ccwgroup_device *)cdev->dev.driver_data;
451 if (get_device(&gdev->dev)) { 439 if (get_device(&gdev->dev)) {
452 if (!list_empty(&gdev->dev.node)) 440 if (klist_node_attached(&gdev->dev.knode_bus))
453 return gdev; 441 return gdev;
454 put_device(&gdev->dev); 442 put_device(&gdev->dev);
455 } 443 }
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 87bd70eeabed..555119cacc27 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -128,34 +128,28 @@ css_probe_device(int irq)
128 return ret; 128 return ret;
129} 129}
130 130
131static int
132check_subchannel(struct device * dev, void * data)
133{
134 struct subchannel *sch;
135 int irq = (unsigned long)data;
136
137 sch = to_subchannel(dev);
138 return (sch->irq == irq);
139}
140
131struct subchannel * 141struct subchannel *
132get_subchannel_by_schid(int irq) 142get_subchannel_by_schid(int irq)
133{ 143{
134 struct subchannel *sch;
135 struct list_head *entry;
136 struct device *dev; 144 struct device *dev;
137 145
138 if (!get_bus(&css_bus_type)) 146 dev = bus_find_device(&css_bus_type, NULL,
139 return NULL; 147 (void *)(unsigned long)irq, check_subchannel);
140 down_read(&css_bus_type.subsys.rwsem);
141 sch = NULL;
142 list_for_each(entry, &css_bus_type.devices.list) {
143 dev = get_device(container_of(entry,
144 struct device, bus_list));
145 if (!dev)
146 continue;
147 sch = to_subchannel(dev);
148 if (sch->irq == irq)
149 break;
150 put_device(dev);
151 sch = NULL;
152 }
153 up_read(&css_bus_type.subsys.rwsem);
154 put_bus(&css_bus_type);
155 148
156 return sch; 149 return dev ? to_subchannel(dev) : NULL;
157} 150}
158 151
152
159static inline int 153static inline int
160css_get_subchannel_status(struct subchannel *sch, int schid) 154css_get_subchannel_status(struct subchannel *sch, int schid)
161{ 155{
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 809e1108a06e..14c76f5e4177 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -514,36 +514,39 @@ ccw_device_register(struct ccw_device *cdev)
514 return ret; 514 return ret;
515} 515}
516 516
517struct match_data {
518 unsigned int devno;
519 struct ccw_device * sibling;
520};
521
522static int
523match_devno(struct device * dev, void * data)
524{
525 struct match_data * d = (struct match_data *)data;
526 struct ccw_device * cdev;
527
528 cdev = to_ccwdev(dev);
529 if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
530 (cdev->private->devno == d->devno) &&
531 (cdev != d->sibling)) {
532 cdev->private->state = DEV_STATE_NOT_OPER;
533 return 1;
534 }
535 return 0;
536}
537
517static struct ccw_device * 538static struct ccw_device *
518get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling) 539get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
519{ 540{
520 struct ccw_device *cdev;
521 struct list_head *entry;
522 struct device *dev; 541 struct device *dev;
542 struct match_data data = {
543 .devno = devno,
544 .sibling = sibling,
545 };
523 546
524 if (!get_bus(&ccw_bus_type)) 547 dev = bus_find_device(&css_bus_type, NULL, &data, match_devno);
525 return NULL;
526 down_read(&ccw_bus_type.subsys.rwsem);
527 cdev = NULL;
528 list_for_each(entry, &ccw_bus_type.devices.list) {
529 dev = get_device(container_of(entry,
530 struct device, bus_list));
531 if (!dev)
532 continue;
533 cdev = to_ccwdev(dev);
534 if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
535 (cdev->private->devno == devno) &&
536 (cdev != sibling)) {
537 cdev->private->state = DEV_STATE_NOT_OPER;
538 break;
539 }
540 put_device(dev);
541 cdev = NULL;
542 }
543 up_read(&ccw_bus_type.subsys.rwsem);
544 put_bus(&ccw_bus_type);
545 548
546 return cdev; 549 return dev ? to_ccwdev(dev) : NULL;
547} 550}
548 551
549static void 552static void
@@ -647,7 +650,7 @@ io_subchannel_register(void *data)
647 cdev = (struct ccw_device *) data; 650 cdev = (struct ccw_device *) data;
648 sch = to_subchannel(cdev->dev.parent); 651 sch = to_subchannel(cdev->dev.parent);
649 652
650 if (!list_empty(&sch->dev.children)) { 653 if (klist_node_attached(&cdev->dev.knode_parent)) {
651 bus_rescan_devices(&ccw_bus_type); 654 bus_rescan_devices(&ccw_bus_type);
652 goto out; 655 goto out;
653 } 656 }
@@ -1019,30 +1022,29 @@ ccw_device_probe_console(void)
1019/* 1022/*
1020 * get ccw_device matching the busid, but only if owned by cdrv 1023 * get ccw_device matching the busid, but only if owned by cdrv
1021 */ 1024 */
1025static int
1026__ccwdev_check_busid(struct device *dev, void *id)
1027{
1028 char *bus_id;
1029
1030 bus_id = (char *)id;
1031
1032 return (strncmp(bus_id, dev->bus_id, BUS_ID_SIZE) == 0);
1033}
1034
1035
1022struct ccw_device * 1036struct ccw_device *
1023get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id) 1037get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id)
1024{ 1038{
1025 struct device *d, *dev; 1039 struct device *dev;
1026 struct device_driver *drv; 1040 struct device_driver *drv;
1027 1041
1028 drv = get_driver(&cdrv->driver); 1042 drv = get_driver(&cdrv->driver);
1029 if (!drv) 1043 if (!drv)
1030 return 0; 1044 return NULL;
1031
1032 down_read(&drv->bus->subsys.rwsem);
1033
1034 dev = NULL;
1035 list_for_each_entry(d, &drv->devices, driver_list) {
1036 dev = get_device(d);
1037 1045
1038 if (dev && !strncmp(bus_id, dev->bus_id, BUS_ID_SIZE)) 1046 dev = driver_find_device(drv, NULL, (void *)bus_id,
1039 break; 1047 __ccwdev_check_busid);
1040 else if (dev) {
1041 put_device(dev);
1042 dev = NULL;
1043 }
1044 }
1045 up_read(&drv->bus->subsys.rwsem);
1046 put_driver(drv); 1048 put_driver(drv);
1047 1049
1048 return dev ? to_ccwdev(dev) : 0; 1050 return dev ? to_ccwdev(dev) : 0;