diff options
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r-- | arch/s390/kernel/smp.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index fd8e3111a4e8..2270730f5354 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -856,13 +856,20 @@ static ssize_t show_idle_count(struct sys_device *dev, | |||
856 | { | 856 | { |
857 | struct s390_idle_data *idle; | 857 | struct s390_idle_data *idle; |
858 | unsigned long long idle_count; | 858 | unsigned long long idle_count; |
859 | unsigned int sequence; | ||
859 | 860 | ||
860 | idle = &per_cpu(s390_idle, dev->id); | 861 | idle = &per_cpu(s390_idle, dev->id); |
861 | spin_lock(&idle->lock); | 862 | repeat: |
863 | sequence = idle->sequence; | ||
864 | smp_rmb(); | ||
865 | if (sequence & 1) | ||
866 | goto repeat; | ||
862 | idle_count = idle->idle_count; | 867 | idle_count = idle->idle_count; |
863 | if (idle->idle_enter) | 868 | if (idle->idle_enter) |
864 | idle_count++; | 869 | idle_count++; |
865 | spin_unlock(&idle->lock); | 870 | smp_rmb(); |
871 | if (idle->sequence != sequence) | ||
872 | goto repeat; | ||
866 | return sprintf(buf, "%llu\n", idle_count); | 873 | return sprintf(buf, "%llu\n", idle_count); |
867 | } | 874 | } |
868 | static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL); | 875 | static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL); |
@@ -872,15 +879,22 @@ static ssize_t show_idle_time(struct sys_device *dev, | |||
872 | { | 879 | { |
873 | struct s390_idle_data *idle; | 880 | struct s390_idle_data *idle; |
874 | unsigned long long now, idle_time, idle_enter; | 881 | unsigned long long now, idle_time, idle_enter; |
882 | unsigned int sequence; | ||
875 | 883 | ||
876 | idle = &per_cpu(s390_idle, dev->id); | 884 | idle = &per_cpu(s390_idle, dev->id); |
877 | spin_lock(&idle->lock); | ||
878 | now = get_clock(); | 885 | now = get_clock(); |
886 | repeat: | ||
887 | sequence = idle->sequence; | ||
888 | smp_rmb(); | ||
889 | if (sequence & 1) | ||
890 | goto repeat; | ||
879 | idle_time = idle->idle_time; | 891 | idle_time = idle->idle_time; |
880 | idle_enter = idle->idle_enter; | 892 | idle_enter = idle->idle_enter; |
881 | if (idle_enter != 0ULL && idle_enter < now) | 893 | if (idle_enter != 0ULL && idle_enter < now) |
882 | idle_time += now - idle_enter; | 894 | idle_time += now - idle_enter; |
883 | spin_unlock(&idle->lock); | 895 | smp_rmb(); |
896 | if (idle->sequence != sequence) | ||
897 | goto repeat; | ||
884 | return sprintf(buf, "%llu\n", idle_time >> 12); | 898 | return sprintf(buf, "%llu\n", idle_time >> 12); |
885 | } | 899 | } |
886 | static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL); | 900 | static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL); |
@@ -908,11 +922,7 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, | |||
908 | case CPU_ONLINE: | 922 | case CPU_ONLINE: |
909 | case CPU_ONLINE_FROZEN: | 923 | case CPU_ONLINE_FROZEN: |
910 | idle = &per_cpu(s390_idle, cpu); | 924 | idle = &per_cpu(s390_idle, cpu); |
911 | spin_lock_irq(&idle->lock); | 925 | memset(idle, 0, sizeof(struct s390_idle_data)); |
912 | idle->idle_enter = 0; | ||
913 | idle->idle_time = 0; | ||
914 | idle->idle_count = 0; | ||
915 | spin_unlock_irq(&idle->lock); | ||
916 | if (sysfs_create_group(&s->kobj, &cpu_online_attr_group)) | 926 | if (sysfs_create_group(&s->kobj, &cpu_online_attr_group)) |
917 | return NOTIFY_BAD; | 927 | return NOTIFY_BAD; |
918 | break; | 928 | break; |