]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/cio: Externalize full CMG characteristics
authorPeter Oberparleiter <oberpar@linux.ibm.com>
Thu, 7 Nov 2024 14:50:36 +0000 (15:50 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Wed, 13 Nov 2024 13:31:31 +0000 (14:31 +0100)
The current "measurement_chars" CHPID sysfs attribute exposes only a
limited, validity-filtered portion of data from the associated Channel-
Measurements Characteristics Block (CMCB). New machine models add data
that is relevant for userspace tooling to the "header"-portion of the
CMCB. This data that is not currently accessible to userspace.

To prevent having to add new sysfs attributes whenever a new bit of data
is added to the CMCB "header", add a new sysfs attribute named
"measurement_chars_full" that exposes the full, unfiltered CMCB.

Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
drivers/s390/cio/chp.c
drivers/s390/cio/chp.h
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc.h

index 8f9aa31bd1a1527164cd02973f11ebd10324a56d..cba2d048a96b3cb0cc79080ef4c771b0f7d5bc34 100644 (file)
@@ -144,6 +144,18 @@ static ssize_t measurement_chars_read(struct file *filp, struct kobject *kobj,
 }
 static BIN_ATTR_ADMIN_RO(measurement_chars, sizeof(struct cmg_chars));
 
+static ssize_t measurement_chars_full_read(struct file *filp,
+                                          struct kobject *kobj,
+                                          struct bin_attribute *bin_attr,
+                                          char *buf, loff_t off, size_t count)
+{
+       struct channel_path *chp = to_channelpath(kobj_to_dev(kobj));
+
+       return memory_read_from_buffer(buf, count, &off, &chp->cmcb,
+                                      sizeof(chp->cmcb));
+}
+static BIN_ATTR_ADMIN_RO(measurement_chars_full, sizeof(struct cmg_cmcb));
+
 static ssize_t chp_measurement_copy_block(void *buf, loff_t off, size_t count,
                                          struct kobject *kobj, bool extended)
 {
@@ -201,6 +213,7 @@ static BIN_ATTR_ADMIN_RO(ext_measurement, sizeof(struct cmg_ext_entry));
 
 static struct bin_attribute *measurement_attrs[] = {
        &bin_attr_measurement_chars,
+       &bin_attr_measurement_chars_full,
        &bin_attr_measurement,
        &bin_attr_ext_measurement,
        NULL,
index a15324a43aa3ad50747297d0ad61299b7aadb2a9..391b52a7474cf7afb0e359390a8e6abb63299f93 100644 (file)
@@ -54,6 +54,7 @@ struct channel_path {
        int extended;
        unsigned long speed;
        struct cmg_chars cmg_chars;
+       struct cmg_cmcb cmcb;
 };
 
 /* Return channel_path struct for given chpid. */
index a86b05d140050321496766017a570e4ecde738ec..e6462317abd0641dd117293e59620cd5aefac0f3 100644 (file)
@@ -1092,19 +1092,7 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
                u32 zeroes1;
                struct chsc_header response;
                u32 zeroes2;
-               u32 not_valid : 1;
-               u32 shared : 1;
-               u32 extended : 1;
-               u32 : 21;
-               u32 chpid : 8;
-               u32 cmcv : 5;
-               u32 : 7;
-               u32 cmgp : 4;
-               u32 cmgq : 8;
-               u32 cmg : 8;
-               u32 : 16;
-               u32 cmgs : 16;
-               u32 data[NR_MEASUREMENT_CHARS];
+               struct cmg_cmcb cmcb;
        } *scmc_area;
 
        chp->shared = -1;
@@ -1135,15 +1123,16 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
                              scmc_area->response.code);
                goto out;
        }
-       if (scmc_area->not_valid)
+       chp->cmcb = scmc_area->cmcb;
+       if (scmc_area->cmcb.not_valid)
                goto out;
 
-       chp->cmg = scmc_area->cmg;
-       chp->shared = scmc_area->shared;
-       chp->extended = scmc_area->extended;
-       chp->speed = scmc_get_speed(scmc_area->cmgs, scmc_area->cmgp);
-       chsc_initialize_cmg_chars(chp, scmc_area->cmcv,
-                                 (struct cmg_chars *) &scmc_area->data);
+       chp->cmg = scmc_area->cmcb.cmg;
+       chp->shared = scmc_area->cmcb.shared;
+       chp->extended = scmc_area->cmcb.extended;
+       chp->speed = scmc_get_speed(scmc_area->cmcb.cmgs, scmc_area->cmcb.cmgp);
+       chsc_initialize_cmg_chars(chp, scmc_area->cmcb.cmcv,
+                                 (struct cmg_chars *)&scmc_area->cmcb.data);
 out:
        spin_unlock_irqrestore(&chsc_page_lock, flags);
        return ret;
index 24cd65dbc5a763979f772177aeba380200ad8aee..6fe983ebf4b38a1e4022d398ed4f1f222b379e40 100644 (file)
@@ -17,6 +17,22 @@ struct cmg_chars {
        u32 values[NR_MEASUREMENT_CHARS];
 };
 
+struct cmg_cmcb {
+       u32 not_valid : 1;
+       u32 shared    : 1;
+       u32 extended  : 1;
+       u32           : 21;
+       u32 chpid     : 8;
+       u32 cmcv      : 5;
+       u32           : 7;
+       u32 cmgp      : 4;
+       u32 cmgq      : 8;
+       u32 cmg       : 8;
+       u32           : 16;
+       u32 cmgs      : 16;
+       u32 data[NR_MEASUREMENT_CHARS];
+};
+
 #define NR_MEASUREMENT_ENTRIES 8
 struct cmg_entry {
        u32 values[NR_MEASUREMENT_ENTRIES];