s390/appldata: do not use stack buffers for hardware data
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 6 Sep 2018 08:47:26 +0000 (10:47 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 9 Oct 2018 09:20:52 +0000 (11:20 +0200)
With CONFIG_VMAP_STACK=y the stack is allocated from the vmalloc space.
Data structures passed to a hardware or a hypervisor interface that
requires V=R can not be allocated on the stack anymore.

Use kmalloc to get memory for the appldata_product_id and the
appldata_parameter_list structures.

Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/appldata/appldata_base.c

index 50dd711..e4b5824 100644 (file)
@@ -137,6 +137,14 @@ static void appldata_work_fn(struct work_struct *work)
        mutex_unlock(&appldata_ops_mutex);
 }
 
+static struct appldata_product_id appldata_id = {
+       .prod_nr    = {0xD3, 0xC9, 0xD5, 0xE4,
+                      0xE7, 0xD2, 0xD9},       /* "LINUXKR" */
+       .prod_fn    = 0xD5D3,                   /* "NL" */
+       .version_nr = 0xF2F6,                   /* "26" */
+       .release_nr = 0xF0F1,                   /* "01" */
+};
+
 /*
  * appldata_diag()
  *
@@ -145,19 +153,22 @@ static void appldata_work_fn(struct work_struct *work)
 int appldata_diag(char record_nr, u16 function, unsigned long buffer,
                        u16 length, char *mod_lvl)
 {
-       struct appldata_parameter_list parm_list;
-       struct appldata_product_id id = {
-               .prod_nr    = {0xD3, 0xC9, 0xD5, 0xE4,
-                              0xE7, 0xD2, 0xD9},       /* "LINUXKR" */
-               .prod_fn    = 0xD5D3,                   /* "NL" */
-               .version_nr = 0xF2F6,                   /* "26" */
-               .release_nr = 0xF0F1,                   /* "01" */
-       };
+       struct appldata_parameter_list *parm_list;
+       struct appldata_product_id *id;
+       int rc;
 
-       id.record_nr = record_nr;
-       id.mod_lvl = (mod_lvl[0]) << 8 | mod_lvl[1];
-       return appldata_asm(&parm_list, &id, function,
-                           (void *) buffer, length);
+       parm_list = kmalloc(sizeof(*parm_list), GFP_KERNEL);
+       id = kmemdup(&appldata_id, sizeof(appldata_id), GFP_KERNEL);
+       rc = -ENOMEM;
+       if (parm_list && id) {
+               id->record_nr = record_nr;
+               id->mod_lvl = (mod_lvl[0]) << 8 | mod_lvl[1];
+               rc = appldata_asm(parm_list, id, function,
+                                 (void *) buffer, length);
+       }
+       kfree(id);
+       kfree(parm_list);
+       return rc;
 }
 /************************ timer, work, DIAG <END> ****************************/