diff options
44 files changed, 483 insertions, 503 deletions
diff --git a/Documentation/PCI/pcieaer-howto.txt b/Documentation/PCI/pcieaer-howto.txt index b4987c0bcb20..ea8cafba255c 100644 --- a/Documentation/PCI/pcieaer-howto.txt +++ b/Documentation/PCI/pcieaer-howto.txt | |||
@@ -49,25 +49,17 @@ depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and | |||
49 | CONFIG_PCIEAER = y. | 49 | CONFIG_PCIEAER = y. |
50 | 50 | ||
51 | 2.2 Load PCI Express AER Root Driver | 51 | 2.2 Load PCI Express AER Root Driver |
52 | There is a case where a system has AER support in BIOS. Enabling the AER | 52 | |
53 | Root driver and having AER support in BIOS may result unpredictable | 53 | Some systems have AER support in firmware. Enabling Linux AER support at |
54 | behavior. To avoid this conflict, a successful load of the AER Root driver | 54 | the same time the firmware handles AER may result in unpredictable |
55 | requires ACPI _OSC support in the BIOS to allow the AER Root driver to | 55 | behavior. Therefore, Linux does not handle AER events unless the firmware |
56 | request for native control of AER. See the PCI FW 3.0 Specification for | 56 | grants AER control to the OS via the ACPI _OSC method. See the PCI FW 3.0 |
57 | details regarding OSC usage. Currently, lots of firmwares don't provide | 57 | Specification for details regarding _OSC usage. |
58 | _OSC support while they use PCI Express. To support such firmwares, | ||
59 | forceload, a parameter of type bool, could enable AER to continue to | ||
60 | be initiated although firmwares have no _OSC support. To enable the | ||
61 | walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line | ||
62 | when booting kernel. Note that forceload=n by default. | ||
63 | |||
64 | nosourceid, another parameter of type bool, can be used when broken | ||
65 | hardware (mostly chipsets) has root ports that cannot obtain the reporting | ||
66 | source ID. nosourceid=n by default. | ||
67 | 58 | ||
68 | 2.3 AER error output | 59 | 2.3 AER error output |
69 | When a PCI-E AER error is captured, an error message will be outputted to | 60 | |
70 | console. If it's a correctable error, it is outputted as a warning. | 61 | When a PCIe AER error is captured, an error message will be output to |
62 | console. If it's a correctable error, it is output as a warning. | ||
71 | Otherwise, it is printed as an error. So users could choose different | 63 | Otherwise, it is printed as an error. So users could choose different |
72 | log level to filter out correctable error messages. | 64 | log level to filter out correctable error messages. |
73 | 65 | ||
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 9ab7507ca1c2..1411dbed5e5e 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h | |||
@@ -23,6 +23,9 @@ struct pci_sysdata { | |||
23 | #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN | 23 | #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN |
24 | void *fwnode; /* IRQ domain for MSI assignment */ | 24 | void *fwnode; /* IRQ domain for MSI assignment */ |
25 | #endif | 25 | #endif |
26 | #if IS_ENABLED(CONFIG_VMD) | ||
27 | bool vmd_domain; /* True if in Intel VMD domain */ | ||
28 | #endif | ||
26 | }; | 29 | }; |
27 | 30 | ||
28 | extern int pci_routeirq; | 31 | extern int pci_routeirq; |
@@ -56,6 +59,17 @@ static inline void *_pci_root_bus_fwnode(struct pci_bus *bus) | |||
56 | #define pci_root_bus_fwnode _pci_root_bus_fwnode | 59 | #define pci_root_bus_fwnode _pci_root_bus_fwnode |
57 | #endif | 60 | #endif |
58 | 61 | ||
62 | static inline bool is_vmd(struct pci_bus *bus) | ||
63 | { | ||
64 | #if IS_ENABLED(CONFIG_VMD) | ||
65 | struct pci_sysdata *sd = bus->sysdata; | ||
66 | |||
67 | return sd->vmd_domain; | ||
68 | #else | ||
69 | return false; | ||
70 | #endif | ||
71 | } | ||
72 | |||
59 | /* Can be used to override the logic in pci_scan_bus for skipping | 73 | /* Can be used to override the logic in pci_scan_bus for skipping |
60 | already-configured bus numbers - to be used for buggy BIOSes | 74 | already-configured bus numbers - to be used for buggy BIOSes |
61 | or architectures with incomplete PCI setup by the loader */ | 75 | or architectures with incomplete PCI setup by the loader */ |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 7b6a9d14c8c0..a4fdfa7dcc1b 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
@@ -677,6 +677,12 @@ static void set_dma_domain_ops(struct pci_dev *pdev) | |||
677 | static void set_dma_domain_ops(struct pci_dev *pdev) {} | 677 | static void set_dma_domain_ops(struct pci_dev *pdev) {} |
678 | #endif | 678 | #endif |
679 | 679 | ||
680 | static void set_dev_domain_options(struct pci_dev *pdev) | ||
681 | { | ||
682 | if (is_vmd(pdev->bus)) | ||
683 | pdev->hotplug_user_indicators = 1; | ||
684 | } | ||
685 | |||
680 | int pcibios_add_device(struct pci_dev *dev) | 686 | int pcibios_add_device(struct pci_dev *dev) |
681 | { | 687 | { |
682 | struct setup_data *data; | 688 | struct setup_data *data; |
@@ -707,6 +713,7 @@ int pcibios_add_device(struct pci_dev *dev) | |||
707 | iounmap(data); | 713 | iounmap(data); |
708 | } | 714 | } |
709 | set_dma_domain_ops(dev); | 715 | set_dma_domain_ops(dev); |
716 | set_dev_domain_options(dev); | ||
710 | return 0; | 717 | return 0; |
711 | } | 718 | } |
712 | 719 | ||
diff --git a/arch/x86/pci/vmd.c b/arch/x86/pci/vmd.c index b814ca675131..a021b7b0eb69 100644 --- a/arch/x86/pci/vmd.c +++ b/arch/x86/pci/vmd.c | |||
@@ -596,6 +596,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd) | |||
596 | .parent = res, | 596 | .parent = res, |
597 | }; | 597 | }; |
598 | 598 | ||
599 | sd->vmd_domain = true; | ||
599 | sd->domain = vmd_find_free_domain(); | 600 | sd->domain = vmd_find_free_domain(); |
600 | if (sd->domain < 0) | 601 | if (sd->domain < 0) |
601 | return sd->domain; | 602 | return sd->domain; |
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 60746ef904e4..f0a029e68d3e 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c | |||
@@ -457,7 +457,7 @@ static void ghes_do_proc(struct ghes *ghes, | |||
457 | 457 | ||
458 | devfn = PCI_DEVFN(pcie_err->device_id.device, | 458 | devfn = PCI_DEVFN(pcie_err->device_id.device, |
459 | pcie_err->device_id.function); | 459 | pcie_err->device_id.function); |
460 | aer_severity = cper_severity_to_aer(sev); | 460 | aer_severity = cper_severity_to_aer(gdata->error_severity); |
461 | 461 | ||
462 | /* | 462 | /* |
463 | * If firmware reset the component to contain | 463 | * If firmware reset the component to contain |
diff --git a/drivers/pci/host/pci-aardvark.c b/drivers/pci/host/pci-aardvark.c index ef9893fa3176..4f5e567fd7e0 100644 --- a/drivers/pci/host/pci-aardvark.c +++ b/drivers/pci/host/pci-aardvark.c | |||
@@ -848,7 +848,7 @@ static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie) | |||
848 | int err, res_valid = 0; | 848 | int err, res_valid = 0; |
849 | struct device *dev = &pcie->pdev->dev; | 849 | struct device *dev = &pcie->pdev->dev; |
850 | struct device_node *np = dev->of_node; | 850 | struct device_node *np = dev->of_node; |
851 | struct resource_entry *win; | 851 | struct resource_entry *win, *tmp; |
852 | resource_size_t iobase; | 852 | resource_size_t iobase; |
853 | 853 | ||
854 | INIT_LIST_HEAD(&pcie->resources); | 854 | INIT_LIST_HEAD(&pcie->resources); |
@@ -862,7 +862,7 @@ static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie) | |||
862 | if (err) | 862 | if (err) |
863 | goto out_release_res; | 863 | goto out_release_res; |
864 | 864 | ||
865 | resource_list_for_each_entry(win, &pcie->resources) { | 865 | resource_list_for_each_entry_safe(win, tmp, &pcie->resources) { |
866 | struct resource *res = win->res; | 866 | struct resource *res = win->res; |
867 | 867 | ||
868 | switch (resource_type(res)) { | 868 | switch (resource_type(res)) { |
@@ -874,9 +874,11 @@ static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie) | |||
874 | lower_32_bits(res->start), | 874 | lower_32_bits(res->start), |
875 | OB_PCIE_IO); | 875 | OB_PCIE_IO); |
876 | err = pci_remap_iospace(res, iobase); | 876 | err = pci_remap_iospace(res, iobase); |
877 | if (err) | 877 | if (err) { |
878 | dev_warn(dev, "error %d: failed to map resource %pR\n", | 878 | dev_warn(dev, "error %d: failed to map resource %pR\n", |
879 | err, res); | 879 | err, res); |
880 | resource_list_destroy_entry(win); | ||
881 | } | ||
880 | break; | 882 | break; |
881 | case IORESOURCE_MEM: | 883 | case IORESOURCE_MEM: |
882 | advk_pcie_set_ob_win(pcie, 0, | 884 | advk_pcie_set_ob_win(pcie, 0, |
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c index 81b3949a26db..19223ed2e619 100644 --- a/drivers/pci/host/pci-dra7xx.c +++ b/drivers/pci/host/pci-dra7xx.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
16 | #include <linux/irqdomain.h> | 16 | #include <linux/irqdomain.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | 18 | #include <linux/init.h> |
19 | #include <linux/of_gpio.h> | 19 | #include <linux/of_gpio.h> |
20 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
21 | #include <linux/phy/phy.h> | 21 | #include <linux/phy/phy.h> |
@@ -443,25 +443,6 @@ err_phy: | |||
443 | return ret; | 443 | return ret; |
444 | } | 444 | } |
445 | 445 | ||
446 | static int __exit dra7xx_pcie_remove(struct platform_device *pdev) | ||
447 | { | ||
448 | struct dra7xx_pcie *dra7xx = platform_get_drvdata(pdev); | ||
449 | struct pcie_port *pp = &dra7xx->pp; | ||
450 | struct device *dev = &pdev->dev; | ||
451 | int count = dra7xx->phy_count; | ||
452 | |||
453 | if (pp->irq_domain) | ||
454 | irq_domain_remove(pp->irq_domain); | ||
455 | pm_runtime_put(dev); | ||
456 | pm_runtime_disable(dev); | ||
457 | while (count--) { | ||
458 | phy_power_off(dra7xx->phy[count]); | ||
459 | phy_exit(dra7xx->phy[count]); | ||
460 | } | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | #ifdef CONFIG_PM_SLEEP | 446 | #ifdef CONFIG_PM_SLEEP |
466 | static int dra7xx_pcie_suspend(struct device *dev) | 447 | static int dra7xx_pcie_suspend(struct device *dev) |
467 | { | 448 | { |
@@ -545,19 +526,13 @@ static const struct of_device_id of_dra7xx_pcie_match[] = { | |||
545 | { .compatible = "ti,dra7-pcie", }, | 526 | { .compatible = "ti,dra7-pcie", }, |
546 | {}, | 527 | {}, |
547 | }; | 528 | }; |
548 | MODULE_DEVICE_TABLE(of, of_dra7xx_pcie_match); | ||
549 | 529 | ||
550 | static struct platform_driver dra7xx_pcie_driver = { | 530 | static struct platform_driver dra7xx_pcie_driver = { |
551 | .remove = __exit_p(dra7xx_pcie_remove), | ||
552 | .driver = { | 531 | .driver = { |
553 | .name = "dra7-pcie", | 532 | .name = "dra7-pcie", |
554 | .of_match_table = of_dra7xx_pcie_match, | 533 | .of_match_table = of_dra7xx_pcie_match, |
534 | .suppress_bind_attrs = true, | ||
555 | .pm = &dra7xx_pcie_pm_ops, | 535 | .pm = &dra7xx_pcie_pm_ops, |
556 | }, | 536 | }, |
557 | }; | 537 | }; |
558 | 538 | builtin_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe); | |
559 | module_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe); | ||
560 | |||
561 | MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); | ||
562 | MODULE_DESCRIPTION("TI PCIe controller driver"); | ||
563 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index 219976103efc..c3ae9c7a6e33 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/host/pci-exynos.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/module.h> | 19 | #include <linux/init.h> |
20 | #include <linux/of_gpio.h> | 20 | #include <linux/of_gpio.h> |
21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
@@ -624,7 +624,6 @@ static const struct of_device_id exynos_pcie_of_match[] = { | |||
624 | { .compatible = "samsung,exynos5440-pcie", }, | 624 | { .compatible = "samsung,exynos5440-pcie", }, |
625 | {}, | 625 | {}, |
626 | }; | 626 | }; |
627 | MODULE_DEVICE_TABLE(of, exynos_pcie_of_match); | ||
628 | 627 | ||
629 | static struct platform_driver exynos_pcie_driver = { | 628 | static struct platform_driver exynos_pcie_driver = { |
630 | .remove = __exit_p(exynos_pcie_remove), | 629 | .remove = __exit_p(exynos_pcie_remove), |
@@ -641,7 +640,3 @@ static int __init exynos_pcie_init(void) | |||
641 | return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe); | 640 | return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe); |
642 | } | 641 | } |
643 | subsys_initcall(exynos_pcie_init); | 642 | subsys_initcall(exynos_pcie_init); |
644 | |||
645 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); | ||
646 | MODULE_DESCRIPTION("Samsung PCIe host controller driver"); | ||
647 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c index 9d9d34e959b6..e3c48b5deb93 100644 --- a/drivers/pci/host/pci-host-common.c +++ b/drivers/pci/host/pci-host-common.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Generic PCI host driver common code | ||
3 | * | ||
2 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
3 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
4 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
@@ -17,7 +19,6 @@ | |||
17 | */ | 19 | */ |
18 | 20 | ||
19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | ||
21 | #include <linux/of_address.h> | 22 | #include <linux/of_address.h> |
22 | #include <linux/of_pci.h> | 23 | #include <linux/of_pci.h> |
23 | #include <linux/pci-ecam.h> | 24 | #include <linux/pci-ecam.h> |
@@ -29,7 +30,7 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev, | |||
29 | int err, res_valid = 0; | 30 | int err, res_valid = 0; |
30 | struct device_node *np = dev->of_node; | 31 | struct device_node *np = dev->of_node; |
31 | resource_size_t iobase; | 32 | resource_size_t iobase; |
32 | struct resource_entry *win; | 33 | struct resource_entry *win, *tmp; |
33 | 34 | ||
34 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase); | 35 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase); |
35 | if (err) | 36 | if (err) |
@@ -39,15 +40,17 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev, | |||
39 | if (err) | 40 | if (err) |
40 | return err; | 41 | return err; |
41 | 42 | ||
42 | resource_list_for_each_entry(win, resources) { | 43 | resource_list_for_each_entry_safe(win, tmp, resources) { |
43 | struct resource *res = win->res; | 44 | struct resource *res = win->res; |
44 | 45 | ||
45 | switch (resource_type(res)) { | 46 | switch (resource_type(res)) { |
46 | case IORESOURCE_IO: | 47 | case IORESOURCE_IO: |
47 | err = pci_remap_iospace(res, iobase); | 48 | err = pci_remap_iospace(res, iobase); |
48 | if (err) | 49 | if (err) { |
49 | dev_warn(dev, "error %d: failed to map resource %pR\n", | 50 | dev_warn(dev, "error %d: failed to map resource %pR\n", |
50 | err, res); | 51 | err, res); |
52 | resource_list_destroy_entry(win); | ||
53 | } | ||
51 | break; | 54 | break; |
52 | case IORESOURCE_MEM: | 55 | case IORESOURCE_MEM: |
53 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); | 56 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); |
@@ -162,7 +165,3 @@ int pci_host_common_probe(struct platform_device *pdev, | |||
162 | pci_bus_add_devices(bus); | 165 | pci_bus_add_devices(bus); |
163 | return 0; | 166 | return 0; |
164 | } | 167 | } |
165 | |||
166 | MODULE_DESCRIPTION("Generic PCI host driver common code"); | ||
167 | MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>"); | ||
168 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index b741a36a67f3..ead4a5c3480b 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c | |||
@@ -739,7 +739,6 @@ static const struct of_device_id imx6_pcie_of_match[] = { | |||
739 | { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, }, | 739 | { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, }, |
740 | {}, | 740 | {}, |
741 | }; | 741 | }; |
742 | MODULE_DEVICE_TABLE(of, imx6_pcie_of_match); | ||
743 | 742 | ||
744 | static struct platform_driver imx6_pcie_driver = { | 743 | static struct platform_driver imx6_pcie_driver = { |
745 | .driver = { | 744 | .driver = { |
@@ -749,14 +748,8 @@ static struct platform_driver imx6_pcie_driver = { | |||
749 | .shutdown = imx6_pcie_shutdown, | 748 | .shutdown = imx6_pcie_shutdown, |
750 | }; | 749 | }; |
751 | 750 | ||
752 | /* Freescale PCIe driver does not allow module unload */ | ||
753 | |||
754 | static int __init imx6_pcie_init(void) | 751 | static int __init imx6_pcie_init(void) |
755 | { | 752 | { |
756 | return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe); | 753 | return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe); |
757 | } | 754 | } |
758 | module_init(imx6_pcie_init); | 755 | device_initcall(imx6_pcie_init); |
759 | |||
760 | MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>"); | ||
761 | MODULE_DESCRIPTION("Freescale i.MX6 PCIe host controller driver"); | ||
762 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 6de0757b11e4..8c2590db609b 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
@@ -621,7 +621,11 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) | |||
621 | if (err < 0) | 621 | if (err < 0) |
622 | return err; | 622 | return err; |
623 | 623 | ||
624 | pci_add_resource_offset(&sys->resources, &pcie->pio, sys->io_offset); | 624 | err = pci_remap_iospace(&pcie->pio, pcie->io.start); |
625 | if (!err) | ||
626 | pci_add_resource_offset(&sys->resources, &pcie->pio, | ||
627 | sys->io_offset); | ||
628 | |||
625 | pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); | 629 | pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); |
626 | pci_add_resource_offset(&sys->resources, &pcie->prefetch, | 630 | pci_add_resource_offset(&sys->resources, &pcie->prefetch, |
627 | sys->mem_offset); | 631 | sys->mem_offset); |
@@ -631,7 +635,6 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) | |||
631 | if (err < 0) | 635 | if (err < 0) |
632 | return err; | 636 | return err; |
633 | 637 | ||
634 | pci_remap_iospace(&pcie->pio, pcie->io.start); | ||
635 | return 1; | 638 | return 1; |
636 | } | 639 | } |
637 | 640 | ||
diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/host/pci-versatile.c index f234405770ab..b7dc07002f13 100644 --- a/drivers/pci/host/pci-versatile.c +++ b/drivers/pci/host/pci-versatile.c | |||
@@ -74,7 +74,7 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev, | |||
74 | int err, mem = 1, res_valid = 0; | 74 | int err, mem = 1, res_valid = 0; |
75 | struct device_node *np = dev->of_node; | 75 | struct device_node *np = dev->of_node; |
76 | resource_size_t iobase; | 76 | resource_size_t iobase; |
77 | struct resource_entry *win; | 77 | struct resource_entry *win, *tmp; |
78 | 78 | ||
79 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, res, &iobase); | 79 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, res, &iobase); |
80 | if (err) | 80 | if (err) |
@@ -84,15 +84,17 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev, | |||
84 | if (err) | 84 | if (err) |
85 | goto out_release_res; | 85 | goto out_release_res; |
86 | 86 | ||
87 | resource_list_for_each_entry(win, res) { | 87 | resource_list_for_each_entry_safe(win, tmp, res) { |
88 | struct resource *res = win->res; | 88 | struct resource *res = win->res; |
89 | 89 | ||
90 | switch (resource_type(res)) { | 90 | switch (resource_type(res)) { |
91 | case IORESOURCE_IO: | 91 | case IORESOURCE_IO: |
92 | err = pci_remap_iospace(res, iobase); | 92 | err = pci_remap_iospace(res, iobase); |
93 | if (err) | 93 | if (err) { |
94 | dev_warn(dev, "error %d: failed to map resource %pR\n", | 94 | dev_warn(dev, "error %d: failed to map resource %pR\n", |
95 | err, res); | 95 | err, res); |
96 | resource_list_destroy_entry(win); | ||
97 | } | ||
96 | break; | 98 | break; |
97 | case IORESOURCE_MEM: | 99 | case IORESOURCE_MEM: |
98 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); | 100 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); |
diff --git a/drivers/pci/host/pcie-altera-msi.c b/drivers/pci/host/pcie-altera-msi.c index 99177f4ccde2..369e033449c6 100644 --- a/drivers/pci/host/pcie-altera-msi.c +++ b/drivers/pci/host/pcie-altera-msi.c | |||
@@ -1,4 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Altera PCIe MSI support | ||
3 | * | ||
4 | * Author: Ley Foon Tan <lftan@altera.com> | ||
5 | * | ||
2 | * Copyright Altera Corporation (C) 2013-2015. All rights reserved | 6 | * Copyright Altera Corporation (C) 2013-2015. All rights reserved |
3 | * | 7 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
@@ -16,7 +20,7 @@ | |||
16 | 20 | ||
17 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
18 | #include <linux/irqchip/chained_irq.h> | 22 | #include <linux/irqchip/chained_irq.h> |
19 | #include <linux/module.h> | 23 | #include <linux/init.h> |
20 | #include <linux/msi.h> | 24 | #include <linux/msi.h> |
21 | #include <linux/of_address.h> | 25 | #include <linux/of_address.h> |
22 | #include <linux/of_irq.h> | 26 | #include <linux/of_irq.h> |
@@ -308,7 +312,3 @@ static int __init altera_msi_init(void) | |||
308 | return platform_driver_register(&altera_msi_driver); | 312 | return platform_driver_register(&altera_msi_driver); |
309 | } | 313 | } |
310 | subsys_initcall(altera_msi_init); | 314 | subsys_initcall(altera_msi_init); |
311 | |||
312 | MODULE_AUTHOR("Ley Foon Tan <lftan@altera.com>"); | ||
313 | MODULE_DESCRIPTION("Altera PCIe MSI support"); | ||
314 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c index 2b7837650db8..48f2736a10cd 100644 --- a/drivers/pci/host/pcie-altera.c +++ b/drivers/pci/host/pcie-altera.c | |||
@@ -1,6 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright Altera Corporation (C) 2013-2015. All rights reserved | 2 | * Copyright Altera Corporation (C) 2013-2015. All rights reserved |
3 | * | 3 | * |
4 | * Author: Ley Foon Tan <lftan@altera.com> | ||
5 | * Description: Altera PCIe host controller driver | ||
6 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms and conditions of the GNU General Public License, | 8 | * under the terms and conditions of the GNU General Public License, |
6 | * version 2, as published by the Free Software Foundation. | 9 | * version 2, as published by the Free Software Foundation. |
@@ -17,7 +20,7 @@ | |||
17 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
18 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
19 | #include <linux/irqchip/chained_irq.h> | 22 | #include <linux/irqchip/chained_irq.h> |
20 | #include <linux/module.h> | 23 | #include <linux/init.h> |
21 | #include <linux/of_address.h> | 24 | #include <linux/of_address.h> |
22 | #include <linux/of_irq.h> | 25 | #include <linux/of_irq.h> |
23 | #include <linux/of_pci.h> | 26 | #include <linux/of_pci.h> |
@@ -568,7 +571,6 @@ static const struct of_device_id altera_pcie_of_match[] = { | |||
568 | { .compatible = "altr,pcie-root-port-1.0", }, | 571 | { .compatible = "altr,pcie-root-port-1.0", }, |
569 | {}, | 572 | {}, |
570 | }; | 573 | }; |
571 | MODULE_DEVICE_TABLE(of, altera_pcie_of_match); | ||
572 | 574 | ||
573 | static struct platform_driver altera_pcie_driver = { | 575 | static struct platform_driver altera_pcie_driver = { |
574 | .probe = altera_pcie_probe, | 576 | .probe = altera_pcie_probe, |
@@ -583,8 +585,4 @@ static int altera_pcie_init(void) | |||
583 | { | 585 | { |
584 | return platform_driver_register(&altera_pcie_driver); | 586 | return platform_driver_register(&altera_pcie_driver); |
585 | } | 587 | } |
586 | module_init(altera_pcie_init); | 588 | device_initcall(altera_pcie_init); |
587 | |||
588 | MODULE_AUTHOR("Ley Foon Tan <lftan@altera.com>"); | ||
589 | MODULE_DESCRIPTION("Altera PCIe host controller driver"); | ||
590 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 12afce19890b..ee64f9755ea6 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
15 | #include <linux/irqdomain.h> | 15 | #include <linux/irqdomain.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | ||
18 | #include <linux/msi.h> | 17 | #include <linux/msi.h> |
19 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
20 | #include <linux/of_pci.h> | 19 | #include <linux/of_pci.h> |
@@ -436,7 +435,7 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
436 | struct resource *cfg_res; | 435 | struct resource *cfg_res; |
437 | int i, ret; | 436 | int i, ret; |
438 | LIST_HEAD(res); | 437 | LIST_HEAD(res); |
439 | struct resource_entry *win; | 438 | struct resource_entry *win, *tmp; |
440 | 439 | ||
441 | cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); | 440 | cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); |
442 | if (cfg_res) { | 441 | if (cfg_res) { |
@@ -457,17 +456,20 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
457 | goto error; | 456 | goto error; |
458 | 457 | ||
459 | /* Get the I/O and memory ranges from DT */ | 458 | /* Get the I/O and memory ranges from DT */ |
460 | resource_list_for_each_entry(win, &res) { | 459 | resource_list_for_each_entry_safe(win, tmp, &res) { |
461 | switch (resource_type(win->res)) { | 460 | switch (resource_type(win->res)) { |
462 | case IORESOURCE_IO: | 461 | case IORESOURCE_IO: |
463 | pp->io = win->res; | 462 | ret = pci_remap_iospace(win->res, pp->io_base); |
464 | pp->io->name = "I/O"; | 463 | if (ret) { |
465 | pp->io_size = resource_size(pp->io); | ||
466 | pp->io_bus_addr = pp->io->start - win->offset; | ||
467 | ret = pci_remap_iospace(pp->io, pp->io_base); | ||
468 | if (ret) | ||
469 | dev_warn(pp->dev, "error %d: failed to map resource %pR\n", | 464 | dev_warn(pp->dev, "error %d: failed to map resource %pR\n", |
470 | ret, pp->io); | 465 | ret, win->res); |
466 | resource_list_destroy_entry(win); | ||
467 | } else { | ||
468 | pp->io = win->res; | ||
469 | pp->io->name = "I/O"; | ||
470 | pp->io_size = resource_size(pp->io); | ||
471 | pp->io_bus_addr = pp->io->start - win->offset; | ||
472 | } | ||
471 | break; | 473 | break; |
472 | case IORESOURCE_MEM: | 474 | case IORESOURCE_MEM: |
473 | pp->mem = win->res; | 475 | pp->mem = win->res; |
@@ -802,7 +804,3 @@ void dw_pcie_setup_rc(struct pcie_port *pp) | |||
802 | val |= PORT_LOGIC_SPEED_CHANGE; | 804 | val |= PORT_LOGIC_SPEED_CHANGE; |
803 | dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); | 805 | dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); |
804 | } | 806 | } |
805 | |||
806 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); | ||
807 | MODULE_DESCRIPTION("Designware PCIe host controller driver"); | ||
808 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-qcom.c b/drivers/pci/host/pcie-qcom.c index f2f90c50f75d..5ec2d440a6b7 100644 --- a/drivers/pci/host/pcie-qcom.c +++ b/drivers/pci/host/pcie-qcom.c | |||
@@ -1,7 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Qualcomm PCIe root complex driver | ||
3 | * | ||
2 | * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. | 4 | * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. |
3 | * Copyright 2015 Linaro Limited. | 5 | * Copyright 2015 Linaro Limited. |
4 | * | 6 | * |
7 | * Author: Stanimir Varbanov <svarbanov@mm-sol.com> | ||
8 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 and | 10 | * it under the terms of the GNU General Public License version 2 and |
7 | * only version 2 as published by the Free Software Foundation. | 11 | * only version 2 as published by the Free Software Foundation. |
@@ -19,7 +23,7 @@ | |||
19 | #include <linux/io.h> | 23 | #include <linux/io.h> |
20 | #include <linux/iopoll.h> | 24 | #include <linux/iopoll.h> |
21 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
22 | #include <linux/module.h> | 26 | #include <linux/init.h> |
23 | #include <linux/of_device.h> | 27 | #include <linux/of_device.h> |
24 | #include <linux/of_gpio.h> | 28 | #include <linux/of_gpio.h> |
25 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
@@ -570,37 +574,19 @@ static int qcom_pcie_probe(struct platform_device *pdev) | |||
570 | return 0; | 574 | return 0; |
571 | } | 575 | } |
572 | 576 | ||
573 | static int qcom_pcie_remove(struct platform_device *pdev) | ||
574 | { | ||
575 | struct qcom_pcie *pcie = platform_get_drvdata(pdev); | ||
576 | |||
577 | qcom_ep_reset_assert(pcie); | ||
578 | phy_power_off(pcie->phy); | ||
579 | phy_exit(pcie->phy); | ||
580 | pcie->ops->deinit(pcie); | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | static const struct of_device_id qcom_pcie_match[] = { | 577 | static const struct of_device_id qcom_pcie_match[] = { |
586 | { .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 }, | 578 | { .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 }, |
587 | { .compatible = "qcom,pcie-apq8064", .data = &ops_v0 }, | 579 | { .compatible = "qcom,pcie-apq8064", .data = &ops_v0 }, |
588 | { .compatible = "qcom,pcie-apq8084", .data = &ops_v1 }, | 580 | { .compatible = "qcom,pcie-apq8084", .data = &ops_v1 }, |
589 | { } | 581 | { } |
590 | }; | 582 | }; |
591 | MODULE_DEVICE_TABLE(of, qcom_pcie_match); | ||
592 | 583 | ||
593 | static struct platform_driver qcom_pcie_driver = { | 584 | static struct platform_driver qcom_pcie_driver = { |
594 | .probe = qcom_pcie_probe, | 585 | .probe = qcom_pcie_probe, |
595 | .remove = qcom_pcie_remove, | ||
596 | .driver = { | 586 | .driver = { |
597 | .name = "qcom-pcie", | 587 | .name = "qcom-pcie", |
588 | .suppress_bind_attrs = true, | ||
598 | .of_match_table = qcom_pcie_match, | 589 | .of_match_table = qcom_pcie_match, |
599 | }, | 590 | }, |
600 | }; | 591 | }; |
601 | 592 | builtin_platform_driver(qcom_pcie_driver); | |
602 | module_platform_driver(qcom_pcie_driver); | ||
603 | |||
604 | MODULE_AUTHOR("Stanimir Varbanov <svarbanov@mm-sol.com>"); | ||
605 | MODULE_DESCRIPTION("Qualcomm PCIe root complex driver"); | ||
606 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 65db7a221509..5f7fcc971cae 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c | |||
@@ -945,7 +945,7 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) | |||
945 | struct device *dev = pci->dev; | 945 | struct device *dev = pci->dev; |
946 | struct device_node *np = dev->of_node; | 946 | struct device_node *np = dev->of_node; |
947 | resource_size_t iobase; | 947 | resource_size_t iobase; |
948 | struct resource_entry *win; | 948 | struct resource_entry *win, *tmp; |
949 | 949 | ||
950 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, &iobase); | 950 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, &iobase); |
951 | if (err) | 951 | if (err) |
@@ -955,14 +955,17 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) | |||
955 | if (err) | 955 | if (err) |
956 | goto out_release_res; | 956 | goto out_release_res; |
957 | 957 | ||
958 | resource_list_for_each_entry(win, &pci->resources) { | 958 | resource_list_for_each_entry_safe(win, tmp, &pci->resources) { |
959 | struct resource *res = win->res; | 959 | struct resource *res = win->res; |
960 | 960 | ||
961 | if (resource_type(res) == IORESOURCE_IO) { | 961 | if (resource_type(res) == IORESOURCE_IO) { |
962 | err = pci_remap_iospace(res, iobase); | 962 | err = pci_remap_iospace(res, iobase); |
963 | if (err) | 963 | if (err) { |
964 | dev_warn(dev, "error %d: failed to map resource %pR\n", | 964 | dev_warn(dev, "error %d: failed to map resource %pR\n", |
965 | err, res); | 965 | err, res); |
966 | |||
967 | resource_list_destroy_entry(win); | ||
968 | } | ||
966 | } | 969 | } |
967 | } | 970 | } |
968 | 971 | ||
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c index a4060b85ab23..09aed85f275a 100644 --- a/drivers/pci/host/pcie-spear13xx.c +++ b/drivers/pci/host/pcie-spear13xx.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | 18 | #include <linux/init.h> |
19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
21 | #include <linux/phy/phy.h> | 21 | #include <linux/phy/phy.h> |
@@ -355,7 +355,6 @@ static const struct of_device_id spear13xx_pcie_of_match[] = { | |||
355 | { .compatible = "st,spear1340-pcie", }, | 355 | { .compatible = "st,spear1340-pcie", }, |
356 | {}, | 356 | {}, |
357 | }; | 357 | }; |
358 | MODULE_DEVICE_TABLE(of, spear13xx_pcie_of_match); | ||
359 | 358 | ||
360 | static struct platform_driver spear13xx_pcie_driver = { | 359 | static struct platform_driver spear13xx_pcie_driver = { |
361 | .probe = spear13xx_pcie_probe, | 360 | .probe = spear13xx_pcie_probe, |
@@ -365,14 +364,8 @@ static struct platform_driver spear13xx_pcie_driver = { | |||
365 | }, | 364 | }, |
366 | }; | 365 | }; |
367 | 366 | ||
368 | /* SPEAr13xx PCIe driver does not allow module unload */ | ||
369 | |||
370 | static int __init spear13xx_pcie_init(void) | 367 | static int __init spear13xx_pcie_init(void) |
371 | { | 368 | { |
372 | return platform_driver_register(&spear13xx_pcie_driver); | 369 | return platform_driver_register(&spear13xx_pcie_driver); |
373 | } | 370 | } |
374 | module_init(spear13xx_pcie_init); | 371 | device_initcall(spear13xx_pcie_init); |
375 | |||
376 | MODULE_DESCRIPTION("ST Microelectronics SPEAr13xx PCIe host controller driver"); | ||
377 | MODULE_AUTHOR("Pratyush Anand <pratyush.anand@gmail.com>"); | ||
378 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/host/pcie-xilinx-nwl.c index 0b597d9190b4..df7fb8b69658 100644 --- a/drivers/pci/host/pcie-xilinx-nwl.c +++ b/drivers/pci/host/pcie-xilinx-nwl.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
16 | #include <linux/irqdomain.h> | 16 | #include <linux/irqdomain.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | 18 | #include <linux/init.h> |
19 | #include <linux/msi.h> | 19 | #include <linux/msi.h> |
20 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
21 | #include <linux/of_pci.h> | 21 | #include <linux/of_pci.h> |
@@ -459,40 +459,6 @@ static const struct irq_domain_ops dev_msi_domain_ops = { | |||
459 | .free = nwl_irq_domain_free, | 459 | .free = nwl_irq_domain_free, |
460 | }; | 460 | }; |
461 | 461 | ||
462 | static void nwl_msi_free_irq_domain(struct nwl_pcie *pcie) | ||
463 | { | ||
464 | struct nwl_msi *msi = &pcie->msi; | ||
465 | |||
466 | if (msi->irq_msi0) | ||
467 | irq_set_chained_handler_and_data(msi->irq_msi0, NULL, NULL); | ||
468 | if (msi->irq_msi1) | ||
469 | irq_set_chained_handler_and_data(msi->irq_msi1, NULL, NULL); | ||
470 | |||
471 | if (msi->msi_domain) | ||
472 | irq_domain_remove(msi->msi_domain); | ||
473 | if (msi->dev_domain) | ||
474 | irq_domain_remove(msi->dev_domain); | ||
475 | |||
476 | kfree(msi->bitmap); | ||
477 | msi->bitmap = NULL; | ||
478 | } | ||
479 | |||
480 | static void nwl_pcie_free_irq_domain(struct nwl_pcie *pcie) | ||
481 | { | ||
482 | int i; | ||
483 | u32 irq; | ||
484 | |||
485 | for (i = 0; i < INTX_NUM; i++) { | ||
486 | irq = irq_find_mapping(pcie->legacy_irq_domain, i + 1); | ||
487 | if (irq > 0) | ||
488 | irq_dispose_mapping(irq); | ||
489 | } | ||
490 | if (pcie->legacy_irq_domain) | ||
491 | irq_domain_remove(pcie->legacy_irq_domain); | ||
492 | |||
493 | nwl_msi_free_irq_domain(pcie); | ||
494 | } | ||
495 | |||
496 | static int nwl_pcie_init_msi_irq_domain(struct nwl_pcie *pcie) | 462 | static int nwl_pcie_init_msi_irq_domain(struct nwl_pcie *pcie) |
497 | { | 463 | { |
498 | #ifdef CONFIG_PCI_MSI | 464 | #ifdef CONFIG_PCI_MSI |
@@ -867,25 +833,12 @@ error: | |||
867 | return err; | 833 | return err; |
868 | } | 834 | } |
869 | 835 | ||
870 | static int nwl_pcie_remove(struct platform_device *pdev) | ||
871 | { | ||
872 | struct nwl_pcie *pcie = platform_get_drvdata(pdev); | ||
873 | |||
874 | nwl_pcie_free_irq_domain(pcie); | ||
875 | platform_set_drvdata(pdev, NULL); | ||
876 | return 0; | ||
877 | } | ||
878 | |||
879 | static struct platform_driver nwl_pcie_driver = { | 836 | static struct platform_driver nwl_pcie_driver = { |
880 | .driver = { | 837 | .driver = { |
881 | .name = "nwl-pcie", | 838 | .name = "nwl-pcie", |
839 | .suppress_bind_attrs = true, | ||
882 | .of_match_table = nwl_pcie_of_match, | 840 | .of_match_table = nwl_pcie_of_match, |
883 | }, | 841 | }, |
884 | .probe = nwl_pcie_probe, | 842 | .probe = nwl_pcie_probe, |
885 | .remove = nwl_pcie_remove, | ||
886 | }; | 843 | }; |
887 | module_platform_driver(nwl_pcie_driver); | 844 | builtin_platform_driver(nwl_pcie_driver); |
888 | |||
889 | MODULE_AUTHOR("Xilinx, Inc"); | ||
890 | MODULE_DESCRIPTION("NWL PCIe driver"); | ||
891 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c index a30e01639557..7b7dbd22bccc 100644 --- a/drivers/pci/host/pcie-xilinx.c +++ b/drivers/pci/host/pcie-xilinx.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <linux/irqdomain.h> | 19 | #include <linux/irqdomain.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/module.h> | 21 | #include <linux/init.h> |
22 | #include <linux/msi.h> | 22 | #include <linux/msi.h> |
23 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
24 | #include <linux/of_pci.h> | 24 | #include <linux/of_pci.h> |
@@ -506,35 +506,6 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data) | |||
506 | } | 506 | } |
507 | 507 | ||
508 | /** | 508 | /** |
509 | * xilinx_pcie_free_irq_domain - Free IRQ domain | ||
510 | * @port: PCIe port information | ||
511 | */ | ||
512 | static void xilinx_pcie_free_irq_domain(struct xilinx_pcie_port *port) | ||
513 | { | ||
514 | int i; | ||
515 | u32 irq, num_irqs; | ||
516 | |||
517 | /* Free IRQ Domain */ | ||
518 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | ||
519 | |||
520 | free_pages(port->msi_pages, 0); | ||
521 | |||
522 | num_irqs = XILINX_NUM_MSI_IRQS; | ||
523 | } else { | ||
524 | /* INTx */ | ||
525 | num_irqs = 4; | ||
526 | } | ||
527 | |||
528 | for (i = 0; i < num_irqs; i++) { | ||
529 | irq = irq_find_mapping(port->irq_domain, i); | ||
530 | if (irq > 0) | ||
531 | irq_dispose_mapping(irq); | ||
532 | } | ||
533 | |||
534 | irq_domain_remove(port->irq_domain); | ||
535 | } | ||
536 | |||
537 | /** | ||
538 | * xilinx_pcie_init_irq_domain - Initialize IRQ domain | 509 | * xilinx_pcie_init_irq_domain - Initialize IRQ domain |
539 | * @port: PCIe port information | 510 | * @port: PCIe port information |
540 | * | 511 | * |
@@ -724,21 +695,6 @@ error: | |||
724 | return err; | 695 | return err; |
725 | } | 696 | } |
726 | 697 | ||
727 | /** | ||
728 | * xilinx_pcie_remove - Remove function | ||
729 | * @pdev: Platform device pointer | ||
730 | * | ||
731 | * Return: '0' always | ||
732 | */ | ||
733 | static int xilinx_pcie_remove(struct platform_device *pdev) | ||
734 | { | ||
735 | struct xilinx_pcie_port *port = platform_get_drvdata(pdev); | ||
736 | |||
737 | xilinx_pcie_free_irq_domain(port); | ||
738 | |||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | static struct of_device_id xilinx_pcie_of_match[] = { | 698 | static struct of_device_id xilinx_pcie_of_match[] = { |
743 | { .compatible = "xlnx,axi-pcie-host-1.00.a", }, | 699 | { .compatible = "xlnx,axi-pcie-host-1.00.a", }, |
744 | {} | 700 | {} |
@@ -751,10 +707,5 @@ static struct platform_driver xilinx_pcie_driver = { | |||
751 | .suppress_bind_attrs = true, | 707 | .suppress_bind_attrs = true, |
752 | }, | 708 | }, |
753 | .probe = xilinx_pcie_probe, | 709 | .probe = xilinx_pcie_probe, |
754 | .remove = xilinx_pcie_remove, | ||
755 | }; | 710 | }; |
756 | module_platform_driver(xilinx_pcie_driver); | 711 | builtin_platform_driver(xilinx_pcie_driver); |
757 | |||
758 | MODULE_AUTHOR("Xilinx Inc"); | ||
759 | MODULE_DESCRIPTION("Xilinx AXI PCIe driver"); | ||
760 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h index 555bcde3b196..60e66e027ebc 100644 --- a/drivers/pci/hotplug/cpci_hotplug.h +++ b/drivers/pci/hotplug/cpci_hotplug.h | |||
@@ -101,10 +101,8 @@ int cpci_unconfigure_slot(struct slot *slot); | |||
101 | 101 | ||
102 | #ifdef CONFIG_HOTPLUG_PCI_CPCI | 102 | #ifdef CONFIG_HOTPLUG_PCI_CPCI |
103 | int cpci_hotplug_init(int debug); | 103 | int cpci_hotplug_init(int debug); |
104 | void cpci_hotplug_exit(void); | ||
105 | #else | 104 | #else |
106 | static inline int cpci_hotplug_init(int debug) { return 0; } | 105 | static inline int cpci_hotplug_init(int debug) { return 0; } |
107 | static inline void cpci_hotplug_exit(void) { } | ||
108 | #endif | 106 | #endif |
109 | 107 | ||
110 | #endif /* _CPCI_HOTPLUG_H */ | 108 | #endif /* _CPCI_HOTPLUG_H */ |
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index 7d3866c47312..7ec8a8f72c69 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c | |||
@@ -719,13 +719,3 @@ cpci_hotplug_init(int debug) | |||
719 | cpci_debug = debug; | 719 | cpci_debug = debug; |
720 | return 0; | 720 | return 0; |
721 | } | 721 | } |
722 | |||
723 | void __exit | ||
724 | cpci_hotplug_exit(void) | ||
725 | { | ||
726 | /* | ||
727 | * Clean everything up. | ||
728 | */ | ||
729 | cpci_hp_stop(); | ||
730 | cpci_hp_unregister_controller(controller); | ||
731 | } | ||
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 9acd1997c6fe..fea0b8b33589 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> /* try_module_get & module_put */ |
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
@@ -537,17 +537,11 @@ static int __init pci_hotplug_init(void) | |||
537 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 537 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
538 | return result; | 538 | return result; |
539 | } | 539 | } |
540 | device_initcall(pci_hotplug_init); | ||
540 | 541 | ||
541 | static void __exit pci_hotplug_exit(void) | 542 | /* |
542 | { | 543 | * not really modular, but the easiest way to keep compat with existing |
543 | cpci_hotplug_exit(); | 544 | * bootargs behaviour is to continue using module_param here. |
544 | } | 545 | */ |
545 | |||
546 | module_init(pci_hotplug_init); | ||
547 | module_exit(pci_hotplug_exit); | ||
548 | |||
549 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
550 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
551 | MODULE_LICENSE("GPL"); | ||
552 | module_param(debug, bool, 0644); | 546 | module_param(debug, bool, 0644); |
553 | MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); | 547 | MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e764918641ae..37d70b5ad22f 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -152,6 +152,9 @@ bool pciehp_check_link_active(struct controller *ctrl); | |||
152 | void pciehp_release_ctrl(struct controller *ctrl); | 152 | void pciehp_release_ctrl(struct controller *ctrl); |
153 | int pciehp_reset_slot(struct slot *slot, int probe); | 153 | int pciehp_reset_slot(struct slot *slot, int probe); |
154 | 154 | ||
155 | int pciehp_set_raw_indicator_status(struct hotplug_slot *h_slot, u8 status); | ||
156 | int pciehp_get_raw_indicator_status(struct hotplug_slot *h_slot, u8 *status); | ||
157 | |||
155 | static inline const char *slot_name(struct slot *slot) | 158 | static inline const char *slot_name(struct slot *slot) |
156 | { | 159 | { |
157 | return hotplug_slot_name(slot->hotplug_slot); | 160 | return hotplug_slot_name(slot->hotplug_slot); |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index ac531e674a05..7d32fa33dcef 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -27,7 +27,6 @@ | |||
27 | * | 27 | * |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/moduleparam.h> | 30 | #include <linux/moduleparam.h> |
32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
@@ -47,10 +46,10 @@ static bool pciehp_force; | |||
47 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 46 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
48 | #define DRIVER_DESC "PCI Express Hot Plug Controller Driver" | 47 | #define DRIVER_DESC "PCI Express Hot Plug Controller Driver" |
49 | 48 | ||
50 | MODULE_AUTHOR(DRIVER_AUTHOR); | 49 | /* |
51 | MODULE_DESCRIPTION(DRIVER_DESC); | 50 | * not really modular, but the easiest way to keep compat with existing |
52 | MODULE_LICENSE("GPL"); | 51 | * bootargs behaviour is to continue using module_param here. |
53 | 52 | */ | |
54 | module_param(pciehp_debug, bool, 0644); | 53 | module_param(pciehp_debug, bool, 0644); |
55 | module_param(pciehp_poll_mode, bool, 0644); | 54 | module_param(pciehp_poll_mode, bool, 0644); |
56 | module_param(pciehp_poll_time, int, 0644); | 55 | module_param(pciehp_poll_time, int, 0644); |
@@ -114,6 +113,9 @@ static int init_slot(struct controller *ctrl) | |||
114 | if (ATTN_LED(ctrl)) { | 113 | if (ATTN_LED(ctrl)) { |
115 | ops->get_attention_status = get_attention_status; | 114 | ops->get_attention_status = get_attention_status; |
116 | ops->set_attention_status = set_attention_status; | 115 | ops->set_attention_status = set_attention_status; |
116 | } else if (ctrl->pcie->port->hotplug_user_indicators) { | ||
117 | ops->get_attention_status = pciehp_get_raw_indicator_status; | ||
118 | ops->set_attention_status = pciehp_set_raw_indicator_status; | ||
117 | } | 119 | } |
118 | 120 | ||
119 | /* register this slot with the hotplug pci core */ | 121 | /* register this slot with the hotplug pci core */ |
@@ -337,13 +339,4 @@ static int __init pcied_init(void) | |||
337 | 339 | ||
338 | return retval; | 340 | return retval; |
339 | } | 341 | } |
340 | 342 | device_initcall(pcied_init); | |
341 | static void __exit pcied_cleanup(void) | ||
342 | { | ||
343 | dbg("unload_pciehpd()\n"); | ||
344 | pcie_port_service_unregister(&hpdriver_portdrv); | ||
345 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); | ||
346 | } | ||
347 | |||
348 | module_init(pcied_init); | ||
349 | module_exit(pcied_cleanup); | ||
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 880978b6d534..efe69e879455 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -106,7 +106,7 @@ static int board_added(struct slot *p_slot) | |||
106 | 106 | ||
107 | /* Check for a power fault */ | 107 | /* Check for a power fault */ |
108 | if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) { | 108 | if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) { |
109 | ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot)); | 109 | ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(p_slot)); |
110 | retval = -EIO; | 110 | retval = -EIO; |
111 | goto err_exit; | 111 | goto err_exit; |
112 | } | 112 | } |
@@ -120,6 +120,7 @@ static int board_added(struct slot *p_slot) | |||
120 | } | 120 | } |
121 | 121 | ||
122 | pciehp_green_led_on(p_slot); | 122 | pciehp_green_led_on(p_slot); |
123 | pciehp_set_attention_status(p_slot, 0); | ||
123 | return 0; | 124 | return 0; |
124 | 125 | ||
125 | err_exit: | 126 | err_exit: |
@@ -253,11 +254,11 @@ static void handle_button_press_event(struct slot *p_slot) | |||
253 | pciehp_get_power_status(p_slot, &getstatus); | 254 | pciehp_get_power_status(p_slot, &getstatus); |
254 | if (getstatus) { | 255 | if (getstatus) { |
255 | p_slot->state = BLINKINGOFF_STATE; | 256 | p_slot->state = BLINKINGOFF_STATE; |
256 | ctrl_info(ctrl, "PCI slot #%s - powering off due to button press\n", | 257 | ctrl_info(ctrl, "Slot(%s): Powering off due to button press\n", |
257 | slot_name(p_slot)); | 258 | slot_name(p_slot)); |
258 | } else { | 259 | } else { |
259 | p_slot->state = BLINKINGON_STATE; | 260 | p_slot->state = BLINKINGON_STATE; |
260 | ctrl_info(ctrl, "PCI slot #%s - powering on due to button press\n", | 261 | ctrl_info(ctrl, "Slot(%s) Powering on due to button press\n", |
261 | slot_name(p_slot)); | 262 | slot_name(p_slot)); |
262 | } | 263 | } |
263 | /* blink green LED and turn off amber */ | 264 | /* blink green LED and turn off amber */ |
@@ -272,14 +273,14 @@ static void handle_button_press_event(struct slot *p_slot) | |||
272 | * press the attention again before the 5 sec. limit | 273 | * press the attention again before the 5 sec. limit |
273 | * expires to cancel hot-add or hot-remove | 274 | * expires to cancel hot-add or hot-remove |
274 | */ | 275 | */ |
275 | ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot)); | 276 | ctrl_info(ctrl, "Slot(%s): Button cancel\n", slot_name(p_slot)); |
276 | cancel_delayed_work(&p_slot->work); | 277 | cancel_delayed_work(&p_slot->work); |
277 | if (p_slot->state == BLINKINGOFF_STATE) | 278 | if (p_slot->state == BLINKINGOFF_STATE) |
278 | pciehp_green_led_on(p_slot); | 279 | pciehp_green_led_on(p_slot); |
279 | else | 280 | else |
280 | pciehp_green_led_off(p_slot); | 281 | pciehp_green_led_off(p_slot); |
281 | pciehp_set_attention_status(p_slot, 0); | 282 | pciehp_set_attention_status(p_slot, 0); |
282 | ctrl_info(ctrl, "PCI slot #%s - action canceled due to button press\n", | 283 | ctrl_info(ctrl, "Slot(%s): Action canceled due to button press\n", |
283 | slot_name(p_slot)); | 284 | slot_name(p_slot)); |
284 | p_slot->state = STATIC_STATE; | 285 | p_slot->state = STATIC_STATE; |
285 | break; | 286 | break; |
@@ -290,10 +291,12 @@ static void handle_button_press_event(struct slot *p_slot) | |||
290 | * this means that the previous attention button action | 291 | * this means that the previous attention button action |
291 | * to hot-add or hot-remove is undergoing | 292 | * to hot-add or hot-remove is undergoing |
292 | */ | 293 | */ |
293 | ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot)); | 294 | ctrl_info(ctrl, "Slot(%s): Button ignored\n", |
295 | slot_name(p_slot)); | ||
294 | break; | 296 | break; |
295 | default: | 297 | default: |
296 | ctrl_warn(ctrl, "ignoring invalid state %#x\n", p_slot->state); | 298 | ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n", |
299 | slot_name(p_slot), p_slot->state); | ||
297 | break; | 300 | break; |
298 | } | 301 | } |
299 | } | 302 | } |
@@ -301,20 +304,6 @@ static void handle_button_press_event(struct slot *p_slot) | |||
301 | /* | 304 | /* |
302 | * Note: This function must be called with slot->lock held | 305 | * Note: This function must be called with slot->lock held |
303 | */ | 306 | */ |
304 | static void handle_surprise_event(struct slot *p_slot) | ||
305 | { | ||
306 | u8 getstatus; | ||
307 | |||
308 | pciehp_get_adapter_status(p_slot, &getstatus); | ||
309 | if (!getstatus) | ||
310 | pciehp_queue_power_work(p_slot, DISABLE_REQ); | ||
311 | else | ||
312 | pciehp_queue_power_work(p_slot, ENABLE_REQ); | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * Note: This function must be called with slot->lock held | ||
317 | */ | ||
318 | static void handle_link_event(struct slot *p_slot, u32 event) | 307 | static void handle_link_event(struct slot *p_slot, u32 event) |
319 | { | 308 | { |
320 | struct controller *ctrl = p_slot->ctrl; | 309 | struct controller *ctrl = p_slot->ctrl; |
@@ -330,31 +319,27 @@ static void handle_link_event(struct slot *p_slot, u32 event) | |||
330 | break; | 319 | break; |
331 | case POWERON_STATE: | 320 | case POWERON_STATE: |
332 | if (event == INT_LINK_UP) { | 321 | if (event == INT_LINK_UP) { |
333 | ctrl_info(ctrl, | 322 | ctrl_info(ctrl, "Slot(%s): Link Up event ignored; already powering on\n", |
334 | "Link Up event ignored on slot(%s): already powering on\n", | ||
335 | slot_name(p_slot)); | 323 | slot_name(p_slot)); |
336 | } else { | 324 | } else { |
337 | ctrl_info(ctrl, | 325 | ctrl_info(ctrl, "Slot(%s): Link Down event queued; currently getting powered on\n", |
338 | "Link Down event queued on slot(%s): currently getting powered on\n", | ||
339 | slot_name(p_slot)); | 326 | slot_name(p_slot)); |
340 | pciehp_queue_power_work(p_slot, DISABLE_REQ); | 327 | pciehp_queue_power_work(p_slot, DISABLE_REQ); |
341 | } | 328 | } |
342 | break; | 329 | break; |
343 | case POWEROFF_STATE: | 330 | case POWEROFF_STATE: |
344 | if (event == INT_LINK_UP) { | 331 | if (event == INT_LINK_UP) { |
345 | ctrl_info(ctrl, | 332 | ctrl_info(ctrl, "Slot(%s): Link Up event queued; currently getting powered off\n", |
346 | "Link Up event queued on slot(%s): currently getting powered off\n", | ||
347 | slot_name(p_slot)); | 333 | slot_name(p_slot)); |
348 | pciehp_queue_power_work(p_slot, ENABLE_REQ); | 334 | pciehp_queue_power_work(p_slot, ENABLE_REQ); |
349 | } else { | 335 | } else { |
350 | ctrl_info(ctrl, | 336 | ctrl_info(ctrl, "Slot(%s): Link Down event ignored; already powering off\n", |
351 | "Link Down event ignored on slot(%s): already powering off\n", | ||
352 | slot_name(p_slot)); | 337 | slot_name(p_slot)); |
353 | } | 338 | } |
354 | break; | 339 | break; |
355 | default: | 340 | default: |
356 | ctrl_err(ctrl, "ignoring invalid state %#x on slot(%s)\n", | 341 | ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n", |
357 | p_slot->state, slot_name(p_slot)); | 342 | slot_name(p_slot), p_slot->state); |
358 | break; | 343 | break; |
359 | } | 344 | } |
360 | } | 345 | } |
@@ -377,14 +362,14 @@ static void interrupt_event_handler(struct work_struct *work) | |||
377 | pciehp_green_led_off(p_slot); | 362 | pciehp_green_led_off(p_slot); |
378 | break; | 363 | break; |
379 | case INT_PRESENCE_ON: | 364 | case INT_PRESENCE_ON: |
380 | handle_surprise_event(p_slot); | 365 | pciehp_queue_power_work(p_slot, ENABLE_REQ); |
381 | break; | 366 | break; |
382 | case INT_PRESENCE_OFF: | 367 | case INT_PRESENCE_OFF: |
383 | /* | 368 | /* |
384 | * Regardless of surprise capability, we need to | 369 | * Regardless of surprise capability, we need to |
385 | * definitely remove a card that has been pulled out! | 370 | * definitely remove a card that has been pulled out! |
386 | */ | 371 | */ |
387 | handle_surprise_event(p_slot); | 372 | pciehp_queue_power_work(p_slot, DISABLE_REQ); |
388 | break; | 373 | break; |
389 | case INT_LINK_UP: | 374 | case INT_LINK_UP: |
390 | case INT_LINK_DOWN: | 375 | case INT_LINK_DOWN: |
@@ -404,18 +389,17 @@ static void interrupt_event_handler(struct work_struct *work) | |||
404 | int pciehp_enable_slot(struct slot *p_slot) | 389 | int pciehp_enable_slot(struct slot *p_slot) |
405 | { | 390 | { |
406 | u8 getstatus = 0; | 391 | u8 getstatus = 0; |
407 | int rc; | ||
408 | struct controller *ctrl = p_slot->ctrl; | 392 | struct controller *ctrl = p_slot->ctrl; |
409 | 393 | ||
410 | pciehp_get_adapter_status(p_slot, &getstatus); | 394 | pciehp_get_adapter_status(p_slot, &getstatus); |
411 | if (!getstatus) { | 395 | if (!getstatus) { |
412 | ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); | 396 | ctrl_info(ctrl, "Slot(%s): No adapter\n", slot_name(p_slot)); |
413 | return -ENODEV; | 397 | return -ENODEV; |
414 | } | 398 | } |
415 | if (MRL_SENS(p_slot->ctrl)) { | 399 | if (MRL_SENS(p_slot->ctrl)) { |
416 | pciehp_get_latch_status(p_slot, &getstatus); | 400 | pciehp_get_latch_status(p_slot, &getstatus); |
417 | if (getstatus) { | 401 | if (getstatus) { |
418 | ctrl_info(ctrl, "Latch open on slot(%s)\n", | 402 | ctrl_info(ctrl, "Slot(%s): Latch open\n", |
419 | slot_name(p_slot)); | 403 | slot_name(p_slot)); |
420 | return -ENODEV; | 404 | return -ENODEV; |
421 | } | 405 | } |
@@ -424,19 +408,13 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
424 | if (POWER_CTRL(p_slot->ctrl)) { | 408 | if (POWER_CTRL(p_slot->ctrl)) { |
425 | pciehp_get_power_status(p_slot, &getstatus); | 409 | pciehp_get_power_status(p_slot, &getstatus); |
426 | if (getstatus) { | 410 | if (getstatus) { |
427 | ctrl_info(ctrl, "Already enabled on slot(%s)\n", | 411 | ctrl_info(ctrl, "Slot(%s): Already enabled\n", |
428 | slot_name(p_slot)); | 412 | slot_name(p_slot)); |
429 | return -EINVAL; | 413 | return -EINVAL; |
430 | } | 414 | } |
431 | } | 415 | } |
432 | 416 | ||
433 | pciehp_get_latch_status(p_slot, &getstatus); | 417 | return board_added(p_slot); |
434 | |||
435 | rc = board_added(p_slot); | ||
436 | if (rc) | ||
437 | pciehp_get_latch_status(p_slot, &getstatus); | ||
438 | |||
439 | return rc; | ||
440 | } | 418 | } |
441 | 419 | ||
442 | /* | 420 | /* |
@@ -453,7 +431,7 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
453 | if (POWER_CTRL(p_slot->ctrl)) { | 431 | if (POWER_CTRL(p_slot->ctrl)) { |
454 | pciehp_get_power_status(p_slot, &getstatus); | 432 | pciehp_get_power_status(p_slot, &getstatus); |
455 | if (!getstatus) { | 433 | if (!getstatus) { |
456 | ctrl_info(ctrl, "Already disabled on slot(%s)\n", | 434 | ctrl_info(ctrl, "Slot(%s): Already disabled\n", |
457 | slot_name(p_slot)); | 435 | slot_name(p_slot)); |
458 | return -EINVAL; | 436 | return -EINVAL; |
459 | } | 437 | } |
@@ -481,17 +459,17 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot) | |||
481 | p_slot->state = STATIC_STATE; | 459 | p_slot->state = STATIC_STATE; |
482 | break; | 460 | break; |
483 | case POWERON_STATE: | 461 | case POWERON_STATE: |
484 | ctrl_info(ctrl, "Slot %s is already in powering on state\n", | 462 | ctrl_info(ctrl, "Slot(%s): Already in powering on state\n", |
485 | slot_name(p_slot)); | 463 | slot_name(p_slot)); |
486 | break; | 464 | break; |
487 | case BLINKINGOFF_STATE: | 465 | case BLINKINGOFF_STATE: |
488 | case POWEROFF_STATE: | 466 | case POWEROFF_STATE: |
489 | ctrl_info(ctrl, "Already enabled on slot %s\n", | 467 | ctrl_info(ctrl, "Slot(%s): Already enabled\n", |
490 | slot_name(p_slot)); | 468 | slot_name(p_slot)); |
491 | break; | 469 | break; |
492 | default: | 470 | default: |
493 | ctrl_err(ctrl, "invalid state %#x on slot %s\n", | 471 | ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n", |
494 | p_slot->state, slot_name(p_slot)); | 472 | slot_name(p_slot), p_slot->state); |
495 | break; | 473 | break; |
496 | } | 474 | } |
497 | mutex_unlock(&p_slot->lock); | 475 | mutex_unlock(&p_slot->lock); |
@@ -518,17 +496,17 @@ int pciehp_sysfs_disable_slot(struct slot *p_slot) | |||
518 | p_slot->state = STATIC_STATE; | 496 | p_slot->state = STATIC_STATE; |
519 | break; | 497 | break; |
520 | case POWEROFF_STATE: | 498 | case POWEROFF_STATE: |
521 | ctrl_info(ctrl, "Slot %s is already in powering off state\n", | 499 | ctrl_info(ctrl, "Slot(%s): Already in powering off state\n", |
522 | slot_name(p_slot)); | 500 | slot_name(p_slot)); |
523 | break; | 501 | break; |
524 | case BLINKINGON_STATE: | 502 | case BLINKINGON_STATE: |
525 | case POWERON_STATE: | 503 | case POWERON_STATE: |
526 | ctrl_info(ctrl, "Already disabled on slot %s\n", | 504 | ctrl_info(ctrl, "Slot(%s): Already disabled\n", |
527 | slot_name(p_slot)); | 505 | slot_name(p_slot)); |
528 | break; | 506 | break; |
529 | default: | 507 | default: |
530 | ctrl_err(ctrl, "invalid state %#x on slot %s\n", | 508 | ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n", |
531 | p_slot->state, slot_name(p_slot)); | 509 | slot_name(p_slot), p_slot->state); |
532 | break; | 510 | break; |
533 | } | 511 | } |
534 | mutex_unlock(&p_slot->lock); | 512 | mutex_unlock(&p_slot->lock); |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 08e84d61874e..b57fc6d6e28a 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -355,6 +355,18 @@ static int pciehp_link_enable(struct controller *ctrl) | |||
355 | return __pciehp_link_set(ctrl, true); | 355 | return __pciehp_link_set(ctrl, true); |
356 | } | 356 | } |
357 | 357 | ||
358 | int pciehp_get_raw_indicator_status(struct hotplug_slot *hotplug_slot, | ||
359 | u8 *status) | ||
360 | { | ||
361 | struct slot *slot = hotplug_slot->private; | ||
362 | struct pci_dev *pdev = ctrl_dev(slot->ctrl); | ||
363 | u16 slot_ctrl; | ||
364 | |||
365 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); | ||
366 | *status = (slot_ctrl & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6; | ||
367 | return 0; | ||
368 | } | ||
369 | |||
358 | void pciehp_get_attention_status(struct slot *slot, u8 *status) | 370 | void pciehp_get_attention_status(struct slot *slot, u8 *status) |
359 | { | 371 | { |
360 | struct controller *ctrl = slot->ctrl; | 372 | struct controller *ctrl = slot->ctrl; |
@@ -431,6 +443,17 @@ int pciehp_query_power_fault(struct slot *slot) | |||
431 | return !!(slot_status & PCI_EXP_SLTSTA_PFD); | 443 | return !!(slot_status & PCI_EXP_SLTSTA_PFD); |
432 | } | 444 | } |
433 | 445 | ||
446 | int pciehp_set_raw_indicator_status(struct hotplug_slot *hotplug_slot, | ||
447 | u8 status) | ||
448 | { | ||
449 | struct slot *slot = hotplug_slot->private; | ||
450 | struct controller *ctrl = slot->ctrl; | ||
451 | |||
452 | pcie_write_cmd_nowait(ctrl, status << 6, | ||
453 | PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC); | ||
454 | return 0; | ||
455 | } | ||
456 | |||
434 | void pciehp_set_attention_status(struct slot *slot, u8 value) | 457 | void pciehp_set_attention_status(struct slot *slot, u8 value) |
435 | { | 458 | { |
436 | struct controller *ctrl = slot->ctrl; | 459 | struct controller *ctrl = slot->ctrl; |
@@ -535,14 +558,14 @@ void pciehp_power_off_slot(struct slot *slot) | |||
535 | PCI_EXP_SLTCTL_PWR_OFF); | 558 | PCI_EXP_SLTCTL_PWR_OFF); |
536 | } | 559 | } |
537 | 560 | ||
538 | static irqreturn_t pcie_isr(int irq, void *dev_id) | 561 | static irqreturn_t pciehp_isr(int irq, void *dev_id) |
539 | { | 562 | { |
540 | struct controller *ctrl = (struct controller *)dev_id; | 563 | struct controller *ctrl = (struct controller *)dev_id; |
541 | struct pci_dev *pdev = ctrl_dev(ctrl); | 564 | struct pci_dev *pdev = ctrl_dev(ctrl); |
542 | struct pci_bus *subordinate = pdev->subordinate; | 565 | struct pci_bus *subordinate = pdev->subordinate; |
543 | struct pci_dev *dev; | 566 | struct pci_dev *dev; |
544 | struct slot *slot = ctrl->slot; | 567 | struct slot *slot = ctrl->slot; |
545 | u16 detected, intr_loc; | 568 | u16 status, events; |
546 | u8 present; | 569 | u8 present; |
547 | bool link; | 570 | bool link; |
548 | 571 | ||
@@ -550,36 +573,31 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
550 | if (pdev->current_state == PCI_D3cold) | 573 | if (pdev->current_state == PCI_D3cold) |
551 | return IRQ_NONE; | 574 | return IRQ_NONE; |
552 | 575 | ||
576 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &status); | ||
577 | if (status == (u16) ~0) { | ||
578 | ctrl_info(ctrl, "%s: no response from device\n", __func__); | ||
579 | return IRQ_NONE; | ||
580 | } | ||
581 | |||
553 | /* | 582 | /* |
554 | * In order to guarantee that all interrupt events are | 583 | * Slot Status contains plain status bits as well as event |
555 | * serviced, we need to re-inspect Slot Status register after | 584 | * notification bits; right now we only want the event bits. |
556 | * clearing what is presumed to be the last pending interrupt. | ||
557 | */ | 585 | */ |
558 | intr_loc = 0; | 586 | events = status & (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | |
559 | do { | 587 | PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_CC | |
560 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &detected); | 588 | PCI_EXP_SLTSTA_DLLSC); |
561 | if (detected == (u16) ~0) { | 589 | if (!events) |
562 | ctrl_info(ctrl, "%s: no response from device\n", | 590 | return IRQ_NONE; |
563 | __func__); | ||
564 | return IRQ_HANDLED; | ||
565 | } | ||
566 | 591 | ||
567 | detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | | 592 | /* Capture link status before clearing interrupts */ |
568 | PCI_EXP_SLTSTA_PDC | | 593 | if (events & PCI_EXP_SLTSTA_DLLSC) |
569 | PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC); | 594 | link = pciehp_check_link_active(ctrl); |
570 | detected &= ~intr_loc; | ||
571 | intr_loc |= detected; | ||
572 | if (!intr_loc) | ||
573 | return IRQ_NONE; | ||
574 | if (detected) | ||
575 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, | ||
576 | intr_loc); | ||
577 | } while (detected); | ||
578 | 595 | ||
579 | ctrl_dbg(ctrl, "pending interrupts %#06x from Slot Status\n", intr_loc); | 596 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, events); |
597 | ctrl_dbg(ctrl, "pending interrupts %#06x from Slot Status\n", events); | ||
580 | 598 | ||
581 | /* Check Command Complete Interrupt Pending */ | 599 | /* Check Command Complete Interrupt Pending */ |
582 | if (intr_loc & PCI_EXP_SLTSTA_CC) { | 600 | if (events & PCI_EXP_SLTSTA_CC) { |
583 | ctrl->cmd_busy = 0; | 601 | ctrl->cmd_busy = 0; |
584 | smp_mb(); | 602 | smp_mb(); |
585 | wake_up(&ctrl->queue); | 603 | wake_up(&ctrl->queue); |
@@ -589,42 +607,38 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
589 | list_for_each_entry(dev, &subordinate->devices, bus_list) { | 607 | list_for_each_entry(dev, &subordinate->devices, bus_list) { |
590 | if (dev->ignore_hotplug) { | 608 | if (dev->ignore_hotplug) { |
591 | ctrl_dbg(ctrl, "ignoring hotplug event %#06x (%s requested no hotplug)\n", | 609 | ctrl_dbg(ctrl, "ignoring hotplug event %#06x (%s requested no hotplug)\n", |
592 | intr_loc, pci_name(dev)); | 610 | events, pci_name(dev)); |
593 | return IRQ_HANDLED; | 611 | return IRQ_HANDLED; |
594 | } | 612 | } |
595 | } | 613 | } |
596 | } | 614 | } |
597 | 615 | ||
598 | if (!(intr_loc & ~PCI_EXP_SLTSTA_CC)) | ||
599 | return IRQ_HANDLED; | ||
600 | |||
601 | /* Check Attention Button Pressed */ | 616 | /* Check Attention Button Pressed */ |
602 | if (intr_loc & PCI_EXP_SLTSTA_ABP) { | 617 | if (events & PCI_EXP_SLTSTA_ABP) { |
603 | ctrl_info(ctrl, "Button pressed on Slot(%s)\n", | 618 | ctrl_info(ctrl, "Slot(%s): Attention button pressed\n", |
604 | slot_name(slot)); | 619 | slot_name(slot)); |
605 | pciehp_queue_interrupt_event(slot, INT_BUTTON_PRESS); | 620 | pciehp_queue_interrupt_event(slot, INT_BUTTON_PRESS); |
606 | } | 621 | } |
607 | 622 | ||
608 | /* Check Presence Detect Changed */ | 623 | /* Check Presence Detect Changed */ |
609 | if (intr_loc & PCI_EXP_SLTSTA_PDC) { | 624 | if (events & PCI_EXP_SLTSTA_PDC) { |
610 | pciehp_get_adapter_status(slot, &present); | 625 | present = !!(status & PCI_EXP_SLTSTA_PDS); |
611 | ctrl_info(ctrl, "Card %spresent on Slot(%s)\n", | 626 | ctrl_info(ctrl, "Slot(%s): Card %spresent\n", slot_name(slot), |
612 | present ? "" : "not ", slot_name(slot)); | 627 | present ? "" : "not "); |
613 | pciehp_queue_interrupt_event(slot, present ? INT_PRESENCE_ON : | 628 | pciehp_queue_interrupt_event(slot, present ? INT_PRESENCE_ON : |
614 | INT_PRESENCE_OFF); | 629 | INT_PRESENCE_OFF); |
615 | } | 630 | } |
616 | 631 | ||
617 | /* Check Power Fault Detected */ | 632 | /* Check Power Fault Detected */ |
618 | if ((intr_loc & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) { | 633 | if ((events & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) { |
619 | ctrl->power_fault_detected = 1; | 634 | ctrl->power_fault_detected = 1; |
620 | ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(slot)); | 635 | ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(slot)); |
621 | pciehp_queue_interrupt_event(slot, INT_POWER_FAULT); | 636 | pciehp_queue_interrupt_event(slot, INT_POWER_FAULT); |
622 | } | 637 | } |
623 | 638 | ||
624 | if (intr_loc & PCI_EXP_SLTSTA_DLLSC) { | 639 | if (events & PCI_EXP_SLTSTA_DLLSC) { |
625 | link = pciehp_check_link_active(ctrl); | 640 | ctrl_info(ctrl, "Slot(%s): Link %s\n", slot_name(slot), |
626 | ctrl_info(ctrl, "slot(%s): Link %s event\n", | 641 | link ? "Up" : "Down"); |
627 | slot_name(slot), link ? "Up" : "Down"); | ||
628 | pciehp_queue_interrupt_event(slot, link ? INT_LINK_UP : | 642 | pciehp_queue_interrupt_event(slot, link ? INT_LINK_UP : |
629 | INT_LINK_DOWN); | 643 | INT_LINK_DOWN); |
630 | } | 644 | } |
@@ -632,6 +646,25 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
632 | return IRQ_HANDLED; | 646 | return IRQ_HANDLED; |
633 | } | 647 | } |
634 | 648 | ||
649 | static irqreturn_t pcie_isr(int irq, void *dev_id) | ||
650 | { | ||
651 | irqreturn_t rc, handled = IRQ_NONE; | ||
652 | |||
653 | /* | ||
654 | * To guarantee that all interrupt events are serviced, we need to | ||
655 | * re-inspect Slot Status register after clearing what is presumed | ||
656 | * to be the last pending interrupt. | ||
657 | */ | ||
658 | do { | ||
659 | rc = pciehp_isr(irq, dev_id); | ||
660 | if (rc == IRQ_HANDLED) | ||
661 | handled = IRQ_HANDLED; | ||
662 | } while (rc == IRQ_HANDLED); | ||
663 | |||
664 | /* Return IRQ_HANDLED if we handled one or more events */ | ||
665 | return handled; | ||
666 | } | ||
667 | |||
635 | void pcie_enable_notification(struct controller *ctrl) | 668 | void pcie_enable_notification(struct controller *ctrl) |
636 | { | 669 | { |
637 | u16 cmd, mask; | 670 | u16 cmd, mask; |
@@ -804,6 +837,10 @@ struct controller *pcie_init(struct pcie_device *dev) | |||
804 | } | 837 | } |
805 | ctrl->pcie = dev; | 838 | ctrl->pcie = dev; |
806 | pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); | 839 | pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); |
840 | |||
841 | if (pdev->hotplug_user_indicators) | ||
842 | slot_cap &= ~(PCI_EXP_SLTCAP_AIP | PCI_EXP_SLTCAP_PIP); | ||
843 | |||
807 | ctrl->slot_cap = slot_cap; | 844 | ctrl->slot_cap = slot_cap; |
808 | mutex_init(&ctrl->ctrl_lock); | 845 | mutex_init(&ctrl->ctrl_lock); |
809 | init_waitqueue_head(&ctrl->queue); | 846 | init_waitqueue_head(&ctrl->queue); |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index e39a67c8ef39..edd78e04b693 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -466,7 +466,6 @@ static void pci_device_shutdown(struct device *dev) | |||
466 | pci_msi_shutdown(pci_dev); | 466 | pci_msi_shutdown(pci_dev); |
467 | pci_msix_shutdown(pci_dev); | 467 | pci_msix_shutdown(pci_dev); |
468 | 468 | ||
469 | #ifdef CONFIG_KEXEC_CORE | ||
470 | /* | 469 | /* |
471 | * If this is a kexec reboot, turn off Bus Master bit on the | 470 | * If this is a kexec reboot, turn off Bus Master bit on the |
472 | * device to tell it to not continue to do DMA. Don't touch | 471 | * device to tell it to not continue to do DMA. Don't touch |
@@ -476,7 +475,6 @@ static void pci_device_shutdown(struct device *dev) | |||
476 | */ | 475 | */ |
477 | if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot)) | 476 | if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot)) |
478 | pci_clear_master(pci_dev); | 477 | pci_clear_master(pci_dev); |
479 | #endif | ||
480 | } | 478 | } |
481 | 479 | ||
482 | #ifdef CONFIG_PM | 480 | #ifdef CONFIG_PM |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 9730c474b016..194521bfb1a3 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -332,6 +332,12 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, | |||
332 | 332 | ||
333 | void pci_enable_acs(struct pci_dev *dev); | 333 | void pci_enable_acs(struct pci_dev *dev); |
334 | 334 | ||
335 | #ifdef CONFIG_PCIE_PTM | ||
336 | void pci_ptm_init(struct pci_dev *dev); | ||
337 | #else | ||
338 | static inline void pci_ptm_init(struct pci_dev *dev) { } | ||
339 | #endif | ||
340 | |||
335 | struct pci_dev_reset_methods { | 341 | struct pci_dev_reset_methods { |
336 | u16 vendor; | 342 | u16 vendor; |
337 | u16 device; | 343 | u16 device; |
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 7fcea75afa4c..7ce77635e5ad 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig | |||
@@ -92,3 +92,14 @@ config PCIE_DPC | |||
92 | will be handled by the DPC driver. If your system doesn't | 92 | will be handled by the DPC driver. If your system doesn't |
93 | have this capability or you do not want to use this feature, | 93 | have this capability or you do not want to use this feature, |
94 | it is safe to answer N. | 94 | it is safe to answer N. |
95 | |||
96 | config PCIE_PTM | ||
97 | bool "PCIe Precision Time Measurement support" | ||
98 | default n | ||
99 | depends on PCIEPORTBUS | ||
100 | help | ||
101 | This enables PCI Express Precision Time Measurement (PTM) | ||
102 | support. | ||
103 | |||
104 | This is only useful if you have devices that support PTM, but it | ||
105 | is safe to enable even if you don't. | ||
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile index b24525b3dec1..36e35ea8fde7 100644 --- a/drivers/pci/pcie/Makefile +++ b/drivers/pci/pcie/Makefile | |||
@@ -16,3 +16,4 @@ obj-$(CONFIG_PCIEAER) += aer/ | |||
16 | obj-$(CONFIG_PCIE_PME) += pme.o | 16 | obj-$(CONFIG_PCIE_PME) += pme.o |
17 | 17 | ||
18 | obj-$(CONFIG_PCIE_DPC) += pcie-dpc.o | 18 | obj-$(CONFIG_PCIE_DPC) += pcie-dpc.o |
19 | obj-$(CONFIG_PCIE_PTM) += ptm.o | ||
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 48d21e0edd56..139150b2bdfd 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
20 | #include <linux/pci-acpi.h> | 19 | #include <linux/pci-acpi.h> |
21 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
@@ -37,9 +36,6 @@ | |||
37 | #define DRIVER_VERSION "v1.0" | 36 | #define DRIVER_VERSION "v1.0" |
38 | #define DRIVER_AUTHOR "tom.l.nguyen@intel.com" | 37 | #define DRIVER_AUTHOR "tom.l.nguyen@intel.com" |
39 | #define DRIVER_DESC "Root Port Advanced Error Reporting Driver" | 38 | #define DRIVER_DESC "Root Port Advanced Error Reporting Driver" |
40 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
41 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
42 | MODULE_LICENSE("GPL"); | ||
43 | 39 | ||
44 | static int aer_probe(struct pcie_device *dev); | 40 | static int aer_probe(struct pcie_device *dev); |
45 | static void aer_remove(struct pcie_device *dev); | 41 | static void aer_remove(struct pcie_device *dev); |
@@ -70,7 +66,7 @@ static int pcie_aer_disable; | |||
70 | 66 | ||
71 | void pci_no_aer(void) | 67 | void pci_no_aer(void) |
72 | { | 68 | { |
73 | pcie_aer_disable = 1; /* has priority over 'forceload' */ | 69 | pcie_aer_disable = 1; |
74 | } | 70 | } |
75 | 71 | ||
76 | bool pci_aer_available(void) | 72 | bool pci_aer_available(void) |
@@ -134,7 +130,7 @@ static void aer_enable_rootport(struct aer_rpc *rpc) | |||
134 | pcie_capability_clear_word(pdev, PCI_EXP_RTCTL, | 130 | pcie_capability_clear_word(pdev, PCI_EXP_RTCTL, |
135 | SYSTEM_ERROR_INTR_ON_MESG_MASK); | 131 | SYSTEM_ERROR_INTR_ON_MESG_MASK); |
136 | 132 | ||
137 | aer_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | 133 | aer_pos = pdev->aer_cap; |
138 | /* Clear error status */ | 134 | /* Clear error status */ |
139 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, ®32); | 135 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, ®32); |
140 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32); | 136 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32); |
@@ -173,7 +169,7 @@ static void aer_disable_rootport(struct aer_rpc *rpc) | |||
173 | */ | 169 | */ |
174 | set_downstream_devices_error_reporting(pdev, false); | 170 | set_downstream_devices_error_reporting(pdev, false); |
175 | 171 | ||
176 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | 172 | pos = pdev->aer_cap; |
177 | /* Disable Root's interrupt in response to error messages */ | 173 | /* Disable Root's interrupt in response to error messages */ |
178 | pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, ®32); | 174 | pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, ®32); |
179 | reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; | 175 | reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; |
@@ -200,7 +196,7 @@ irqreturn_t aer_irq(int irq, void *context) | |||
200 | unsigned long flags; | 196 | unsigned long flags; |
201 | int pos; | 197 | int pos; |
202 | 198 | ||
203 | pos = pci_find_ext_capability(pdev->port, PCI_EXT_CAP_ID_ERR); | 199 | pos = pdev->port->aer_cap; |
204 | /* | 200 | /* |
205 | * Must lock access to Root Error Status Reg, Root Error ID Reg, | 201 | * Must lock access to Root Error Status Reg, Root Error ID Reg, |
206 | * and Root error producer/consumer index | 202 | * and Root error producer/consumer index |
@@ -294,7 +290,6 @@ static void aer_remove(struct pcie_device *dev) | |||
294 | /** | 290 | /** |
295 | * aer_probe - initialize resources | 291 | * aer_probe - initialize resources |
296 | * @dev: pointer to the pcie_dev data structure | 292 | * @dev: pointer to the pcie_dev data structure |
297 | * @id: pointer to the service id data structure | ||
298 | * | 293 | * |
299 | * Invoked when PCI Express bus loads AER service driver. | 294 | * Invoked when PCI Express bus loads AER service driver. |
300 | */ | 295 | */ |
@@ -304,11 +299,6 @@ static int aer_probe(struct pcie_device *dev) | |||
304 | struct aer_rpc *rpc; | 299 | struct aer_rpc *rpc; |
305 | struct device *device = &dev->device; | 300 | struct device *device = &dev->device; |
306 | 301 | ||
307 | /* Init */ | ||
308 | status = aer_init(dev); | ||
309 | if (status) | ||
310 | return status; | ||
311 | |||
312 | /* Alloc rpc data structure */ | 302 | /* Alloc rpc data structure */ |
313 | rpc = aer_alloc_rpc(dev); | 303 | rpc = aer_alloc_rpc(dev); |
314 | if (!rpc) { | 304 | if (!rpc) { |
@@ -343,7 +333,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) | |||
343 | u32 reg32; | 333 | u32 reg32; |
344 | int pos; | 334 | int pos; |
345 | 335 | ||
346 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 336 | pos = dev->aer_cap; |
347 | 337 | ||
348 | /* Disable Root's interrupt in response to error messages */ | 338 | /* Disable Root's interrupt in response to error messages */ |
349 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ®32); | 339 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ®32); |
@@ -396,7 +386,7 @@ static void aer_error_resume(struct pci_dev *dev) | |||
396 | pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16); | 386 | pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16); |
397 | 387 | ||
398 | /* Clean AER Root Error Status */ | 388 | /* Clean AER Root Error Status */ |
399 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 389 | pos = dev->aer_cap; |
400 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); | 390 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); |
401 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); | 391 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); |
402 | if (dev->error_state == pci_channel_io_normal) | 392 | if (dev->error_state == pci_channel_io_normal) |
@@ -417,16 +407,4 @@ static int __init aer_service_init(void) | |||
417 | return -ENXIO; | 407 | return -ENXIO; |
418 | return pcie_port_service_register(&aerdriver); | 408 | return pcie_port_service_register(&aerdriver); |
419 | } | 409 | } |
420 | 410 | device_initcall(aer_service_init); | |
421 | /** | ||
422 | * aer_service_exit - unregister AER root service driver | ||
423 | * | ||
424 | * Invoked when AER root service driver is unloaded. | ||
425 | */ | ||
426 | static void __exit aer_service_exit(void) | ||
427 | { | ||
428 | pcie_port_service_unregister(&aerdriver); | ||
429 | } | ||
430 | |||
431 | module_init(aer_service_init); | ||
432 | module_exit(aer_service_exit); | ||
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index 945c939a86c5..d51e4a57b190 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h | |||
@@ -60,6 +60,7 @@ struct aer_rpc { | |||
60 | struct pcie_device *rpd; /* Root Port device */ | 60 | struct pcie_device *rpd; /* Root Port device */ |
61 | struct work_struct dpc_handler; | 61 | struct work_struct dpc_handler; |
62 | struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX]; | 62 | struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX]; |
63 | struct aer_err_info e_info; | ||
63 | unsigned short prod_idx; /* Error Producer Index */ | 64 | unsigned short prod_idx; /* Error Producer Index */ |
64 | unsigned short cons_idx; /* Error Consumer Index */ | 65 | unsigned short cons_idx; /* Error Consumer Index */ |
65 | int isr; | 66 | int isr; |
@@ -105,7 +106,6 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig, | |||
105 | } | 106 | } |
106 | 107 | ||
107 | extern struct bus_type pcie_port_bus_type; | 108 | extern struct bus_type pcie_port_bus_type; |
108 | int aer_init(struct pcie_device *dev); | ||
109 | void aer_isr(struct work_struct *work); | 109 | void aer_isr(struct work_struct *work); |
110 | void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); | 110 | void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); |
111 | void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info); | 111 | void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info); |
@@ -121,11 +121,4 @@ static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev) | |||
121 | return 0; | 121 | return 0; |
122 | } | 122 | } |
123 | #endif | 123 | #endif |
124 | |||
125 | static inline void pcie_aer_force_firmware_first(struct pci_dev *pci_dev, | ||
126 | int enable) | ||
127 | { | ||
128 | pci_dev->__aer_firmware_first = !!enable; | ||
129 | pci_dev->__aer_firmware_first_valid = 1; | ||
130 | } | ||
131 | #endif /* _AERDRV_H_ */ | 124 | #endif /* _AERDRV_H_ */ |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 521e39c1b66d..b1303b32053f 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -27,11 +27,6 @@ | |||
27 | #include <linux/kfifo.h> | 27 | #include <linux/kfifo.h> |
28 | #include "aerdrv.h" | 28 | #include "aerdrv.h" |
29 | 29 | ||
30 | static bool forceload; | ||
31 | static bool nosourceid; | ||
32 | module_param(forceload, bool, 0); | ||
33 | module_param(nosourceid, bool, 0); | ||
34 | |||
35 | #define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ | 30 | #define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ |
36 | PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) | 31 | PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) |
37 | 32 | ||
@@ -40,7 +35,7 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev) | |||
40 | if (pcie_aer_get_firmware_first(dev)) | 35 | if (pcie_aer_get_firmware_first(dev)) |
41 | return -EIO; | 36 | return -EIO; |
42 | 37 | ||
43 | if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) | 38 | if (!dev->aer_cap) |
44 | return -EIO; | 39 | return -EIO; |
45 | 40 | ||
46 | return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS); | 41 | return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS); |
@@ -62,7 +57,7 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) | |||
62 | int pos; | 57 | int pos; |
63 | u32 status; | 58 | u32 status; |
64 | 59 | ||
65 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 60 | pos = dev->aer_cap; |
66 | if (!pos) | 61 | if (!pos) |
67 | return -EIO; | 62 | return -EIO; |
68 | 63 | ||
@@ -83,7 +78,7 @@ int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) | |||
83 | if (!pci_is_pcie(dev)) | 78 | if (!pci_is_pcie(dev)) |
84 | return -ENODEV; | 79 | return -ENODEV; |
85 | 80 | ||
86 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 81 | pos = dev->aer_cap; |
87 | if (!pos) | 82 | if (!pos) |
88 | return -EIO; | 83 | return -EIO; |
89 | 84 | ||
@@ -102,6 +97,12 @@ int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) | |||
102 | return 0; | 97 | return 0; |
103 | } | 98 | } |
104 | 99 | ||
100 | int pci_aer_init(struct pci_dev *dev) | ||
101 | { | ||
102 | dev->aer_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | ||
103 | return pci_cleanup_aer_error_status_regs(dev); | ||
104 | } | ||
105 | |||
105 | /** | 106 | /** |
106 | * add_error_device - list device to be handled | 107 | * add_error_device - list device to be handled |
107 | * @e_info: pointer to error info | 108 | * @e_info: pointer to error info |
@@ -132,7 +133,8 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) | |||
132 | * When bus id is equal to 0, it might be a bad id | 133 | * When bus id is equal to 0, it might be a bad id |
133 | * reported by root port. | 134 | * reported by root port. |
134 | */ | 135 | */ |
135 | if (!nosourceid && (PCI_BUS_NUM(e_info->id) != 0)) { | 136 | if ((PCI_BUS_NUM(e_info->id) != 0) && |
137 | !(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_AERSID)) { | ||
136 | /* Device ID match? */ | 138 | /* Device ID match? */ |
137 | if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) | 139 | if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) |
138 | return true; | 140 | return true; |
@@ -144,10 +146,10 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) | |||
144 | 146 | ||
145 | /* | 147 | /* |
146 | * When either | 148 | * When either |
147 | * 1) nosourceid==y; | 149 | * 1) bus id is equal to 0. Some ports might lose the bus |
148 | * 2) bus id is equal to 0. Some ports might lose the bus | ||
149 | * id of error source id; | 150 | * id of error source id; |
150 | * 3) There are multiple errors and prior id comparing fails; | 151 | * 2) bus flag PCI_BUS_FLAGS_NO_AERSID is set |
152 | * 3) There are multiple errors and prior ID comparing fails; | ||
151 | * We check AER status registers to find possible reporter. | 153 | * We check AER status registers to find possible reporter. |
152 | */ | 154 | */ |
153 | if (atomic_read(&dev->enable_cnt) == 0) | 155 | if (atomic_read(&dev->enable_cnt) == 0) |
@@ -158,7 +160,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) | |||
158 | if (!(reg16 & PCI_EXP_AER_FLAGS)) | 160 | if (!(reg16 & PCI_EXP_AER_FLAGS)) |
159 | return false; | 161 | return false; |
160 | 162 | ||
161 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 163 | pos = dev->aer_cap; |
162 | if (!pos) | 164 | if (!pos) |
163 | return false; | 165 | return false; |
164 | 166 | ||
@@ -555,7 +557,7 @@ static void handle_error_source(struct pcie_device *aerdev, | |||
555 | * Correctable error does not need software intervention. | 557 | * Correctable error does not need software intervention. |
556 | * No need to go through error recovery process. | 558 | * No need to go through error recovery process. |
557 | */ | 559 | */ |
558 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 560 | pos = dev->aer_cap; |
559 | if (pos) | 561 | if (pos) |
560 | pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, | 562 | pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, |
561 | info->status); | 563 | info->status); |
@@ -647,7 +649,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) | |||
647 | info->status = 0; | 649 | info->status = 0; |
648 | info->tlp_header_valid = 0; | 650 | info->tlp_header_valid = 0; |
649 | 651 | ||
650 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 652 | pos = dev->aer_cap; |
651 | 653 | ||
652 | /* The device might not support AER */ | 654 | /* The device might not support AER */ |
653 | if (!pos) | 655 | if (!pos) |
@@ -715,15 +717,8 @@ static inline void aer_process_err_devices(struct pcie_device *p_device, | |||
715 | static void aer_isr_one_error(struct pcie_device *p_device, | 717 | static void aer_isr_one_error(struct pcie_device *p_device, |
716 | struct aer_err_source *e_src) | 718 | struct aer_err_source *e_src) |
717 | { | 719 | { |
718 | struct aer_err_info *e_info; | 720 | struct aer_rpc *rpc = get_service_data(p_device); |
719 | 721 | struct aer_err_info *e_info = &rpc->e_info; | |
720 | /* struct aer_err_info might be big, so we allocate it with slab */ | ||
721 | e_info = kmalloc(sizeof(struct aer_err_info), GFP_KERNEL); | ||
722 | if (!e_info) { | ||
723 | dev_printk(KERN_DEBUG, &p_device->port->dev, | ||
724 | "Can't allocate mem when processing AER errors\n"); | ||
725 | return; | ||
726 | } | ||
727 | 722 | ||
728 | /* | 723 | /* |
729 | * There is a possibility that both correctable error and | 724 | * There is a possibility that both correctable error and |
@@ -762,8 +757,6 @@ static void aer_isr_one_error(struct pcie_device *p_device, | |||
762 | if (find_source_device(p_device->port, e_info)) | 757 | if (find_source_device(p_device->port, e_info)) |
763 | aer_process_err_devices(p_device, e_info); | 758 | aer_process_err_devices(p_device, e_info); |
764 | } | 759 | } |
765 | |||
766 | kfree(e_info); | ||
767 | } | 760 | } |
768 | 761 | ||
769 | /** | 762 | /** |
@@ -812,19 +805,3 @@ void aer_isr(struct work_struct *work) | |||
812 | aer_isr_one_error(p_device, &e_src); | 805 | aer_isr_one_error(p_device, &e_src); |
813 | mutex_unlock(&rpc->rpc_mutex); | 806 | mutex_unlock(&rpc->rpc_mutex); |
814 | } | 807 | } |
815 | |||
816 | /** | ||
817 | * aer_init - provide AER initialization | ||
818 | * @dev: pointer to AER pcie device | ||
819 | * | ||
820 | * Invoked when AER service driver is loaded. | ||
821 | */ | ||
822 | int aer_init(struct pcie_device *dev) | ||
823 | { | ||
824 | if (forceload) { | ||
825 | dev_printk(KERN_DEBUG, &dev->device, | ||
826 | "aerdrv forceload requested.\n"); | ||
827 | pcie_aer_force_firmware_first(dev->port, 0); | ||
828 | } | ||
829 | return 0; | ||
830 | } | ||
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index 167fe411ce2e..54c4b691e51f 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c | |||
@@ -219,15 +219,13 @@ int cper_severity_to_aer(int cper_severity) | |||
219 | } | 219 | } |
220 | EXPORT_SYMBOL_GPL(cper_severity_to_aer); | 220 | EXPORT_SYMBOL_GPL(cper_severity_to_aer); |
221 | 221 | ||
222 | void cper_print_aer(struct pci_dev *dev, int cper_severity, | 222 | void cper_print_aer(struct pci_dev *dev, int aer_severity, |
223 | struct aer_capability_regs *aer) | 223 | struct aer_capability_regs *aer) |
224 | { | 224 | { |
225 | int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0; | 225 | int layer, agent, status_strs_size, tlp_header_valid = 0; |
226 | u32 status, mask; | 226 | u32 status, mask; |
227 | const char **status_strs; | 227 | const char **status_strs; |
228 | 228 | ||
229 | aer_severity = cper_severity_to_aer(cper_severity); | ||
230 | |||
231 | if (aer_severity == AER_CORRECTABLE) { | 229 | if (aer_severity == AER_CORRECTABLE) { |
232 | status = aer->cor_status; | 230 | status = aer->cor_status; |
233 | mask = aer->cor_mask; | 231 | mask = aer->cor_mask; |
diff --git a/drivers/pci/pcie/pcie-dpc.c b/drivers/pci/pcie/pcie-dpc.c index 250f87861786..9811b14d9ad8 100644 --- a/drivers/pci/pcie/pcie-dpc.c +++ b/drivers/pci/pcie/pcie-dpc.c | |||
@@ -1,5 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * PCI Express Downstream Port Containment services driver | 2 | * PCI Express Downstream Port Containment services driver |
3 | * Author: Keith Busch <keith.busch@intel.com> | ||
4 | * | ||
3 | * Copyright (C) 2016 Intel Corp. | 5 | * Copyright (C) 2016 Intel Corp. |
4 | * | 6 | * |
5 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -9,7 +11,7 @@ | |||
9 | 11 | ||
10 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
11 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
12 | #include <linux/module.h> | 14 | #include <linux/init.h> |
13 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
14 | #include <linux/pcieport_if.h> | 16 | #include <linux/pcieport_if.h> |
15 | 17 | ||
@@ -143,16 +145,4 @@ static int __init dpc_service_init(void) | |||
143 | { | 145 | { |
144 | return pcie_port_service_register(&dpcdriver); | 146 | return pcie_port_service_register(&dpcdriver); |
145 | } | 147 | } |
146 | 148 | device_initcall(dpc_service_init); | |
147 | static void __exit dpc_service_exit(void) | ||
148 | { | ||
149 | pcie_port_service_unregister(&dpcdriver); | ||
150 | } | ||
151 | |||
152 | MODULE_DESCRIPTION("PCI Express Downstream Port Containment driver"); | ||
153 | MODULE_AUTHOR("Keith Busch <keith.busch@intel.com>"); | ||
154 | MODULE_LICENSE("GPL"); | ||
155 | MODULE_VERSION("0.1"); | ||
156 | |||
157 | module_init(dpc_service_init); | ||
158 | module_exit(dpc_service_exit); | ||
diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index 1ae4c73e7a3c..884bad5320f8 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c | |||
@@ -10,7 +10,6 @@ | |||
10 | * for more details. | 10 | * for more details. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
15 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
16 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
@@ -449,17 +448,6 @@ static int pcie_pme_resume(struct pcie_device *srv) | |||
449 | return 0; | 448 | return 0; |
450 | } | 449 | } |
451 | 450 | ||
452 | /** | ||
453 | * pcie_pme_remove - Prepare PCIe PME service device for removal. | ||
454 | * @srv - PCIe service device to remove. | ||
455 | */ | ||
456 | static void pcie_pme_remove(struct pcie_device *srv) | ||
457 | { | ||
458 | pcie_pme_suspend(srv); | ||
459 | free_irq(srv->irq, srv); | ||
460 | kfree(get_service_data(srv)); | ||
461 | } | ||
462 | |||
463 | static struct pcie_port_service_driver pcie_pme_driver = { | 451 | static struct pcie_port_service_driver pcie_pme_driver = { |
464 | .name = "pcie_pme", | 452 | .name = "pcie_pme", |
465 | .port_type = PCI_EXP_TYPE_ROOT_PORT, | 453 | .port_type = PCI_EXP_TYPE_ROOT_PORT, |
@@ -468,7 +456,6 @@ static struct pcie_port_service_driver pcie_pme_driver = { | |||
468 | .probe = pcie_pme_probe, | 456 | .probe = pcie_pme_probe, |
469 | .suspend = pcie_pme_suspend, | 457 | .suspend = pcie_pme_suspend, |
470 | .resume = pcie_pme_resume, | 458 | .resume = pcie_pme_resume, |
471 | .remove = pcie_pme_remove, | ||
472 | }; | 459 | }; |
473 | 460 | ||
474 | /** | 461 | /** |
@@ -478,5 +465,4 @@ static int __init pcie_pme_service_init(void) | |||
478 | { | 465 | { |
479 | return pcie_port_service_register(&pcie_pme_driver); | 466 | return pcie_port_service_register(&pcie_pme_driver); |
480 | } | 467 | } |
481 | 468 | device_initcall(pcie_pme_service_init); | |
482 | module_init(pcie_pme_service_init); | ||
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 70d7ad8c6d17..79327cc14e7d 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
@@ -1,12 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * File: portdrv_pci.c | 2 | * File: portdrv_pci.c |
3 | * Purpose: PCI Express Port Bus Driver | 3 | * Purpose: PCI Express Port Bus Driver |
4 | * Author: Tom Nguyen <tom.l.nguyen@intel.com> | ||
5 | * Version: v1.0 | ||
4 | * | 6 | * |
5 | * Copyright (C) 2004 Intel | 7 | * Copyright (C) 2004 Intel |
6 | * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) | 8 | * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) |
7 | */ | 9 | */ |
8 | 10 | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
11 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
12 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
@@ -21,16 +22,6 @@ | |||
21 | #include "portdrv.h" | 22 | #include "portdrv.h" |
22 | #include "aer/aerdrv.h" | 23 | #include "aer/aerdrv.h" |
23 | 24 | ||
24 | /* | ||
25 | * Version Information | ||
26 | */ | ||
27 | #define DRIVER_VERSION "v1.0" | ||
28 | #define DRIVER_AUTHOR "tom.l.nguyen@intel.com" | ||
29 | #define DRIVER_DESC "PCIe Port Bus Driver" | ||
30 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
31 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
32 | MODULE_LICENSE("GPL"); | ||
33 | |||
34 | /* If this switch is set, PCIe port native services should not be enabled. */ | 25 | /* If this switch is set, PCIe port native services should not be enabled. */ |
35 | bool pcie_ports_disabled; | 26 | bool pcie_ports_disabled; |
36 | 27 | ||
@@ -341,7 +332,6 @@ static const struct pci_device_id port_pci_ids[] = { { | |||
341 | PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0), | 332 | PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0), |
342 | }, { /* end: all zeroes */ } | 333 | }, { /* end: all zeroes */ } |
343 | }; | 334 | }; |
344 | MODULE_DEVICE_TABLE(pci, port_pci_ids); | ||
345 | 335 | ||
346 | static const struct pci_error_handlers pcie_portdrv_err_handler = { | 336 | static const struct pci_error_handlers pcie_portdrv_err_handler = { |
347 | .error_detected = pcie_portdrv_error_detected, | 337 | .error_detected = pcie_portdrv_error_detected, |
@@ -406,5 +396,4 @@ static int __init pcie_portdrv_init(void) | |||
406 | out: | 396 | out: |
407 | return retval; | 397 | return retval; |
408 | } | 398 | } |
409 | 399 | device_initcall(pcie_portdrv_init); | |
410 | module_init(pcie_portdrv_init); | ||
diff --git a/drivers/pci/pcie/ptm.c b/drivers/pci/pcie/ptm.c new file mode 100644 index 000000000000..bab8ac63c4f3 --- /dev/null +++ b/drivers/pci/pcie/ptm.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * PCI Express Precision Time Measurement | ||
3 | * Copyright (c) 2016, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include "../pci.h" | ||
19 | |||
20 | static void pci_ptm_info(struct pci_dev *dev) | ||
21 | { | ||
22 | char clock_desc[8]; | ||
23 | |||
24 | switch (dev->ptm_granularity) { | ||
25 | case 0: | ||
26 | snprintf(clock_desc, sizeof(clock_desc), "unknown"); | ||
27 | break; | ||
28 | case 255: | ||
29 | snprintf(clock_desc, sizeof(clock_desc), ">254ns"); | ||
30 | break; | ||
31 | default: | ||
32 | snprintf(clock_desc, sizeof(clock_desc), "%udns", | ||
33 | dev->ptm_granularity); | ||
34 | break; | ||
35 | } | ||
36 | dev_info(&dev->dev, "PTM enabled%s, %s granularity\n", | ||
37 | dev->ptm_root ? " (root)" : "", clock_desc); | ||
38 | } | ||
39 | |||
40 | void pci_ptm_init(struct pci_dev *dev) | ||
41 | { | ||
42 | int pos; | ||
43 | u32 cap, ctrl; | ||
44 | u8 local_clock; | ||
45 | struct pci_dev *ups; | ||
46 | |||
47 | if (!pci_is_pcie(dev)) | ||
48 | return; | ||
49 | |||
50 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PTM); | ||
51 | if (!pos) | ||
52 | return; | ||
53 | |||
54 | /* | ||
55 | * Enable PTM only on interior devices (root ports, switch ports, | ||
56 | * etc.) on the assumption that it causes no link traffic until an | ||
57 | * endpoint enables it. | ||
58 | */ | ||
59 | if ((pci_pcie_type(dev) == PCI_EXP_TYPE_ENDPOINT || | ||
60 | pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END)) | ||
61 | return; | ||
62 | |||
63 | pci_read_config_dword(dev, pos + PCI_PTM_CAP, &cap); | ||
64 | local_clock = (cap & PCI_PTM_GRANULARITY_MASK) >> 8; | ||
65 | |||
66 | /* | ||
67 | * There's no point in enabling PTM unless it's enabled in the | ||
68 | * upstream device or this device can be a PTM Root itself. Per | ||
69 | * the spec recommendation (PCIe r3.1, sec 7.32.3), select the | ||
70 | * furthest upstream Time Source as the PTM Root. | ||
71 | */ | ||
72 | ups = pci_upstream_bridge(dev); | ||
73 | if (ups && ups->ptm_enabled) { | ||
74 | ctrl = PCI_PTM_CTRL_ENABLE; | ||
75 | if (ups->ptm_granularity == 0) | ||
76 | dev->ptm_granularity = 0; | ||
77 | else if (ups->ptm_granularity > local_clock) | ||
78 | dev->ptm_granularity = ups->ptm_granularity; | ||
79 | } else { | ||
80 | if (cap & PCI_PTM_CAP_ROOT) { | ||
81 | ctrl = PCI_PTM_CTRL_ENABLE | PCI_PTM_CTRL_ROOT; | ||
82 | dev->ptm_root = 1; | ||
83 | dev->ptm_granularity = local_clock; | ||
84 | } else | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | ctrl |= dev->ptm_granularity << 8; | ||
89 | pci_write_config_dword(dev, pos + PCI_PTM_CTRL, ctrl); | ||
90 | dev->ptm_enabled = 1; | ||
91 | |||
92 | pci_ptm_info(dev); | ||
93 | } | ||
94 | |||
95 | int pci_enable_ptm(struct pci_dev *dev, u8 *granularity) | ||
96 | { | ||
97 | int pos; | ||
98 | u32 cap, ctrl; | ||
99 | struct pci_dev *ups; | ||
100 | |||
101 | if (!pci_is_pcie(dev)) | ||
102 | return -EINVAL; | ||
103 | |||
104 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PTM); | ||
105 | if (!pos) | ||
106 | return -EINVAL; | ||
107 | |||
108 | pci_read_config_dword(dev, pos + PCI_PTM_CAP, &cap); | ||
109 | if (!(cap & PCI_PTM_CAP_REQ)) | ||
110 | return -EINVAL; | ||
111 | |||
112 | /* | ||
113 | * For a PCIe Endpoint, PTM is only useful if the endpoint can | ||
114 | * issue PTM requests to upstream devices that have PTM enabled. | ||
115 | * | ||
116 | * For Root Complex Integrated Endpoints, there is no upstream | ||
117 | * device, so there must be some implementation-specific way to | ||
118 | * associate the endpoint with a time source. | ||
119 | */ | ||
120 | if (pci_pcie_type(dev) == PCI_EXP_TYPE_ENDPOINT) { | ||
121 | ups = pci_upstream_bridge(dev); | ||
122 | if (!ups || !ups->ptm_enabled) | ||
123 | return -EINVAL; | ||
124 | |||
125 | dev->ptm_granularity = ups->ptm_granularity; | ||
126 | } else if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) { | ||
127 | dev->ptm_granularity = 0; | ||
128 | } else | ||
129 | return -EINVAL; | ||
130 | |||
131 | ctrl = PCI_PTM_CTRL_ENABLE; | ||
132 | ctrl |= dev->ptm_granularity << 8; | ||
133 | pci_write_config_dword(dev, pos + PCI_PTM_CTRL, ctrl); | ||
134 | dev->ptm_enabled = 1; | ||
135 | |||
136 | pci_ptm_info(dev); | ||
137 | |||
138 | if (granularity) | ||
139 | *granularity = dev->ptm_granularity; | ||
140 | return 0; | ||
141 | } | ||
142 | EXPORT_SYMBOL(pci_enable_ptm); | ||
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 93f280df3428..ab002671fa60 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -1666,7 +1666,11 @@ static void pci_init_capabilities(struct pci_dev *dev) | |||
1666 | /* Enable ACS P2P upstream forwarding */ | 1666 | /* Enable ACS P2P upstream forwarding */ |
1667 | pci_enable_acs(dev); | 1667 | pci_enable_acs(dev); |
1668 | 1668 | ||
1669 | pci_cleanup_aer_error_status_regs(dev); | 1669 | /* Precision Time Measurement */ |
1670 | pci_ptm_init(dev); | ||
1671 | |||
1672 | /* Advanced Error Reporting */ | ||
1673 | pci_aer_init(dev); | ||
1670 | } | 1674 | } |
1671 | 1675 | ||
1672 | /* | 1676 | /* |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 37ff0158e45f..6297942649bf 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -4428,3 +4428,20 @@ static void quirk_intel_qat_vf_cap(struct pci_dev *pdev) | |||
4428 | } | 4428 | } |
4429 | } | 4429 | } |
4430 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x443, quirk_intel_qat_vf_cap); | 4430 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x443, quirk_intel_qat_vf_cap); |
4431 | |||
4432 | /* | ||
4433 | * VMD-enabled root ports will change the source ID for all messages | ||
4434 | * to the VMD device. Rather than doing device matching with the source | ||
4435 | * ID, the AER driver should traverse the child device tree, reading | ||
4436 | * AER registers to find the faulting device. | ||
4437 | */ | ||
4438 | static void quirk_no_aersid(struct pci_dev *pdev) | ||
4439 | { | ||
4440 | /* VMD Domain */ | ||
4441 | if (pdev->bus->sysdata && pci_domain_nr(pdev->bus) >= 0x10000) | ||
4442 | pdev->bus->bus_flags |= PCI_BUS_FLAGS_NO_AERSID; | ||
4443 | } | ||
4444 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2030, quirk_no_aersid); | ||
4445 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid); | ||
4446 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid); | ||
4447 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid); | ||
diff --git a/include/linux/aer.h b/include/linux/aer.h index 164049357e5c..04602cbe85dc 100644 --- a/include/linux/aer.h +++ b/include/linux/aer.h | |||
@@ -63,7 +63,7 @@ static inline int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) | |||
63 | } | 63 | } |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | void cper_print_aer(struct pci_dev *dev, int cper_severity, | 66 | void cper_print_aer(struct pci_dev *dev, int aer_severity, |
67 | struct aer_capability_regs *aer); | 67 | struct aer_capability_regs *aer); |
68 | int cper_severity_to_aer(int cper_severity); | 68 | int cper_severity_to_aer(int cper_severity); |
69 | void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, | 69 | void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 2599a980340f..b0e4ed19b315 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -187,8 +187,9 @@ enum pci_irq_reroute_variant { | |||
187 | 187 | ||
188 | typedef unsigned short __bitwise pci_bus_flags_t; | 188 | typedef unsigned short __bitwise pci_bus_flags_t; |
189 | enum pci_bus_flags { | 189 | enum pci_bus_flags { |
190 | PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, | 190 | PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, |
191 | PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2, | 191 | PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2, |
192 | PCI_BUS_FLAGS_NO_AERSID = (__force pci_bus_flags_t) 4, | ||
192 | }; | 193 | }; |
193 | 194 | ||
194 | /* These values come from the PCI Express Spec */ | 195 | /* These values come from the PCI Express Spec */ |
@@ -268,6 +269,9 @@ struct pci_dev { | |||
268 | unsigned int class; /* 3 bytes: (base,sub,prog-if) */ | 269 | unsigned int class; /* 3 bytes: (base,sub,prog-if) */ |
269 | u8 revision; /* PCI revision, low byte of class word */ | 270 | u8 revision; /* PCI revision, low byte of class word */ |
270 | u8 hdr_type; /* PCI header type (`multi' flag masked out) */ | 271 | u8 hdr_type; /* PCI header type (`multi' flag masked out) */ |
272 | #ifdef CONFIG_PCIEAER | ||
273 | u16 aer_cap; /* AER capability offset */ | ||
274 | #endif | ||
271 | u8 pcie_cap; /* PCIe capability offset */ | 275 | u8 pcie_cap; /* PCIe capability offset */ |
272 | u8 msi_cap; /* MSI capability offset */ | 276 | u8 msi_cap; /* MSI capability offset */ |
273 | u8 msix_cap; /* MSI-X capability offset */ | 277 | u8 msix_cap; /* MSI-X capability offset */ |
@@ -308,6 +312,9 @@ struct pci_dev { | |||
308 | powered on/off by the | 312 | powered on/off by the |
309 | corresponding bridge */ | 313 | corresponding bridge */ |
310 | unsigned int ignore_hotplug:1; /* Ignore hotplug events */ | 314 | unsigned int ignore_hotplug:1; /* Ignore hotplug events */ |
315 | unsigned int hotplug_user_indicators:1; /* SlotCtl indicators | ||
316 | controlled exclusively by | ||
317 | user sysfs */ | ||
311 | unsigned int d3_delay; /* D3->D0 transition time in ms */ | 318 | unsigned int d3_delay; /* D3->D0 transition time in ms */ |
312 | unsigned int d3cold_delay; /* D3cold->D0 transition time in ms */ | 319 | unsigned int d3cold_delay; /* D3cold->D0 transition time in ms */ |
313 | 320 | ||
@@ -367,6 +374,12 @@ struct pci_dev { | |||
367 | int rom_attr_enabled; /* has display of the rom attribute been enabled? */ | 374 | int rom_attr_enabled; /* has display of the rom attribute been enabled? */ |
368 | struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ | 375 | struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ |
369 | struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */ | 376 | struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */ |
377 | |||
378 | #ifdef CONFIG_PCIE_PTM | ||
379 | unsigned int ptm_root:1; | ||
380 | unsigned int ptm_enabled:1; | ||
381 | u8 ptm_granularity; | ||
382 | #endif | ||
370 | #ifdef CONFIG_PCI_MSI | 383 | #ifdef CONFIG_PCI_MSI |
371 | const struct attribute_group **msi_irq_groups; | 384 | const struct attribute_group **msi_irq_groups; |
372 | #endif | 385 | #endif |
@@ -1368,9 +1381,11 @@ static inline bool pcie_aspm_support_enabled(void) { return false; } | |||
1368 | #ifdef CONFIG_PCIEAER | 1381 | #ifdef CONFIG_PCIEAER |
1369 | void pci_no_aer(void); | 1382 | void pci_no_aer(void); |
1370 | bool pci_aer_available(void); | 1383 | bool pci_aer_available(void); |
1384 | int pci_aer_init(struct pci_dev *dev); | ||
1371 | #else | 1385 | #else |
1372 | static inline void pci_no_aer(void) { } | 1386 | static inline void pci_no_aer(void) { } |
1373 | static inline bool pci_aer_available(void) { return false; } | 1387 | static inline bool pci_aer_available(void) { return false; } |
1388 | static inline int pci_aer_init(struct pci_dev *d) { return -ENODEV; } | ||
1374 | #endif | 1389 | #endif |
1375 | 1390 | ||
1376 | #ifdef CONFIG_PCIE_ECRC | 1391 | #ifdef CONFIG_PCIE_ECRC |
@@ -1402,6 +1417,13 @@ static inline void pci_disable_ats(struct pci_dev *d) { } | |||
1402 | static inline int pci_ats_queue_depth(struct pci_dev *d) { return -ENODEV; } | 1417 | static inline int pci_ats_queue_depth(struct pci_dev *d) { return -ENODEV; } |
1403 | #endif | 1418 | #endif |
1404 | 1419 | ||
1420 | #ifdef CONFIG_PCIE_PTM | ||
1421 | int pci_enable_ptm(struct pci_dev *dev, u8 *granularity); | ||
1422 | #else | ||
1423 | static inline int pci_enable_ptm(struct pci_dev *dev, u8 *granularity) | ||
1424 | { return -EINVAL; } | ||
1425 | #endif | ||
1426 | |||
1405 | void pci_cfg_access_lock(struct pci_dev *dev); | 1427 | void pci_cfg_access_lock(struct pci_dev *dev); |
1406 | bool pci_cfg_access_trylock(struct pci_dev *dev); | 1428 | bool pci_cfg_access_trylock(struct pci_dev *dev); |
1407 | void pci_cfg_access_unlock(struct pci_dev *dev); | 1429 | void pci_cfg_access_unlock(struct pci_dev *dev); |
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 404095124ae2..d812172d1d7b 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h | |||
@@ -671,7 +671,8 @@ | |||
671 | #define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */ | 671 | #define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */ |
672 | #define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */ | 672 | #define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */ |
673 | #define PCI_EXT_CAP_ID_DPC 0x1D /* Downstream Port Containment */ | 673 | #define PCI_EXT_CAP_ID_DPC 0x1D /* Downstream Port Containment */ |
674 | #define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_DPC | 674 | #define PCI_EXT_CAP_ID_PTM 0x1F /* Precision Time Measurement */ |
675 | #define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PTM | ||
675 | 676 | ||
676 | #define PCI_EXT_CAP_DSN_SIZEOF 12 | 677 | #define PCI_EXT_CAP_DSN_SIZEOF 12 |
677 | #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 | 678 | #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 |
@@ -964,4 +965,13 @@ | |||
964 | 965 | ||
965 | #define PCI_EXP_DPC_SOURCE_ID 10 /* DPC Source Identifier */ | 966 | #define PCI_EXP_DPC_SOURCE_ID 10 /* DPC Source Identifier */ |
966 | 967 | ||
968 | /* Precision Time Measurement */ | ||
969 | #define PCI_PTM_CAP 0x04 /* PTM Capability */ | ||
970 | #define PCI_PTM_CAP_REQ 0x00000001 /* Requester capable */ | ||
971 | #define PCI_PTM_CAP_ROOT 0x00000004 /* Root capable */ | ||
972 | #define PCI_PTM_GRANULARITY_MASK 0x0000FF00 /* Clock granularity */ | ||
973 | #define PCI_PTM_CTRL 0x08 /* PTM Control */ | ||
974 | #define PCI_PTM_CTRL_ENABLE 0x00000001 /* PTM enable */ | ||
975 | #define PCI_PTM_CTRL_ROOT 0x00000002 /* Root select */ | ||
976 | |||
967 | #endif /* LINUX_PCI_REGS_H */ | 977 | #endif /* LINUX_PCI_REGS_H */ |