diff options
Diffstat (limited to 'drivers/s390/cio/css.c')
-rw-r--r-- | drivers/s390/cio/css.c | 67 |
1 files changed, 33 insertions, 34 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index ac94ac751459..c47b25fd3f43 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * driver for channel subsystem | 2 | * driver for channel subsystem |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2002, 2009 | 4 | * Copyright IBM Corp. 2002, 2010 |
5 | * | 5 | * |
6 | * Author(s): Arnd Bergmann (arndb@de.ibm.com) | 6 | * Author(s): Arnd Bergmann (arndb@de.ibm.com) |
7 | * Cornelia Huck (cornelia.huck@de.ibm.com) | 7 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
@@ -35,6 +35,7 @@ int css_init_done = 0; | |||
35 | int max_ssid; | 35 | int max_ssid; |
36 | 36 | ||
37 | struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1]; | 37 | struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1]; |
38 | static struct bus_type css_bus_type; | ||
38 | 39 | ||
39 | int | 40 | int |
40 | for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data) | 41 | for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data) |
@@ -577,7 +578,7 @@ static int __unset_registered(struct device *dev, void *data) | |||
577 | return 0; | 578 | return 0; |
578 | } | 579 | } |
579 | 580 | ||
580 | void css_schedule_eval_all_unreg(void) | 581 | static void css_schedule_eval_all_unreg(void) |
581 | { | 582 | { |
582 | unsigned long flags; | 583 | unsigned long flags; |
583 | struct idset *unreg_set; | 584 | struct idset *unreg_set; |
@@ -618,6 +619,7 @@ EXPORT_SYMBOL_GPL(css_schedule_reprobe); | |||
618 | static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) | 619 | static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) |
619 | { | 620 | { |
620 | struct subchannel_id mchk_schid; | 621 | struct subchannel_id mchk_schid; |
622 | struct subchannel *sch; | ||
621 | 623 | ||
622 | if (overflow) { | 624 | if (overflow) { |
623 | css_schedule_eval_all(); | 625 | css_schedule_eval_all(); |
@@ -635,8 +637,15 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) | |||
635 | init_subchannel_id(&mchk_schid); | 637 | init_subchannel_id(&mchk_schid); |
636 | mchk_schid.sch_no = crw0->rsid; | 638 | mchk_schid.sch_no = crw0->rsid; |
637 | if (crw1) | 639 | if (crw1) |
638 | mchk_schid.ssid = (crw1->rsid >> 8) & 3; | 640 | mchk_schid.ssid = (crw1->rsid >> 4) & 3; |
639 | 641 | ||
642 | if (crw0->erc == CRW_ERC_PMOD) { | ||
643 | sch = get_subchannel_by_schid(mchk_schid); | ||
644 | if (sch) { | ||
645 | css_update_ssd_info(sch); | ||
646 | put_device(&sch->dev); | ||
647 | } | ||
648 | } | ||
640 | /* | 649 | /* |
641 | * Since we are always presented with IPI in the CRW, we have to | 650 | * Since we are always presented with IPI in the CRW, we have to |
642 | * use stsch() to find out if the subchannel in question has come | 651 | * use stsch() to find out if the subchannel in question has come |
@@ -790,7 +799,6 @@ static struct notifier_block css_reboot_notifier = { | |||
790 | static int css_power_event(struct notifier_block *this, unsigned long event, | 799 | static int css_power_event(struct notifier_block *this, unsigned long event, |
791 | void *ptr) | 800 | void *ptr) |
792 | { | 801 | { |
793 | void *secm_area; | ||
794 | int ret, i; | 802 | int ret, i; |
795 | 803 | ||
796 | switch (event) { | 804 | switch (event) { |
@@ -806,15 +814,8 @@ static int css_power_event(struct notifier_block *this, unsigned long event, | |||
806 | mutex_unlock(&css->mutex); | 814 | mutex_unlock(&css->mutex); |
807 | continue; | 815 | continue; |
808 | } | 816 | } |
809 | secm_area = (void *)get_zeroed_page(GFP_KERNEL | | 817 | if (__chsc_do_secm(css, 0)) |
810 | GFP_DMA); | ||
811 | if (secm_area) { | ||
812 | if (__chsc_do_secm(css, 0, secm_area)) | ||
813 | ret = NOTIFY_BAD; | ||
814 | free_page((unsigned long)secm_area); | ||
815 | } else | ||
816 | ret = NOTIFY_BAD; | 818 | ret = NOTIFY_BAD; |
817 | |||
818 | mutex_unlock(&css->mutex); | 819 | mutex_unlock(&css->mutex); |
819 | } | 820 | } |
820 | break; | 821 | break; |
@@ -830,15 +831,8 @@ static int css_power_event(struct notifier_block *this, unsigned long event, | |||
830 | mutex_unlock(&css->mutex); | 831 | mutex_unlock(&css->mutex); |
831 | continue; | 832 | continue; |
832 | } | 833 | } |
833 | secm_area = (void *)get_zeroed_page(GFP_KERNEL | | 834 | if (__chsc_do_secm(css, 1)) |
834 | GFP_DMA); | ||
835 | if (secm_area) { | ||
836 | if (__chsc_do_secm(css, 1, secm_area)) | ||
837 | ret = NOTIFY_BAD; | ||
838 | free_page((unsigned long)secm_area); | ||
839 | } else | ||
840 | ret = NOTIFY_BAD; | 835 | ret = NOTIFY_BAD; |
841 | |||
842 | mutex_unlock(&css->mutex); | 836 | mutex_unlock(&css->mutex); |
843 | } | 837 | } |
844 | /* search for subchannels, which appeared during hibernation */ | 838 | /* search for subchannels, which appeared during hibernation */ |
@@ -863,14 +857,11 @@ static int __init css_bus_init(void) | |||
863 | { | 857 | { |
864 | int ret, i; | 858 | int ret, i; |
865 | 859 | ||
866 | ret = chsc_determine_css_characteristics(); | 860 | ret = chsc_init(); |
867 | if (ret == -ENOMEM) | ||
868 | goto out; | ||
869 | |||
870 | ret = chsc_alloc_sei_area(); | ||
871 | if (ret) | 861 | if (ret) |
872 | goto out; | 862 | return ret; |
873 | 863 | ||
864 | chsc_determine_css_characteristics(); | ||
874 | /* Try to enable MSS. */ | 865 | /* Try to enable MSS. */ |
875 | ret = chsc_enable_facility(CHSC_SDA_OC_MSS); | 866 | ret = chsc_enable_facility(CHSC_SDA_OC_MSS); |
876 | if (ret) | 867 | if (ret) |
@@ -956,9 +947,9 @@ out_unregister: | |||
956 | } | 947 | } |
957 | bus_unregister(&css_bus_type); | 948 | bus_unregister(&css_bus_type); |
958 | out: | 949 | out: |
959 | crw_unregister_handler(CRW_RSC_CSS); | 950 | crw_unregister_handler(CRW_RSC_SCH); |
960 | chsc_free_sei_area(); | ||
961 | idset_free(slow_subchannel_set); | 951 | idset_free(slow_subchannel_set); |
952 | chsc_init_cleanup(); | ||
962 | pr_alert("The CSS device driver initialization failed with " | 953 | pr_alert("The CSS device driver initialization failed with " |
963 | "errno=%d\n", ret); | 954 | "errno=%d\n", ret); |
964 | return ret; | 955 | return ret; |
@@ -978,9 +969,9 @@ static void __init css_bus_cleanup(void) | |||
978 | device_unregister(&css->device); | 969 | device_unregister(&css->device); |
979 | } | 970 | } |
980 | bus_unregister(&css_bus_type); | 971 | bus_unregister(&css_bus_type); |
981 | crw_unregister_handler(CRW_RSC_CSS); | 972 | crw_unregister_handler(CRW_RSC_SCH); |
982 | chsc_free_sei_area(); | ||
983 | idset_free(slow_subchannel_set); | 973 | idset_free(slow_subchannel_set); |
974 | chsc_init_cleanup(); | ||
984 | isc_unregister(IO_SCH_ISC); | 975 | isc_unregister(IO_SCH_ISC); |
985 | } | 976 | } |
986 | 977 | ||
@@ -1048,7 +1039,16 @@ subsys_initcall_sync(channel_subsystem_init_sync); | |||
1048 | 1039 | ||
1049 | void channel_subsystem_reinit(void) | 1040 | void channel_subsystem_reinit(void) |
1050 | { | 1041 | { |
1042 | struct channel_path *chp; | ||
1043 | struct chp_id chpid; | ||
1044 | |||
1051 | chsc_enable_facility(CHSC_SDA_OC_MSS); | 1045 | chsc_enable_facility(CHSC_SDA_OC_MSS); |
1046 | chp_id_for_each(&chpid) { | ||
1047 | chp = chpid_to_chp(chpid); | ||
1048 | if (!chp) | ||
1049 | continue; | ||
1050 | chsc_determine_base_channel_path_desc(chpid, &chp->desc); | ||
1051 | } | ||
1052 | } | 1052 | } |
1053 | 1053 | ||
1054 | #ifdef CONFIG_PROC_FS | 1054 | #ifdef CONFIG_PROC_FS |
@@ -1067,6 +1067,7 @@ static ssize_t cio_settle_write(struct file *file, const char __user *buf, | |||
1067 | static const struct file_operations cio_settle_proc_fops = { | 1067 | static const struct file_operations cio_settle_proc_fops = { |
1068 | .open = nonseekable_open, | 1068 | .open = nonseekable_open, |
1069 | .write = cio_settle_write, | 1069 | .write = cio_settle_write, |
1070 | .llseek = no_llseek, | ||
1070 | }; | 1071 | }; |
1071 | 1072 | ||
1072 | static int __init cio_settle_init(void) | 1073 | static int __init cio_settle_init(void) |
@@ -1199,6 +1200,7 @@ static int css_pm_restore(struct device *dev) | |||
1199 | struct subchannel *sch = to_subchannel(dev); | 1200 | struct subchannel *sch = to_subchannel(dev); |
1200 | struct css_driver *drv; | 1201 | struct css_driver *drv; |
1201 | 1202 | ||
1203 | css_update_ssd_info(sch); | ||
1202 | if (!sch->dev.driver) | 1204 | if (!sch->dev.driver) |
1203 | return 0; | 1205 | return 0; |
1204 | drv = to_cssdriver(sch->dev.driver); | 1206 | drv = to_cssdriver(sch->dev.driver); |
@@ -1213,7 +1215,7 @@ static const struct dev_pm_ops css_pm_ops = { | |||
1213 | .restore = css_pm_restore, | 1215 | .restore = css_pm_restore, |
1214 | }; | 1216 | }; |
1215 | 1217 | ||
1216 | struct bus_type css_bus_type = { | 1218 | static struct bus_type css_bus_type = { |
1217 | .name = "css", | 1219 | .name = "css", |
1218 | .match = css_bus_match, | 1220 | .match = css_bus_match, |
1219 | .probe = css_probe, | 1221 | .probe = css_probe, |
@@ -1232,9 +1234,7 @@ struct bus_type css_bus_type = { | |||
1232 | */ | 1234 | */ |
1233 | int css_driver_register(struct css_driver *cdrv) | 1235 | int css_driver_register(struct css_driver *cdrv) |
1234 | { | 1236 | { |
1235 | cdrv->drv.name = cdrv->name; | ||
1236 | cdrv->drv.bus = &css_bus_type; | 1237 | cdrv->drv.bus = &css_bus_type; |
1237 | cdrv->drv.owner = cdrv->owner; | ||
1238 | return driver_register(&cdrv->drv); | 1238 | return driver_register(&cdrv->drv); |
1239 | } | 1239 | } |
1240 | EXPORT_SYMBOL_GPL(css_driver_register); | 1240 | EXPORT_SYMBOL_GPL(css_driver_register); |
@@ -1252,4 +1252,3 @@ void css_driver_unregister(struct css_driver *cdrv) | |||
1252 | EXPORT_SYMBOL_GPL(css_driver_unregister); | 1252 | EXPORT_SYMBOL_GPL(css_driver_unregister); |
1253 | 1253 | ||
1254 | MODULE_LICENSE("GPL"); | 1254 | MODULE_LICENSE("GPL"); |
1255 | EXPORT_SYMBOL(css_bus_type); | ||