]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
s390/cio: rework channel-utilization-block handling
authorPeter Oberparleiter <oberpar@linux.ibm.com>
Tue, 26 Mar 2024 16:03:20 +0000 (17:03 +0100)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Fri, 12 Apr 2024 14:11:28 +0000 (16:11 +0200)
Convert channel-utilization-block (CUB) address variables from separate
named fields to arrays of addresses. Also simplify error handling and
introduce named constants. This is done in preparation of introducing
additional CUBs.

Note: With this change the __packed annotation of secm_area is required
to prevent an alignment hole that would otherwise occur due to the
switch from u32 to dma64_t.

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

index 675d7ed82356a9494d7df785494bd7d2ce8e2ec6..0edb6dd0f10524881115628b1a7466cffbf39765 100644 (file)
@@ -161,12 +161,12 @@ static void chp_measurement_copy_block(struct cmg_entry *buf,
        struct cmg_entry *entry, reference_buf;
        int idx;
 
-       if (chpid.id < 128) {
-               area = css->cub_addr1;
+       if (chpid.id < CSS_CUES_PER_PAGE) {
+               area = css->cub[0];
                idx = chpid.id;
        } else {
-               area = css->cub_addr2;
-               idx = chpid.id - 128;
+               area = css->cub[1];
+               idx = chpid.id - CSS_CUES_PER_PAGE;
        }
        entry = area + (idx * sizeof(struct cmg_entry));
        do {
index 89e51f197cdd51448bc64588b5c176d36d3c196a..3344fa996ec45cab5322e631aa63132aaacc1308 100644 (file)
@@ -874,19 +874,16 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable)
                u32 : 30;
                u32 key : 4;
                u32 : 28;
-               u32 zeroes1;
-               dma32_t cub_addr1;
-               u32 zeroes2;
-               dma32_t cub_addr2;
+               dma64_t cub[CSS_NUM_CUB_PAGES];
                u32 reserved[13];
                struct chsc_header response;
                u32 status : 8;
                u32 : 4;
                u32 fmt : 4;
                u32 : 16;
-       } *secm_area;
+       } __packed *secm_area;
        unsigned long flags;
-       int ret, ccode;
+       int ret, ccode, i;
 
        spin_lock_irqsave(&chsc_page_lock, flags);
        memset(chsc_page, 0, PAGE_SIZE);
@@ -895,8 +892,9 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable)
        secm_area->request.code = 0x0016;
 
        secm_area->key = PAGE_DEFAULT_KEY >> 4;
-       secm_area->cub_addr1 = virt_to_dma32(css->cub_addr1);
-       secm_area->cub_addr2 = virt_to_dma32(css->cub_addr2);
+
+       for (i = 0; i < CSS_NUM_CUB_PAGES; i++)
+               secm_area->cub[i] = (__force dma64_t)virt_to_dma32(css->cub[i]);
 
        secm_area->operation_code = enable ? 0 : 1;
 
@@ -922,19 +920,38 @@ out:
        return ret;
 }
 
+static int cub_alloc(struct channel_subsystem *css)
+{
+       int i;
+
+       for (i = 0; i < CSS_NUM_CUB_PAGES; i++) {
+               css->cub[i] = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+               if (!css->cub[i])
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void cub_free(struct channel_subsystem *css)
+{
+       int i;
+
+       for (i = 0; i < CSS_NUM_CUB_PAGES; i++) {
+               free_page((unsigned long)css->cub[i]);
+               css->cub[i] = NULL;
+       }
+}
+
 int
 chsc_secm(struct channel_subsystem *css, int enable)
 {
        int ret;
 
        if (enable && !css->cm_enabled) {
-               css->cub_addr1 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-               css->cub_addr2 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-               if (!css->cub_addr1 || !css->cub_addr2) {
-                       free_page((unsigned long)css->cub_addr1);
-                       free_page((unsigned long)css->cub_addr2);
-                       return -ENOMEM;
-               }
+               ret = cub_alloc(css);
+               if (ret)
+                       goto out;
        }
        ret = __chsc_do_secm(css, enable);
        if (!ret) {
@@ -948,10 +965,11 @@ chsc_secm(struct channel_subsystem *css, int enable)
                } else
                        chsc_remove_cmg_attr(css);
        }
-       if (!css->cm_enabled) {
-               free_page((unsigned long)css->cub_addr1);
-               free_page((unsigned long)css->cub_addr2);
-       }
+
+out:
+       if (!css->cm_enabled)
+               cub_free(css);
+
        return ret;
 }
 
index ea55505542974044a2613330d4718ab712ddd847..aca11dacb224139fa1e28f1fa7dbf5e9c6434009 100644 (file)
 #define SNID_STATE3_MULTI_PATH    1
 #define SNID_STATE3_SINGLE_PATH           0
 
+/*
+ * Miscellaneous constants
+ */
+
+#define CSS_NUM_CUB_PAGES              2
+#define CSS_CUES_PER_PAGE              128
+
 /*
  * Conditions used to specify which subchannels need evaluation
  */
@@ -122,8 +129,7 @@ struct channel_subsystem {
        struct mutex mutex;
        /* channel measurement related */
        int cm_enabled;
-       void *cub_addr1;
-       void *cub_addr2;
+       void *cub[CSS_NUM_CUB_PAGES];
        /* for orphaned ccw devices */
        struct subchannel *pseudo_subchannel;
 };