summaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64/kernel')
-rw-r--r--arch/ppc64/kernel/bpa_iic.c28
-rw-r--r--arch/ppc64/kernel/eeh.c55
-rw-r--r--arch/ppc64/kernel/iomap.c20
-rw-r--r--arch/ppc64/kernel/iommu.c3
-rw-r--r--arch/ppc64/kernel/maple_pci.c4
-rw-r--r--arch/ppc64/kernel/misc.S6
-rw-r--r--arch/ppc64/kernel/pSeries_iommu.c72
-rw-r--r--arch/ppc64/kernel/pci.c66
-rw-r--r--arch/ppc64/kernel/pci.h1
-rw-r--r--arch/ppc64/kernel/pci_dn.c47
-rw-r--r--arch/ppc64/kernel/pci_iommu.c2
-rw-r--r--arch/ppc64/kernel/pmac_feature.c8
-rw-r--r--arch/ppc64/kernel/pmac_pci.c6
-rw-r--r--arch/ppc64/kernel/prom.c1
-rw-r--r--arch/ppc64/kernel/rtas_pci.c39
-rw-r--r--arch/ppc64/kernel/sys_ppc32.c55
-rw-r--r--arch/ppc64/kernel/syscalls.c4
-rw-r--r--arch/ppc64/kernel/u3_iommu.c4
-rw-r--r--arch/ppc64/kernel/udbg.c6
19 files changed, 260 insertions, 167 deletions
diff --git a/arch/ppc64/kernel/bpa_iic.c b/arch/ppc64/kernel/bpa_iic.c
index c8f3dc3fad7..0aaa878e19d 100644
--- a/arch/ppc64/kernel/bpa_iic.c
+++ b/arch/ppc64/kernel/bpa_iic.c
@@ -205,6 +205,18 @@ static struct iic_regs __iomem *find_iic(int cpu)
}
#ifdef CONFIG_SMP
+
+/* Use the highest interrupt priorities for IPI */
+static inline int iic_ipi_to_irq(int ipi)
+{
+ return IIC_IPI_OFFSET + IIC_NUM_IPIS - 1 - ipi;
+}
+
+static inline int iic_irq_to_ipi(int irq)
+{
+ return IIC_NUM_IPIS - 1 - (irq - IIC_IPI_OFFSET);
+}
+
void iic_setup_cpu(void)
{
out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
@@ -212,18 +224,20 @@ void iic_setup_cpu(void)
void iic_cause_IPI(int cpu, int mesg)
{
- out_be64(&per_cpu(iic, cpu).regs->generate, mesg);
+ out_be64(&per_cpu(iic, cpu).regs->generate, (IIC_NUM_IPIS - 1 - mesg) << 4);
}
static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
{
-
- smp_message_recv(irq - IIC_IPI_OFFSET, regs);
+ smp_message_recv(iic_irq_to_ipi(irq), regs);
return IRQ_HANDLED;
}
-static void iic_request_ipi(int irq, const char *name)
+static void iic_request_ipi(int ipi, const char *name)
{
+ int irq;
+
+ irq = iic_ipi_to_irq(ipi);
/* IPIs are marked SA_INTERRUPT as they must run with irqs
* disabled */
get_irq_desc(irq)->handler = &iic_pic;
@@ -233,10 +247,10 @@ static void iic_request_ipi(int irq, const char *name)
void iic_request_IPIs(void)
{
- iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call");
- iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched");
+ iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call");
+ iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched");
#ifdef CONFIG_DEBUGGER
- iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
+ iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
#endif /* CONFIG_DEBUGGER */
}
#endif /* CONFIG_SMP */
diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
index 4c857a6516f..ba93fd73122 100644
--- a/arch/ppc64/kernel/eeh.c
+++ b/arch/ppc64/kernel/eeh.c
@@ -254,6 +254,7 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
static void __pci_addr_cache_insert_device(struct pci_dev *dev)
{
struct device_node *dn;
+ struct pci_dn *pdn;
int i;
int inserted = 0;
@@ -265,8 +266,9 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
}
/* Skip any devices for which EEH is not enabled. */
- if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
- dn->eeh_mode & EEH_MODE_NOCHECK) {
+ pdn = dn->data;
+ if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
+ pdn->eeh_mode & EEH_MODE_NOCHECK) {
#ifdef DEBUG
printk(KERN_INFO "PCI: skip building address cache for=%s\n",
pci_name(dev));
@@ -415,6 +417,7 @@ int eeh_unregister_notifier(struct notifier_block *nb)
static int read_slot_reset_state(struct device_node *dn, int rets[])
{
int token, outputs;
+ struct pci_dn *pdn = dn->data;
if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {
token = ibm_read_slot_reset_state2;
@@ -424,8 +427,8 @@ static int read_slot_reset_state(struct device_node *dn, int rets[])
outputs = 3;
}
- return rtas_call(token, 3, outputs, rets, dn->eeh_config_addr,
- BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid));
+ return rtas_call(token, 3, outputs, rets, pdn->eeh_config_addr,
+ BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid));
}
/**
@@ -534,6 +537,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
unsigned long flags;
int rc, reset_state;
struct eeh_event *event;
+ struct pci_dn *pdn;
__get_cpu_var(total_mmio_ffs)++;
@@ -542,14 +546,15 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
if (!dn)
return 0;
+ pdn = dn->data;
/* Access to IO BARs might get this far and still not want checking. */
- if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
- dn->eeh_mode & EEH_MODE_NOCHECK) {
+ if (!pdn->eeh_capable || !(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
+ pdn->eeh_mode & EEH_MODE_NOCHECK) {
return 0;
}
- if (!dn->eeh_config_addr) {
+ if (!pdn->eeh_config_addr) {
return 0;
}
@@ -557,7 +562,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
* If we already have a pending isolation event for this
* slot, we know it's bad already, we don't need to check...
*/
- if (dn->eeh_mode & EEH_MODE_ISOLATED) {
+ if (pdn->eeh_mode & EEH_MODE_ISOLATED) {
atomic_inc(&eeh_fail_count);
if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) {
/* re-read the slot reset state */
@@ -582,7 +587,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
}
/* prevent repeated reports of this failure */
- dn->eeh_mode |= EEH_MODE_ISOLATED;
+ pdn->eeh_mode |= EEH_MODE_ISOLATED;
reset_state = rets[0];
@@ -590,9 +595,9 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
memset(slot_errbuf, 0, eeh_error_buf_size);
rc = rtas_call(ibm_slot_error_detail,
- 8, 1, NULL, dn->eeh_config_addr,
- BUID_HI(dn->phb->buid),
- BUID_LO(dn->phb->buid), NULL, 0,
+ 8, 1, NULL, pdn->eeh_config_addr,
+ BUID_HI(pdn->phb->buid),
+ BUID_LO(pdn->phb->buid), NULL, 0,
virt_to_phys(slot_errbuf),
eeh_error_buf_size,
1 /* Temporary Error */);
@@ -679,8 +684,9 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
u32 *device_id = (u32 *)get_property(dn, "device-id", NULL);
u32 *regs;
int enable;
+ struct pci_dn *pdn = dn->data;
- dn->eeh_mode = 0;
+ pdn->eeh_mode = 0;
if (status && strcmp(status, "ok") != 0)
return NULL; /* ignore devices with bad status */
@@ -691,7 +697,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
/* There is nothing to check on PCI to ISA bridges */
if (dn->type && !strcmp(dn->type, "isa")) {
- dn->eeh_mode |= EEH_MODE_NOCHECK;
+ pdn->eeh_mode |= EEH_MODE_NOCHECK;
return NULL;
}
@@ -708,7 +714,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
enable = 0;
if (!enable)
- dn->eeh_mode |= EEH_MODE_NOCHECK;
+ pdn->eeh_mode |= EEH_MODE_NOCHECK;
/* Ok... see if this device supports EEH. Some do, some don't,
* and the only way to find out is to check each and every one. */
@@ -721,8 +727,8 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
EEH_ENABLE);
if (ret == 0) {
eeh_subsystem_enabled = 1;
- dn->eeh_mode |= EEH_MODE_SUPPORTED;
- dn->eeh_config_addr = regs[0];
+ pdn->eeh_mode |= EEH_MODE_SUPPORTED;
+ pdn->eeh_config_addr = regs[0];
#ifdef DEBUG
printk(KERN_DEBUG "EEH: %s: eeh enabled\n", dn->full_name);
#endif
@@ -730,10 +736,11 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
/* This device doesn't support EEH, but it may have an
* EEH parent, in which case we mark it as supported. */
- if (dn->parent && (dn->parent->eeh_mode & EEH_MODE_SUPPORTED)) {
+ if (dn->parent && dn->parent->data
+ && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) {
/* Parent supports EEH. */
- dn->eeh_mode |= EEH_MODE_SUPPORTED;
- dn->eeh_config_addr = dn->parent->eeh_config_addr;
+ pdn->eeh_mode |= EEH_MODE_SUPPORTED;
+ pdn->eeh_config_addr = PCI_DN(dn->parent)->eeh_config_addr;
return NULL;
}
}
@@ -790,11 +797,13 @@ void __init eeh_init(void)
for (phb = of_find_node_by_name(NULL, "pci"); phb;
phb = of_find_node_by_name(phb, "pci")) {
unsigned long buid;
+ struct pci_dn *pci;
buid = get_phb_buid(phb);
- if (buid == 0)
+ if (buid == 0 || phb->data == NULL)
continue;
+ pci = phb->data;
info.buid_lo = BUID_LO(buid);
info.buid_hi = BUID_HI(buid);
traverse_pci_devices(phb, early_enable_eeh, &info);
@@ -823,9 +832,9 @@ void eeh_add_device_early(struct device_node *dn)
struct pci_controller *phb;
struct eeh_early_enable_info info;
- if (!dn)
+ if (!dn || !dn->data)
return;
- phb = dn->phb;
+ phb = PCI_DN(dn)->phb;
if (NULL == phb || 0 == phb->buid) {
printk(KERN_WARNING "EEH: Expected buid but found none\n");
return;
diff --git a/arch/ppc64/kernel/iomap.c b/arch/ppc64/kernel/iomap.c
index 09a3062309e..6160c8dbb7c 100644
--- a/arch/ppc64/kernel/iomap.c
+++ b/arch/ppc64/kernel/iomap.c
@@ -22,13 +22,23 @@ unsigned int fastcall ioread16(void __iomem *addr)
{
return readw(addr);
}
+unsigned int fastcall ioread16be(void __iomem *addr)
+{
+ return in_be16(addr);
+}
unsigned int fastcall ioread32(void __iomem *addr)
{
return readl(addr);
}
+unsigned int fastcall ioread32be(void __iomem *addr)
+{
+ return in_be32(addr);
+}
EXPORT_SYMBOL(ioread8);
EXPORT_SYMBOL(ioread16);
+EXPORT_SYMBOL(ioread16be);
EXPORT_SYMBOL(ioread32);
+EXPORT_SYMBOL(ioread32be);
void fastcall iowrite8(u8 val, void __iomem *addr)
{
@@ -38,13 +48,23 @@ void fastcall iowrite16(u16 val, void __iomem *addr)
{
writew(val, addr);
}
+void fastcall iowrite16be(u16 val, void __iomem *addr)
+{
+ out_be16(addr, val);
+}
void fastcall iowrite32(u32 val, void __iomem *addr)
{
writel(val, addr);
}
+void fastcall iowrite32be(u32 val, void __iomem *addr)
+{
+ out_be32(addr, val);
+}
EXPORT_SYMBOL(iowrite8);
EXPORT_SYMBOL(iowrite16);
+EXPORT_SYMBOL(iowrite16be);
EXPORT_SYMBOL(iowrite32);
+EXPORT_SYMBOL(iowrite32be);
/*
* These are the "repeat read/write" functions. Note the
diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c
index 845eebd1e28..9032b6bfe03 100644
--- a/arch/ppc64/kernel/iommu.c
+++ b/arch/ppc64/kernel/iommu.c
@@ -438,7 +438,8 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl)
void iommu_free_table(struct device_node *dn)
{
- struct iommu_table *tbl = dn->iommu_table;
+ struct pci_dn *pdn = dn->data;
+ struct iommu_table *tbl = pdn->iommu_table;
unsigned long bitmap_sz, i;
unsigned int order;
diff --git a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c
index 53993999b26..5a8b4d8c2dd 100644
--- a/arch/ppc64/kernel/maple_pci.c
+++ b/arch/ppc64/kernel/maple_pci.c
@@ -447,9 +447,9 @@ void __init maple_pci_init(void)
*/
if (u3_agp) {
struct device_node *np = u3_agp->arch_data;
- np->busno = 0xf0;
+ PCI_DN(np)->busno = 0xf0;
for (np = np->child; np; np = np->sibling)
- np->busno = 0xf0;
+ PCI_DN(np)->busno = 0xf0;
}
/* Tell pci.c to use the common resource allocation mecanism */
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index 6d860c1d9fa..c047663eb48 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -1431,9 +1431,9 @@ _GLOBAL(sys_call_table)
.llong .sys_ni_syscall /* 195 - 32bit only stat64 */
.llong .sys_ni_syscall /* 32bit only lstat64 */
.llong .sys_ni_syscall /* 32bit only fstat64 */
- .llong .sys_ni_syscall /* 32bit only pciconfig_read */
- .llong .sys_ni_syscall /* 32bit only pciconfig_write */
- .llong .sys_ni_syscall /* 32bit only pciconfig_iobase */
+ .llong .sys_pciconfig_read
+ .llong .sys_pciconfig_write
+ .llong .sys_pciconfig_iobase /* 200 - pciconfig_iobase */
.llong .sys_ni_syscall /* reserved for MacOnLinux */
.llong .sys_getdents64
.llong .sys_pivot_root
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c
index 9d5e1e7fc38..f0fd7fbd653 100644
--- a/arch/ppc64/kernel/pSeries_iommu.c
+++ b/arch/ppc64/kernel/pSeries_iommu.c
@@ -295,7 +295,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
struct iommu_table *tbl,
unsigned int *dma_window)
{
- tbl->it_busno = dn->bussubno;
+ tbl->it_busno = PCI_DN(dn)->bussubno;
/* TODO: Parse field size properties properly. */
tbl->it_size = (((unsigned long)dma_window[4] << 32) |
@@ -311,6 +311,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
static void iommu_bus_setup_pSeries(struct pci_bus *bus)
{
struct device_node *dn, *pdn;
+ struct pci_dn *pci;
struct iommu_table *tbl;
DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self);
@@ -325,6 +326,7 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
*/
dn = pci_bus_to_OF_node(bus);
+ pci = dn->data;
if (!bus->self) {
/* Root bus */
@@ -341,18 +343,18 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
* alltogether. This leaves 768MB for the window.
*/
DBG("PHB has io-hole, reserving 256MB\n");
- dn->phb->dma_window_size = 3 << 28;
- dn->phb->dma_window_base_cur = 1 << 28;
+ pci->phb->dma_window_size = 3 << 28;
+ pci->phb->dma_window_base_cur = 1 << 28;
} else {
/* 1GB window by default */
- dn->phb->dma_window_size = 1 << 30;
- dn->phb->dma_window_base_cur = 0;
+ pci->phb->dma_window_size = 1 << 30;
+ pci->phb->dma_window_base_cur = 0;
}
tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
- iommu_table_setparms(dn->phb, dn, tbl);
- dn->iommu_table = iommu_init_table(tbl);
+ iommu_table_setparms(pci->phb, dn, tbl);
+ pci->iommu_table = iommu_init_table(tbl);
} else {
/* Do a 128MB table at root. This is used for the IDE
* controller on some SMP-mode POWER4 machines. It
@@ -363,16 +365,16 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
* Allocate at offset 128MB to avoid having to deal
* with ISA holes; 128MB table for IDE is plenty.
*/
- dn->phb->dma_window_size = 1 << 27;
- dn->phb->dma_window_base_cur = 1 << 27;
+ pci->phb->dma_window_size = 1 << 27;
+ pci->phb->dma_window_base_cur = 1 << 27;
tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
- iommu_table_setparms(dn->phb, dn, tbl);
- dn->iommu_table = iommu_init_table(tbl);
+ iommu_table_setparms(pci->phb, dn, tbl);
+ pci->iommu_table = iommu_init_table(tbl);
/* All child buses have 256MB tables */
- dn->phb->dma_window_size = 1 << 28;
+ pci->phb->dma_window_size = 1 << 28;
}
} else {
pdn = pci_bus_to_OF_node(bus->parent);
@@ -386,12 +388,12 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
- iommu_table_setparms(dn->phb, dn, tbl);
+ iommu_table_setparms(pci->phb, dn, tbl);
- dn->iommu_table = iommu_init_table(tbl);
+ pci->iommu_table = iommu_init_table(tbl);
} else {
/* Lower than first child or under python, use parent table */
- dn->iommu_table = pdn->iommu_table;
+ pci->iommu_table = PCI_DN(pdn)->iommu_table;
}
}
}
@@ -401,6 +403,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
{
struct iommu_table *tbl;
struct device_node *dn, *pdn;
+ struct pci_dn *ppci;
unsigned int *dma_window = NULL;
DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self);
@@ -419,22 +422,24 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
return;
}
- if (!pdn->iommu_table) {
+ ppci = pdn->data;
+ if (!ppci->iommu_table) {
/* Bussubno hasn't been copied yet.
* Do it now because iommu_table_setparms_lpar needs it.
*/
- pdn->bussubno = bus->number;
+
+ ppci->bussubno = bus->number;
tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
GFP_KERNEL);
- iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window);
+ iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
- pdn->iommu_table = iommu_init_table(tbl);
+ ppci->iommu_table = iommu_init_table(tbl);
}
if (pdn != dn)
- dn->iommu_table = pdn->iommu_table;
+ PCI_DN(dn)->iommu_table = ppci->iommu_table;
}
@@ -449,11 +454,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev)
*/
mydn = dn = pci_device_to_OF_node(dev);
- while (dn && dn->iommu_table == NULL)
+ while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL)
dn = dn->parent;
- if (dn) {
- mydn->iommu_table = dn->iommu_table;
+ if (dn && dn->data) {
+ PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table;
} else {
DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, dev->pretty_name);
}
@@ -463,10 +468,11 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
{
int err = NOTIFY_OK;
struct device_node *np = node;
+ struct pci_dn *pci = np->data;
switch (action) {
case PSERIES_RECONFIG_REMOVE:
- if (np->iommu_table &&
+ if (pci->iommu_table &&
get_property(np, "ibm,dma-window", NULL))
iommu_free_table(np);
break;
@@ -486,6 +492,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
struct device_node *pdn, *dn;
struct iommu_table *tbl;
int *dma_window = NULL;
+ struct pci_dn *pci;
DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, dev->pretty_name);
@@ -497,8 +504,10 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
*/
dn = pci_device_to_OF_node(dev);
- for (pdn = dn; pdn && !pdn->iommu_table; pdn = pdn->parent) {
- dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL);
+ for (pdn = dn; pdn && pdn->data && !PCI_DN(pdn)->iommu_table;
+ pdn = pdn->parent) {
+ dma_window = (unsigned int *)
+ get_property(pdn, "ibm,dma-window", NULL);
if (dma_window)
break;
}
@@ -515,20 +524,21 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
DBG("Found DMA window, allocating table\n");
}
- if (!pdn->iommu_table) {
+ pci = pdn->data;
+ if (!pci->iommu_table) {
/* iommu_table_setparms_lpar needs bussubno. */
- pdn->bussubno = pdn->phb->bus->number;
+ pci->bussubno = pci->phb->bus->number;
tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
GFP_KERNEL);
- iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window);
+ iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
- pdn->iommu_table = iommu_init_table(tbl);
+ pci->iommu_table = iommu_init_table(tbl);
}
if (pdn != dn)
- dn->iommu_table = pdn->iommu_table;
+ PCI_DN(dn)->iommu_table = pci->iommu_table;
}
static void iommu_bus_setup_null(struct pci_bus *b) { }
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index b5ca7d8347e..8447dcc2c2b 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -21,6 +21,7 @@
#include <linux/bootmem.h>
#include <linux/mm.h>
#include <linux/list.h>
+#include <linux/syscalls.h>
#include <asm/processor.h>
#include <asm/io.h>
@@ -837,9 +838,11 @@ int pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
* device tree. If they are then we need to scan all the
* functions of this slot.
*/
- for (dn = busdn->child; dn; dn = dn->sibling)
- if ((dn->devfn >> 3) == (devfn >> 3))
+ for (dn = busdn->child; dn; dn = dn->sibling) {
+ struct pci_dn *pdn = dn->data;
+ if (pdn && (pdn->devfn >> 3) == (devfn >> 3))
return 1;
+ }
return 0;
}
@@ -982,3 +985,62 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
}
#endif /* CONFIG_PPC_MULTIPLATFORM */
+
+
+#define IOBASE_BRIDGE_NUMBER 0
+#define IOBASE_MEMORY 1
+#define IOBASE_IO 2
+#define IOBASE_ISA_IO 3
+#define IOBASE_ISA_MEM 4
+
+long sys_pciconfig_iobase(long which, unsigned long in_bus,
+ unsigned long in_devfn)
+{
+ struct pci_controller* hose;
+ struct list_head *ln;
+ struct pci_bus *bus = NULL;
+ struct device_node *hose_node;
+
+ /* Argh ! Please forgive me for that hack, but that's the
+ * simplest way to get existing XFree to not lockup on some
+ * G5 machines... So when something asks for bus 0 io base
+ * (bus 0 is HT root), we return the AGP one instead.
+ */
+#ifdef CONFIG_PPC_PMAC
+ if (systemcfg->platform == PLATFORM_POWERMAC &&
+ machine_is_compatible("MacRISC4"))
+ if (in_bus == 0)
+ in_bus = 0xf0;
+#endif /* CONFIG_PPC_PMAC */
+
+ /* That syscall isn't quite compatible with PCI domains, but it's
+ * used on pre-domains setup. We return the first match
+ */
+
+ for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
+ bus = pci_bus_b(ln);
+ if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate))
+ break;
+ bus = NULL;
+ }
+ if (bus == NULL || bus->sysdata == NULL)
+ return -ENODEV;
+
+ hose_node = (struct device_node *)bus->sysdata;
+ hose = PCI_DN(hose_node)->phb;
+
+ switch (which) {
+ case IOBASE_BRIDGE_NUMBER:
+ return (long)hose->first_busno;
+ case IOBASE_MEMORY:
+ return (long)hose->pci_mem_offset;
+ case IOBASE_IO:
+ return (long)hose->io_base_phys;
+ case IOBASE_ISA_IO:
+ return (long)isa_io_base;
+ case IOBASE_ISA_MEM:
+ return -EINVAL;
+ }
+
+ return -EOPNOTSUPP;
+}
diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
index 26be78b13af..5eb2cc32056 100644
--- a/arch/ppc64/kernel/pci.h
+++ b/arch/ppc64/kernel/pci.h
@@ -34,7 +34,6 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
void pci_devs_phb_init(void);
void pci_devs_phb_init_dynamic(struct pci_controller *phb);
-struct device_node *fetch_dev_dn(struct pci_dev *dev);
/* PCI address cache management routines */
void pci_addr_cache_insert_device(struct pci_dev *dev);
diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c
index ec345462afc..a86389d07d5 100644
--- a/arch/ppc64/kernel/pci_dn.c
+++ b/arch/ppc64/kernel/pci_dn.c
@@ -23,6 +23,8 @@
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/bootmem.h>
#include <asm/io.h>
#include <asm/prom.h>
@@ -40,16 +42,26 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
struct pci_controller *phb = data;
int *type = (int *)get_property(dn, "ibm,pci-config-space-type", NULL);
u32 *regs;
-
- dn->phb = phb;
+ struct pci_dn *pdn;
+
+ if (phb->is_dynamic)
+ pdn = kmalloc(sizeof(*pdn), GFP_KERNEL);
+ else
+ pdn = alloc_bootmem(sizeof(*pdn));
+ if (pdn == NULL)
+ return NULL;
+ memset(pdn, 0, sizeof(*pdn));
+ dn->data = pdn;
+ pdn->node = dn;
+ pdn->phb = phb;
regs = (u32 *)get_property(dn, "reg", NULL);
if (regs) {
/* First register entry is addr (00BBSS00) */
- dn->busno = (regs[0] >> 16) & 0xff;
- dn->devfn = (regs[0] >> 8) & 0xff;
+ pdn->busno = (regs[0] >> 16) & 0xff;
+ pdn->devfn = (regs[0] >> 8) & 0xff;
}
- dn->pci_ext_config_space = (type && *type == 1);
+ pdn->pci_ext_config_space = (type && *type == 1);
return NULL;
}
@@ -112,10 +124,15 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
{
struct device_node * dn = (struct device_node *) phb->arch_data;
+ struct pci_dn *pdn;
/* PHB nodes themselves must not match */
- dn->devfn = dn->busno = -1;
- dn->phb = phb;
+ update_dn_pci_info(dn, phb);
+ pdn = dn->data;
+ if (pdn) {
+ pdn->devfn = pdn->busno = -1;
+ pdn->phb = phb;
+ }
/* Update dn->phb ptrs for new phb and children devices */
traverse_pci_devices(dn, update_dn_pci_info, phb);
@@ -123,14 +140,17 @@ void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
/*
* Traversal func that looks for a <busno,devfcn> value.
- * If found, the device_node is returned (thus terminating the traversal).
+ * If found, the pci_dn is returned (thus terminating the traversal).
*/
static void *is_devfn_node(struct device_node *dn, void *data)
{
int busno = ((unsigned long)data >> 8) & 0xff;
int devfn = ((unsigned long)data) & 0xff;
+ struct pci_dn *pci = dn->data;
- return ((devfn == dn->devfn) && (busno == dn->busno)) ? dn : NULL;
+ if (pci && (devfn == pci->devfn) && (busno == pci->busno))
+ return dn;
+ return NULL;
}
/*
@@ -149,13 +169,10 @@ static void *is_devfn_node(struct device_node *dn, void *data)
struct device_node *fetch_dev_dn(struct pci_dev *dev)
{
struct device_node *orig_dn = dev->sysdata;
- struct pci_controller *phb = orig_dn->phb; /* assume same phb as orig_dn */
- struct device_node *phb_dn;
struct device_node *dn;
unsigned long searchval = (dev->bus->number << 8) | dev->devfn;
- phb_dn = phb->arch_data;
- dn = traverse_pci_devices(phb_dn, is_devfn_node, (void *)searchval);
+ dn = traverse_pci_devices(orig_dn, is_devfn_node, (void *)searchval);
if (dn)
dev->sysdata = dn;
return dn;
@@ -165,11 +182,13 @@ EXPORT_SYMBOL(fetch_dev_dn);
static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
{
struct device_node *np = node;
+ struct pci_dn *pci;
int err = NOTIFY_OK;
switch (action) {
case PSERIES_RECONFIG_ADD:
- update_dn_pci_info(np, np->parent->phb);
+ pci = np->parent->data;
+ update_dn_pci_info(np, pci->phb);
break;
default:
err = NOTIFY_DONE;
diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c
index ef0a62b916b..14647e09c9c 100644
--- a/arch/ppc64/kernel/pci_iommu.c
+++ b/arch/ppc64/kernel/pci_iommu.c
@@ -66,7 +66,7 @@ static inline struct iommu_table *devnode_table(struct device *dev)
#endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_MULTIPLATFORM
- return PCI_GET_DN(pdev)->iommu_table;
+ return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
#endif /* CONFIG_PPC_MULTIPLATFORM */
}
diff --git a/arch/ppc64/kernel/pmac_feature.c b/arch/ppc64/kernel/pmac_feature.c
index 98ed2bccab1..eb4e6c3f694 100644
--- a/arch/ppc64/kernel/pmac_feature.c
+++ b/arch/ppc64/kernel/pmac_feature.c
@@ -674,6 +674,7 @@ void __init pmac_check_ht_link(void)
#if 0 /* Disabled for now */
u32 ufreq, freq, ucfg, cfg;
struct device_node *pcix_node;
+ struct pci_dn *pdn;
u8 px_bus, px_devfn;
struct pci_controller *px_hose;
@@ -687,9 +688,10 @@ void __init pmac_check_ht_link(void)
printk("No PCI-X bridge found\n");
return;
}
- px_hose = pcix_node->phb;
- px_bus = pcix_node->busno;
- px_devfn = pcix_node->devfn;
+ pdn = pcix_node->data;
+ px_hose = pdn->phb;
+ px_bus = pdn->busno;
+ px_devfn = pdn->devfn;
early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg);
early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq);
diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c
index 71fe911ad18..d37bff2d7d4 100644
--- a/arch/ppc64/kernel/pmac_pci.c
+++ b/arch/ppc64/kernel/pmac_pci.c
@@ -242,7 +242,7 @@ static int u3_ht_skip_device(struct pci_controller *hose,
else
busdn = hose->arch_data;
for (dn = busdn->child; dn; dn = dn->sibling)
- if (dn->devfn == devfn)
+ if (dn->data && PCI_DN(dn)->devfn == devfn)
break;
if (dn == NULL)
return -1;
@@ -746,9 +746,9 @@ void __init pmac_pci_init(void)
*/
if (u3_agp) {
struct device_node *np = u3_agp->arch_data;
- np->busno = 0xf0;
+ PCI_DN(np)->busno = 0xf0;
for (np = np->child; np; np = np->sibling)
- np->busno = 0xf0;
+ PCI_DN(np)->busno = 0xf0;
}
pmac_check_ht_link();
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index 6ad5a8467f8..7035deb6de9 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -1733,6 +1733,7 @@ static void of_node_release(struct kref *kref)
kfree(node->intrs);
kfree(node->addrs);
kfree(node->full_name);
+ kfree(node->data);
kfree(node);
}
diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c
index 1dccadaddd1..4a9719b48ab 100644
--- a/arch/ppc64/kernel/rtas_pci.c
+++ b/arch/ppc64/kernel/rtas_pci.c
@@ -48,7 +48,7 @@ static int write_pci_config;
static int ibm_read_pci_config;
static int ibm_write_pci_config;
-static int config_access_valid(struct device_node *dn, int where)
+static int config_access_valid(struct pci_dn *dn, int where)
{
if (where < 256)
return 1;
@@ -78,15 +78,17 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va
int returnval = -1;
unsigned long buid, addr;
int ret;
+ struct pci_dn *pdn;
- if (!dn)
+ if (!dn || !dn->data)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (!config_access_valid(dn, where))
+ pdn = dn->data;
+ if (!config_access_valid(pdn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
- addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
- (dn->devfn << 8) | (where & 0xff);
- buid = dn->phb->buid;
+ addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
+ (pdn->devfn << 8) | (where & 0xff);
+ buid = pdn->phb->buid;
if (buid) {
ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
addr, buid >> 32, buid & 0xffffffff, size);
@@ -98,8 +100,8 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va
if (ret)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (returnval == EEH_IO_ERROR_VALUE(size)
- && eeh_dn_check_failure (dn, NULL))
+ if (returnval == EEH_IO_ERROR_VALUE(size) &&
+ eeh_dn_check_failure (dn, NULL))
return PCIBIOS_DEVICE_NOT_FOUND;
return PCIBIOS_SUCCESSFUL;
@@ -118,24 +120,28 @@ static int rtas_pci_read_config(struct pci_bus *bus,
/* Search only direct children of the bus */
for (dn = busdn->child; dn; dn = dn->sibling)
- if (dn->devfn == devfn && of_device_available(dn))
+ if (dn->data && PCI_DN(dn)->devfn == devfn
+ && of_device_available(dn))
return rtas_read_config(dn, where, size, val);
+
return PCIBIOS_DEVICE_NOT_FOUND;
}
-static int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
+int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
{
unsigned long buid, addr;
int ret;
+ struct pci_dn *pdn;
- if (!dn)
+ if (!dn || !dn->data)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (!config_access_valid(dn, where))
+ pdn = dn->data;
+ if (!config_access_valid(pdn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
- addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
- (dn->devfn << 8) | (where & 0xff);
- buid = dn->phb->buid;
+ addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
+ (pdn->devfn << 8) | (where & 0xff);
+ buid = pdn->phb->buid;
if (buid) {
ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);
} else {
@@ -161,7 +167,8 @@ static int rtas_pci_write_config(struct pci_bus *bus,
/* Search only direct children of the bus */
for (dn = busdn->child; dn; dn = dn->sibling)
- if (dn->devfn == devfn && of_device_available(dn))
+ if (dn->data && PCI_DN(dn)->devfn == devfn
+ && of_device_available(dn))
return rtas_write_config(dn, where, size, val);
return PCIBIOS_DEVICE_NOT_FOUND;
}
diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
index 214914a95a5..e93c1345891 100644
--- a/arch/ppc64/kernel/sys_ppc32.c
+++ b/arch/ppc64/kernel/sys_ppc32.c
@@ -708,62 +708,9 @@ asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubu
compat_ptr(ubuf));
}
-#define IOBASE_BRIDGE_NUMBER 0
-#define IOBASE_MEMORY 1
-#define IOBASE_IO 2
-#define IOBASE_ISA_IO 3
-#define IOBASE_ISA_MEM 4
-
asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
{
-#ifdef CONFIG_PCI
- struct pci_controller* hose;
- struct list_head *ln;
- struct pci_bus *bus = NULL;
- struct device_node *hose_node;
-
- /* Argh ! Please forgive me for that hack, but that's the
- * simplest way to get existing XFree to not lockup on some
- * G5 machines... So when something asks for bus 0 io base
- * (bus 0 is HT root), we return the AGP one instead.
- */
-#ifdef CONFIG_PPC_PMAC
- if (systemcfg->platform == PLATFORM_POWERMAC &&
- machine_is_compatible("MacRISC4"))
- if (in_bus == 0)
- in_bus = 0xf0;
-#endif /* CONFIG_PPC_PMAC */
-
- /* That syscall isn't quite compatible with PCI domains, but it's
- * used on pre-domains setup. We return the first match
- */
-
- for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
- bus = pci_bus_b(ln);
- if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate))
- break;
- bus = NULL;
- }
- if (bus == NULL || bus->sysdata == NULL)
- return -ENODEV;
-
- hose_node = (struct device_node *)bus->sysdata;
- hose = hose_node->phb;
-
- switch (which) {
- case IOBASE_BRIDGE_NUMBER:
- return (long)hose->first_busno;
- case IOBASE_MEMORY:
- return (long)hose->pci_mem_offset;
- case IOBASE_IO:
- return (long)hose->io_base_phys;
- case IOBASE_ISA_IO:
- return (long)isa_io_base;
- case IOBASE_ISA_MEM:
- return -EINVAL;
- }
-#endif /* CONFIG_PCI */
- return -EOPNOTSUPP;
+ return sys_pciconfig_iobase(which, in_bus, in_devfn);
}
diff --git a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c
index a8cbb202b8c..05f16633bd2 100644
--- a/arch/ppc64/kernel/syscalls.c
+++ b/arch/ppc64/kernel/syscalls.c
@@ -46,10 +46,6 @@
extern unsigned long wall_jiffies;
-void
-check_bugs(void)
-{
-}
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
diff --git a/arch/ppc64/kernel/u3_iommu.c b/arch/ppc64/kernel/u3_iommu.c
index b6e3bca4102..41ea09cb9ac 100644
--- a/arch/ppc64/kernel/u3_iommu.c
+++ b/arch/ppc64/kernel/u3_iommu.c
@@ -276,7 +276,7 @@ static void iommu_dev_setup_u3(struct pci_dev *dev)
dn = pci_device_to_OF_node(dev);
if (dn)
- dn->iommu_table = &iommu_table_u3;
+ PCI_DN(dn)->iommu_table = &iommu_table_u3;
}
static void iommu_bus_setup_u3(struct pci_bus *bus)
@@ -291,7 +291,7 @@ static void iommu_bus_setup_u3(struct pci_bus *bus)
dn = pci_bus_to_OF_node(bus);
if (dn)
- dn->iommu_table = &iommu_table_u3;
+ PCI_DN(dn)->iommu_table = &iommu_table_u3;
}
static void iommu_dev_setup_null(struct pci_dev *dev) { }
diff --git a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c
index ed6766e21f5..d49c3613c8e 100644
--- a/arch/ppc64/kernel/udbg.c
+++ b/arch/ppc64/kernel/udbg.c
@@ -158,14 +158,20 @@ static struct console udbg_console = {
.index = -1,
};
+static int early_console_initialized;
+
void __init disable_early_printk(void)
{
+ if (!early_console_initialized)
+ return;
unregister_console(&udbg_console);
+ early_console_initialized = 0;
}
/* called by setup_system */
void register_early_udbg_console(void)
{
+ early_console_initialized = 1;
register_console(&udbg_console);
}