Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
[linux-2.6] / arch / s390 / kernel / diag.c
1 /*
2  * Implementation of s390 diagnose codes
3  *
4  * Copyright IBM Corp. 2007
5  * Author(s): Michael Holzheu <holzheu@de.ibm.com>
6  */
7
8 #include <linux/module.h>
9 #include <asm/diag.h>
10
11 /*
12  * Diagnose 10: Release pages
13  */
14 void diag10(unsigned long addr)
15 {
16         if (addr >= 0x7ff00000)
17                 return;
18         asm volatile(
19 #ifdef CONFIG_64BIT
20                 "       sam31\n"
21                 "       diag    %0,%0,0x10\n"
22                 "0:     sam64\n"
23 #else
24                 "       diag    %0,%0,0x10\n"
25                 "0:\n"
26 #endif
27                 EX_TABLE(0b, 0b)
28                 : : "a" (addr));
29 }
30 EXPORT_SYMBOL(diag10);
31
32 /*
33  * Diagnose 14: Input spool file manipulation
34  */
35 int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
36 {
37         register unsigned long _ry1 asm("2") = ry1;
38         register unsigned long _ry2 asm("3") = subcode;
39         int rc = 0;
40
41         asm volatile(
42 #ifdef CONFIG_64BIT
43                 "   sam31\n"
44                 "   diag    %2,2,0x14\n"
45                 "   sam64\n"
46 #else
47                 "   diag    %2,2,0x14\n"
48 #endif
49                 "   ipm     %0\n"
50                 "   srl     %0,28\n"
51                 : "=d" (rc), "+d" (_ry2)
52                 : "d" (rx), "d" (_ry1)
53                 : "cc");
54
55         return rc;
56 }
57 EXPORT_SYMBOL(diag14);
58
59 /*
60  * Diagnose 210: Get information about a virtual device
61  */
62 int diag210(struct diag210 *addr)
63 {
64         /*
65          * diag 210 needs its data below the 2GB border, so we
66          * use a static data area to be sure
67          */
68         static struct diag210 diag210_tmp;
69         static DEFINE_SPINLOCK(diag210_lock);
70         unsigned long flags;
71         int ccode;
72
73         spin_lock_irqsave(&diag210_lock, flags);
74         diag210_tmp = *addr;
75
76 #ifdef CONFIG_64BIT
77         asm volatile(
78                 "       lhi     %0,-1\n"
79                 "       sam31\n"
80                 "       diag    %1,0,0x210\n"
81                 "0:     ipm     %0\n"
82                 "       srl     %0,28\n"
83                 "1:     sam64\n"
84                 EX_TABLE(0b, 1b)
85                 : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
86 #else
87         asm volatile(
88                 "       lhi     %0,-1\n"
89                 "       diag    %1,0,0x210\n"
90                 "0:     ipm     %0\n"
91                 "       srl     %0,28\n"
92                 "1:\n"
93                 EX_TABLE(0b, 1b)
94                 : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
95 #endif
96
97         *addr = diag210_tmp;
98         spin_unlock_irqrestore(&diag210_lock, flags);
99
100         return ccode;
101 }
102 EXPORT_SYMBOL(diag210);