s390/appldata_net_sum: do not use static data
authorSebastian Ott <sebott@linux.vnet.ibm.com>
Tue, 25 Jun 2013 13:37:44 +0000 (15:37 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 26 Jun 2013 19:10:31 +0000 (21:10 +0200)
Using static data for fields which are accessed by HW will fail if
the driver is build as a module (since this would be vmalloc'ed
memory). This Bug was revealed via
"s390: remove virt_to_phys implementation" - the old virt_to_phys
implementation would have translated the address but it was not
guaranteed that the memory was contiguous.

Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/appldata/appldata_net_sum.c

index 2d224b945355c2897ac9b805284245f5f2ab0204..66037d2622b4075c708068a414aa4b346f8740c1 100644 (file)
@@ -29,7 +29,7 @@
  * book:
  * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml
  */
-static struct appldata_net_sum_data {
+struct appldata_net_sum_data {
        u64 timestamp;
        u32 sync_count_1;       /* after VM collected the record data, */
        u32 sync_count_2;       /* sync_count_1 and sync_count_2 should be the
@@ -51,7 +51,7 @@ static struct appldata_net_sum_data {
        u64 rx_dropped;         /* no space in linux buffers     */
        u64 tx_dropped;         /* no space available in linux   */
        u64 collisions;         /* collisions while transmitting */
-} __attribute__((packed)) appldata_net_sum_data;
+} __packed;
 
 
 /*
@@ -121,7 +121,6 @@ static struct appldata_ops ops = {
        .record_nr = APPLDATA_RECORD_NET_SUM_ID,
        .size      = sizeof(struct appldata_net_sum_data),
        .callback  = &appldata_get_net_sum_data,
-       .data      = &appldata_net_sum_data,
        .owner     = THIS_MODULE,
        .mod_lvl   = {0xF0, 0xF0},              /* EBCDIC "00" */
 };
@@ -134,7 +133,17 @@ static struct appldata_ops ops = {
  */
 static int __init appldata_net_init(void)
 {
-       return appldata_register_ops(&ops);
+       int ret;
+
+       ops.data = kzalloc(sizeof(struct appldata_net_sum_data), GFP_KERNEL);
+       if (!ops.data)
+               return -ENOMEM;
+
+       ret = appldata_register_ops(&ops);
+       if (ret)
+               kfree(ops.data);
+
+       return ret;
 }
 
 /*
@@ -145,6 +154,7 @@ static int __init appldata_net_init(void)
 static void __exit appldata_net_exit(void)
 {
        appldata_unregister_ops(&ops);
+       kfree(ops.data);
 }