aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/pci
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 /arch/s390/pci
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>
Diffstat (limited to 'arch/s390/pci')
-rw-r--r--arch/s390/pci/Makefile5
-rw-r--r--arch/s390/pci/pci.c557
2 files changed, 562 insertions, 0 deletions
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);