]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - arch/s390/kernel/cpcmd.c
[PATCH] s390: cleanup Kconfig
[mirror_ubuntu-artful-kernel.git] / arch / s390 / kernel / cpcmd.c
CommitLineData
1da177e4
LT
1/*
2 * arch/s390/kernel/cpcmd.c
3 *
4 * S390 version
6b979de3 5 * Copyright (C) 1999,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
1da177e4
LT
6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
7 * Christian Borntraeger (cborntra@de.ibm.com),
8 */
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/slab.h>
13#include <linux/spinlock.h>
14#include <linux/stddef.h>
15#include <linux/string.h>
16#include <asm/ebcdic.h>
17#include <asm/cpcmd.h>
18#include <asm/system.h>
19
20static DEFINE_SPINLOCK(cpcmd_lock);
6b979de3 21static char cpcmd_buf[241];
1da177e4
LT
22
23/*
24 * the caller of __cpcmd has to ensure that the response buffer is below 2 GB
25 */
6b979de3 26int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
1da177e4
LT
27{
28 const int mask = 0x40000000L;
29 unsigned long flags;
6b979de3
CB
30 int return_code;
31 int return_len;
1da177e4
LT
32 int cmdlen;
33
34 spin_lock_irqsave(&cpcmd_lock, flags);
35 cmdlen = strlen(cmd);
36 BUG_ON(cmdlen > 240);
6b979de3 37 memcpy(cpcmd_buf, cmd, cmdlen);
1da177e4
LT
38 ASCEBC(cpcmd_buf, cmdlen);
39
40 if (response != NULL && rlen > 0) {
41 memset(response, 0, rlen);
347a8dc3 42#ifndef CONFIG_64BIT
6b979de3
CB
43 asm volatile ( "lra 2,0(%2)\n"
44 "lr 4,%3\n"
45 "o 4,%6\n"
46 "lra 3,0(%4)\n"
47 "lr 5,%5\n"
48 "diag 2,4,0x8\n"
0cbdff4f 49 "brc 8, 1f\n"
6b979de3 50 "ar 5, %5\n"
0cbdff4f 51 "1: \n"
6b979de3
CB
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" );
347a8dc3 58#else /* CONFIG_64BIT */
6b979de3
CB
59 asm volatile ( "lrag 2,0(%2)\n"
60 "lgr 4,%3\n"
61 "o 4,%6\n"
62 "lrag 3,0(%4)\n"
63 "lgr 5,%5\n"
64 "sam31\n"
65 "diag 2,4,0x8\n"
66 "sam64\n"
0cbdff4f 67 "brc 8, 1f\n"
6b979de3 68 "agr 5, %5\n"
0cbdff4f 69 "1: \n"
6b979de3
CB
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" );
347a8dc3 76#endif /* CONFIG_64BIT */
1da177e4
LT
77 EBCASC(response, rlen);
78 } else {
6b979de3 79 return_len = 0;
347a8dc3 80#ifndef CONFIG_64BIT
6b979de3
CB
81 asm volatile ( "lra 2,0(%1)\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" );
347a8dc3 88#else /* CONFIG_64BIT */
6b979de3
CB
89 asm volatile ( "lrag 2,0(%1)\n"
90 "lgr 3,%2\n"
91 "sam31\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" );
347a8dc3 98#endif /* CONFIG_64BIT */
1da177e4
LT
99 }
100 spin_unlock_irqrestore(&cpcmd_lock, flags);
6b979de3
CB
101 if (response_code != NULL)
102 *response_code = return_code;
103 return return_len;
1da177e4
LT
104}
105
106EXPORT_SYMBOL(__cpcmd);
107
347a8dc3 108#ifdef CONFIG_64BIT
6b979de3 109int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
1da177e4
LT
110{
111 char *lowbuf;
6b979de3
CB
112 int len;
113
1da177e4
LT
114 if ((rlen == 0) || (response == NULL)
115 || !((unsigned long)response >> 31))
6b979de3 116 len = __cpcmd(cmd, response, rlen, response_code);
1da177e4
LT
117 else {
118 lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
119 if (!lowbuf) {
120 printk(KERN_WARNING
121 "cpcmd: could not allocate response buffer\n");
6b979de3 122 return -ENOMEM;
1da177e4 123 }
6b979de3 124 len = __cpcmd(cmd, lowbuf, rlen, response_code);
1da177e4
LT
125 memcpy(response, lowbuf, rlen);
126 kfree(lowbuf);
127 }
6b979de3 128 return len;
1da177e4
LT
129}
130
131EXPORT_SYMBOL(cpcmd);
347a8dc3 132#endif /* CONFIG_64BIT */