diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2013-04-16 08:14:44 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-04-17 08:07:37 -0400 |
commit | cbcca5d070c30909fd355018ed96134ee9018425 (patch) | |
tree | 869e1b9966b80c4e81b71b1d448e238b1e958cb2 /arch/s390/pci | |
parent | af0a8a8453f7c7b3497c9fecc053897690e00695 (diff) |
s390/pci: uninline instruction wrappers
Uninline pci related instruction wrappers to de-bloat the code:
add/remove: 15/0 grow/shrink: 2/24 up/down: 1326/-12628 (-11302)
This is especially useful for the inlined pci read and write functions
which are used all over the kernel. Also remove the unused __stpcifc
while at it.
Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/pci')
-rw-r--r-- | arch/s390/pci/Makefile | 4 | ||||
-rw-r--r-- | arch/s390/pci/pci_insn.c | 194 |
2 files changed, 196 insertions, 2 deletions
diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile index f0f426a113ce..086a2e37935d 100644 --- a/arch/s390/pci/Makefile +++ b/arch/s390/pci/Makefile | |||
@@ -2,5 +2,5 @@ | |||
2 | # Makefile for the s390 PCI subsystem. | 2 | # Makefile for the s390 PCI subsystem. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_PCI) += pci.o pci_dma.o pci_clp.o pci_msi.o \ | 5 | obj-$(CONFIG_PCI) += pci.o pci_dma.o pci_clp.o pci_msi.o pci_sysfs.o \ |
6 | pci_sysfs.o pci_event.o pci_debug.o | 6 | pci_event.o pci_debug.o pci_insn.o |
diff --git a/arch/s390/pci/pci_insn.c b/arch/s390/pci/pci_insn.c new file mode 100644 index 000000000000..c55962529f4f --- /dev/null +++ b/arch/s390/pci/pci_insn.c | |||
@@ -0,0 +1,194 @@ | |||
1 | /* | ||
2 | * s390 specific pci instructions | ||
3 | * | ||
4 | * Copyright IBM Corp. 2013 | ||
5 | */ | ||
6 | |||
7 | #include <linux/export.h> | ||
8 | #include <linux/errno.h> | ||
9 | #include <linux/delay.h> | ||
10 | #include <asm/pci_insn.h> | ||
11 | |||
12 | #define ZPCI_INSN_BUSY_DELAY 1 /* 1 microsecond */ | ||
13 | |||
14 | /* Modify PCI Function Controls */ | ||
15 | static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status) | ||
16 | { | ||
17 | u8 cc; | ||
18 | |||
19 | asm volatile ( | ||
20 | " .insn rxy,0xe300000000d0,%[req],%[fib]\n" | ||
21 | " ipm %[cc]\n" | ||
22 | " srl %[cc],28\n" | ||
23 | : [cc] "=d" (cc), [req] "+d" (req), [fib] "+Q" (*fib) | ||
24 | : : "cc"); | ||
25 | *status = req >> 24 & 0xff; | ||
26 | return cc; | ||
27 | } | ||
28 | |||
29 | int mpcifc_instr(u64 req, struct zpci_fib *fib) | ||
30 | { | ||
31 | u8 cc, status; | ||
32 | |||
33 | do { | ||
34 | cc = __mpcifc(req, fib, &status); | ||
35 | if (cc == 2) | ||
36 | msleep(ZPCI_INSN_BUSY_DELAY); | ||
37 | } while (cc == 2); | ||
38 | |||
39 | if (cc) | ||
40 | printk_once(KERN_ERR "%s: error cc: %d status: %d\n", | ||
41 | __func__, cc, status); | ||
42 | return (cc) ? -EIO : 0; | ||
43 | } | ||
44 | |||
45 | /* Refresh PCI Translations */ | ||
46 | static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status) | ||
47 | { | ||
48 | register u64 __addr asm("2") = addr; | ||
49 | register u64 __range asm("3") = range; | ||
50 | u8 cc; | ||
51 | |||
52 | asm volatile ( | ||
53 | " .insn rre,0xb9d30000,%[fn],%[addr]\n" | ||
54 | " ipm %[cc]\n" | ||
55 | " srl %[cc],28\n" | ||
56 | : [cc] "=d" (cc), [fn] "+d" (fn) | ||
57 | : [addr] "d" (__addr), "d" (__range) | ||
58 | : "cc"); | ||
59 | *status = fn >> 24 & 0xff; | ||
60 | return cc; | ||
61 | } | ||
62 | |||
63 | int rpcit_instr(u64 fn, u64 addr, u64 range) | ||
64 | { | ||
65 | u8 cc, status; | ||
66 | |||
67 | do { | ||
68 | cc = __rpcit(fn, addr, range, &status); | ||
69 | if (cc == 2) | ||
70 | udelay(ZPCI_INSN_BUSY_DELAY); | ||
71 | } while (cc == 2); | ||
72 | |||
73 | if (cc) | ||
74 | printk_once(KERN_ERR "%s: error cc: %d status: %d dma_addr: %Lx size: %Lx\n", | ||
75 | __func__, cc, status, addr, range); | ||
76 | return (cc) ? -EIO : 0; | ||
77 | } | ||
78 | |||
79 | /* Set Interruption Controls */ | ||
80 | void sic_instr(u16 ctl, char *unused, u8 isc) | ||
81 | { | ||
82 | asm volatile ( | ||
83 | " .insn rsy,0xeb00000000d1,%[ctl],%[isc],%[u]\n" | ||
84 | : : [ctl] "d" (ctl), [isc] "d" (isc << 27), [u] "Q" (*unused)); | ||
85 | } | ||
86 | |||
87 | /* PCI Load */ | ||
88 | static inline u8 __pcilg(u64 *data, u64 req, u64 offset, u8 *status) | ||
89 | { | ||
90 | register u64 __req asm("2") = req; | ||
91 | register u64 __offset asm("3") = offset; | ||
92 | u64 __data; | ||
93 | u8 cc; | ||
94 | |||
95 | asm volatile ( | ||
96 | " .insn rre,0xb9d20000,%[data],%[req]\n" | ||
97 | " ipm %[cc]\n" | ||
98 | " srl %[cc],28\n" | ||
99 | : [cc] "=d" (cc), [data] "=d" (__data), [req] "+d" (__req) | ||
100 | : "d" (__offset) | ||
101 | : "cc"); | ||
102 | *status = __req >> 24 & 0xff; | ||
103 | *data = __data; | ||
104 | return cc; | ||
105 | } | ||
106 | |||
107 | int pcilg_instr(u64 *data, u64 req, u64 offset) | ||
108 | { | ||
109 | u8 cc, status; | ||
110 | |||
111 | do { | ||
112 | cc = __pcilg(data, req, offset, &status); | ||
113 | if (cc == 2) | ||
114 | udelay(ZPCI_INSN_BUSY_DELAY); | ||
115 | } while (cc == 2); | ||
116 | |||
117 | if (cc) { | ||
118 | printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n", | ||
119 | __func__, cc, status, req, offset); | ||
120 | /* TODO: on IO errors set data to 0xff... | ||
121 | * here or in users of pcilg (le conversion)? | ||
122 | */ | ||
123 | } | ||
124 | return (cc) ? -EIO : 0; | ||
125 | } | ||
126 | EXPORT_SYMBOL_GPL(pcilg_instr); | ||
127 | |||
128 | /* PCI Store */ | ||
129 | static inline u8 __pcistg(u64 data, u64 req, u64 offset, u8 *status) | ||
130 | { | ||
131 | register u64 __req asm("2") = req; | ||
132 | register u64 __offset asm("3") = offset; | ||
133 | u8 cc; | ||
134 | |||
135 | asm volatile ( | ||
136 | " .insn rre,0xb9d00000,%[data],%[req]\n" | ||
137 | " ipm %[cc]\n" | ||
138 | " srl %[cc],28\n" | ||
139 | : [cc] "=d" (cc), [req] "+d" (__req) | ||
140 | : "d" (__offset), [data] "d" (data) | ||
141 | : "cc"); | ||
142 | *status = __req >> 24 & 0xff; | ||
143 | return cc; | ||
144 | } | ||
145 | |||
146 | int pcistg_instr(u64 data, u64 req, u64 offset) | ||
147 | { | ||
148 | u8 cc, status; | ||
149 | |||
150 | do { | ||
151 | cc = __pcistg(data, req, offset, &status); | ||
152 | if (cc == 2) | ||
153 | udelay(ZPCI_INSN_BUSY_DELAY); | ||
154 | } while (cc == 2); | ||
155 | |||
156 | if (cc) | ||
157 | printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n", | ||
158 | __func__, cc, status, req, offset); | ||
159 | return (cc) ? -EIO : 0; | ||
160 | } | ||
161 | EXPORT_SYMBOL_GPL(pcistg_instr); | ||
162 | |||
163 | /* PCI Store Block */ | ||
164 | static inline u8 __pcistb(const u64 *data, u64 req, u64 offset, u8 *status) | ||
165 | { | ||
166 | u8 cc; | ||
167 | |||
168 | asm volatile ( | ||
169 | " .insn rsy,0xeb00000000d0,%[req],%[offset],%[data]\n" | ||
170 | " ipm %[cc]\n" | ||
171 | " srl %[cc],28\n" | ||
172 | : [cc] "=d" (cc), [req] "+d" (req) | ||
173 | : [offset] "d" (offset), [data] "Q" (*data) | ||
174 | : "cc"); | ||
175 | *status = req >> 24 & 0xff; | ||
176 | return cc; | ||
177 | } | ||
178 | |||
179 | int pcistb_instr(const u64 *data, u64 req, u64 offset) | ||
180 | { | ||
181 | u8 cc, status; | ||
182 | |||
183 | do { | ||
184 | cc = __pcistb(data, req, offset, &status); | ||
185 | if (cc == 2) | ||
186 | udelay(ZPCI_INSN_BUSY_DELAY); | ||
187 | } while (cc == 2); | ||
188 | |||
189 | if (cc) | ||
190 | printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n", | ||
191 | __func__, cc, status, req, offset); | ||
192 | return (cc) ? -EIO : 0; | ||
193 | } | ||
194 | EXPORT_SYMBOL_GPL(pcistb_instr); | ||