diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 30 | ||||
-rw-r--r-- | drivers/s390/cio/css.c | 34 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 84 |
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 | ||
406 | static inline struct device * | 406 | static 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 | ||
422 | void | 415 | void |
423 | ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) | 416 | ccwgroup_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 | ||
131 | static int | ||
132 | check_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 | |||
131 | struct subchannel * | 141 | struct subchannel * |
132 | get_subchannel_by_schid(int irq) | 142 | get_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 | |||
159 | static inline int | 153 | static inline int |
160 | css_get_subchannel_status(struct subchannel *sch, int schid) | 154 | css_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 | ||
517 | struct match_data { | ||
518 | unsigned int devno; | ||
519 | struct ccw_device * sibling; | ||
520 | }; | ||
521 | |||
522 | static int | ||
523 | match_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 | |||
517 | static struct ccw_device * | 538 | static struct ccw_device * |
518 | get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling) | 539 | get_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 | ||
549 | static void | 552 | static 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 | */ |
1025 | static 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 | |||
1022 | struct ccw_device * | 1036 | struct ccw_device * |
1023 | get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id) | 1037 | get_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; |