aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/css.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/css.c')
-rw-r--r--drivers/s390/cio/css.c36
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;
813out_pseudo:
814 device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev);
815out_file: 822out_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);
818out_device: 826out_device:
819 device_unregister(&channel_subsystems[i]->device); 827 device_unregister(&channel_subsystems[i]->device);
820out_free_all:
821 kfree(channel_subsystems[i]->pseudo_subchannel->lock);
822 kfree(channel_subsystems[i]->pseudo_subchannel);
823out_free:
824 kfree(channel_subsystems[i]);
825out_unregister: 828out_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);