diff options
Diffstat (limited to 'drivers/s390/cio/device.c')
-rw-r--r-- | drivers/s390/cio/device.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index d3d3716ff84b..0f604621de40 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -585,12 +585,13 @@ static struct ccw_device * get_disc_ccwdev_by_dev_id(struct ccw_dev_id *dev_id, | |||
585 | } | 585 | } |
586 | 586 | ||
587 | static void | 587 | static void |
588 | ccw_device_add_changed(void *data) | 588 | ccw_device_add_changed(struct work_struct *work) |
589 | { | 589 | { |
590 | 590 | struct ccw_device_private *priv; | |
591 | struct ccw_device *cdev; | 591 | struct ccw_device *cdev; |
592 | 592 | ||
593 | cdev = data; | 593 | priv = container_of(work, struct ccw_device_private, kick_work); |
594 | cdev = priv->cdev; | ||
594 | if (device_add(&cdev->dev)) { | 595 | if (device_add(&cdev->dev)) { |
595 | put_device(&cdev->dev); | 596 | put_device(&cdev->dev); |
596 | return; | 597 | return; |
@@ -605,13 +606,15 @@ ccw_device_add_changed(void *data) | |||
605 | extern int css_get_ssd_info(struct subchannel *sch); | 606 | extern int css_get_ssd_info(struct subchannel *sch); |
606 | 607 | ||
607 | void | 608 | void |
608 | ccw_device_do_unreg_rereg(void *data) | 609 | ccw_device_do_unreg_rereg(struct work_struct *work) |
609 | { | 610 | { |
611 | struct ccw_device_private *priv; | ||
610 | struct ccw_device *cdev; | 612 | struct ccw_device *cdev; |
611 | struct subchannel *sch; | 613 | struct subchannel *sch; |
612 | int need_rename; | 614 | int need_rename; |
613 | 615 | ||
614 | cdev = data; | 616 | priv = container_of(work, struct ccw_device_private, kick_work); |
617 | cdev = priv->cdev; | ||
615 | sch = to_subchannel(cdev->dev.parent); | 618 | sch = to_subchannel(cdev->dev.parent); |
616 | if (cdev->private->dev_id.devno != sch->schib.pmcw.dev) { | 619 | if (cdev->private->dev_id.devno != sch->schib.pmcw.dev) { |
617 | /* | 620 | /* |
@@ -659,7 +662,7 @@ ccw_device_do_unreg_rereg(void *data) | |||
659 | snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", | 662 | snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", |
660 | sch->schid.ssid, sch->schib.pmcw.dev); | 663 | sch->schid.ssid, sch->schib.pmcw.dev); |
661 | PREPARE_WORK(&cdev->private->kick_work, | 664 | PREPARE_WORK(&cdev->private->kick_work, |
662 | ccw_device_add_changed, cdev); | 665 | ccw_device_add_changed); |
663 | queue_work(ccw_device_work, &cdev->private->kick_work); | 666 | queue_work(ccw_device_work, &cdev->private->kick_work); |
664 | } | 667 | } |
665 | 668 | ||
@@ -677,14 +680,16 @@ ccw_device_release(struct device *dev) | |||
677 | * Register recognized device. | 680 | * Register recognized device. |
678 | */ | 681 | */ |
679 | static void | 682 | static void |
680 | io_subchannel_register(void *data) | 683 | io_subchannel_register(struct work_struct *work) |
681 | { | 684 | { |
685 | struct ccw_device_private *priv; | ||
682 | struct ccw_device *cdev; | 686 | struct ccw_device *cdev; |
683 | struct subchannel *sch; | 687 | struct subchannel *sch; |
684 | int ret; | 688 | int ret; |
685 | unsigned long flags; | 689 | unsigned long flags; |
686 | 690 | ||
687 | cdev = data; | 691 | priv = container_of(work, struct ccw_device_private, kick_work); |
692 | cdev = priv->cdev; | ||
688 | sch = to_subchannel(cdev->dev.parent); | 693 | sch = to_subchannel(cdev->dev.parent); |
689 | 694 | ||
690 | /* | 695 | /* |
@@ -734,11 +739,14 @@ out: | |||
734 | } | 739 | } |
735 | 740 | ||
736 | void | 741 | void |
737 | ccw_device_call_sch_unregister(void *data) | 742 | ccw_device_call_sch_unregister(struct work_struct *work) |
738 | { | 743 | { |
739 | struct ccw_device *cdev = data; | 744 | struct ccw_device_private *priv; |
745 | struct ccw_device *cdev; | ||
740 | struct subchannel *sch; | 746 | struct subchannel *sch; |
741 | 747 | ||
748 | priv = container_of(work, struct ccw_device_private, kick_work); | ||
749 | cdev = priv->cdev; | ||
742 | sch = to_subchannel(cdev->dev.parent); | 750 | sch = to_subchannel(cdev->dev.parent); |
743 | css_sch_device_unregister(sch); | 751 | css_sch_device_unregister(sch); |
744 | /* Reset intparm to zeroes. */ | 752 | /* Reset intparm to zeroes. */ |
@@ -768,7 +776,7 @@ io_subchannel_recog_done(struct ccw_device *cdev) | |||
768 | break; | 776 | break; |
769 | sch = to_subchannel(cdev->dev.parent); | 777 | sch = to_subchannel(cdev->dev.parent); |
770 | PREPARE_WORK(&cdev->private->kick_work, | 778 | PREPARE_WORK(&cdev->private->kick_work, |
771 | ccw_device_call_sch_unregister, cdev); | 779 | ccw_device_call_sch_unregister); |
772 | queue_work(slow_path_wq, &cdev->private->kick_work); | 780 | queue_work(slow_path_wq, &cdev->private->kick_work); |
773 | if (atomic_dec_and_test(&ccw_device_init_count)) | 781 | if (atomic_dec_and_test(&ccw_device_init_count)) |
774 | wake_up(&ccw_device_init_wq); | 782 | wake_up(&ccw_device_init_wq); |
@@ -783,7 +791,7 @@ io_subchannel_recog_done(struct ccw_device *cdev) | |||
783 | if (!get_device(&cdev->dev)) | 791 | if (!get_device(&cdev->dev)) |
784 | break; | 792 | break; |
785 | PREPARE_WORK(&cdev->private->kick_work, | 793 | PREPARE_WORK(&cdev->private->kick_work, |
786 | io_subchannel_register, cdev); | 794 | io_subchannel_register); |
787 | queue_work(slow_path_wq, &cdev->private->kick_work); | 795 | queue_work(slow_path_wq, &cdev->private->kick_work); |
788 | break; | 796 | break; |
789 | } | 797 | } |
@@ -865,6 +873,7 @@ io_subchannel_probe (struct subchannel *sch) | |||
865 | kfree(cdev); | 873 | kfree(cdev); |
866 | return -ENOMEM; | 874 | return -ENOMEM; |
867 | } | 875 | } |
876 | cdev->private->cdev = cdev; | ||
868 | atomic_set(&cdev->private->onoff, 0); | 877 | atomic_set(&cdev->private->onoff, 0); |
869 | cdev->dev.parent = &sch->dev; | 878 | cdev->dev.parent = &sch->dev; |
870 | cdev->dev.release = ccw_device_release; | 879 | cdev->dev.release = ccw_device_release; |
@@ -890,12 +899,13 @@ io_subchannel_probe (struct subchannel *sch) | |||
890 | return rc; | 899 | return rc; |
891 | } | 900 | } |
892 | 901 | ||
893 | static void | 902 | static void ccw_device_unregister(struct work_struct *work) |
894 | ccw_device_unregister(void *data) | ||
895 | { | 903 | { |
904 | struct ccw_device_private *priv; | ||
896 | struct ccw_device *cdev; | 905 | struct ccw_device *cdev; |
897 | 906 | ||
898 | cdev = (struct ccw_device *)data; | 907 | priv = container_of(work, struct ccw_device_private, kick_work); |
908 | cdev = priv->cdev; | ||
899 | if (test_and_clear_bit(1, &cdev->private->registered)) | 909 | if (test_and_clear_bit(1, &cdev->private->registered)) |
900 | device_unregister(&cdev->dev); | 910 | device_unregister(&cdev->dev); |
901 | put_device(&cdev->dev); | 911 | put_device(&cdev->dev); |
@@ -921,7 +931,7 @@ io_subchannel_remove (struct subchannel *sch) | |||
921 | */ | 931 | */ |
922 | if (get_device(&cdev->dev)) { | 932 | if (get_device(&cdev->dev)) { |
923 | PREPARE_WORK(&cdev->private->kick_work, | 933 | PREPARE_WORK(&cdev->private->kick_work, |
924 | ccw_device_unregister, cdev); | 934 | ccw_device_unregister); |
925 | queue_work(ccw_device_work, &cdev->private->kick_work); | 935 | queue_work(ccw_device_work, &cdev->private->kick_work); |
926 | } | 936 | } |
927 | return 0; | 937 | return 0; |
@@ -1048,6 +1058,7 @@ ccw_device_probe_console(void) | |||
1048 | memset(&console_cdev, 0, sizeof(struct ccw_device)); | 1058 | memset(&console_cdev, 0, sizeof(struct ccw_device)); |
1049 | memset(&console_private, 0, sizeof(struct ccw_device_private)); | 1059 | memset(&console_private, 0, sizeof(struct ccw_device_private)); |
1050 | console_cdev.private = &console_private; | 1060 | console_cdev.private = &console_private; |
1061 | console_private.cdev = &console_cdev; | ||
1051 | ret = ccw_device_console_enable(&console_cdev, sch); | 1062 | ret = ccw_device_console_enable(&console_cdev, sch); |
1052 | if (ret) { | 1063 | if (ret) { |
1053 | cio_release_console(); | 1064 | cio_release_console(); |