aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r--arch/s390/kernel/smp.c28
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); 862repeat:
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}
868static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL); 875static 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();
886repeat:
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}
886static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL); 900static 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;