diff options
Diffstat (limited to 'arch/s390/kernel/cpcmd.c')
-rw-r--r-- | arch/s390/kernel/cpcmd.c | 83 |
1 files changed, 30 insertions, 53 deletions
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c index 4ef44e536b2c..1eae74e72f95 100644 --- a/arch/s390/kernel/cpcmd.c +++ b/arch/s390/kernel/cpcmd.c | |||
@@ -25,11 +25,8 @@ static char cpcmd_buf[241]; | |||
25 | */ | 25 | */ |
26 | int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) | 26 | int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) |
27 | { | 27 | { |
28 | const int mask = 0x40000000L; | 28 | unsigned long flags, cmdlen; |
29 | unsigned long flags; | 29 | int return_code, return_len; |
30 | int return_code; | ||
31 | int return_len; | ||
32 | int cmdlen; | ||
33 | 30 | ||
34 | spin_lock_irqsave(&cpcmd_lock, flags); | 31 | spin_lock_irqsave(&cpcmd_lock, flags); |
35 | cmdlen = strlen(cmd); | 32 | cmdlen = strlen(cmd); |
@@ -38,64 +35,44 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) | |||
38 | ASCEBC(cpcmd_buf, cmdlen); | 35 | ASCEBC(cpcmd_buf, cmdlen); |
39 | 36 | ||
40 | if (response != NULL && rlen > 0) { | 37 | if (response != NULL && rlen > 0) { |
38 | register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf; | ||
39 | register unsigned long reg3 asm ("3") = (addr_t) response; | ||
40 | register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L; | ||
41 | register unsigned long reg5 asm ("5") = rlen; | ||
42 | |||
41 | memset(response, 0, rlen); | 43 | memset(response, 0, rlen); |
44 | asm volatile( | ||
42 | #ifndef CONFIG_64BIT | 45 | #ifndef CONFIG_64BIT |
43 | asm volatile ( "lra 2,0(%2)\n" | 46 | " diag %2,%0,0x8\n" |
44 | "lr 4,%3\n" | 47 | " brc 8,1f\n" |
45 | "o 4,%6\n" | 48 | " ar %1,%4\n" |
46 | "lra 3,0(%4)\n" | ||
47 | "lr 5,%5\n" | ||
48 | "diag 2,4,0x8\n" | ||
49 | "brc 8, 1f\n" | ||
50 | "ar 5, %5\n" | ||
51 | "1: \n" | ||
52 | "lr %0,4\n" | ||
53 | "lr %1,5\n" | ||
54 | : "=d" (return_code), "=d" (return_len) | ||
55 | : "a" (cpcmd_buf), "d" (cmdlen), | ||
56 | "a" (response), "d" (rlen), "m" (mask) | ||
57 | : "cc", "2", "3", "4", "5" ); | ||
58 | #else /* CONFIG_64BIT */ | 49 | #else /* CONFIG_64BIT */ |
59 | asm volatile ( "lrag 2,0(%2)\n" | 50 | " sam31\n" |
60 | "lgr 4,%3\n" | 51 | " diag %2,%0,0x8\n" |
61 | "o 4,%6\n" | 52 | " sam64\n" |
62 | "lrag 3,0(%4)\n" | 53 | " brc 8,1f\n" |
63 | "lgr 5,%5\n" | 54 | " agr %1,%4\n" |
64 | "sam31\n" | ||
65 | "diag 2,4,0x8\n" | ||
66 | "sam64\n" | ||
67 | "brc 8, 1f\n" | ||
68 | "agr 5, %5\n" | ||
69 | "1: \n" | ||
70 | "lgr %0,4\n" | ||
71 | "lgr %1,5\n" | ||
72 | : "=d" (return_code), "=d" (return_len) | ||
73 | : "a" (cpcmd_buf), "d" (cmdlen), | ||
74 | "a" (response), "d" (rlen), "m" (mask) | ||
75 | : "cc", "2", "3", "4", "5" ); | ||
76 | #endif /* CONFIG_64BIT */ | 55 | #endif /* CONFIG_64BIT */ |
56 | "1:\n" | ||
57 | : "+d" (reg4), "+d" (reg5) | ||
58 | : "d" (reg2), "d" (reg3), "d" (rlen) : "cc"); | ||
59 | return_code = (int) reg4; | ||
60 | return_len = (int) reg5; | ||
77 | EBCASC(response, rlen); | 61 | EBCASC(response, rlen); |
78 | } else { | 62 | } else { |
63 | register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf; | ||
64 | register unsigned long reg3 asm ("3") = cmdlen; | ||
79 | return_len = 0; | 65 | return_len = 0; |
66 | asm volatile( | ||
80 | #ifndef CONFIG_64BIT | 67 | #ifndef CONFIG_64BIT |
81 | asm volatile ( "lra 2,0(%1)\n" | 68 | " diag %1,%0,0x8\n" |
82 | "lr 3,%2\n" | ||
83 | "diag 2,3,0x8\n" | ||
84 | "lr %0,3\n" | ||
85 | : "=d" (return_code) | ||
86 | : "a" (cpcmd_buf), "d" (cmdlen) | ||
87 | : "2", "3" ); | ||
88 | #else /* CONFIG_64BIT */ | 69 | #else /* CONFIG_64BIT */ |
89 | asm volatile ( "lrag 2,0(%1)\n" | 70 | " sam31\n" |
90 | "lgr 3,%2\n" | 71 | " diag %1,%0,0x8\n" |
91 | "sam31\n" | 72 | " sam64\n" |
92 | "diag 2,3,0x8\n" | ||
93 | "sam64\n" | ||
94 | "lgr %0,3\n" | ||
95 | : "=d" (return_code) | ||
96 | : "a" (cpcmd_buf), "d" (cmdlen) | ||
97 | : "2", "3" ); | ||
98 | #endif /* CONFIG_64BIT */ | 73 | #endif /* CONFIG_64BIT */ |
74 | : "+d" (reg3) : "d" (reg2) : "cc"); | ||
75 | return_code = (int) reg3; | ||
99 | } | 76 | } |
100 | spin_unlock_irqrestore(&cpcmd_lock, flags); | 77 | spin_unlock_irqrestore(&cpcmd_lock, flags); |
101 | if (response_code != NULL) | 78 | if (response_code != NULL) |