aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/chsc.c
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2010-04-22 11:17:03 -0400
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-04-22 11:17:19 -0400
commit818c272bd74b834c3ca9347c6a540c2ec880afdc (patch)
treece5353ca2f9b0786096508ff218f2615ecb06807 /drivers/s390/cio/chsc.c
parent6a5176c474e3e722ab273d940442238e554e5e58 (diff)
[S390] cio: allow enable_facility from outside init functions
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>
Diffstat (limited to 'drivers/s390/cio/chsc.c')
-rw-r--r--drivers/s390/cio/chsc.c29
1 files changed, 14 insertions, 15 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 4038f5b4f144..ce7cb87479fe 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -29,6 +29,7 @@
29#include "chsc.h" 29#include "chsc.h"
30 30
31static void *sei_page; 31static void *sei_page;
32static DEFINE_SPINLOCK(sda_lock);
32 33
33/** 34/**
34 * chsc_error_from_response() - convert a chsc response to an error 35 * chsc_error_from_response() - convert a chsc response to an error
@@ -832,11 +833,10 @@ void __init chsc_free_sei_area(void)
832 kfree(sei_page); 833 kfree(sei_page);
833} 834}
834 835
835int __init 836int chsc_enable_facility(int operation_code)
836chsc_enable_facility(int operation_code)
837{ 837{
838 int ret; 838 int ret;
839 struct { 839 static struct {
840 struct chsc_header request; 840 struct chsc_header request;
841 u8 reserved1:4; 841 u8 reserved1:4;
842 u8 format:4; 842 u8 format:4;
@@ -849,33 +849,32 @@ chsc_enable_facility(int operation_code)
849 u32 reserved5:4; 849 u32 reserved5:4;
850 u32 format2:4; 850 u32 format2:4;
851 u32 reserved6:24; 851 u32 reserved6:24;
852 } __attribute__ ((packed)) *sda_area; 852 } __attribute__ ((packed, aligned(4096))) sda_area;
853 853
854 sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA); 854 spin_lock(&sda_lock);
855 if (!sda_area) 855 memset(&sda_area, 0, sizeof(sda_area));
856 return -ENOMEM; 856 sda_area.request.length = 0x0400;
857 sda_area->request.length = 0x0400; 857 sda_area.request.code = 0x0031;
858 sda_area->request.code = 0x0031; 858 sda_area.operation_code = operation_code;
859 sda_area->operation_code = operation_code;
860 859
861 ret = chsc(sda_area); 860 ret = chsc(&sda_area);
862 if (ret > 0) { 861 if (ret > 0) {
863 ret = (ret == 3) ? -ENODEV : -EBUSY; 862 ret = (ret == 3) ? -ENODEV : -EBUSY;
864 goto out; 863 goto out;
865 } 864 }
866 865
867 switch (sda_area->response.code) { 866 switch (sda_area.response.code) {
868 case 0x0101: 867 case 0x0101:
869 ret = -EOPNOTSUPP; 868 ret = -EOPNOTSUPP;
870 break; 869 break;
871 default: 870 default:
872 ret = chsc_error_from_response(sda_area->response.code); 871 ret = chsc_error_from_response(sda_area.response.code);
873 } 872 }
874 if (ret != 0) 873 if (ret != 0)
875 CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n", 874 CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n",
876 operation_code, sda_area->response.code); 875 operation_code, sda_area.response.code);
877 out: 876 out:
878 free_page((unsigned long)sda_area); 877 spin_unlock(&sda_lock);
879 return ret; 878 return ret;
880} 879}
881 880