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: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 59affcd3
...@@ -174,6 +174,8 @@ struct pci_dn { ...@@ -174,6 +174,8 @@ struct pci_dn {
/* Get the pointer to a device_node's pci_dn */ /* Get the pointer to a device_node's pci_dn */
#define PCI_DN(dn) ((struct pci_dn *) (dn)->data) #define PCI_DN(dn) ((struct pci_dn *) (dn)->data)
extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev);
extern void * update_dn_pci_info(struct device_node *dn, void *data); extern void * update_dn_pci_info(struct device_node *dn, void *data);
static inline int pci_device_from_OF_node(struct device_node *np, static inline int pci_device_from_OF_node(struct device_node *np,
......
...@@ -266,3 +266,13 @@ int pcibus_to_node(struct pci_bus *bus) ...@@ -266,3 +266,13 @@ int pcibus_to_node(struct pci_bus *bus)
} }
EXPORT_SYMBOL(pcibus_to_node); EXPORT_SYMBOL(pcibus_to_node);
#endif #endif
static void quirk_radeon_32bit_msi(struct pci_dev *dev)
{
struct pci_dn *pdn = pci_get_pdn(dev);
if (pdn)
pdn->force_32bit_msi = 1;
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon_32bit_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon_32bit_msi);
...@@ -32,6 +32,14 @@ ...@@ -32,6 +32,14 @@
#include <asm/ppc-pci.h> #include <asm/ppc-pci.h>
#include <asm/firmware.h> #include <asm/firmware.h>
struct pci_dn *pci_get_pdn(struct pci_dev *pdev)
{
struct device_node *dn = pci_device_to_OF_node(pdev);
if (!dn)
return NULL;
return PCI_DN(dn);
}
/* /*
* Traverse_func that inits the PCI fields of the device node. * Traverse_func that inits the PCI fields of the device node.
* NOTE: this *must* be done before read/write config to the device. * NOTE: this *must* be done before read/write config to the device.
......
...@@ -68,16 +68,6 @@ define_pe_printk_level(pe_err, KERN_ERR); ...@@ -68,16 +68,6 @@ define_pe_printk_level(pe_err, KERN_ERR);
define_pe_printk_level(pe_warn, KERN_WARNING); define_pe_printk_level(pe_warn, KERN_WARNING);
define_pe_printk_level(pe_info, KERN_INFO); define_pe_printk_level(pe_info, KERN_INFO);
static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev)
{
struct device_node *np;
np = pci_device_to_OF_node(dev);
if (!np)
return NULL;
return PCI_DN(np);
}
static int pnv_ioda_alloc_pe(struct pnv_phb *phb) static int pnv_ioda_alloc_pe(struct pnv_phb *phb)
{ {
unsigned long pe; unsigned long pe;
...@@ -110,7 +100,7 @@ static struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev) ...@@ -110,7 +100,7 @@ static struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev)
{ {
struct pci_controller *hose = pci_bus_to_host(dev->bus); struct pci_controller *hose = pci_bus_to_host(dev->bus);
struct pnv_phb *phb = hose->private_data; struct pnv_phb *phb = hose->private_data;
struct pci_dn *pdn = pnv_ioda_get_pdn(dev); struct pci_dn *pdn = pci_get_pdn(dev);
if (!pdn) if (!pdn)
return NULL; return NULL;
...@@ -173,7 +163,7 @@ static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) ...@@ -173,7 +163,7 @@ static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe)
/* Add to all parents PELT-V */ /* Add to all parents PELT-V */
while (parent) { while (parent) {
struct pci_dn *pdn = pnv_ioda_get_pdn(parent); struct pci_dn *pdn = pci_get_pdn(parent);
if (pdn && pdn->pe_number != IODA_INVALID_PE) { if (pdn && pdn->pe_number != IODA_INVALID_PE) {
rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number, rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number,
pe->pe_number, OPAL_ADD_PE_TO_DOMAIN); 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,7 +242,7 @@ static struct pnv_ioda_pe *pnv_ioda_setup_dev_PE(struct pci_dev *dev)
{ {
struct pci_controller *hose = pci_bus_to_host(dev->bus); struct pci_controller *hose = pci_bus_to_host(dev->bus);
struct pnv_phb *phb = hose->private_data; struct pnv_phb *phb = hose->private_data;
struct pci_dn *pdn = pnv_ioda_get_pdn(dev); struct pci_dn *pdn = pci_get_pdn(dev);
struct pnv_ioda_pe *pe; struct pnv_ioda_pe *pe;
int pe_num; int pe_num;
...@@ -323,7 +313,7 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe) ...@@ -323,7 +313,7 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe)
struct pci_dev *dev; struct pci_dev *dev;
list_for_each_entry(dev, &bus->devices, bus_list) { list_for_each_entry(dev, &bus->devices, bus_list) {
struct pci_dn *pdn = pnv_ioda_get_pdn(dev); struct pci_dn *pdn = pci_get_pdn(dev);
if (pdn == NULL) { if (pdn == NULL) {
pr_warn("%s: No device node associated with device !\n", pr_warn("%s: No device node associated with device !\n",
...@@ -436,7 +426,7 @@ static void pnv_pci_ioda_setup_PEs(void) ...@@ -436,7 +426,7 @@ static void pnv_pci_ioda_setup_PEs(void)
static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev) static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev)
{ {
struct pci_dn *pdn = pnv_ioda_get_pdn(pdev); struct pci_dn *pdn = pci_get_pdn(pdev);
struct pnv_ioda_pe *pe; struct pnv_ioda_pe *pe;
/* /*
...@@ -768,6 +758,7 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, ...@@ -768,6 +758,7 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
unsigned int is_64, struct msi_msg *msg) unsigned int is_64, struct msi_msg *msg)
{ {
struct pnv_ioda_pe *pe = pnv_ioda_get_pe(dev); struct pnv_ioda_pe *pe = pnv_ioda_get_pe(dev);
struct pci_dn *pdn = pci_get_pdn(dev);
struct irq_data *idata; struct irq_data *idata;
struct irq_chip *ichip; struct irq_chip *ichip;
unsigned int xive_num = hwirq - phb->msi_base; 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,6 +774,10 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
if (pe->mve_number < 0) if (pe->mve_number < 0)
return -ENXIO; return -ENXIO;
/* Force 32-bit MSI on some broken devices */
if (pdn && pdn->force_32bit_msi)
is_64 = 0;
/* Assign XIVE to PE */ /* Assign XIVE to PE */
rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num); rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num);
if (rc) { if (rc) {
...@@ -1035,7 +1030,7 @@ static int pnv_pci_enable_device_hook(struct pci_dev *dev) ...@@ -1035,7 +1030,7 @@ static int pnv_pci_enable_device_hook(struct pci_dev *dev)
if (!phb->initialized) if (!phb->initialized)
return 0; return 0;
pdn = pnv_ioda_get_pdn(dev); pdn = pci_get_pdn(dev);
if (!pdn || pdn->pe_number == IODA_INVALID_PE) if (!pdn || pdn->pe_number == IODA_INVALID_PE)
return -EINVAL; return -EINVAL;
......
...@@ -47,6 +47,10 @@ static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type) ...@@ -47,6 +47,10 @@ static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type)
{ {
struct pci_controller *hose = pci_bus_to_host(pdev->bus); struct pci_controller *hose = pci_bus_to_host(pdev->bus);
struct pnv_phb *phb = hose->private_data; struct pnv_phb *phb = hose->private_data;
struct pci_dn *pdn = pci_get_pdn(pdev);
if (pdn && pdn->force_32bit_msi && !phb->msi32_support)
return -ENODEV;
return (phb && phb->msi_bmp.bitmap) ? 0 : -ENODEV; return (phb && phb->msi_bmp.bitmap) ? 0 : -ENODEV;
} }
......
...@@ -26,26 +26,6 @@ static int query_token, change_token; ...@@ -26,26 +26,6 @@ static int query_token, change_token;
#define RTAS_CHANGE_MSIX_FN 4 #define RTAS_CHANGE_MSIX_FN 4
#define RTAS_CHANGE_32MSI_FN 5 #define RTAS_CHANGE_32MSI_FN 5
static struct pci_dn *get_pdn(struct pci_dev *pdev)
{
struct device_node *dn;
struct pci_dn *pdn;
dn = pci_device_to_OF_node(pdev);
if (!dn) {
dev_dbg(&pdev->dev, "rtas_msi: No OF device node\n");
return NULL;
}
pdn = PCI_DN(dn);
if (!pdn) {
dev_dbg(&pdev->dev, "rtas_msi: No PCI DN\n");
return NULL;
}
return pdn;
}
/* RTAS Helpers */ /* RTAS Helpers */
static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs) 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,7 +71,7 @@ static void rtas_disable_msi(struct pci_dev *pdev)
{ {
struct pci_dn *pdn; struct pci_dn *pdn;
pdn = get_pdn(pdev); pdn = pci_get_pdn(pdev);
if (!pdn) if (!pdn)
return; return;
...@@ -152,7 +132,7 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name) ...@@ -152,7 +132,7 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
struct pci_dn *pdn; struct pci_dn *pdn;
const u32 *req_msi; const u32 *req_msi;
pdn = get_pdn(pdev); pdn = pci_get_pdn(pdev);
if (!pdn) if (!pdn)
return -ENODEV; return -ENODEV;
...@@ -402,7 +382,7 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) ...@@ -402,7 +382,7 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
struct msi_msg msg; struct msi_msg msg;
int nvec = nvec_in; int nvec = nvec_in;
pdn = get_pdn(pdev); pdn = pci_get_pdn(pdev);
if (!pdn) if (!pdn)
return -ENODEV; return -ENODEV;
...@@ -518,12 +498,3 @@ static int rtas_msi_init(void) ...@@ -518,12 +498,3 @@ static int rtas_msi_init(void)
} }
arch_initcall(rtas_msi_init); arch_initcall(rtas_msi_init);
static void quirk_radeon(struct pci_dev *dev)
{
struct pci_dn *pdn = get_pdn(dev);
if (pdn)
pdn->force_32bit_msi = 1;
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment