aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/device.c')
-rw-r--r--drivers/s390/cio/device.c44
1 files changed, 13 insertions, 31 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index e28f8ae53453..c4d2f667a2f6 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -457,12 +457,13 @@ int ccw_device_set_online(struct ccw_device *cdev)
457 return (ret == 0) ? -ENODEV : ret; 457 return (ret == 0) ? -ENODEV : ret;
458} 458}
459 459
460static void online_store_handle_offline(struct ccw_device *cdev) 460static int online_store_handle_offline(struct ccw_device *cdev)
461{ 461{
462 if (cdev->private->state == DEV_STATE_DISCONNECTED) 462 if (cdev->private->state == DEV_STATE_DISCONNECTED)
463 ccw_device_remove_disconnected(cdev); 463 ccw_device_remove_disconnected(cdev);
464 else if (cdev->drv && cdev->drv->set_offline) 464 else if (cdev->online && cdev->drv && cdev->drv->set_offline)
465 ccw_device_set_offline(cdev); 465 return ccw_device_set_offline(cdev);
466 return 0;
466} 467}
467 468
468static int online_store_recog_and_online(struct ccw_device *cdev) 469static int online_store_recog_and_online(struct ccw_device *cdev)
@@ -530,13 +531,10 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
530 goto out; 531 goto out;
531 switch (i) { 532 switch (i) {
532 case 0: 533 case 0:
533 online_store_handle_offline(cdev); 534 ret = online_store_handle_offline(cdev);
534 ret = count;
535 break; 535 break;
536 case 1: 536 case 1:
537 ret = online_store_handle_online(cdev, force); 537 ret = online_store_handle_online(cdev, force);
538 if (!ret)
539 ret = count;
540 break; 538 break;
541 default: 539 default:
542 ret = -EINVAL; 540 ret = -EINVAL;
@@ -545,7 +543,7 @@ out:
545 if (cdev->drv) 543 if (cdev->drv)
546 module_put(cdev->drv->owner); 544 module_put(cdev->drv->owner);
547 atomic_set(&cdev->private->onoff, 0); 545 atomic_set(&cdev->private->onoff, 0);
548 return ret; 546 return (ret < 0) ? ret : count;
549} 547}
550 548
551static ssize_t 549static ssize_t
@@ -681,35 +679,22 @@ get_orphaned_ccwdev_by_dev_id(struct channel_subsystem *css,
681 return dev ? to_ccwdev(dev) : NULL; 679 return dev ? to_ccwdev(dev) : NULL;
682} 680}
683 681
684static void 682void ccw_device_do_unbind_bind(struct work_struct *work)
685ccw_device_add_changed(struct work_struct *work)
686{
687 struct ccw_device_private *priv;
688 struct ccw_device *cdev;
689
690 priv = container_of(work, struct ccw_device_private, kick_work);
691 cdev = priv->cdev;
692 if (device_add(&cdev->dev)) {
693 put_device(&cdev->dev);
694 return;
695 }
696 set_bit(1, &cdev->private->registered);
697}
698
699void ccw_device_do_unreg_rereg(struct work_struct *work)
700{ 683{
701 struct ccw_device_private *priv; 684 struct ccw_device_private *priv;
702 struct ccw_device *cdev; 685 struct ccw_device *cdev;
703 struct subchannel *sch; 686 struct subchannel *sch;
687 int ret;
704 688
705 priv = container_of(work, struct ccw_device_private, kick_work); 689 priv = container_of(work, struct ccw_device_private, kick_work);
706 cdev = priv->cdev; 690 cdev = priv->cdev;
707 sch = to_subchannel(cdev->dev.parent); 691 sch = to_subchannel(cdev->dev.parent);
708 692
709 ccw_device_unregister(cdev); 693 if (test_bit(1, &cdev->private->registered)) {
710 PREPARE_WORK(&cdev->private->kick_work, 694 device_release_driver(&cdev->dev);
711 ccw_device_add_changed); 695 ret = device_attach(&cdev->dev);
712 queue_work(ccw_device_work, &cdev->private->kick_work); 696 WARN_ON(ret == -ENODEV);
697 }
713} 698}
714 699
715static void 700static void
@@ -1035,8 +1020,6 @@ static void ccw_device_call_sch_unregister(struct work_struct *work)
1035void 1020void
1036io_subchannel_recog_done(struct ccw_device *cdev) 1021io_subchannel_recog_done(struct ccw_device *cdev)
1037{ 1022{
1038 struct subchannel *sch;
1039
1040 if (css_init_done == 0) { 1023 if (css_init_done == 0) {
1041 cdev->private->flags.recog_done = 1; 1024 cdev->private->flags.recog_done = 1;
1042 return; 1025 return;
@@ -1047,7 +1030,6 @@ io_subchannel_recog_done(struct ccw_device *cdev)
1047 /* Remove device found not operational. */ 1030 /* Remove device found not operational. */
1048 if (!get_device(&cdev->dev)) 1031 if (!get_device(&cdev->dev))
1049 break; 1032 break;
1050 sch = to_subchannel(cdev->dev.parent);
1051 PREPARE_WORK(&cdev->private->kick_work, 1033 PREPARE_WORK(&cdev->private->kick_work,
1052 ccw_device_call_sch_unregister); 1034 ccw_device_call_sch_unregister);
1053 queue_work(slow_path_wq, &cdev->private->kick_work); 1035 queue_work(slow_path_wq, &cdev->private->kick_work);