diff options
Diffstat (limited to 'drivers/s390/cio/css.c')
-rw-r--r-- | drivers/s390/cio/css.c | 36 |
1 files changed, 20 insertions, 16 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 51489eff6b0b..76bbb1e74c29 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -633,6 +633,11 @@ channel_subsystem_release(struct device *dev) | |||
633 | 633 | ||
634 | css = to_css(dev); | 634 | css = to_css(dev); |
635 | mutex_destroy(&css->mutex); | 635 | mutex_destroy(&css->mutex); |
636 | if (css->pseudo_subchannel) { | ||
637 | /* Implies that it has been generated but never registered. */ | ||
638 | css_subchannel_release(&css->pseudo_subchannel->dev); | ||
639 | css->pseudo_subchannel = NULL; | ||
640 | } | ||
636 | kfree(css); | 641 | kfree(css); |
637 | } | 642 | } |
638 | 643 | ||
@@ -693,7 +698,7 @@ static int __init setup_css(int nr) | |||
693 | return -ENOMEM; | 698 | return -ENOMEM; |
694 | css->pseudo_subchannel->dev.parent = &css->device; | 699 | css->pseudo_subchannel->dev.parent = &css->device; |
695 | css->pseudo_subchannel->dev.release = css_subchannel_release; | 700 | css->pseudo_subchannel->dev.release = css_subchannel_release; |
696 | sprintf(css->pseudo_subchannel->dev.bus_id, "defunct"); | 701 | dev_set_name(&css->pseudo_subchannel->dev, "defunct"); |
697 | ret = cio_create_sch_lock(css->pseudo_subchannel); | 702 | ret = cio_create_sch_lock(css->pseudo_subchannel); |
698 | if (ret) { | 703 | if (ret) { |
699 | kfree(css->pseudo_subchannel); | 704 | kfree(css->pseudo_subchannel); |
@@ -702,7 +707,7 @@ static int __init setup_css(int nr) | |||
702 | mutex_init(&css->mutex); | 707 | mutex_init(&css->mutex); |
703 | css->valid = 1; | 708 | css->valid = 1; |
704 | css->cssid = nr; | 709 | css->cssid = nr; |
705 | sprintf(css->device.bus_id, "css%x", nr); | 710 | dev_set_name(&css->device, "css%x", nr); |
706 | css->device.release = channel_subsystem_release; | 711 | css->device.release = channel_subsystem_release; |
707 | tod_high = (u32) (get_clock() >> 32); | 712 | tod_high = (u32) (get_clock() >> 32); |
708 | css_generate_pgid(css, tod_high); | 713 | css_generate_pgid(css, tod_high); |
@@ -785,11 +790,15 @@ init_channel_subsystem (void) | |||
785 | } | 790 | } |
786 | channel_subsystems[i] = css; | 791 | channel_subsystems[i] = css; |
787 | ret = setup_css(i); | 792 | ret = setup_css(i); |
788 | if (ret) | 793 | if (ret) { |
789 | goto out_free; | 794 | kfree(channel_subsystems[i]); |
795 | goto out_unregister; | ||
796 | } | ||
790 | ret = device_register(&css->device); | 797 | ret = device_register(&css->device); |
791 | if (ret) | 798 | if (ret) { |
792 | goto out_free_all; | 799 | put_device(&css->device); |
800 | goto out_unregister; | ||
801 | } | ||
793 | if (css_chsc_characteristics.secm) { | 802 | if (css_chsc_characteristics.secm) { |
794 | ret = device_create_file(&css->device, | 803 | ret = device_create_file(&css->device, |
795 | &dev_attr_cm_enable); | 804 | &dev_attr_cm_enable); |
@@ -802,7 +811,7 @@ init_channel_subsystem (void) | |||
802 | } | 811 | } |
803 | ret = register_reboot_notifier(&css_reboot_notifier); | 812 | ret = register_reboot_notifier(&css_reboot_notifier); |
804 | if (ret) | 813 | if (ret) |
805 | goto out_pseudo; | 814 | goto out_unregister; |
806 | css_init_done = 1; | 815 | css_init_done = 1; |
807 | 816 | ||
808 | /* Enable default isc for I/O subchannels. */ | 817 | /* Enable default isc for I/O subchannels. */ |
@@ -810,18 +819,12 @@ init_channel_subsystem (void) | |||
810 | 819 | ||
811 | for_each_subchannel(__init_channel_subsystem, NULL); | 820 | for_each_subchannel(__init_channel_subsystem, NULL); |
812 | return 0; | 821 | return 0; |
813 | out_pseudo: | ||
814 | device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev); | ||
815 | out_file: | 822 | out_file: |
816 | device_remove_file(&channel_subsystems[i]->device, | 823 | if (css_chsc_characteristics.secm) |
817 | &dev_attr_cm_enable); | 824 | device_remove_file(&channel_subsystems[i]->device, |
825 | &dev_attr_cm_enable); | ||
818 | out_device: | 826 | out_device: |
819 | device_unregister(&channel_subsystems[i]->device); | 827 | device_unregister(&channel_subsystems[i]->device); |
820 | out_free_all: | ||
821 | kfree(channel_subsystems[i]->pseudo_subchannel->lock); | ||
822 | kfree(channel_subsystems[i]->pseudo_subchannel); | ||
823 | out_free: | ||
824 | kfree(channel_subsystems[i]); | ||
825 | out_unregister: | 828 | out_unregister: |
826 | while (i > 0) { | 829 | while (i > 0) { |
827 | struct channel_subsystem *css; | 830 | struct channel_subsystem *css; |
@@ -829,6 +832,7 @@ out_unregister: | |||
829 | i--; | 832 | i--; |
830 | css = channel_subsystems[i]; | 833 | css = channel_subsystems[i]; |
831 | device_unregister(&css->pseudo_subchannel->dev); | 834 | device_unregister(&css->pseudo_subchannel->dev); |
835 | css->pseudo_subchannel = NULL; | ||
832 | if (css_chsc_characteristics.secm) | 836 | if (css_chsc_characteristics.secm) |
833 | device_remove_file(&css->device, | 837 | device_remove_file(&css->device, |
834 | &dev_attr_cm_enable); | 838 | &dev_attr_cm_enable); |