aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Glauber <jang@linux.vnet.ibm.com>2012-11-29 06:50:30 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-11-30 09:40:45 -0500
commitcd24834130ac655d15accee6757e0eaeab4ad4ef (patch)
tree33be1efb537d6a08557a488f096c22516da0b3c2
parentd07dc5d8ab6f15353c866e2768c389abdc1faba6 (diff)
s390/pci: base support
Add PCI support for s390, (only 64 bit mode is supported by hardware): - PCI facility tests - PCI instructions: pcilg, pcistg, pcistb, stpcifc, mpcifc, rpcit - map readb/w/l/q and writeb/w/l/q to pcilg and pcistg instructions - pci_iomap implementation - memcpy_fromio/toio - pci_root_ops using special pcilg/pcistg - device, bus and domain allocation Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/Kbuild1
-rw-r--r--arch/s390/include/asm/io.h55
-rw-r--r--arch/s390/include/asm/pci.h82
-rw-r--r--arch/s390/include/asm/pci_insn.h280
-rw-r--r--arch/s390/include/asm/pci_io.h194
-rw-r--r--arch/s390/kernel/dis.c15
-rw-r--r--arch/s390/pci/Makefile5
-rw-r--r--arch/s390/pci/pci.c557
-rw-r--r--include/asm-generic/io.h21
9 files changed, 1201 insertions, 9 deletions
diff --git a/arch/s390/Kbuild b/arch/s390/Kbuild
index cc45d25487b0..647c3eccc3d0 100644
--- a/arch/s390/Kbuild
+++ b/arch/s390/Kbuild
@@ -6,3 +6,4 @@ obj-$(CONFIG_S390_HYPFS_FS) += hypfs/
6obj-$(CONFIG_APPLDATA_BASE) += appldata/ 6obj-$(CONFIG_APPLDATA_BASE) += appldata/
7obj-$(CONFIG_MATHEMU) += math-emu/ 7obj-$(CONFIG_MATHEMU) += math-emu/
8obj-y += net/ 8obj-y += net/
9obj-$(CONFIG_PCI) += pci/
diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h
index 559e921a6bba..16c3eb164f4f 100644
--- a/arch/s390/include/asm/io.h
+++ b/arch/s390/include/asm/io.h
@@ -9,9 +9,9 @@
9#ifndef _S390_IO_H 9#ifndef _S390_IO_H
10#define _S390_IO_H 10#define _S390_IO_H
11 11
12#include <linux/kernel.h>
12#include <asm/page.h> 13#include <asm/page.h>
13 14#include <asm/pci_io.h>
14#define IO_SPACE_LIMIT 0xffffffff
15 15
16/* 16/*
17 * Change virtual addresses to physical addresses and vv. 17 * Change virtual addresses to physical addresses and vv.
@@ -24,10 +24,11 @@ static inline unsigned long virt_to_phys(volatile void * address)
24 " lra %0,0(%1)\n" 24 " lra %0,0(%1)\n"
25 " jz 0f\n" 25 " jz 0f\n"
26 " la %0,0\n" 26 " la %0,0\n"
27 "0:" 27 "0:"
28 : "=a" (real_address) : "a" (address) : "cc"); 28 : "=a" (real_address) : "a" (address) : "cc");
29 return real_address; 29 return real_address;
30} 30}
31#define virt_to_phys virt_to_phys
31 32
32static inline void * phys_to_virt(unsigned long address) 33static inline void * phys_to_virt(unsigned long address)
33{ 34{
@@ -42,4 +43,50 @@ void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
42 */ 43 */
43#define xlate_dev_kmem_ptr(p) p 44#define xlate_dev_kmem_ptr(p) p
44 45
46#define IO_SPACE_LIMIT 0
47
48#ifdef CONFIG_PCI
49
50#define ioremap_nocache(addr, size) ioremap(addr, size)
51#define ioremap_wc ioremap_nocache
52
53/* TODO: s390 cannot support io_remap_pfn_range... */
54#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
55 remap_pfn_range(vma, vaddr, pfn, size, prot)
56
57static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
58{
59 return (void __iomem *) offset;
60}
61
62static inline void iounmap(volatile void __iomem *addr)
63{
64}
65
66/*
67 * s390 needs a private implementation of pci_iomap since ioremap with its
68 * offset parameter isn't sufficient. That's because BAR spaces are not
69 * disjunctive on s390 so we need the bar parameter of pci_iomap to find
70 * the corresponding device and create the mapping cookie.
71 */
72#define pci_iomap pci_iomap
73#define pci_iounmap pci_iounmap
74
75#define memcpy_fromio(dst, src, count) zpci_memcpy_fromio(dst, src, count)
76#define memcpy_toio(dst, src, count) zpci_memcpy_toio(dst, src, count)
77#define memset_io(dst, val, count) zpci_memset_io(dst, val, count)
78
79#define __raw_readb zpci_read_u8
80#define __raw_readw zpci_read_u16
81#define __raw_readl zpci_read_u32
82#define __raw_readq zpci_read_u64
83#define __raw_writeb zpci_write_u8
84#define __raw_writew zpci_write_u16
85#define __raw_writel zpci_write_u32
86#define __raw_writeq zpci_write_u64
87
88#endif /* CONFIG_PCI */
89
90#include <asm-generic/io.h>
91
45#endif 92#endif
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 42a145c9ddd6..ff7b3596f47c 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -1,10 +1,84 @@
1#ifndef __ASM_S390_PCI_H 1#ifndef __ASM_S390_PCI_H
2#define __ASM_S390_PCI_H 2#define __ASM_S390_PCI_H
3 3
4/* S/390 systems don't have a PCI bus. This file is just here because some stupid .c code 4/* must be set before including asm-generic/pci.h */
5 * includes it even if CONFIG_PCI is not set.
6 */
7#define PCI_DMA_BUS_IS_PHYS (0) 5#define PCI_DMA_BUS_IS_PHYS (0)
6/* must be set before including pci_clp.h */
7#define PCI_BAR_COUNT 6
8 8
9#endif /* __ASM_S390_PCI_H */ 9#include <asm-generic/pci.h>
10#include <asm-generic/pci-dma-compat.h>
10 11
12#define PCIBIOS_MIN_IO 0x1000
13#define PCIBIOS_MIN_MEM 0x10000000
14
15#define pcibios_assign_all_busses() (0)
16
17void __iomem *pci_iomap(struct pci_dev *, int, unsigned long);
18void pci_iounmap(struct pci_dev *, void __iomem *);
19int pci_domain_nr(struct pci_bus *);
20int pci_proc_domain(struct pci_bus *);
21
22#define ZPCI_BUS_NR 0 /* default bus number */
23#define ZPCI_DEVFN 0 /* default device number */
24
25/* PCI Function Controls */
26#define ZPCI_FC_FN_ENABLED 0x80
27#define ZPCI_FC_ERROR 0x40
28#define ZPCI_FC_BLOCKED 0x20
29#define ZPCI_FC_DMA_ENABLED 0x10
30
31enum zpci_state {
32 ZPCI_FN_STATE_RESERVED,
33 ZPCI_FN_STATE_STANDBY,
34 ZPCI_FN_STATE_CONFIGURED,
35 ZPCI_FN_STATE_ONLINE,
36 NR_ZPCI_FN_STATES,
37};
38
39struct zpci_bar_struct {
40 u32 val; /* bar start & 3 flag bits */
41 u8 size; /* order 2 exponent */
42 u16 map_idx; /* index into bar mapping array */
43};
44
45/* Private data per function */
46struct zpci_dev {
47 struct pci_dev *pdev;
48 struct pci_bus *bus;
49 struct list_head entry; /* list of all zpci_devices, needed for hotplug, etc. */
50
51 enum zpci_state state;
52 u32 fid; /* function ID, used by sclp */
53 u32 fh; /* function handle, used by insn's */
54 u16 pchid; /* physical channel ID */
55 u8 pfgid; /* function group ID */
56 u16 domain;
57
58 struct zpci_bar_struct bars[PCI_BAR_COUNT];
59
60 enum pci_bus_speed max_bus_speed;
61};
62
63static inline bool zdev_enabled(struct zpci_dev *zdev)
64{
65 return (zdev->fh & (1UL << 31)) ? true : false;
66}
67
68/* -----------------------------------------------------------------------------
69 Prototypes
70----------------------------------------------------------------------------- */
71/* Base stuff */
72struct zpci_dev *zpci_alloc_device(void);
73int zpci_create_device(struct zpci_dev *);
74int zpci_enable_device(struct zpci_dev *);
75void zpci_stop_device(struct zpci_dev *);
76void zpci_free_device(struct zpci_dev *);
77int zpci_scan_device(struct zpci_dev *);
78
79/* Helpers */
80struct zpci_dev *get_zdev(struct pci_dev *);
81struct zpci_dev *get_zdev_by_fid(u32);
82bool zpci_fid_present(u32);
83
84#endif
diff --git a/arch/s390/include/asm/pci_insn.h b/arch/s390/include/asm/pci_insn.h
new file mode 100644
index 000000000000..15b88b908e8c
--- /dev/null
+++ b/arch/s390/include/asm/pci_insn.h
@@ -0,0 +1,280 @@
1#ifndef _ASM_S390_PCI_INSN_H
2#define _ASM_S390_PCI_INSN_H
3
4#include <linux/delay.h>
5
6#define ZPCI_INSN_BUSY_DELAY 1 /* 1 millisecond */
7
8/* Load/Store status codes */
9#define ZPCI_PCI_ST_FUNC_NOT_ENABLED 4
10#define ZPCI_PCI_ST_FUNC_IN_ERR 8
11#define ZPCI_PCI_ST_BLOCKED 12
12#define ZPCI_PCI_ST_INSUF_RES 16
13#define ZPCI_PCI_ST_INVAL_AS 20
14#define ZPCI_PCI_ST_FUNC_ALREADY_ENABLED 24
15#define ZPCI_PCI_ST_DMA_AS_NOT_ENABLED 28
16#define ZPCI_PCI_ST_2ND_OP_IN_INV_AS 36
17#define ZPCI_PCI_ST_FUNC_NOT_AVAIL 40
18#define ZPCI_PCI_ST_ALREADY_IN_RQ_STATE 44
19
20/* Load/Store return codes */
21#define ZPCI_PCI_LS_OK 0
22#define ZPCI_PCI_LS_ERR 1
23#define ZPCI_PCI_LS_BUSY 2
24#define ZPCI_PCI_LS_INVAL_HANDLE 3
25
26/* Load/Store address space identifiers */
27#define ZPCI_PCIAS_MEMIO_0 0
28#define ZPCI_PCIAS_MEMIO_1 1
29#define ZPCI_PCIAS_MEMIO_2 2
30#define ZPCI_PCIAS_MEMIO_3 3
31#define ZPCI_PCIAS_MEMIO_4 4
32#define ZPCI_PCIAS_MEMIO_5 5
33#define ZPCI_PCIAS_CFGSPC 15
34
35/* Modify PCI Function Controls */
36#define ZPCI_MOD_FC_REG_INT 2
37#define ZPCI_MOD_FC_DEREG_INT 3
38#define ZPCI_MOD_FC_REG_IOAT 4
39#define ZPCI_MOD_FC_DEREG_IOAT 5
40#define ZPCI_MOD_FC_REREG_IOAT 6
41#define ZPCI_MOD_FC_RESET_ERROR 7
42#define ZPCI_MOD_FC_RESET_BLOCK 9
43#define ZPCI_MOD_FC_SET_MEASURE 10
44
45/* FIB function controls */
46#define ZPCI_FIB_FC_ENABLED 0x80
47#define ZPCI_FIB_FC_ERROR 0x40
48#define ZPCI_FIB_FC_LS_BLOCKED 0x20
49#define ZPCI_FIB_FC_DMAAS_REG 0x10
50
51/* FIB function controls */
52#define ZPCI_FIB_FC_ENABLED 0x80
53#define ZPCI_FIB_FC_ERROR 0x40
54#define ZPCI_FIB_FC_LS_BLOCKED 0x20
55#define ZPCI_FIB_FC_DMAAS_REG 0x10
56
57/* Function Information Block */
58struct zpci_fib {
59 u32 fmt : 8; /* format */
60 u32 : 24;
61 u32 reserved1;
62 u8 fc; /* function controls */
63 u8 reserved2;
64 u16 reserved3;
65 u32 reserved4;
66 u64 pba; /* PCI base address */
67 u64 pal; /* PCI address limit */
68 u64 iota; /* I/O Translation Anchor */
69 u32 : 1;
70 u32 isc : 3; /* Interrupt subclass */
71 u32 noi : 12; /* Number of interrupts */
72 u32 : 2;
73 u32 aibvo : 6; /* Adapter interrupt bit vector offset */
74 u32 sum : 1; /* Adapter int summary bit enabled */
75 u32 : 1;
76 u32 aisbo : 6; /* Adapter int summary bit offset */
77 u32 reserved5;
78 u64 aibv; /* Adapter int bit vector address */
79 u64 aisb; /* Adapter int summary bit address */
80 u64 fmb_addr; /* Function measurement block address and key */
81 u64 reserved6;
82 u64 reserved7;
83} __packed;
84
85/* Modify PCI Function Controls */
86static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status)
87{
88 u8 cc;
89
90 asm volatile (
91 " .insn rxy,0xe300000000d0,%[req],%[fib]\n"
92 " ipm %[cc]\n"
93 " srl %[cc],28\n"
94 : [cc] "=d" (cc), [req] "+d" (req), [fib] "+Q" (*fib)
95 : : "cc");
96 *status = req >> 24 & 0xff;
97 return cc;
98}
99
100static inline int mpcifc_instr(u64 req, struct zpci_fib *fib)
101{
102 u8 cc, status;
103
104 do {
105 cc = __mpcifc(req, fib, &status);
106 if (cc == 2)
107 msleep(ZPCI_INSN_BUSY_DELAY);
108 } while (cc == 2);
109
110 if (cc)
111 printk_once(KERN_ERR "%s: error cc: %d status: %d\n",
112 __func__, cc, status);
113 return (cc) ? -EIO : 0;
114}
115
116/* Refresh PCI Translations */
117static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status)
118{
119 register u64 __addr asm("2") = addr;
120 register u64 __range asm("3") = range;
121 u8 cc;
122
123 asm volatile (
124 " .insn rre,0xb9d30000,%[fn],%[addr]\n"
125 " ipm %[cc]\n"
126 " srl %[cc],28\n"
127 : [cc] "=d" (cc), [fn] "+d" (fn)
128 : [addr] "d" (__addr), "d" (__range)
129 : "cc");
130 *status = fn >> 24 & 0xff;
131 return cc;
132}
133
134static inline int rpcit_instr(u64 fn, u64 addr, u64 range)
135{
136 u8 cc, status;
137
138 do {
139 cc = __rpcit(fn, addr, range, &status);
140 if (cc == 2)
141 msleep(ZPCI_INSN_BUSY_DELAY);
142 } while (cc == 2);
143
144 if (cc)
145 printk_once(KERN_ERR "%s: error cc: %d status: %d dma_addr: %Lx size: %Lx\n",
146 __func__, cc, status, addr, range);
147 return (cc) ? -EIO : 0;
148}
149
150/* Store PCI function controls */
151static inline u8 __stpcifc(u32 handle, u8 space, struct zpci_fib *fib, u8 *status)
152{
153 u64 fn = (u64) handle << 32 | space << 16;
154 u8 cc;
155
156 asm volatile (
157 " .insn rxy,0xe300000000d4,%[fn],%[fib]\n"
158 " ipm %[cc]\n"
159 " srl %[cc],28\n"
160 : [cc] "=d" (cc), [fn] "+d" (fn), [fib] "=m" (*fib)
161 : : "cc");
162 *status = fn >> 24 & 0xff;
163 return cc;
164}
165
166/* Set Interruption Controls */
167static inline void sic_instr(u16 ctl, char *unused, u8 isc)
168{
169 asm volatile (
170 " .insn rsy,0xeb00000000d1,%[ctl],%[isc],%[u]\n"
171 : : [ctl] "d" (ctl), [isc] "d" (isc << 27), [u] "Q" (*unused));
172}
173
174/* PCI Load */
175static inline u8 __pcilg(u64 *data, u64 req, u64 offset, u8 *status)
176{
177 register u64 __req asm("2") = req;
178 register u64 __offset asm("3") = offset;
179 u64 __data;
180 u8 cc;
181
182 asm volatile (
183 " .insn rre,0xb9d20000,%[data],%[req]\n"
184 " ipm %[cc]\n"
185 " srl %[cc],28\n"
186 : [cc] "=d" (cc), [data] "=d" (__data), [req] "+d" (__req)
187 : "d" (__offset)
188 : "cc");
189 *status = __req >> 24 & 0xff;
190 *data = __data;
191 return cc;
192}
193
194static inline int pcilg_instr(u64 *data, u64 req, u64 offset)
195{
196 u8 cc, status;
197
198 do {
199 cc = __pcilg(data, req, offset, &status);
200 if (cc == 2)
201 msleep(ZPCI_INSN_BUSY_DELAY);
202 } while (cc == 2);
203
204 if (cc) {
205 printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n",
206 __func__, cc, status, req, offset);
207 /* TODO: on IO errors set data to 0xff...
208 * here or in users of pcilg (le conversion)?
209 */
210 }
211 return (cc) ? -EIO : 0;
212}
213
214/* PCI Store */
215static inline u8 __pcistg(u64 data, u64 req, u64 offset, u8 *status)
216{
217 register u64 __req asm("2") = req;
218 register u64 __offset asm("3") = offset;
219 u8 cc;
220
221 asm volatile (
222 " .insn rre,0xb9d00000,%[data],%[req]\n"
223 " ipm %[cc]\n"
224 " srl %[cc],28\n"
225 : [cc] "=d" (cc), [req] "+d" (__req)
226 : "d" (__offset), [data] "d" (data)
227 : "cc");
228 *status = __req >> 24 & 0xff;
229 return cc;
230}
231
232static inline int pcistg_instr(u64 data, u64 req, u64 offset)
233{
234 u8 cc, status;
235
236 do {
237 cc = __pcistg(data, req, offset, &status);
238 if (cc == 2)
239 msleep(ZPCI_INSN_BUSY_DELAY);
240 } while (cc == 2);
241
242 if (cc)
243 printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n",
244 __func__, cc, status, req, offset);
245 return (cc) ? -EIO : 0;
246}
247
248/* PCI Store Block */
249static inline u8 __pcistb(const u64 *data, u64 req, u64 offset, u8 *status)
250{
251 u8 cc;
252
253 asm volatile (
254 " .insn rsy,0xeb00000000d0,%[req],%[offset],%[data]\n"
255 " ipm %[cc]\n"
256 " srl %[cc],28\n"
257 : [cc] "=d" (cc), [req] "+d" (req)
258 : [offset] "d" (offset), [data] "Q" (*data)
259 : "cc");
260 *status = req >> 24 & 0xff;
261 return cc;
262}
263
264static inline int pcistb_instr(const u64 *data, u64 req, u64 offset)
265{
266 u8 cc, status;
267
268 do {
269 cc = __pcistb(data, req, offset, &status);
270 if (cc == 2)
271 msleep(ZPCI_INSN_BUSY_DELAY);
272 } while (cc == 2);
273
274 if (cc)
275 printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n",
276 __func__, cc, status, req, offset);
277 return (cc) ? -EIO : 0;
278}
279
280#endif
diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h
new file mode 100644
index 000000000000..5fd81f31d6c7
--- /dev/null
+++ b/arch/s390/include/asm/pci_io.h
@@ -0,0 +1,194 @@
1#ifndef _ASM_S390_PCI_IO_H
2#define _ASM_S390_PCI_IO_H
3
4#ifdef CONFIG_PCI
5
6#include <linux/kernel.h>
7#include <linux/slab.h>
8#include <asm/pci_insn.h>
9
10/* I/O Map */
11#define ZPCI_IOMAP_MAX_ENTRIES 0x7fff
12#define ZPCI_IOMAP_ADDR_BASE 0x8000000000000000ULL
13#define ZPCI_IOMAP_ADDR_IDX_MASK 0x7fff000000000000ULL
14#define ZPCI_IOMAP_ADDR_OFF_MASK 0x0000ffffffffffffULL
15
16struct zpci_iomap_entry {
17 u32 fh;
18 u8 bar;
19};
20
21extern struct zpci_iomap_entry *zpci_iomap_start;
22
23#define ZPCI_IDX(addr) \
24 (((__force u64) addr & ZPCI_IOMAP_ADDR_IDX_MASK) >> 48)
25#define ZPCI_OFFSET(addr) \
26 ((__force u64) addr & ZPCI_IOMAP_ADDR_OFF_MASK)
27
28#define ZPCI_CREATE_REQ(handle, space, len) \
29 ((u64) handle << 32 | space << 16 | len)
30
31#define zpci_read(LENGTH, RETTYPE) \
32static inline RETTYPE zpci_read_##RETTYPE(const volatile void __iomem *addr) \
33{ \
34 struct zpci_iomap_entry *entry = &zpci_iomap_start[ZPCI_IDX(addr)]; \
35 u64 req = ZPCI_CREATE_REQ(entry->fh, entry->bar, LENGTH); \
36 u64 data; \
37 int rc; \
38 \
39 rc = pcilg_instr(&data, req, ZPCI_OFFSET(addr)); \
40 if (rc) \
41 data = -1ULL; \
42 return (RETTYPE) data; \
43}
44
45#define zpci_write(LENGTH, VALTYPE) \
46static inline void zpci_write_##VALTYPE(VALTYPE val, \
47 const volatile void __iomem *addr) \
48{ \
49 struct zpci_iomap_entry *entry = &zpci_iomap_start[ZPCI_IDX(addr)]; \
50 u64 req = ZPCI_CREATE_REQ(entry->fh, entry->bar, LENGTH); \
51 u64 data = (VALTYPE) val; \
52 \
53 pcistg_instr(data, req, ZPCI_OFFSET(addr)); \
54}
55
56zpci_read(8, u64)
57zpci_read(4, u32)
58zpci_read(2, u16)
59zpci_read(1, u8)
60zpci_write(8, u64)
61zpci_write(4, u32)
62zpci_write(2, u16)
63zpci_write(1, u8)
64
65static inline int zpci_write_single(u64 req, const u64 *data, u64 offset, u8 len)
66{
67 u64 val;
68
69 switch (len) {
70 case 1:
71 val = (u64) *((u8 *) data);
72 break;
73 case 2:
74 val = (u64) *((u16 *) data);
75 break;
76 case 4:
77 val = (u64) *((u32 *) data);
78 break;
79 case 8:
80 val = (u64) *((u64 *) data);
81 break;
82 default:
83 val = 0; /* let FW report error */
84 break;
85 }
86 return pcistg_instr(val, req, offset);
87}
88
89static inline int zpci_read_single(u64 req, u64 *dst, u64 offset, u8 len)
90{
91 u64 data;
92 u8 cc;
93
94 cc = pcilg_instr(&data, req, offset);
95 switch (len) {
96 case 1:
97 *((u8 *) dst) = (u8) data;
98 break;
99 case 2:
100 *((u16 *) dst) = (u16) data;
101 break;
102 case 4:
103 *((u32 *) dst) = (u32) data;
104 break;
105 case 8:
106 *((u64 *) dst) = (u64) data;
107 break;
108 }
109 return cc;
110}
111
112static inline int zpci_write_block(u64 req, const u64 *data, u64 offset)
113{
114 return pcistb_instr(data, req, offset);
115}
116
117static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max)
118{
119 int count = len > max ? max : len, size = 1;
120
121 while (!(src & 0x1) && !(dst & 0x1) && ((size << 1) <= count)) {
122 dst = dst >> 1;
123 src = src >> 1;
124 size = size << 1;
125 }
126 return size;
127}
128
129static inline int zpci_memcpy_fromio(void *dst,
130 const volatile void __iomem *src,
131 unsigned long n)
132{
133 struct zpci_iomap_entry *entry = &zpci_iomap_start[ZPCI_IDX(src)];
134 u64 req, offset = ZPCI_OFFSET(src);
135 int size, rc = 0;
136
137 while (n > 0) {
138 size = zpci_get_max_write_size((u64) src, (u64) dst, n, 8);
139 req = ZPCI_CREATE_REQ(entry->fh, entry->bar, size);
140 rc = zpci_read_single(req, dst, offset, size);
141 if (rc)
142 break;
143 offset += size;
144 dst += size;
145 n -= size;
146 }
147 return rc;
148}
149
150static inline int zpci_memcpy_toio(volatile void __iomem *dst,
151 const void *src, unsigned long n)
152{
153 struct zpci_iomap_entry *entry = &zpci_iomap_start[ZPCI_IDX(dst)];
154 u64 req, offset = ZPCI_OFFSET(dst);
155 int size, rc = 0;
156
157 if (!src)
158 return -EINVAL;
159
160 while (n > 0) {
161 size = zpci_get_max_write_size((u64) dst, (u64) src, n, 128);
162 req = ZPCI_CREATE_REQ(entry->fh, entry->bar, size);
163
164 if (size > 8) /* main path */
165 rc = zpci_write_block(req, src, offset);
166 else
167 rc = zpci_write_single(req, src, offset, size);
168 if (rc)
169 break;
170 offset += size;
171 src += size;
172 n -= size;
173 }
174 return rc;
175}
176
177static inline int zpci_memset_io(volatile void __iomem *dst,
178 unsigned char val, size_t count)
179{
180 u8 *src = kmalloc(count, GFP_KERNEL);
181 int rc;
182
183 if (src == NULL)
184 return -ENOMEM;
185 memset(src, val, count);
186
187 rc = zpci_memcpy_toio(dst, src, count);
188 kfree(src);
189 return rc;
190}
191
192#endif /* CONFIG_PCI */
193
194#endif /* _ASM_S390_PCI_IO_H */
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index afdb9729cf9b..a7f9abd98cf2 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -399,6 +399,10 @@ enum {
399 LONG_INSN_TABORT, 399 LONG_INSN_TABORT,
400 LONG_INSN_TBEGIN, 400 LONG_INSN_TBEGIN,
401 LONG_INSN_TBEGINC, 401 LONG_INSN_TBEGINC,
402 LONG_INSN_PCISTG,
403 LONG_INSN_MPCIFC,
404 LONG_INSN_STPCIFC,
405 LONG_INSN_PCISTB,
402}; 406};
403 407
404static char *long_insn_name[] = { 408static char *long_insn_name[] = {
@@ -469,6 +473,10 @@ static char *long_insn_name[] = {
469 [LONG_INSN_TABORT] = "tabort", 473 [LONG_INSN_TABORT] = "tabort",
470 [LONG_INSN_TBEGIN] = "tbegin", 474 [LONG_INSN_TBEGIN] = "tbegin",
471 [LONG_INSN_TBEGINC] = "tbeginc", 475 [LONG_INSN_TBEGINC] = "tbeginc",
476 [LONG_INSN_PCISTG] = "pcistg",
477 [LONG_INSN_MPCIFC] = "mpcifc",
478 [LONG_INSN_STPCIFC] = "stpcifc",
479 [LONG_INSN_PCISTB] = "pcistb",
472}; 480};
473 481
474static struct insn opcode[] = { 482static struct insn opcode[] = {
@@ -1115,6 +1123,9 @@ static struct insn opcode_b9[] = {
1115 { { 0, LONG_INSN_SLHHHR }, 0xcb, INSTR_RRF_R0RR2 }, 1123 { { 0, LONG_INSN_SLHHHR }, 0xcb, INSTR_RRF_R0RR2 },
1116 { "chhr", 0xcd, INSTR_RRE_RR }, 1124 { "chhr", 0xcd, INSTR_RRE_RR },
1117 { "clhhr", 0xcf, INSTR_RRE_RR }, 1125 { "clhhr", 0xcf, INSTR_RRE_RR },
1126 { { 0, LONG_INSN_PCISTG }, 0xd0, INSTR_RRE_RR },
1127 { "pcilg", 0xd2, INSTR_RRE_RR },
1128 { "rpcit", 0xd3, INSTR_RRE_RR },
1118 { "ahhlr", 0xd8, INSTR_RRF_R0RR2 }, 1129 { "ahhlr", 0xd8, INSTR_RRF_R0RR2 },
1119 { "shhlr", 0xd9, INSTR_RRF_R0RR2 }, 1130 { "shhlr", 0xd9, INSTR_RRF_R0RR2 },
1120 { { 0, LONG_INSN_ALHHLR }, 0xda, INSTR_RRF_R0RR2 }, 1131 { { 0, LONG_INSN_ALHHLR }, 0xda, INSTR_RRF_R0RR2 },
@@ -1346,6 +1357,8 @@ static struct insn opcode_e3[] = {
1346 { "stfh", 0xcb, INSTR_RXY_RRRD }, 1357 { "stfh", 0xcb, INSTR_RXY_RRRD },
1347 { "chf", 0xcd, INSTR_RXY_RRRD }, 1358 { "chf", 0xcd, INSTR_RXY_RRRD },
1348 { "clhf", 0xcf, INSTR_RXY_RRRD }, 1359 { "clhf", 0xcf, INSTR_RXY_RRRD },
1360 { { 0, LONG_INSN_MPCIFC }, 0xd0, INSTR_RXY_RRRD },
1361 { { 0, LONG_INSN_STPCIFC }, 0xd4, INSTR_RXY_RRRD },
1349#endif 1362#endif
1350 { "lrv", 0x1e, INSTR_RXY_RRRD }, 1363 { "lrv", 0x1e, INSTR_RXY_RRRD },
1351 { "lrvh", 0x1f, INSTR_RXY_RRRD }, 1364 { "lrvh", 0x1f, INSTR_RXY_RRRD },
@@ -1423,6 +1436,8 @@ static struct insn opcode_eb[] = {
1423 { "lmy", 0x98, INSTR_RSY_RRRD }, 1436 { "lmy", 0x98, INSTR_RSY_RRRD },
1424 { "lamy", 0x9a, INSTR_RSY_AARD }, 1437 { "lamy", 0x9a, INSTR_RSY_AARD },
1425 { "stamy", 0x9b, INSTR_RSY_AARD }, 1438 { "stamy", 0x9b, INSTR_RSY_AARD },
1439 { { 0, LONG_INSN_PCISTB }, 0xd0, INSTR_RSY_RRRD },
1440 { "sic", 0xd1, INSTR_RSY_RRRD },
1426 { "srak", 0xdc, INSTR_RSY_RRRD }, 1441 { "srak", 0xdc, INSTR_RSY_RRRD },
1427 { "slak", 0xdd, INSTR_RSY_RRRD }, 1442 { "slak", 0xdd, INSTR_RSY_RRRD },
1428 { "srlk", 0xde, INSTR_RSY_RRRD }, 1443 { "srlk", 0xde, INSTR_RSY_RRRD },
diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
new file mode 100644
index 000000000000..78a1344ff7b1
--- /dev/null
+++ b/arch/s390/pci/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the s390 PCI subsystem.
3#
4
5obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
new file mode 100644
index 000000000000..0b80ac7e158f
--- /dev/null
+++ b/arch/s390/pci/pci.c
@@ -0,0 +1,557 @@
1/*
2 * Copyright IBM Corp. 2012
3 *
4 * Author(s):
5 * Jan Glauber <jang@linux.vnet.ibm.com>
6 *
7 * The System z PCI code is a rewrite from a prototype by
8 * the following people (Kudoz!):
9 * Alexander Schmidt <alexschm@de.ibm.com>
10 * Christoph Raisch <raisch@de.ibm.com>
11 * Hannes Hering <hering2@de.ibm.com>
12 * Hoang-Nam Nguyen <hnguyen@de.ibm.com>
13 * Jan-Bernd Themann <themann@de.ibm.com>
14 * Stefan Roscher <stefan.roscher@de.ibm.com>
15 * Thomas Klein <tklein@de.ibm.com>
16 */
17
18#define COMPONENT "zPCI"
19#define pr_fmt(fmt) COMPONENT ": " fmt
20
21#include <linux/kernel.h>
22#include <linux/slab.h>
23#include <linux/err.h>
24#include <linux/export.h>
25#include <linux/delay.h>
26#include <linux/seq_file.h>
27#include <linux/pci.h>
28#include <linux/msi.h>
29
30#include <asm/facility.h>
31#include <asm/pci_insn.h>
32
33#define DEBUG /* enable pr_debug */
34
35#define ZPCI_NR_DMA_SPACES 1
36#define ZPCI_NR_DEVICES CONFIG_PCI_NR_FUNCTIONS
37
38/* list of all detected zpci devices */
39LIST_HEAD(zpci_list);
40DEFINE_MUTEX(zpci_list_lock);
41
42static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES);
43static DEFINE_SPINLOCK(zpci_domain_lock);
44
45/* I/O Map */
46static DEFINE_SPINLOCK(zpci_iomap_lock);
47static DECLARE_BITMAP(zpci_iomap, ZPCI_IOMAP_MAX_ENTRIES);
48struct zpci_iomap_entry *zpci_iomap_start;
49EXPORT_SYMBOL_GPL(zpci_iomap_start);
50
51struct zpci_dev *get_zdev(struct pci_dev *pdev)
52{
53 return (struct zpci_dev *) pdev->sysdata;
54}
55
56struct zpci_dev *get_zdev_by_fid(u32 fid)
57{
58 struct zpci_dev *tmp, *zdev = NULL;
59
60 mutex_lock(&zpci_list_lock);
61 list_for_each_entry(tmp, &zpci_list, entry) {
62 if (tmp->fid == fid) {
63 zdev = tmp;
64 break;
65 }
66 }
67 mutex_unlock(&zpci_list_lock);
68 return zdev;
69}
70
71bool zpci_fid_present(u32 fid)
72{
73 return (get_zdev_by_fid(fid) != NULL) ? true : false;
74}
75
76static struct zpci_dev *get_zdev_by_bus(struct pci_bus *bus)
77{
78 return (bus && bus->sysdata) ? (struct zpci_dev *) bus->sysdata : NULL;
79}
80
81int pci_domain_nr(struct pci_bus *bus)
82{
83 return ((struct zpci_dev *) bus->sysdata)->domain;
84}
85EXPORT_SYMBOL_GPL(pci_domain_nr);
86
87int pci_proc_domain(struct pci_bus *bus)
88{
89 return pci_domain_nr(bus);
90}
91EXPORT_SYMBOL_GPL(pci_proc_domain);
92
93/* Store PCI function information block */
94static int zpci_store_fib(struct zpci_dev *zdev, u8 *fc)
95{
96 struct zpci_fib *fib;
97 u8 status, cc;
98
99 fib = (void *) get_zeroed_page(GFP_KERNEL);
100 if (!fib)
101 return -ENOMEM;
102
103 do {
104 cc = __stpcifc(zdev->fh, 0, fib, &status);
105 if (cc == 2) {
106 msleep(ZPCI_INSN_BUSY_DELAY);
107 memset(fib, 0, PAGE_SIZE);
108 }
109 } while (cc == 2);
110
111 if (cc)
112 pr_err_once("%s: cc: %u status: %u\n",
113 __func__, cc, status);
114
115 /* Return PCI function controls */
116 *fc = fib->fc;
117
118 free_page((unsigned long) fib);
119 return (cc) ? -EIO : 0;
120}
121
122#define ZPCI_PCIAS_CFGSPC 15
123
124static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len)
125{
126 u64 req = ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len);
127 u64 data;
128 int rc;
129
130 rc = pcilg_instr(&data, req, offset);
131 data = data << ((8 - len) * 8);
132 data = le64_to_cpu(data);
133 if (!rc)
134 *val = (u32) data;
135 else
136 *val = 0xffffffff;
137 return rc;
138}
139
140static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len)
141{
142 u64 req = ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len);
143 u64 data = val;
144 int rc;
145
146 data = cpu_to_le64(data);
147 data = data >> ((8 - len) * 8);
148 rc = pcistg_instr(data, req, offset);
149 return rc;
150}
151
152void __devinit pcibios_fixup_bus(struct pci_bus *bus)
153{
154}
155
156resource_size_t pcibios_align_resource(void *data, const struct resource *res,
157 resource_size_t size,
158 resource_size_t align)
159{
160 return 0;
161}
162
163/* Create a virtual mapping cookie for a PCI BAR */
164void __iomem *pci_iomap(struct pci_dev *pdev, int bar, unsigned long max)
165{
166 struct zpci_dev *zdev = get_zdev(pdev);
167 u64 addr;
168 int idx;
169
170 if ((bar & 7) != bar)
171 return NULL;
172
173 idx = zdev->bars[bar].map_idx;
174 spin_lock(&zpci_iomap_lock);
175 zpci_iomap_start[idx].fh = zdev->fh;
176 zpci_iomap_start[idx].bar = bar;
177 spin_unlock(&zpci_iomap_lock);
178
179 addr = ZPCI_IOMAP_ADDR_BASE | ((u64) idx << 48);
180 return (void __iomem *) addr;
181}
182EXPORT_SYMBOL_GPL(pci_iomap);
183
184void pci_iounmap(struct pci_dev *pdev, void __iomem *addr)
185{
186 unsigned int idx;
187
188 idx = (((__force u64) addr) & ~ZPCI_IOMAP_ADDR_BASE) >> 48;
189 spin_lock(&zpci_iomap_lock);
190 zpci_iomap_start[idx].fh = 0;
191 zpci_iomap_start[idx].bar = 0;
192 spin_unlock(&zpci_iomap_lock);
193}
194EXPORT_SYMBOL_GPL(pci_iounmap);
195
196static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
197 int size, u32 *val)
198{
199 struct zpci_dev *zdev = get_zdev_by_bus(bus);
200
201 if (!zdev || devfn != ZPCI_DEVFN)
202 return 0;
203 return zpci_cfg_load(zdev, where, val, size);
204}
205
206static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
207 int size, u32 val)
208{
209 struct zpci_dev *zdev = get_zdev_by_bus(bus);
210
211 if (!zdev || devfn != ZPCI_DEVFN)
212 return 0;
213 return zpci_cfg_store(zdev, where, val, size);
214}
215
216static struct pci_ops pci_root_ops = {
217 .read = pci_read,
218 .write = pci_write,
219};
220
221static void zpci_map_resources(struct zpci_dev *zdev)
222{
223 struct pci_dev *pdev = zdev->pdev;
224 resource_size_t len;
225 int i;
226
227 for (i = 0; i < PCI_BAR_COUNT; i++) {
228 len = pci_resource_len(pdev, i);
229 if (!len)
230 continue;
231 pdev->resource[i].start = (resource_size_t) pci_iomap(pdev, i, 0);
232 pdev->resource[i].end = pdev->resource[i].start + len - 1;
233 pr_debug("BAR%i: -> start: %Lx end: %Lx\n",
234 i, pdev->resource[i].start, pdev->resource[i].end);
235 }
236};
237
238static void zpci_unmap_resources(struct pci_dev *pdev)
239{
240 resource_size_t len;
241 int i;
242
243 for (i = 0; i < PCI_BAR_COUNT; i++) {
244 len = pci_resource_len(pdev, i);
245 if (!len)
246 continue;
247 pci_iounmap(pdev, (void *) pdev->resource[i].start);
248 }
249};
250
251struct zpci_dev *zpci_alloc_device(void)
252{
253 struct zpci_dev *zdev;
254
255 /* Alloc memory for our private pci device data */
256 zdev = kzalloc(sizeof(*zdev), GFP_KERNEL);
257 if (!zdev)
258 return ERR_PTR(-ENOMEM);
259 return zdev;
260}
261
262void zpci_free_device(struct zpci_dev *zdev)
263{
264 kfree(zdev);
265}
266
267/* Called on removal of pci_dev, leaves zpci and bus device */
268static void zpci_remove_device(struct pci_dev *pdev)
269{
270 struct zpci_dev *zdev = get_zdev(pdev);
271
272 dev_info(&pdev->dev, "Removing device %u\n", zdev->domain);
273 zdev->state = ZPCI_FN_STATE_CONFIGURED;
274 zpci_unmap_resources(pdev);
275 list_del(&zdev->entry); /* can be called from init */
276 zdev->pdev = NULL;
277}
278
279static void zpci_scan_devices(void)
280{
281 struct zpci_dev *zdev;
282
283 mutex_lock(&zpci_list_lock);
284 list_for_each_entry(zdev, &zpci_list, entry)
285 if (zdev->state == ZPCI_FN_STATE_CONFIGURED)
286 zpci_scan_device(zdev);
287 mutex_unlock(&zpci_list_lock);
288}
289
290/*
291 * Too late for any s390 specific setup, since interrupts must be set up
292 * already which requires DMA setup too and the pci scan will access the
293 * config space, which only works if the function handle is enabled.
294 */
295int pcibios_enable_device(struct pci_dev *pdev, int mask)
296{
297 struct resource *res;
298 u16 cmd;
299 int i;
300
301 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
302
303 for (i = 0; i < PCI_BAR_COUNT; i++) {
304 res = &pdev->resource[i];
305
306 if (res->flags & IORESOURCE_IO)
307 return -EINVAL;
308
309 if (res->flags & IORESOURCE_MEM)
310 cmd |= PCI_COMMAND_MEMORY;
311 }
312 pci_write_config_word(pdev, PCI_COMMAND, cmd);
313 return 0;
314}
315
316void pcibios_disable_device(struct pci_dev *pdev)
317{
318 zpci_remove_device(pdev);
319 pdev->sysdata = NULL;
320}
321
322static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size,
323 unsigned long flags, int domain)
324{
325 struct resource *r;
326 char *name;
327 int rc;
328
329 r = kzalloc(sizeof(*r), GFP_KERNEL);
330 if (!r)
331 return ERR_PTR(-ENOMEM);
332 r->start = start;
333 r->end = r->start + size - 1;
334 r->flags = flags;
335 r->parent = &iomem_resource;
336 name = kmalloc(18, GFP_KERNEL);
337 if (!name) {
338 kfree(r);
339 return ERR_PTR(-ENOMEM);
340 }
341 sprintf(name, "PCI Bus: %04x:%02x", domain, ZPCI_BUS_NR);
342 r->name = name;
343
344 rc = request_resource(&iomem_resource, r);
345 if (rc)
346 pr_debug("request resource %pR failed\n", r);
347 return r;
348}
349
350static int zpci_alloc_iomap(struct zpci_dev *zdev)
351{
352 int entry;
353
354 spin_lock(&zpci_iomap_lock);
355 entry = find_first_zero_bit(zpci_iomap, ZPCI_IOMAP_MAX_ENTRIES);
356 if (entry == ZPCI_IOMAP_MAX_ENTRIES) {
357 spin_unlock(&zpci_iomap_lock);
358 return -ENOSPC;
359 }
360 set_bit(entry, zpci_iomap);
361 spin_unlock(&zpci_iomap_lock);
362 return entry;
363}
364
365static void zpci_free_iomap(struct zpci_dev *zdev, int entry)
366{
367 spin_lock(&zpci_iomap_lock);
368 memset(&zpci_iomap_start[entry], 0, sizeof(struct zpci_iomap_entry));
369 clear_bit(entry, zpci_iomap);
370 spin_unlock(&zpci_iomap_lock);
371}
372
373static int zpci_create_device_bus(struct zpci_dev *zdev)
374{
375 struct resource *res;
376 LIST_HEAD(resources);
377 int i;
378
379 /* allocate mapping entry for each used bar */
380 for (i = 0; i < PCI_BAR_COUNT; i++) {
381 unsigned long addr, size, flags;
382 int entry;
383
384 if (!zdev->bars[i].size)
385 continue;
386 entry = zpci_alloc_iomap(zdev);
387 if (entry < 0)
388 return entry;
389 zdev->bars[i].map_idx = entry;
390
391 /* only MMIO is supported */
392 flags = IORESOURCE_MEM;
393 if (zdev->bars[i].val & 8)
394 flags |= IORESOURCE_PREFETCH;
395 if (zdev->bars[i].val & 4)
396 flags |= IORESOURCE_MEM_64;
397
398 addr = ZPCI_IOMAP_ADDR_BASE + ((u64) entry << 48);
399
400 size = 1UL << zdev->bars[i].size;
401
402 res = zpci_alloc_bus_resource(addr, size, flags, zdev->domain);
403 if (IS_ERR(res)) {
404 zpci_free_iomap(zdev, entry);
405 return PTR_ERR(res);
406 }
407 pci_add_resource(&resources, res);
408 }
409
410 zdev->bus = pci_create_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops,
411 zdev, &resources);
412 if (!zdev->bus)
413 return -EIO;
414
415 zdev->bus->max_bus_speed = zdev->max_bus_speed;
416 return 0;
417}
418
419static int zpci_alloc_domain(struct zpci_dev *zdev)
420{
421 spin_lock(&zpci_domain_lock);
422 zdev->domain = find_first_zero_bit(zpci_domain, ZPCI_NR_DEVICES);
423 if (zdev->domain == ZPCI_NR_DEVICES) {
424 spin_unlock(&zpci_domain_lock);
425 return -ENOSPC;
426 }
427 set_bit(zdev->domain, zpci_domain);
428 spin_unlock(&zpci_domain_lock);
429 return 0;
430}
431
432static void zpci_free_domain(struct zpci_dev *zdev)
433{
434 spin_lock(&zpci_domain_lock);
435 clear_bit(zdev->domain, zpci_domain);
436 spin_unlock(&zpci_domain_lock);
437}
438
439int zpci_create_device(struct zpci_dev *zdev)
440{
441 int rc;
442
443 rc = zpci_alloc_domain(zdev);
444 if (rc)
445 goto out;
446
447 rc = zpci_create_device_bus(zdev);
448 if (rc)
449 goto out_bus;
450
451 mutex_lock(&zpci_list_lock);
452 list_add_tail(&zdev->entry, &zpci_list);
453 mutex_unlock(&zpci_list_lock);
454
455 if (zdev->state == ZPCI_FN_STATE_STANDBY)
456 return 0;
457
458 return 0;
459
460out_bus:
461 zpci_free_domain(zdev);
462out:
463 return rc;
464}
465
466void zpci_stop_device(struct zpci_dev *zdev)
467{
468 /*
469 * Note: SCLP disables fh via set-pci-fn so don't
470 * do that here.
471 */
472}
473EXPORT_SYMBOL_GPL(zpci_stop_device);
474
475int zpci_scan_device(struct zpci_dev *zdev)
476{
477 zdev->pdev = pci_scan_single_device(zdev->bus, ZPCI_DEVFN);
478 if (!zdev->pdev) {
479 pr_err("pci_scan_single_device failed for fid: 0x%x\n",
480 zdev->fid);
481 goto out;
482 }
483
484 zpci_map_resources(zdev);
485 pci_bus_add_devices(zdev->bus);
486
487 /* now that pdev was added to the bus mark it as used */
488 zdev->state = ZPCI_FN_STATE_ONLINE;
489 return 0;
490
491out:
492 return -EIO;
493}
494EXPORT_SYMBOL_GPL(zpci_scan_device);
495
496static inline int barsize(u8 size)
497{
498 return (size) ? (1 << size) >> 10 : 0;
499}
500
501static int zpci_mem_init(void)
502{
503 /* TODO: use realloc */
504 zpci_iomap_start = kzalloc(ZPCI_IOMAP_MAX_ENTRIES * sizeof(*zpci_iomap_start),
505 GFP_KERNEL);
506 if (!zpci_iomap_start)
507 goto error_zdev;
508 return 0;
509
510error_zdev:
511 return -ENOMEM;
512}
513
514static void zpci_mem_exit(void)
515{
516 kfree(zpci_iomap_start);
517}
518
519unsigned int pci_probe = 1;
520EXPORT_SYMBOL_GPL(pci_probe);
521
522char * __init pcibios_setup(char *str)
523{
524 if (!strcmp(str, "off")) {
525 pci_probe = 0;
526 return NULL;
527 }
528 return str;
529}
530
531static int __init pci_base_init(void)
532{
533 int rc;
534
535 if (!pci_probe)
536 return 0;
537
538 if (!test_facility(2) || !test_facility(69)
539 || !test_facility(71) || !test_facility(72))
540 return 0;
541
542 pr_info("Probing PCI hardware: PCI:%d SID:%d AEN:%d\n",
543 test_facility(69), test_facility(70),
544 test_facility(71));
545
546 rc = zpci_mem_init();
547 if (rc)
548 goto out_mem;
549
550 zpci_scan_devices();
551 return 0;
552
553 zpci_mem_exit();
554out_mem:
555 return rc;
556}
557subsys_initcall(pci_base_init);
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 448303bdb85f..9e0ebe051243 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -83,19 +83,25 @@ static inline void __raw_writel(u32 b, volatile void __iomem *addr)
83#define writel(b,addr) __raw_writel(__cpu_to_le32(b),addr) 83#define writel(b,addr) __raw_writel(__cpu_to_le32(b),addr)
84 84
85#ifdef CONFIG_64BIT 85#ifdef CONFIG_64BIT
86#ifndef __raw_readq
86static inline u64 __raw_readq(const volatile void __iomem *addr) 87static inline u64 __raw_readq(const volatile void __iomem *addr)
87{ 88{
88 return *(const volatile u64 __force *) addr; 89 return *(const volatile u64 __force *) addr;
89} 90}
91#endif
92
90#define readq(addr) __le64_to_cpu(__raw_readq(addr)) 93#define readq(addr) __le64_to_cpu(__raw_readq(addr))
91 94
95#ifndef __raw_writeq
92static inline void __raw_writeq(u64 b, volatile void __iomem *addr) 96static inline void __raw_writeq(u64 b, volatile void __iomem *addr)
93{ 97{
94 *(volatile u64 __force *) addr = b; 98 *(volatile u64 __force *) addr = b;
95} 99}
96#define writeq(b,addr) __raw_writeq(__cpu_to_le64(b),addr)
97#endif 100#endif
98 101
102#define writeq(b, addr) __raw_writeq(__cpu_to_le64(b), addr)
103#endif /* CONFIG_64BIT */
104
99#ifndef PCI_IOBASE 105#ifndef PCI_IOBASE
100#define PCI_IOBASE ((void __iomem *) 0) 106#define PCI_IOBASE ((void __iomem *) 0)
101#endif 107#endif
@@ -286,15 +292,20 @@ static inline void writesb(const void __iomem *addr, const void *buf, int len)
286 292
287#ifndef CONFIG_GENERIC_IOMAP 293#ifndef CONFIG_GENERIC_IOMAP
288struct pci_dev; 294struct pci_dev;
295extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
296
297#ifndef pci_iounmap
289static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p) 298static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p)
290{ 299{
291} 300}
301#endif
292#endif /* CONFIG_GENERIC_IOMAP */ 302#endif /* CONFIG_GENERIC_IOMAP */
293 303
294/* 304/*
295 * Change virtual addresses to physical addresses and vv. 305 * Change virtual addresses to physical addresses and vv.
296 * These are pretty trivial 306 * These are pretty trivial
297 */ 307 */
308#ifndef virt_to_phys
298static inline unsigned long virt_to_phys(volatile void *address) 309static inline unsigned long virt_to_phys(volatile void *address)
299{ 310{
300 return __pa((unsigned long)address); 311 return __pa((unsigned long)address);
@@ -304,6 +315,7 @@ static inline void *phys_to_virt(unsigned long address)
304{ 315{
305 return __va(address); 316 return __va(address);
306} 317}
318#endif
307 319
308/* 320/*
309 * Change "struct page" to physical address. 321 * Change "struct page" to physical address.
@@ -363,9 +375,16 @@ static inline void *bus_to_virt(unsigned long address)
363} 375}
364#endif 376#endif
365 377
378#ifndef memset_io
366#define memset_io(a, b, c) memset(__io_virt(a), (b), (c)) 379#define memset_io(a, b, c) memset(__io_virt(a), (b), (c))
380#endif
381
382#ifndef memcpy_fromio
367#define memcpy_fromio(a, b, c) memcpy((a), __io_virt(b), (c)) 383#define memcpy_fromio(a, b, c) memcpy((a), __io_virt(b), (c))
384#endif
385#ifndef memcpy_toio
368#define memcpy_toio(a, b, c) memcpy(__io_virt(a), (b), (c)) 386#define memcpy_toio(a, b, c) memcpy(__io_virt(a), (b), (c))
387#endif
369 388
370#endif /* __KERNEL__ */ 389#endif /* __KERNEL__ */
371 390