diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-05-21 18:58:21 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-05-24 04:13:45 -0400 |
commit | b72c1f651491e4cd33ddec79c504a49071a512f0 (patch) | |
tree | bd17bad6c182c986bbadd5a30d1afe98804f07ea /arch | |
parent | 59affcd3e460b97492bc1aa2b843bafe7c54f596 (diff) |
powerpc: Make radeon 32-bit MSI quirk work on powernv
This moves the quirk itself to pci_64.c as to get built on all ppc64
platforms (the only ones with a pci_dn), factors the two implementations
of get_pdn() into a single pci_get_dn() and use the quirk to do 32-bit
MSIs on IODA based powernv platforms.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/include/asm/pci-bridge.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 10 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_dn.c | 8 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci-ioda.c | 27 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/msi.c | 35 |
6 files changed, 38 insertions, 48 deletions
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 8b11b5bd9938..2c1d8cb9b265 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h | |||
@@ -174,6 +174,8 @@ struct pci_dn { | |||
174 | /* Get the pointer to a device_node's pci_dn */ | 174 | /* Get the pointer to a device_node's pci_dn */ |
175 | #define PCI_DN(dn) ((struct pci_dn *) (dn)->data) | 175 | #define PCI_DN(dn) ((struct pci_dn *) (dn)->data) |
176 | 176 | ||
177 | extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev); | ||
178 | |||
177 | extern void * update_dn_pci_info(struct device_node *dn, void *data); | 179 | extern void * update_dn_pci_info(struct device_node *dn, void *data); |
178 | 180 | ||
179 | static inline int pci_device_from_OF_node(struct device_node *np, | 181 | static inline int pci_device_from_OF_node(struct device_node *np, |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 873050d26840..2e8629654ca8 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -266,3 +266,13 @@ int pcibus_to_node(struct pci_bus *bus) | |||
266 | } | 266 | } |
267 | EXPORT_SYMBOL(pcibus_to_node); | 267 | EXPORT_SYMBOL(pcibus_to_node); |
268 | #endif | 268 | #endif |
269 | |||
270 | static void quirk_radeon_32bit_msi(struct pci_dev *dev) | ||
271 | { | ||
272 | struct pci_dn *pdn = pci_get_pdn(dev); | ||
273 | |||
274 | if (pdn) | ||
275 | pdn->force_32bit_msi = 1; | ||
276 | } | ||
277 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon_32bit_msi); | ||
278 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon_32bit_msi); | ||
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index e7af165f8b9d..df038442548a 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c | |||
@@ -32,6 +32,14 @@ | |||
32 | #include <asm/ppc-pci.h> | 32 | #include <asm/ppc-pci.h> |
33 | #include <asm/firmware.h> | 33 | #include <asm/firmware.h> |
34 | 34 | ||
35 | struct pci_dn *pci_get_pdn(struct pci_dev *pdev) | ||
36 | { | ||
37 | struct device_node *dn = pci_device_to_OF_node(pdev); | ||
38 | if (!dn) | ||
39 | return NULL; | ||
40 | return PCI_DN(dn); | ||
41 | } | ||
42 | |||
35 | /* | 43 | /* |
36 | * Traverse_func that inits the PCI fields of the device node. | 44 | * Traverse_func that inits the PCI fields of the device node. |
37 | * NOTE: this *must* be done before read/write config to the device. | 45 | * NOTE: this *must* be done before read/write config to the device. |
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 3937aaae5bc4..9c9d15e4cdf2 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
@@ -68,16 +68,6 @@ define_pe_printk_level(pe_err, KERN_ERR); | |||
68 | define_pe_printk_level(pe_warn, KERN_WARNING); | 68 | define_pe_printk_level(pe_warn, KERN_WARNING); |
69 | define_pe_printk_level(pe_info, KERN_INFO); | 69 | define_pe_printk_level(pe_info, KERN_INFO); |
70 | 70 | ||
71 | static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev) | ||
72 | { | ||
73 | struct device_node *np; | ||
74 | |||
75 | np = pci_device_to_OF_node(dev); | ||
76 | if (!np) | ||
77 | return NULL; | ||
78 | return PCI_DN(np); | ||
79 | } | ||
80 | |||
81 | static int pnv_ioda_alloc_pe(struct pnv_phb *phb) | 71 | static int pnv_ioda_alloc_pe(struct pnv_phb *phb) |
82 | { | 72 | { |
83 | unsigned long pe; | 73 | unsigned long pe; |
@@ -110,7 +100,7 @@ static struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev) | |||
110 | { | 100 | { |
111 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | 101 | struct pci_controller *hose = pci_bus_to_host(dev->bus); |
112 | struct pnv_phb *phb = hose->private_data; | 102 | struct pnv_phb *phb = hose->private_data; |
113 | struct pci_dn *pdn = pnv_ioda_get_pdn(dev); | 103 | struct pci_dn *pdn = pci_get_pdn(dev); |
114 | 104 | ||
115 | if (!pdn) | 105 | if (!pdn) |
116 | return NULL; | 106 | return NULL; |
@@ -173,7 +163,7 @@ static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) | |||
173 | 163 | ||
174 | /* Add to all parents PELT-V */ | 164 | /* Add to all parents PELT-V */ |
175 | while (parent) { | 165 | while (parent) { |
176 | struct pci_dn *pdn = pnv_ioda_get_pdn(parent); | 166 | struct pci_dn *pdn = pci_get_pdn(parent); |
177 | if (pdn && pdn->pe_number != IODA_INVALID_PE) { | 167 | if (pdn && pdn->pe_number != IODA_INVALID_PE) { |
178 | rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number, | 168 | rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number, |
179 | pe->pe_number, OPAL_ADD_PE_TO_DOMAIN); | 169 | pe->pe_number, OPAL_ADD_PE_TO_DOMAIN); |
@@ -252,7 +242,7 @@ static struct pnv_ioda_pe *pnv_ioda_setup_dev_PE(struct pci_dev *dev) | |||
252 | { | 242 | { |
253 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | 243 | struct pci_controller *hose = pci_bus_to_host(dev->bus); |
254 | struct pnv_phb *phb = hose->private_data; | 244 | struct pnv_phb *phb = hose->private_data; |
255 | struct pci_dn *pdn = pnv_ioda_get_pdn(dev); | 245 | struct pci_dn *pdn = pci_get_pdn(dev); |
256 | struct pnv_ioda_pe *pe; | 246 | struct pnv_ioda_pe *pe; |
257 | int pe_num; | 247 | int pe_num; |
258 | 248 | ||
@@ -323,7 +313,7 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe) | |||
323 | struct pci_dev *dev; | 313 | struct pci_dev *dev; |
324 | 314 | ||
325 | list_for_each_entry(dev, &bus->devices, bus_list) { | 315 | list_for_each_entry(dev, &bus->devices, bus_list) { |
326 | struct pci_dn *pdn = pnv_ioda_get_pdn(dev); | 316 | struct pci_dn *pdn = pci_get_pdn(dev); |
327 | 317 | ||
328 | if (pdn == NULL) { | 318 | if (pdn == NULL) { |
329 | pr_warn("%s: No device node associated with device !\n", | 319 | pr_warn("%s: No device node associated with device !\n", |
@@ -436,7 +426,7 @@ static void pnv_pci_ioda_setup_PEs(void) | |||
436 | 426 | ||
437 | static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev) | 427 | static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev) |
438 | { | 428 | { |
439 | struct pci_dn *pdn = pnv_ioda_get_pdn(pdev); | 429 | struct pci_dn *pdn = pci_get_pdn(pdev); |
440 | struct pnv_ioda_pe *pe; | 430 | struct pnv_ioda_pe *pe; |
441 | 431 | ||
442 | /* | 432 | /* |
@@ -768,6 +758,7 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, | |||
768 | unsigned int is_64, struct msi_msg *msg) | 758 | unsigned int is_64, struct msi_msg *msg) |
769 | { | 759 | { |
770 | struct pnv_ioda_pe *pe = pnv_ioda_get_pe(dev); | 760 | struct pnv_ioda_pe *pe = pnv_ioda_get_pe(dev); |
761 | struct pci_dn *pdn = pci_get_pdn(dev); | ||
771 | struct irq_data *idata; | 762 | struct irq_data *idata; |
772 | struct irq_chip *ichip; | 763 | struct irq_chip *ichip; |
773 | unsigned int xive_num = hwirq - phb->msi_base; | 764 | unsigned int xive_num = hwirq - phb->msi_base; |
@@ -783,6 +774,10 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, | |||
783 | if (pe->mve_number < 0) | 774 | if (pe->mve_number < 0) |
784 | return -ENXIO; | 775 | return -ENXIO; |
785 | 776 | ||
777 | /* Force 32-bit MSI on some broken devices */ | ||
778 | if (pdn && pdn->force_32bit_msi) | ||
779 | is_64 = 0; | ||
780 | |||
786 | /* Assign XIVE to PE */ | 781 | /* Assign XIVE to PE */ |
787 | rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num); | 782 | rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num); |
788 | if (rc) { | 783 | if (rc) { |
@@ -1035,7 +1030,7 @@ static int pnv_pci_enable_device_hook(struct pci_dev *dev) | |||
1035 | if (!phb->initialized) | 1030 | if (!phb->initialized) |
1036 | return 0; | 1031 | return 0; |
1037 | 1032 | ||
1038 | pdn = pnv_ioda_get_pdn(dev); | 1033 | pdn = pci_get_pdn(dev); |
1039 | if (!pdn || pdn->pe_number == IODA_INVALID_PE) | 1034 | if (!pdn || pdn->pe_number == IODA_INVALID_PE) |
1040 | return -EINVAL; | 1035 | return -EINVAL; |
1041 | 1036 | ||
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 098d3573315c..277343cc6a3d 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c | |||
@@ -47,6 +47,10 @@ static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type) | |||
47 | { | 47 | { |
48 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | 48 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); |
49 | struct pnv_phb *phb = hose->private_data; | 49 | struct pnv_phb *phb = hose->private_data; |
50 | struct pci_dn *pdn = pci_get_pdn(pdev); | ||
51 | |||
52 | if (pdn && pdn->force_32bit_msi && !phb->msi32_support) | ||
53 | return -ENODEV; | ||
50 | 54 | ||
51 | return (phb && phb->msi_bmp.bitmap) ? 0 : -ENODEV; | 55 | return (phb && phb->msi_bmp.bitmap) ? 0 : -ENODEV; |
52 | } | 56 | } |
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index 420524e6f8c9..d34f4ffdb796 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c | |||
@@ -26,26 +26,6 @@ static int query_token, change_token; | |||
26 | #define RTAS_CHANGE_MSIX_FN 4 | 26 | #define RTAS_CHANGE_MSIX_FN 4 |
27 | #define RTAS_CHANGE_32MSI_FN 5 | 27 | #define RTAS_CHANGE_32MSI_FN 5 |
28 | 28 | ||
29 | static struct pci_dn *get_pdn(struct pci_dev *pdev) | ||
30 | { | ||
31 | struct device_node *dn; | ||
32 | struct pci_dn *pdn; | ||
33 | |||
34 | dn = pci_device_to_OF_node(pdev); | ||
35 | if (!dn) { | ||
36 | dev_dbg(&pdev->dev, "rtas_msi: No OF device node\n"); | ||
37 | return NULL; | ||
38 | } | ||
39 | |||
40 | pdn = PCI_DN(dn); | ||
41 | if (!pdn) { | ||
42 | dev_dbg(&pdev->dev, "rtas_msi: No PCI DN\n"); | ||
43 | return NULL; | ||
44 | } | ||
45 | |||
46 | return pdn; | ||
47 | } | ||
48 | |||
49 | /* RTAS Helpers */ | 29 | /* RTAS Helpers */ |
50 | 30 | ||
51 | static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs) | 31 | static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs) |
@@ -91,7 +71,7 @@ static void rtas_disable_msi(struct pci_dev *pdev) | |||
91 | { | 71 | { |
92 | struct pci_dn *pdn; | 72 | struct pci_dn *pdn; |
93 | 73 | ||
94 | pdn = get_pdn(pdev); | 74 | pdn = pci_get_pdn(pdev); |
95 | if (!pdn) | 75 | if (!pdn) |
96 | return; | 76 | return; |
97 | 77 | ||
@@ -152,7 +132,7 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name) | |||
152 | struct pci_dn *pdn; | 132 | struct pci_dn *pdn; |
153 | const u32 *req_msi; | 133 | const u32 *req_msi; |
154 | 134 | ||
155 | pdn = get_pdn(pdev); | 135 | pdn = pci_get_pdn(pdev); |
156 | if (!pdn) | 136 | if (!pdn) |
157 | return -ENODEV; | 137 | return -ENODEV; |
158 | 138 | ||
@@ -402,7 +382,7 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) | |||
402 | struct msi_msg msg; | 382 | struct msi_msg msg; |
403 | int nvec = nvec_in; | 383 | int nvec = nvec_in; |
404 | 384 | ||
405 | pdn = get_pdn(pdev); | 385 | pdn = pci_get_pdn(pdev); |
406 | if (!pdn) | 386 | if (!pdn) |
407 | return -ENODEV; | 387 | return -ENODEV; |
408 | 388 | ||
@@ -518,12 +498,3 @@ static int rtas_msi_init(void) | |||
518 | } | 498 | } |
519 | arch_initcall(rtas_msi_init); | 499 | arch_initcall(rtas_msi_init); |
520 | 500 | ||
521 | static void quirk_radeon(struct pci_dev *dev) | ||
522 | { | ||
523 | struct pci_dn *pdn = get_pdn(dev); | ||
524 | |||
525 | if (pdn) | ||
526 | pdn->force_32bit_msi = 1; | ||
527 | } | ||
528 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon); | ||
529 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon); | ||