diff options
Diffstat (limited to 'arch/s390/pci/pci.c')
-rw-r--r-- | arch/s390/pci/pci.c | 255 |
1 files changed, 86 insertions, 169 deletions
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 27e7fed3707d..d65dc4f50e2a 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c | |||
@@ -50,24 +50,23 @@ EXPORT_SYMBOL_GPL(zpci_list); | |||
50 | DEFINE_MUTEX(zpci_list_lock); | 50 | DEFINE_MUTEX(zpci_list_lock); |
51 | EXPORT_SYMBOL_GPL(zpci_list_lock); | 51 | EXPORT_SYMBOL_GPL(zpci_list_lock); |
52 | 52 | ||
53 | static struct pci_hp_callback_ops *hotplug_ops; | ||
54 | 53 | ||
55 | static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES); | 54 | static void zpci_enable_irq(struct irq_data *data); |
56 | static DEFINE_SPINLOCK(zpci_domain_lock); | 55 | static void zpci_disable_irq(struct irq_data *data); |
57 | 56 | ||
58 | struct callback { | 57 | static struct irq_chip zpci_irq_chip = { |
59 | irq_handler_t handler; | 58 | .name = "zPCI", |
60 | void *data; | 59 | .irq_unmask = zpci_enable_irq, |
60 | .irq_mask = zpci_disable_irq, | ||
61 | }; | 61 | }; |
62 | 62 | ||
63 | struct zdev_irq_map { | 63 | static struct pci_hp_callback_ops *hotplug_ops; |
64 | struct airq_iv *aibv; /* Adapter interrupt bit vector */ | 64 | |
65 | struct callback *cb; /* callback handler array */ | 65 | static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES); |
66 | int msi_vecs; /* consecutive MSI-vectors used */ | 66 | static DEFINE_SPINLOCK(zpci_domain_lock); |
67 | }; | ||
68 | 67 | ||
69 | static struct airq_iv *zpci_aisb_iv; | 68 | static struct airq_iv *zpci_aisb_iv; |
70 | static struct zdev_irq_map *zpci_imap[ZPCI_NR_DEVICES]; | 69 | static struct airq_iv *zpci_aibv[ZPCI_NR_DEVICES]; |
71 | 70 | ||
72 | /* Adapter interrupt definitions */ | 71 | /* Adapter interrupt definitions */ |
73 | static void zpci_irq_handler(struct airq_struct *airq); | 72 | static void zpci_irq_handler(struct airq_struct *airq); |
@@ -83,19 +82,8 @@ static DECLARE_BITMAP(zpci_iomap, ZPCI_IOMAP_MAX_ENTRIES); | |||
83 | struct zpci_iomap_entry *zpci_iomap_start; | 82 | struct zpci_iomap_entry *zpci_iomap_start; |
84 | EXPORT_SYMBOL_GPL(zpci_iomap_start); | 83 | EXPORT_SYMBOL_GPL(zpci_iomap_start); |
85 | 84 | ||
86 | static struct kmem_cache *zdev_irq_cache; | ||
87 | static struct kmem_cache *zdev_fmb_cache; | 85 | static struct kmem_cache *zdev_fmb_cache; |
88 | 86 | ||
89 | static inline int irq_to_msi_nr(unsigned int irq) | ||
90 | { | ||
91 | return irq & ZPCI_MSI_VEC_MASK; | ||
92 | } | ||
93 | |||
94 | static inline int irq_to_dev_nr(unsigned int irq) | ||
95 | { | ||
96 | return irq >> ZPCI_MSI_VEC_BITS; | ||
97 | } | ||
98 | |||
99 | struct zpci_dev *get_zdev(struct pci_dev *pdev) | 87 | struct zpci_dev *get_zdev(struct pci_dev *pdev) |
100 | { | 88 | { |
101 | return (struct zpci_dev *) pdev->sysdata; | 89 | return (struct zpci_dev *) pdev->sysdata; |
@@ -283,21 +271,42 @@ static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len) | |||
283 | return rc; | 271 | return rc; |
284 | } | 272 | } |
285 | 273 | ||
286 | void enable_irq(unsigned int irq) | 274 | static int zpci_msi_set_mask_bits(struct msi_desc *msi, u32 mask, u32 flag) |
275 | { | ||
276 | int offset, pos; | ||
277 | u32 mask_bits; | ||
278 | |||
279 | if (msi->msi_attrib.is_msix) { | ||
280 | offset = msi->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | ||
281 | PCI_MSIX_ENTRY_VECTOR_CTRL; | ||
282 | msi->masked = readl(msi->mask_base + offset); | ||
283 | writel(flag, msi->mask_base + offset); | ||
284 | } else if (msi->msi_attrib.maskbit) { | ||
285 | pos = (long) msi->mask_base; | ||
286 | pci_read_config_dword(msi->dev, pos, &mask_bits); | ||
287 | mask_bits &= ~(mask); | ||
288 | mask_bits |= flag & mask; | ||
289 | pci_write_config_dword(msi->dev, pos, mask_bits); | ||
290 | } else | ||
291 | return 0; | ||
292 | |||
293 | msi->msi_attrib.maskbit = !!flag; | ||
294 | return 1; | ||
295 | } | ||
296 | |||
297 | static void zpci_enable_irq(struct irq_data *data) | ||
287 | { | 298 | { |
288 | struct msi_desc *msi = irq_get_msi_desc(irq); | 299 | struct msi_desc *msi = irq_get_msi_desc(data->irq); |
289 | 300 | ||
290 | zpci_msi_set_mask_bits(msi, 1, 0); | 301 | zpci_msi_set_mask_bits(msi, 1, 0); |
291 | } | 302 | } |
292 | EXPORT_SYMBOL_GPL(enable_irq); | ||
293 | 303 | ||
294 | void disable_irq(unsigned int irq) | 304 | static void zpci_disable_irq(struct irq_data *data) |
295 | { | 305 | { |
296 | struct msi_desc *msi = irq_get_msi_desc(irq); | 306 | struct msi_desc *msi = irq_get_msi_desc(data->irq); |
297 | 307 | ||
298 | zpci_msi_set_mask_bits(msi, 1, 1); | 308 | zpci_msi_set_mask_bits(msi, 1, 1); |
299 | } | 309 | } |
300 | EXPORT_SYMBOL_GPL(disable_irq); | ||
301 | 310 | ||
302 | void pcibios_fixup_bus(struct pci_bus *bus) | 311 | void pcibios_fixup_bus(struct pci_bus *bus) |
303 | { | 312 | { |
@@ -385,7 +394,7 @@ static struct pci_ops pci_root_ops = { | |||
385 | static void zpci_irq_handler(struct airq_struct *airq) | 394 | static void zpci_irq_handler(struct airq_struct *airq) |
386 | { | 395 | { |
387 | unsigned long si, ai; | 396 | unsigned long si, ai; |
388 | struct zdev_irq_map *imap; | 397 | struct airq_iv *aibv; |
389 | int irqs_on = 0; | 398 | int irqs_on = 0; |
390 | 399 | ||
391 | inc_irq_stat(IRQIO_PCI); | 400 | inc_irq_stat(IRQIO_PCI); |
@@ -403,69 +412,33 @@ static void zpci_irq_handler(struct airq_struct *airq) | |||
403 | } | 412 | } |
404 | 413 | ||
405 | /* Scan the adapter interrupt vector for this device. */ | 414 | /* Scan the adapter interrupt vector for this device. */ |
406 | imap = zpci_imap[si]; | 415 | aibv = zpci_aibv[si]; |
407 | for (ai = 0;;) { | 416 | for (ai = 0;;) { |
408 | ai = airq_iv_scan(imap->aibv, ai, imap->msi_vecs); | 417 | ai = airq_iv_scan(aibv, ai, airq_iv_end(aibv)); |
409 | if (ai == -1UL) | 418 | if (ai == -1UL) |
410 | break; | 419 | break; |
411 | inc_irq_stat(IRQIO_MSI); | 420 | inc_irq_stat(IRQIO_MSI); |
412 | airq_iv_lock(imap->aibv, ai); | 421 | airq_iv_lock(aibv, ai); |
413 | if (imap->cb[ai].handler) | 422 | generic_handle_irq(airq_iv_get_data(aibv, ai)); |
414 | imap->cb[ai].handler(ai, imap->cb[ai].data); | 423 | airq_iv_unlock(aibv, ai); |
415 | airq_iv_unlock(imap->aibv, ai); | ||
416 | } | 424 | } |
417 | } | 425 | } |
418 | } | 426 | } |
419 | 427 | ||
420 | static int zpci_alloc_msi(struct zpci_dev *zdev, int msi_vecs) | ||
421 | { | ||
422 | unsigned long size; | ||
423 | |||
424 | /* Alloc aibv & callback space */ | ||
425 | zdev->irq_map = kmem_cache_zalloc(zdev_irq_cache, GFP_KERNEL); | ||
426 | if (!zdev->irq_map) | ||
427 | goto out; | ||
428 | /* Store the number of used MSI vectors */ | ||
429 | zdev->irq_map->msi_vecs = msi_vecs; | ||
430 | /* Allocate callback array */ | ||
431 | size = sizeof(struct callback) * msi_vecs; | ||
432 | zdev->irq_map->cb = kzalloc(size, GFP_KERNEL); | ||
433 | if (!zdev->irq_map->cb) | ||
434 | goto out_map; | ||
435 | /* Allocate msi_map array */ | ||
436 | size = sizeof(struct msi_map) * msi_vecs; | ||
437 | zdev->msi_map = kzalloc(size, GFP_KERNEL); | ||
438 | if (!zdev->msi_map) | ||
439 | goto out_cb; | ||
440 | return 0; | ||
441 | |||
442 | out_cb: | ||
443 | kfree(zdev->irq_map->cb); | ||
444 | out_map: | ||
445 | kmem_cache_free(zdev_irq_cache, zdev->irq_map); | ||
446 | out: | ||
447 | return -ENOMEM; | ||
448 | } | ||
449 | |||
450 | static void zpci_free_msi(struct zpci_dev *zdev) | ||
451 | { | ||
452 | kfree(zdev->msi_map); | ||
453 | kfree(zdev->irq_map->cb); | ||
454 | kmem_cache_free(zdev_irq_cache, zdev->irq_map); | ||
455 | } | ||
456 | |||
457 | int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | 428 | int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) |
458 | { | 429 | { |
459 | struct zpci_dev *zdev = get_zdev(pdev); | 430 | struct zpci_dev *zdev = get_zdev(pdev); |
460 | unsigned int msi_nr, msi_vecs; | 431 | unsigned int hwirq, irq, msi_vecs; |
461 | unsigned long aisb; | 432 | unsigned long aisb; |
462 | struct msi_desc *msi; | 433 | struct msi_desc *msi; |
434 | struct msi_msg msg; | ||
463 | int rc; | 435 | int rc; |
464 | 436 | ||
465 | pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec); | 437 | pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec); |
466 | if (type != PCI_CAP_ID_MSIX && type != PCI_CAP_ID_MSI) | 438 | if (type != PCI_CAP_ID_MSIX && type != PCI_CAP_ID_MSI) |
467 | return -EINVAL; | 439 | return -EINVAL; |
468 | msi_vecs = min(nvec, ZPCI_MSI_VEC_MAX); | 440 | msi_vecs = min(nvec, ZPCI_MSI_VEC_MAX); |
441 | msi_vecs = min_t(unsigned int, msi_vecs, CONFIG_PCI_NR_MSI); | ||
469 | 442 | ||
470 | /* Allocate adapter summary indicator bit */ | 443 | /* Allocate adapter summary indicator bit */ |
471 | rc = -EIO; | 444 | rc = -EIO; |
@@ -476,30 +449,31 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
476 | 449 | ||
477 | /* Create adapter interrupt vector */ | 450 | /* Create adapter interrupt vector */ |
478 | rc = -ENOMEM; | 451 | rc = -ENOMEM; |
479 | zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_BITLOCK); | 452 | zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK); |
480 | if (!zdev->aibv) | 453 | if (!zdev->aibv) |
481 | goto out_si; | 454 | goto out_si; |
482 | 455 | ||
483 | /* Allocate data structures for msi interrupts */ | ||
484 | rc = zpci_alloc_msi(zdev, msi_vecs); | ||
485 | if (rc) | ||
486 | goto out_iv; | ||
487 | |||
488 | /* Wire up shortcut pointer */ | 456 | /* Wire up shortcut pointer */ |
489 | zpci_imap[aisb] = zdev->irq_map; | 457 | zpci_aibv[aisb] = zdev->aibv; |
490 | zdev->irq_map->aibv = zdev->aibv; | ||
491 | 458 | ||
492 | /* | 459 | /* Request MSI interrupts */ |
493 | * TODO: irq number 0 wont be found if we return less than the | 460 | hwirq = 0; |
494 | * requested MSIs. Ignore it for now and fix in common code. | ||
495 | */ | ||
496 | msi_nr = aisb << ZPCI_MSI_VEC_BITS; | ||
497 | list_for_each_entry(msi, &pdev->msi_list, list) { | 461 | list_for_each_entry(msi, &pdev->msi_list, list) { |
498 | rc = zpci_setup_msi_irq(zdev, msi, msi_nr, | 462 | rc = -EIO; |
499 | aisb << ZPCI_MSI_VEC_BITS); | 463 | irq = irq_alloc_desc(0); /* Alloc irq on node 0 */ |
464 | if (irq == NO_IRQ) | ||
465 | goto out_msi; | ||
466 | rc = irq_set_msi_desc(irq, msi); | ||
500 | if (rc) | 467 | if (rc) |
501 | goto out_msi; | 468 | goto out_msi; |
502 | msi_nr++; | 469 | irq_set_chip_and_handler(irq, &zpci_irq_chip, |
470 | handle_simple_irq); | ||
471 | msg.data = hwirq; | ||
472 | msg.address_lo = zdev->msi_addr & 0xffffffff; | ||
473 | msg.address_hi = zdev->msi_addr >> 32; | ||
474 | write_msi_msg(irq, &msg); | ||
475 | airq_iv_set_data(zdev->aibv, hwirq, irq); | ||
476 | hwirq++; | ||
503 | } | 477 | } |
504 | 478 | ||
505 | /* Enable adapter interrupts */ | 479 | /* Enable adapter interrupts */ |
@@ -510,14 +484,17 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
510 | return (msi_vecs == nvec) ? 0 : msi_vecs; | 484 | return (msi_vecs == nvec) ? 0 : msi_vecs; |
511 | 485 | ||
512 | out_msi: | 486 | out_msi: |
513 | msi_nr -= aisb << ZPCI_MSI_VEC_BITS; | ||
514 | list_for_each_entry(msi, &pdev->msi_list, list) { | 487 | list_for_each_entry(msi, &pdev->msi_list, list) { |
515 | if (msi_nr-- == 0) | 488 | if (hwirq-- == 0) |
516 | break; | 489 | break; |
517 | zpci_teardown_msi_irq(zdev, msi); | 490 | irq_set_msi_desc(msi->irq, NULL); |
491 | irq_free_desc(msi->irq); | ||
492 | msi->msg.address_lo = 0; | ||
493 | msi->msg.address_hi = 0; | ||
494 | msi->msg.data = 0; | ||
495 | msi->irq = 0; | ||
518 | } | 496 | } |
519 | zpci_free_msi(zdev); | 497 | zpci_aibv[aisb] = NULL; |
520 | out_iv: | ||
521 | airq_iv_release(zdev->aibv); | 498 | airq_iv_release(zdev->aibv); |
522 | out_si: | 499 | out_si: |
523 | airq_iv_free_bit(zpci_aisb_iv, aisb); | 500 | airq_iv_free_bit(zpci_aisb_iv, aisb); |
@@ -541,10 +518,18 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev) | |||
541 | return; | 518 | return; |
542 | } | 519 | } |
543 | 520 | ||
544 | list_for_each_entry(msi, &pdev->msi_list, list) | 521 | /* Release MSI interrupts */ |
545 | zpci_teardown_msi_irq(zdev, msi); | 522 | list_for_each_entry(msi, &pdev->msi_list, list) { |
523 | zpci_msi_set_mask_bits(msi, 1, 1); | ||
524 | irq_set_msi_desc(msi->irq, NULL); | ||
525 | irq_free_desc(msi->irq); | ||
526 | msi->msg.address_lo = 0; | ||
527 | msi->msg.address_hi = 0; | ||
528 | msi->msg.data = 0; | ||
529 | msi->irq = 0; | ||
530 | } | ||
546 | 531 | ||
547 | zpci_free_msi(zdev); | 532 | zpci_aibv[zdev->aisb] = NULL; |
548 | airq_iv_release(zdev->aibv); | 533 | airq_iv_release(zdev->aibv); |
549 | airq_iv_free_bit(zpci_aisb_iv, zdev->aisb); | 534 | airq_iv_free_bit(zpci_aisb_iv, zdev->aisb); |
550 | } | 535 | } |
@@ -625,61 +610,6 @@ int pcibios_add_platform_entries(struct pci_dev *pdev) | |||
625 | return zpci_sysfs_add_device(&pdev->dev); | 610 | return zpci_sysfs_add_device(&pdev->dev); |
626 | } | 611 | } |
627 | 612 | ||
628 | int zpci_request_irq(unsigned int irq, irq_handler_t handler, void *data) | ||
629 | { | ||
630 | unsigned int msi_nr = irq_to_msi_nr(irq); | ||
631 | unsigned int dev_nr = irq_to_dev_nr(irq); | ||
632 | struct zdev_irq_map *imap; | ||
633 | struct msi_desc *msi; | ||
634 | |||
635 | msi = irq_get_msi_desc(irq); | ||
636 | if (!msi) | ||
637 | return -EIO; | ||
638 | |||
639 | imap = zpci_imap[dev_nr]; | ||
640 | imap->cb[msi_nr].handler = handler; | ||
641 | imap->cb[msi_nr].data = data; | ||
642 | |||
643 | /* | ||
644 | * The generic MSI code returns with the interrupt disabled on the | ||
645 | * card, using the MSI mask bits. Firmware doesn't appear to unmask | ||
646 | * at that level, so we do it here by hand. | ||
647 | */ | ||
648 | zpci_msi_set_mask_bits(msi, 1, 0); | ||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | void zpci_free_irq(unsigned int irq) | ||
653 | { | ||
654 | unsigned int msi_nr = irq_to_msi_nr(irq); | ||
655 | unsigned int dev_nr = irq_to_dev_nr(irq); | ||
656 | struct zdev_irq_map *imap; | ||
657 | struct msi_desc *msi; | ||
658 | |||
659 | /* Disable interrupt */ | ||
660 | msi = irq_get_msi_desc(irq); | ||
661 | if (!msi) | ||
662 | return; | ||
663 | zpci_msi_set_mask_bits(msi, 1, 1); | ||
664 | imap = zpci_imap[dev_nr]; | ||
665 | imap->cb[msi_nr].handler = NULL; | ||
666 | imap->cb[msi_nr].data = NULL; | ||
667 | synchronize_rcu(); | ||
668 | } | ||
669 | |||
670 | int request_irq(unsigned int irq, irq_handler_t handler, | ||
671 | unsigned long irqflags, const char *devname, void *dev_id) | ||
672 | { | ||
673 | return zpci_request_irq(irq, handler, dev_id); | ||
674 | } | ||
675 | EXPORT_SYMBOL_GPL(request_irq); | ||
676 | |||
677 | void free_irq(unsigned int irq, void *dev_id) | ||
678 | { | ||
679 | zpci_free_irq(irq); | ||
680 | } | ||
681 | EXPORT_SYMBOL_GPL(free_irq); | ||
682 | |||
683 | static int __init zpci_irq_init(void) | 613 | static int __init zpci_irq_init(void) |
684 | { | 614 | { |
685 | int rc; | 615 | int rc; |
@@ -930,15 +860,10 @@ static inline int barsize(u8 size) | |||
930 | 860 | ||
931 | static int zpci_mem_init(void) | 861 | static int zpci_mem_init(void) |
932 | { | 862 | { |
933 | zdev_irq_cache = kmem_cache_create("PCI_IRQ_cache", sizeof(struct zdev_irq_map), | ||
934 | L1_CACHE_BYTES, SLAB_HWCACHE_ALIGN, NULL); | ||
935 | if (!zdev_irq_cache) | ||
936 | goto error_zdev; | ||
937 | |||
938 | zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb), | 863 | zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb), |
939 | 16, 0, NULL); | 864 | 16, 0, NULL); |
940 | if (!zdev_fmb_cache) | 865 | if (!zdev_fmb_cache) |
941 | goto error_fmb; | 866 | goto error_zdev; |
942 | 867 | ||
943 | /* TODO: use realloc */ | 868 | /* TODO: use realloc */ |
944 | zpci_iomap_start = kzalloc(ZPCI_IOMAP_MAX_ENTRIES * sizeof(*zpci_iomap_start), | 869 | zpci_iomap_start = kzalloc(ZPCI_IOMAP_MAX_ENTRIES * sizeof(*zpci_iomap_start), |
@@ -949,8 +874,6 @@ static int zpci_mem_init(void) | |||
949 | 874 | ||
950 | error_iomap: | 875 | error_iomap: |
951 | kmem_cache_destroy(zdev_fmb_cache); | 876 | kmem_cache_destroy(zdev_fmb_cache); |
952 | error_fmb: | ||
953 | kmem_cache_destroy(zdev_irq_cache); | ||
954 | error_zdev: | 877 | error_zdev: |
955 | return -ENOMEM; | 878 | return -ENOMEM; |
956 | } | 879 | } |
@@ -958,7 +881,6 @@ error_zdev: | |||
958 | static void zpci_mem_exit(void) | 881 | static void zpci_mem_exit(void) |
959 | { | 882 | { |
960 | kfree(zpci_iomap_start); | 883 | kfree(zpci_iomap_start); |
961 | kmem_cache_destroy(zdev_irq_cache); | ||
962 | kmem_cache_destroy(zdev_fmb_cache); | 884 | kmem_cache_destroy(zdev_fmb_cache); |
963 | } | 885 | } |
964 | 886 | ||
@@ -1007,16 +929,12 @@ static int __init pci_base_init(void) | |||
1007 | 929 | ||
1008 | rc = zpci_debug_init(); | 930 | rc = zpci_debug_init(); |
1009 | if (rc) | 931 | if (rc) |
1010 | return rc; | 932 | goto out; |
1011 | 933 | ||
1012 | rc = zpci_mem_init(); | 934 | rc = zpci_mem_init(); |
1013 | if (rc) | 935 | if (rc) |
1014 | goto out_mem; | 936 | goto out_mem; |
1015 | 937 | ||
1016 | rc = zpci_msihash_init(); | ||
1017 | if (rc) | ||
1018 | goto out_hash; | ||
1019 | |||
1020 | rc = zpci_irq_init(); | 938 | rc = zpci_irq_init(); |
1021 | if (rc) | 939 | if (rc) |
1022 | goto out_irq; | 940 | goto out_irq; |
@@ -1036,11 +954,10 @@ out_find: | |||
1036 | out_dma: | 954 | out_dma: |
1037 | zpci_irq_exit(); | 955 | zpci_irq_exit(); |
1038 | out_irq: | 956 | out_irq: |
1039 | zpci_msihash_exit(); | ||
1040 | out_hash: | ||
1041 | zpci_mem_exit(); | 957 | zpci_mem_exit(); |
1042 | out_mem: | 958 | out_mem: |
1043 | zpci_debug_exit(); | 959 | zpci_debug_exit(); |
960 | out: | ||
1044 | return rc; | 961 | return rc; |
1045 | } | 962 | } |
1046 | subsys_initcall(pci_base_init); | 963 | subsys_initcall(pci_base_init); |