diff options
Diffstat (limited to 'drivers/s390/cio/css.c')
-rw-r--r-- | drivers/s390/cio/css.c | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 65939e2eb415..0bf716619378 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -580,12 +580,24 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr, | |||
580 | 580 | ||
581 | static DEVICE_ATTR(cm_enable, 0644, css_cm_enable_show, css_cm_enable_store); | 581 | static DEVICE_ATTR(cm_enable, 0644, css_cm_enable_show, css_cm_enable_store); |
582 | 582 | ||
583 | static inline void __init | 583 | static inline int __init setup_css(int nr) |
584 | setup_css(int nr) | ||
585 | { | 584 | { |
586 | u32 tod_high; | 585 | u32 tod_high; |
586 | int ret; | ||
587 | 587 | ||
588 | memset(css[nr], 0, sizeof(struct channel_subsystem)); | 588 | memset(css[nr], 0, sizeof(struct channel_subsystem)); |
589 | css[nr]->pseudo_subchannel = | ||
590 | kzalloc(sizeof(*css[nr]->pseudo_subchannel), GFP_KERNEL); | ||
591 | if (!css[nr]->pseudo_subchannel) | ||
592 | return -ENOMEM; | ||
593 | css[nr]->pseudo_subchannel->dev.parent = &css[nr]->device; | ||
594 | css[nr]->pseudo_subchannel->dev.release = css_subchannel_release; | ||
595 | sprintf(css[nr]->pseudo_subchannel->dev.bus_id, "defunct"); | ||
596 | ret = cio_create_sch_lock(css[nr]->pseudo_subchannel); | ||
597 | if (ret) { | ||
598 | kfree(css[nr]->pseudo_subchannel); | ||
599 | return ret; | ||
600 | } | ||
589 | mutex_init(&css[nr]->mutex); | 601 | mutex_init(&css[nr]->mutex); |
590 | css[nr]->valid = 1; | 602 | css[nr]->valid = 1; |
591 | css[nr]->cssid = nr; | 603 | css[nr]->cssid = nr; |
@@ -593,6 +605,7 @@ setup_css(int nr) | |||
593 | css[nr]->device.release = channel_subsystem_release; | 605 | css[nr]->device.release = channel_subsystem_release; |
594 | tod_high = (u32) (get_clock() >> 32); | 606 | tod_high = (u32) (get_clock() >> 32); |
595 | css_generate_pgid(css[nr], tod_high); | 607 | css_generate_pgid(css[nr], tod_high); |
608 | return 0; | ||
596 | } | 609 | } |
597 | 610 | ||
598 | /* | 611 | /* |
@@ -629,10 +642,12 @@ init_channel_subsystem (void) | |||
629 | ret = -ENOMEM; | 642 | ret = -ENOMEM; |
630 | goto out_unregister; | 643 | goto out_unregister; |
631 | } | 644 | } |
632 | setup_css(i); | 645 | ret = setup_css(i); |
633 | ret = device_register(&css[i]->device); | ||
634 | if (ret) | 646 | if (ret) |
635 | goto out_free; | 647 | goto out_free; |
648 | ret = device_register(&css[i]->device); | ||
649 | if (ret) | ||
650 | goto out_free_all; | ||
636 | if (css_characteristics_avail && | 651 | if (css_characteristics_avail && |
637 | css_chsc_characteristics.secm) { | 652 | css_chsc_characteristics.secm) { |
638 | ret = device_create_file(&css[i]->device, | 653 | ret = device_create_file(&css[i]->device, |
@@ -640,6 +655,9 @@ init_channel_subsystem (void) | |||
640 | if (ret) | 655 | if (ret) |
641 | goto out_device; | 656 | goto out_device; |
642 | } | 657 | } |
658 | ret = device_register(&css[i]->pseudo_subchannel->dev); | ||
659 | if (ret) | ||
660 | goto out_file; | ||
643 | } | 661 | } |
644 | css_init_done = 1; | 662 | css_init_done = 1; |
645 | 663 | ||
@@ -647,13 +665,19 @@ init_channel_subsystem (void) | |||
647 | 665 | ||
648 | for_each_subchannel(__init_channel_subsystem, NULL); | 666 | for_each_subchannel(__init_channel_subsystem, NULL); |
649 | return 0; | 667 | return 0; |
668 | out_file: | ||
669 | device_remove_file(&css[i]->device, &dev_attr_cm_enable); | ||
650 | out_device: | 670 | out_device: |
651 | device_unregister(&css[i]->device); | 671 | device_unregister(&css[i]->device); |
672 | out_free_all: | ||
673 | kfree(css[i]->pseudo_subchannel->lock); | ||
674 | kfree(css[i]->pseudo_subchannel); | ||
652 | out_free: | 675 | out_free: |
653 | kfree(css[i]); | 676 | kfree(css[i]); |
654 | out_unregister: | 677 | out_unregister: |
655 | while (i > 0) { | 678 | while (i > 0) { |
656 | i--; | 679 | i--; |
680 | device_unregister(&css[i]->pseudo_subchannel->dev); | ||
657 | if (css_characteristics_avail && css_chsc_characteristics.secm) | 681 | if (css_characteristics_avail && css_chsc_characteristics.secm) |
658 | device_remove_file(&css[i]->device, | 682 | device_remove_file(&css[i]->device, |
659 | &dev_attr_cm_enable); | 683 | &dev_attr_cm_enable); |
@@ -665,6 +689,11 @@ out: | |||
665 | return ret; | 689 | return ret; |
666 | } | 690 | } |
667 | 691 | ||
692 | int sch_is_pseudo_sch(struct subchannel *sch) | ||
693 | { | ||
694 | return sch == to_css(sch->dev.parent)->pseudo_subchannel; | ||
695 | } | ||
696 | |||
668 | /* | 697 | /* |
669 | * find a driver for a subchannel. They identify by the subchannel | 698 | * find a driver for a subchannel. They identify by the subchannel |
670 | * type with the exception that the console subchannel driver has its own | 699 | * type with the exception that the console subchannel driver has its own |