diff options
Diffstat (limited to 'arch/s390/kernel/cpcmd.c')
-rw-r--r-- | arch/s390/kernel/cpcmd.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c index 1eae74e72f95..a5972f1541fe 100644 --- a/arch/s390/kernel/cpcmd.c +++ b/arch/s390/kernel/cpcmd.c | |||
@@ -21,14 +21,15 @@ static DEFINE_SPINLOCK(cpcmd_lock); | |||
21 | static char cpcmd_buf[241]; | 21 | static char cpcmd_buf[241]; |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * the caller of __cpcmd has to ensure that the response buffer is below 2 GB | 24 | * __cpcmd has some restrictions over cpcmd |
25 | * - the response buffer must reside below 2GB (if any) | ||
26 | * - __cpcmd is unlocked and therefore not SMP-safe | ||
25 | */ | 27 | */ |
26 | int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) | 28 | int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) |
27 | { | 29 | { |
28 | unsigned long flags, cmdlen; | 30 | unsigned cmdlen; |
29 | int return_code, return_len; | 31 | int return_code, return_len; |
30 | 32 | ||
31 | spin_lock_irqsave(&cpcmd_lock, flags); | ||
32 | cmdlen = strlen(cmd); | 33 | cmdlen = strlen(cmd); |
33 | BUG_ON(cmdlen > 240); | 34 | BUG_ON(cmdlen > 240); |
34 | memcpy(cpcmd_buf, cmd, cmdlen); | 35 | memcpy(cpcmd_buf, cmd, cmdlen); |
@@ -74,7 +75,6 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) | |||
74 | : "+d" (reg3) : "d" (reg2) : "cc"); | 75 | : "+d" (reg3) : "d" (reg2) : "cc"); |
75 | return_code = (int) reg3; | 76 | return_code = (int) reg3; |
76 | } | 77 | } |
77 | spin_unlock_irqrestore(&cpcmd_lock, flags); | ||
78 | if (response_code != NULL) | 78 | if (response_code != NULL) |
79 | *response_code = return_code; | 79 | *response_code = return_code; |
80 | return return_len; | 80 | return return_len; |
@@ -82,15 +82,18 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) | |||
82 | 82 | ||
83 | EXPORT_SYMBOL(__cpcmd); | 83 | EXPORT_SYMBOL(__cpcmd); |
84 | 84 | ||
85 | #ifdef CONFIG_64BIT | ||
86 | int cpcmd(const char *cmd, char *response, int rlen, int *response_code) | 85 | int cpcmd(const char *cmd, char *response, int rlen, int *response_code) |
87 | { | 86 | { |
88 | char *lowbuf; | 87 | char *lowbuf; |
89 | int len; | 88 | int len; |
89 | unsigned long flags; | ||
90 | 90 | ||
91 | if ((rlen == 0) || (response == NULL) | 91 | if ((rlen == 0) || (response == NULL) |
92 | || !((unsigned long)response >> 31)) | 92 | || !((unsigned long)response >> 31)) { |
93 | spin_lock_irqsave(&cpcmd_lock, flags); | ||
93 | len = __cpcmd(cmd, response, rlen, response_code); | 94 | len = __cpcmd(cmd, response, rlen, response_code); |
95 | spin_unlock_irqrestore(&cpcmd_lock, flags); | ||
96 | } | ||
94 | else { | 97 | else { |
95 | lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA); | 98 | lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA); |
96 | if (!lowbuf) { | 99 | if (!lowbuf) { |
@@ -98,7 +101,9 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) | |||
98 | "cpcmd: could not allocate response buffer\n"); | 101 | "cpcmd: could not allocate response buffer\n"); |
99 | return -ENOMEM; | 102 | return -ENOMEM; |
100 | } | 103 | } |
104 | spin_lock_irqsave(&cpcmd_lock, flags); | ||
101 | len = __cpcmd(cmd, lowbuf, rlen, response_code); | 105 | len = __cpcmd(cmd, lowbuf, rlen, response_code); |
106 | spin_unlock_irqrestore(&cpcmd_lock, flags); | ||
102 | memcpy(response, lowbuf, rlen); | 107 | memcpy(response, lowbuf, rlen); |
103 | kfree(lowbuf); | 108 | kfree(lowbuf); |
104 | } | 109 | } |
@@ -106,4 +111,3 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) | |||
106 | } | 111 | } |
107 | 112 | ||
108 | EXPORT_SYMBOL(cpcmd); | 113 | EXPORT_SYMBOL(cpcmd); |
109 | #endif /* CONFIG_64BIT */ | ||