}
 
 struct cpu_cf_events {
-       struct cpumf_ctr_info   info;
        atomic_t                ctr_set[CPUMF_CTR_SET_MAX];
        u64                     state;          /* For perf_event_open SVC */
        u64                     dev_state;      /* For /dev/hwctr */
 static unsigned int cfdiag_cpu_speed;  /* CPU speed for CF_DIAG trailer */
 static debug_info_t *cf_dbg;
 
+/*
+ * The CPU Measurement query counter information instruction contains
+ * information which varies per machine generation, but is constant and
+ * does not change when running on a particular machine, such as counter
+ * first and second version number. This is needed to determine the size
+ * of counter sets. Extract this information at device driver initialization.
+ */
+static struct cpumf_ctr_info   cpumf_ctr_info;
+
 #define        CF_DIAG_CTRSET_DEF              0xfeef  /* Counter set header mark */
                                                /* interval in seconds */
 
 /* Create the trailer data at the end of a page. */
 static void cfdiag_trailer(struct cf_trailer_entry *te)
 {
-       struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
        struct cpuid cpuid;
 
-       te->cfvn = cpuhw->info.cfvn;            /* Counter version numbers */
-       te->csvn = cpuhw->info.csvn;
+       te->cfvn = cpumf_ctr_info.cfvn;         /* Counter version numbers */
+       te->csvn = cpumf_ctr_info.csvn;
 
        get_cpu_id(&cpuid);                     /* Machine type */
        te->mach_type = cpuid.machine;
 }
 
 /*
- * Return the maximum possible counter set size (in number of 8 byte counters)
- * depending on type and model number.
+ * The number of counters per counter set varies between machine generations,
+ * but is constant when running on a particular machine generation.
+ * Determine each counter set size at device driver initialization and
+ * retrieve it later.
  */
-static size_t cpum_cf_ctrset_size(enum cpumf_ctr_set ctrset,
-                                 struct cpumf_ctr_info *info)
+static size_t cpumf_ctr_setsizes[CPUMF_CTR_SET_MAX];
+static void cpum_cf_make_setsize(enum cpumf_ctr_set ctrset)
 {
        size_t ctrset_size = 0;
 
        switch (ctrset) {
        case CPUMF_CTR_SET_BASIC:
-               if (info->cfvn >= 1)
+               if (cpumf_ctr_info.cfvn >= 1)
                        ctrset_size = 6;
                break;
        case CPUMF_CTR_SET_USER:
-               if (info->cfvn == 1)
+               if (cpumf_ctr_info.cfvn == 1)
                        ctrset_size = 6;
-               else if (info->cfvn >= 3)
+               else if (cpumf_ctr_info.cfvn >= 3)
                        ctrset_size = 2;
                break;
        case CPUMF_CTR_SET_CRYPTO:
-               if (info->csvn >= 1 && info->csvn <= 5)
+               if (cpumf_ctr_info.csvn >= 1 && cpumf_ctr_info.csvn <= 5)
                        ctrset_size = 16;
-               else if (info->csvn == 6 || info->csvn == 7)
+               else if (cpumf_ctr_info.csvn == 6 || cpumf_ctr_info.csvn == 7)
                        ctrset_size = 20;
                break;
        case CPUMF_CTR_SET_EXT:
-               if (info->csvn == 1)
+               if (cpumf_ctr_info.csvn == 1)
                        ctrset_size = 32;
-               else if (info->csvn == 2)
+               else if (cpumf_ctr_info.csvn == 2)
                        ctrset_size = 48;
-               else if (info->csvn >= 3 && info->csvn <= 5)
+               else if (cpumf_ctr_info.csvn >= 3 && cpumf_ctr_info.csvn <= 5)
                        ctrset_size = 128;
-               else if (info->csvn == 6 || info->csvn == 7)
+               else if (cpumf_ctr_info.csvn == 6 || cpumf_ctr_info.csvn == 7)
                        ctrset_size = 160;
                break;
        case CPUMF_CTR_SET_MT_DIAG:
-               if (info->csvn > 3)
+               if (cpumf_ctr_info.csvn > 3)
                        ctrset_size = 48;
                break;
        case CPUMF_CTR_SET_MAX:
                break;
        }
+       cpumf_ctr_setsizes[ctrset] = ctrset_size;
+}
 
-       return ctrset_size;
+/*
+ * Return the maximum possible counter set size (in number of 8 byte counters)
+ * depending on type and model number.
+ */
+static size_t cpum_cf_read_setsize(enum cpumf_ctr_set ctrset)
+{
+       return cpumf_ctr_setsizes[ctrset];
 }
 
 /* Read a counter set. The counter set number determines the counter set and
 static size_t cfdiag_getctrset(struct cf_ctrset_entry *ctrdata, int ctrset,
                               size_t room, bool error_ok)
 {
-       struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
        size_t ctrset_size, need = 0;
        int rc = 3;                             /* Assume write failure */
 
        ctrdata->def = CF_DIAG_CTRSET_DEF;
        ctrdata->set = ctrset;
        ctrdata->res1 = 0;
-       ctrset_size = cpum_cf_ctrset_size(ctrset, &cpuhw->info);
+       ctrset_size = cpum_cf_read_setsize(ctrset);
 
        if (ctrset_size) {                      /* Save data */
                need = ctrset_size * sizeof(u64) + sizeof(*ctrdata);
                        need = 0;
        }
 
-       debug_sprintf_event(cf_dbg, 3,
-                           "%s ctrset %d ctrset_size %zu cfvn %d csvn %d"
-                           " need %zd rc %d\n", __func__, ctrset, ctrset_size,
-                           cpuhw->info.cfvn, cpuhw->info.csvn, need, rc);
        return need;
 }
 
 static int validate_ctr_version(const struct hw_perf_event *hwc,
                                enum cpumf_ctr_set set)
 {
-       struct cpu_cf_events *cpuhw;
-       int err = 0;
        u16 mtdiag_ctl;
-
-       cpuhw = &get_cpu_var(cpu_cf_events);
+       int err = 0;
 
        /* check required version for counter sets */
        switch (set) {
        case CPUMF_CTR_SET_BASIC:
        case CPUMF_CTR_SET_USER:
-               if (cpuhw->info.cfvn < 1)
+               if (cpumf_ctr_info.cfvn < 1)
                        err = -EOPNOTSUPP;
                break;
        case CPUMF_CTR_SET_CRYPTO:
-               if ((cpuhw->info.csvn >= 1 && cpuhw->info.csvn <= 5 &&
+               if ((cpumf_ctr_info.csvn >= 1 && cpumf_ctr_info.csvn <= 5 &&
                     hwc->config > 79) ||
-                   (cpuhw->info.csvn >= 6 && hwc->config > 83))
+                   (cpumf_ctr_info.csvn >= 6 && hwc->config > 83))
                        err = -EOPNOTSUPP;
                break;
        case CPUMF_CTR_SET_EXT:
-               if (cpuhw->info.csvn < 1)
+               if (cpumf_ctr_info.csvn < 1)
                        err = -EOPNOTSUPP;
-               if ((cpuhw->info.csvn == 1 && hwc->config > 159) ||
-                   (cpuhw->info.csvn == 2 && hwc->config > 175) ||
-                   (cpuhw->info.csvn >= 3 && cpuhw->info.csvn <= 5
+               if ((cpumf_ctr_info.csvn == 1 && hwc->config > 159) ||
+                   (cpumf_ctr_info.csvn == 2 && hwc->config > 175) ||
+                   (cpumf_ctr_info.csvn >= 3 && cpumf_ctr_info.csvn <= 5
                     && hwc->config > 255) ||
-                   (cpuhw->info.csvn >= 6 && hwc->config > 287))
+                   (cpumf_ctr_info.csvn >= 6 && hwc->config > 287))
                        err = -EOPNOTSUPP;
                break;
        case CPUMF_CTR_SET_MT_DIAG:
-               if (cpuhw->info.csvn <= 3)
+               if (cpumf_ctr_info.csvn <= 3)
                        err = -EOPNOTSUPP;
                /*
                 * MT-diagnostic counters are read-only.  The counter set
                 * counter set is enabled and active.
                 */
                mtdiag_ctl = cpumf_ctr_ctl[CPUMF_CTR_SET_MT_DIAG];
-               if (!((cpuhw->info.auth_ctl & mtdiag_ctl) &&
-                     (cpuhw->info.enable_ctl & mtdiag_ctl) &&
-                     (cpuhw->info.act_ctl & mtdiag_ctl)))
+               if (!((cpumf_ctr_info.auth_ctl & mtdiag_ctl) &&
+                     (cpumf_ctr_info.enable_ctl & mtdiag_ctl) &&
+                     (cpumf_ctr_info.act_ctl & mtdiag_ctl)))
                        err = -EOPNOTSUPP;
                break;
        case CPUMF_CTR_SET_MAX:
                err = -EOPNOTSUPP;
        }
 
-       put_cpu_var(cpu_cf_events);
        return err;
 }
 
 static int validate_ctr_auth(const struct hw_perf_event *hwc)
 {
-       struct cpu_cf_events *cpuhw;
-       int err = 0;
-
-       cpuhw = &get_cpu_var(cpu_cf_events);
+       int err = -ENOENT;
 
        /* Check authorization for cpu counter sets.
         * If the particular CPU counter set is not authorized,
         * return with -ENOENT in order to fall back to other
         * PMUs that might suffice the event request.
         */
-       if (!(hwc->config_base & cpuhw->info.auth_ctl))
-               err = -ENOENT;
+       if ((hwc->config_base & cpumf_ctr_info.auth_ctl))
+               err = 0;
 
-       put_cpu_var(cpu_cf_events);
        return err;
 }
 
 
        switch ((unsigned long)flags) {
        case PMC_INIT:
-               memset(&cpuhw->info, 0, sizeof(cpuhw->info));
-               qctri(&cpuhw->info);
                cpuhw->flags |= PMU_F_RESERVED;
                break;
 
 
        /* counter authorization change alert */
        if (alert & CPU_MF_INT_CF_CACA)
-               qctri(&cpuhw->info);
+               qctri(&cpumf_ctr_info);
 
        /* loss of counter data alert */
        if (alert & CPU_MF_INT_CF_LCDA)
 {
        int rc;
 
-       if (!cpum_cf_avail())
+       /* Extract counter measurement facility information */
+       if (!cpum_cf_avail() || qctri(&cpumf_ctr_info))
                return -ENODEV;
 
+       /* Determine and store counter set sizes for later reference */
+       for (rc = CPUMF_CTR_SET_BASIC; rc < CPUMF_CTR_SET_MAX; ++rc)
+               cpum_cf_make_setsize(rc);
+
        /*
         * Clear bit 15 of cr0 to unauthorize problem-state to
         * extract measurement counters
  */
 static size_t cfset_needspace(unsigned int sets)
 {
-       struct cpu_cf_events *cpuhw = get_cpu_ptr(&cpu_cf_events);
        size_t bytes = 0;
        int i;
 
        for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
                if (!(sets & cpumf_ctr_ctl[i]))
                        continue;
-               bytes += cpum_cf_ctrset_size(i, &cpuhw->info) * sizeof(u64) +
+               bytes += cpum_cf_read_setsize(i) * sizeof(u64) +
                         sizeof(((struct s390_ctrset_setdata *)0)->set) +
                         sizeof(((struct s390_ctrset_setdata *)0)->no_cnts);
        }
        bytes = sizeof(((struct s390_ctrset_read *)0)->no_cpus) + nr_cpu_ids *
                (bytes + sizeof(((struct s390_ctrset_cpudata *)0)->cpu_nr) +
                     sizeof(((struct s390_ctrset_cpudata *)0)->no_sets));
-       put_cpu_ptr(&cpu_cf_events);
        return bytes;
 }
 
 
                if (!(p->sets & cpumf_ctr_ctl[set]))
                        continue;       /* Counter set not in list */
-               set_size = cpum_cf_ctrset_size(set, &cpuhw->info);
+               set_size = cpum_cf_read_setsize(set);
                space = sizeof(cpuhw->data) - cpuhw->used;
                space = cfset_cpuset_read(sp, set, set_size, space);
                if (space) {
 
 static int get_authctrsets(void)
 {
-       struct cpu_cf_events *cpuhw;
        unsigned long auth = 0;
        enum cpumf_ctr_set i;
 
-       cpuhw = &get_cpu_var(cpu_cf_events);
        for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
-               if (cpuhw->info.auth_ctl & cpumf_ctr_ctl[i])
+               if (cpumf_ctr_info.auth_ctl & cpumf_ctr_ctl[i])
                        auth |= cpumf_ctr_ctl[i];
        }
-       put_cpu_var(cpu_cf_events);
        return auth;
 }
 
        enum cpumf_ctr_set i;
 
        for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
-               size_t size = cpum_cf_ctrset_size(i, info);
+               size_t size = cpum_cf_read_setsize(i);
 
                if (size)
                        max_size += size * sizeof(u64) +
 
 static int cfset_init(void)
 {
-       struct cpumf_ctr_info info;
        size_t need;
        int rc;
 
-       if (qctri(&info))
-               return -ENODEV;
-
        cfdiag_get_cpu_speed();
        /* Make sure the counter set data fits into predefined buffer. */
-       need = cfdiag_maxsize(&info);
+       need = cfdiag_maxsize(&cpumf_ctr_info);
        if (need > sizeof(((struct cpu_cf_events *)0)->start)) {
                pr_err("Insufficient memory for PMU(cpum_cf_diag) need=%zu\n",
                       need);