[S390] cio: allow enable_facility from outside init functions
authorSebastian Ott <sebott@linux.vnet.ibm.com>
Thu, 22 Apr 2010 15:17:03 +0000 (17:17 +0200)
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>
Thu, 22 Apr 2010 15:17:19 +0000 (17:17 +0200)
Prepare chsc_enable_facility to be used from outside init functions.
Use static memory for the chsc call and protect its access by a
spinlock (although there is no concurrent usage).

Cc: <stable@kernel.org>
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/cio/chsc.c
drivers/s390/cio/css.c

index 4038f5b4f144e565bae3a5aac6201bce651b41bb..ce7cb87479fe3b8aed786eeea182549da7352b35 100644 (file)
@@ -29,6 +29,7 @@
 #include "chsc.h"
 
 static void *sei_page;
+static DEFINE_SPINLOCK(sda_lock);
 
 /**
  * chsc_error_from_response() - convert a chsc response to an error
@@ -832,11 +833,10 @@ void __init chsc_free_sei_area(void)
        kfree(sei_page);
 }
 
-int __init
-chsc_enable_facility(int operation_code)
+int chsc_enable_facility(int operation_code)
 {
        int ret;
-       struct {
+       static struct {
                struct chsc_header request;
                u8 reserved1:4;
                u8 format:4;
@@ -849,33 +849,32 @@ chsc_enable_facility(int operation_code)
                u32 reserved5:4;
                u32 format2:4;
                u32 reserved6:24;
-       } __attribute__ ((packed)) *sda_area;
+       } __attribute__ ((packed, aligned(4096))) sda_area;
 
-       sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA);
-       if (!sda_area)
-               return -ENOMEM;
-       sda_area->request.length = 0x0400;
-       sda_area->request.code = 0x0031;
-       sda_area->operation_code = operation_code;
+       spin_lock(&sda_lock);
+       memset(&sda_area, 0, sizeof(sda_area));
+       sda_area.request.length = 0x0400;
+       sda_area.request.code = 0x0031;
+       sda_area.operation_code = operation_code;
 
-       ret = chsc(sda_area);
+       ret = chsc(&sda_area);
        if (ret > 0) {
                ret = (ret == 3) ? -ENODEV : -EBUSY;
                goto out;
        }
 
-       switch (sda_area->response.code) {
+       switch (sda_area.response.code) {
        case 0x0101:
                ret = -EOPNOTSUPP;
                break;
        default:
-               ret = chsc_error_from_response(sda_area->response.code);
+               ret = chsc_error_from_response(sda_area.response.code);
        }
        if (ret != 0)
                CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n",
-                             operation_code, sda_area->response.code);
+                             operation_code, sda_area.response.code);
  out:
-       free_page((unsigned long)sda_area);
+       spin_unlock(&sda_lock);
        return ret;
 }
 
index 2769da54f2b96ebf9f26f86ff76c049ff71c5e82..19635d47dede2851e4e2a06b609a057ccde49f9b 100644 (file)
@@ -870,15 +870,10 @@ static int __init css_bus_init(void)
 
        /* Try to enable MSS. */
        ret = chsc_enable_facility(CHSC_SDA_OC_MSS);
-       switch (ret) {
-       case 0: /* Success. */
-               max_ssid = __MAX_SSID;
-               break;
-       case -ENOMEM:
-               goto out;
-       default:
+       if (ret)
                max_ssid = 0;
-       }
+       else /* Success. */
+               max_ssid = __MAX_SSID;
 
        ret = slow_subchannel_init();
        if (ret)