diff options
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r-- | arch/s390/kernel/smp.c | 83 |
1 files changed, 81 insertions, 2 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 5448aa87fa23..d1e8e8a3fb66 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -68,7 +68,9 @@ enum s390_cpu_state { | |||
68 | }; | 68 | }; |
69 | 69 | ||
70 | DEFINE_MUTEX(smp_cpu_state_mutex); | 70 | DEFINE_MUTEX(smp_cpu_state_mutex); |
71 | int smp_cpu_polarization[NR_CPUS]; | ||
71 | static int smp_cpu_state[NR_CPUS]; | 72 | static int smp_cpu_state[NR_CPUS]; |
73 | static int cpu_management; | ||
72 | 74 | ||
73 | static DEFINE_PER_CPU(struct cpu, cpu_devices); | 75 | static DEFINE_PER_CPU(struct cpu, cpu_devices); |
74 | DEFINE_PER_CPU(struct s390_idle_data, s390_idle); | 76 | DEFINE_PER_CPU(struct s390_idle_data, s390_idle); |
@@ -454,6 +456,7 @@ static int smp_rescan_cpus_sigp(cpumask_t avail) | |||
454 | if (cpu_known(cpu_id)) | 456 | if (cpu_known(cpu_id)) |
455 | continue; | 457 | continue; |
456 | __cpu_logical_map[logical_cpu] = cpu_id; | 458 | __cpu_logical_map[logical_cpu] = cpu_id; |
459 | smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN; | ||
457 | if (!cpu_stopped(logical_cpu)) | 460 | if (!cpu_stopped(logical_cpu)) |
458 | continue; | 461 | continue; |
459 | cpu_set(logical_cpu, cpu_present_map); | 462 | cpu_set(logical_cpu, cpu_present_map); |
@@ -487,6 +490,7 @@ static int smp_rescan_cpus_sclp(cpumask_t avail) | |||
487 | if (cpu_known(cpu_id)) | 490 | if (cpu_known(cpu_id)) |
488 | continue; | 491 | continue; |
489 | __cpu_logical_map[logical_cpu] = cpu_id; | 492 | __cpu_logical_map[logical_cpu] = cpu_id; |
493 | smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN; | ||
490 | cpu_set(logical_cpu, cpu_present_map); | 494 | cpu_set(logical_cpu, cpu_present_map); |
491 | if (cpu >= info->configured) | 495 | if (cpu >= info->configured) |
492 | smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY; | 496 | smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY; |
@@ -844,6 +848,7 @@ void __init smp_prepare_boot_cpu(void) | |||
844 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; | 848 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; |
845 | current_set[0] = current; | 849 | current_set[0] = current; |
846 | smp_cpu_state[0] = CPU_STATE_CONFIGURED; | 850 | smp_cpu_state[0] = CPU_STATE_CONFIGURED; |
851 | smp_cpu_polarization[0] = POLARIZATION_UNKNWN; | ||
847 | spin_lock_init(&(&__get_cpu_var(s390_idle))->lock); | 852 | spin_lock_init(&(&__get_cpu_var(s390_idle))->lock); |
848 | } | 853 | } |
849 | 854 | ||
@@ -895,15 +900,19 @@ static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf, | |||
895 | case 0: | 900 | case 0: |
896 | if (smp_cpu_state[cpu] == CPU_STATE_CONFIGURED) { | 901 | if (smp_cpu_state[cpu] == CPU_STATE_CONFIGURED) { |
897 | rc = sclp_cpu_deconfigure(__cpu_logical_map[cpu]); | 902 | rc = sclp_cpu_deconfigure(__cpu_logical_map[cpu]); |
898 | if (!rc) | 903 | if (!rc) { |
899 | smp_cpu_state[cpu] = CPU_STATE_STANDBY; | 904 | smp_cpu_state[cpu] = CPU_STATE_STANDBY; |
905 | smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN; | ||
906 | } | ||
900 | } | 907 | } |
901 | break; | 908 | break; |
902 | case 1: | 909 | case 1: |
903 | if (smp_cpu_state[cpu] == CPU_STATE_STANDBY) { | 910 | if (smp_cpu_state[cpu] == CPU_STATE_STANDBY) { |
904 | rc = sclp_cpu_configure(__cpu_logical_map[cpu]); | 911 | rc = sclp_cpu_configure(__cpu_logical_map[cpu]); |
905 | if (!rc) | 912 | if (!rc) { |
906 | smp_cpu_state[cpu] = CPU_STATE_CONFIGURED; | 913 | smp_cpu_state[cpu] = CPU_STATE_CONFIGURED; |
914 | smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN; | ||
915 | } | ||
907 | } | 916 | } |
908 | break; | 917 | break; |
909 | default: | 918 | default: |
@@ -917,6 +926,34 @@ out: | |||
917 | static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store); | 926 | static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store); |
918 | #endif /* CONFIG_HOTPLUG_CPU */ | 927 | #endif /* CONFIG_HOTPLUG_CPU */ |
919 | 928 | ||
929 | static ssize_t cpu_polarization_show(struct sys_device *dev, char *buf) | ||
930 | { | ||
931 | int cpu = dev->id; | ||
932 | ssize_t count; | ||
933 | |||
934 | mutex_lock(&smp_cpu_state_mutex); | ||
935 | switch (smp_cpu_polarization[cpu]) { | ||
936 | case POLARIZATION_HRZ: | ||
937 | count = sprintf(buf, "horizontal\n"); | ||
938 | break; | ||
939 | case POLARIZATION_VL: | ||
940 | count = sprintf(buf, "vertical:low\n"); | ||
941 | break; | ||
942 | case POLARIZATION_VM: | ||
943 | count = sprintf(buf, "vertical:medium\n"); | ||
944 | break; | ||
945 | case POLARIZATION_VH: | ||
946 | count = sprintf(buf, "vertical:high\n"); | ||
947 | break; | ||
948 | default: | ||
949 | count = sprintf(buf, "unknown\n"); | ||
950 | break; | ||
951 | } | ||
952 | mutex_unlock(&smp_cpu_state_mutex); | ||
953 | return count; | ||
954 | } | ||
955 | static SYSDEV_ATTR(polarization, 0444, cpu_polarization_show, NULL); | ||
956 | |||
920 | static ssize_t show_cpu_address(struct sys_device *dev, char *buf) | 957 | static ssize_t show_cpu_address(struct sys_device *dev, char *buf) |
921 | { | 958 | { |
922 | return sprintf(buf, "%d\n", __cpu_logical_map[dev->id]); | 959 | return sprintf(buf, "%d\n", __cpu_logical_map[dev->id]); |
@@ -929,6 +966,7 @@ static struct attribute *cpu_common_attrs[] = { | |||
929 | &attr_configure.attr, | 966 | &attr_configure.attr, |
930 | #endif | 967 | #endif |
931 | &attr_address.attr, | 968 | &attr_address.attr, |
969 | &attr_polarization.attr, | ||
932 | NULL, | 970 | NULL, |
933 | }; | 971 | }; |
934 | 972 | ||
@@ -1073,11 +1111,48 @@ static ssize_t __ref rescan_store(struct sys_device *dev, | |||
1073 | out: | 1111 | out: |
1074 | put_online_cpus(); | 1112 | put_online_cpus(); |
1075 | mutex_unlock(&smp_cpu_state_mutex); | 1113 | mutex_unlock(&smp_cpu_state_mutex); |
1114 | if (!cpus_empty(newcpus)) | ||
1115 | topology_schedule_update(); | ||
1076 | return rc ? rc : count; | 1116 | return rc ? rc : count; |
1077 | } | 1117 | } |
1078 | static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store); | 1118 | static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store); |
1079 | #endif /* CONFIG_HOTPLUG_CPU */ | 1119 | #endif /* CONFIG_HOTPLUG_CPU */ |
1080 | 1120 | ||
1121 | static ssize_t dispatching_show(struct sys_device *dev, char *buf) | ||
1122 | { | ||
1123 | ssize_t count; | ||
1124 | |||
1125 | mutex_lock(&smp_cpu_state_mutex); | ||
1126 | count = sprintf(buf, "%d\n", cpu_management); | ||
1127 | mutex_unlock(&smp_cpu_state_mutex); | ||
1128 | return count; | ||
1129 | } | ||
1130 | |||
1131 | static ssize_t dispatching_store(struct sys_device *dev, const char *buf, | ||
1132 | size_t count) | ||
1133 | { | ||
1134 | int val, rc; | ||
1135 | char delim; | ||
1136 | |||
1137 | if (sscanf(buf, "%d %c", &val, &delim) != 1) | ||
1138 | return -EINVAL; | ||
1139 | if (val != 0 && val != 1) | ||
1140 | return -EINVAL; | ||
1141 | rc = 0; | ||
1142 | mutex_lock(&smp_cpu_state_mutex); | ||
1143 | get_online_cpus(); | ||
1144 | if (cpu_management == val) | ||
1145 | goto out; | ||
1146 | rc = topology_set_cpu_management(val); | ||
1147 | if (!rc) | ||
1148 | cpu_management = val; | ||
1149 | out: | ||
1150 | put_online_cpus(); | ||
1151 | mutex_unlock(&smp_cpu_state_mutex); | ||
1152 | return rc ? rc : count; | ||
1153 | } | ||
1154 | static SYSDEV_ATTR(dispatching, 0644, dispatching_show, dispatching_store); | ||
1155 | |||
1081 | static int __init topology_init(void) | 1156 | static int __init topology_init(void) |
1082 | { | 1157 | { |
1083 | int cpu; | 1158 | int cpu; |
@@ -1091,6 +1166,10 @@ static int __init topology_init(void) | |||
1091 | if (rc) | 1166 | if (rc) |
1092 | return rc; | 1167 | return rc; |
1093 | #endif | 1168 | #endif |
1169 | rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, | ||
1170 | &attr_dispatching.attr); | ||
1171 | if (rc) | ||
1172 | return rc; | ||
1094 | for_each_present_cpu(cpu) { | 1173 | for_each_present_cpu(cpu) { |
1095 | rc = smp_add_present_cpu(cpu); | 1174 | rc = smp_add_present_cpu(cpu); |
1096 | if (rc) | 1175 | if (rc) |