static int s7a_workaround;
-/******************************************************************************
- *
- * pSeries I/O Operations to access the PCI configuration space.
- *
- *****************************************************************************/
-#define RTAS_PCI_READ_OP(size, type, nbytes) \
-int \
-rtas_read_config_##size(struct device_node *dn, int offset, type val) { \
- unsigned long returnval = ~0L; \
- unsigned long buid; \
- unsigned int addr; \
- int ret; \
- \
- if (dn == NULL) { \
- ret = -2; \
- } else { \
- addr = (dn->busno << 16) | (dn->devfn << 8) | offset; \
- buid = dn->phb->buid; \
- if (buid) { \
- ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, addr, buid >> 32, buid & 0xffffffff, nbytes); \
- if (ret < 0|| (returnval == 0xffffffff)) \
- ret = rtas_fake_read(dn, offset, nbytes, &returnval); \
- } else { \
- ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, nbytes); \
- } \
- } \
- *val = returnval; \
- return ret; \
-} \
-int \
-rtas_pci_read_config_##size(struct pci_dev *dev, int offset, type val) { \
- struct device_node *dn = pci_device_to_OF_node(dev); \
- int ret = rtas_read_config_##size(dn, offset, val); \
- /* udbg_printf("read bus=%x, devfn=%x, ret=%d phb=%lx, dn=%lx\n", dev->bus->number, dev->devfn, ret, dn ? dn->phb : 0, dn); */ \
- return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; \
+static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
+{
+ unsigned long returnval = ~0L;
+ unsigned long buid, addr;
+ int ret;
+
+ if (!dn)
+ return -2;
+
+ addr = (dn->busno << 16) | (dn->devfn << 8) | where;
+ buid = dn->phb->buid;
+ if (buid) {
+ ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, addr, buid >> 32, buid & 0xffffffff, size);
+ if (ret < 0|| (returnval == 0xffffffff))
+ ret = rtas_fake_read(dn, where, size, &returnval);
+ } else {
+ ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size);
+ }
+ *val = returnval;
+ return ret;
+}
+
+static int rtas_pci_read_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ struct device_node *busdn, *dn;
+
+ if (bus->self)
+ busdn = pci_device_to_OF_node(bus->self);
+ else
+ busdn = bus->sysdata; /* must be a phb */
+
+ /* Search only direct children of the bus */
+ for (dn = busdn->child; dn; dn = dn->sibling)
+ if (dn->devfn == devfn)
+ return rtas_read_config(dn, where, size, val);
+ return PCIBIOS_DEVICE_NOT_FOUND;
}
-#define RTAS_PCI_WRITE_OP(size, type, nbytes) \
-int \
-rtas_write_config_##size(struct device_node *dn, int offset, type val) { \
- unsigned long buid; \
- unsigned int addr; \
- int ret; \
- \
- if (dn == NULL) { \
- ret = -2; \
- } else { \
- buid = dn->phb->buid; \
- addr = (dn->busno << 16) | (dn->devfn << 8) | offset; \
- if (buid) { \
- ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, nbytes, (ulong) val); \
- } else { \
- ret = rtas_call(write_pci_config, 3, 1, NULL, addr, nbytes, (ulong)val); \
- } \
- } \
- return ret; \
-} \
-int \
-rtas_pci_write_config_##size(struct pci_dev *dev, int offset, type val) { \
- struct device_node* dn = pci_device_to_OF_node(dev); \
- int ret = rtas_write_config_##size(dn, offset, val); \
- /* udbg_printf("write bus=%x, devfn=%x, ret=%d phb=%lx, dn=%lx\n", dev->bus->number, dev->devfn, ret, dn ? dn->phb : 0, dn); */ \
- return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; \
+static int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
+{
+ unsigned long buid, addr;
+ int ret;
+
+ if (!dn)
+ return -2;
+
+ addr = (dn->busno << 16) | (dn->devfn << 8) | where;
+ buid = dn->phb->buid;
+ if (buid) {
+ ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);
+ } else {
+ ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val);
+ }
+ return ret;
}
-RTAS_PCI_READ_OP(byte, u8 *, 1)
-RTAS_PCI_READ_OP(word, u16 *, 2)
-RTAS_PCI_READ_OP(dword, u32 *, 4)
-RTAS_PCI_WRITE_OP(byte, u8, 1)
-RTAS_PCI_WRITE_OP(word, u16, 2)
-RTAS_PCI_WRITE_OP(dword, u32, 4)
+static int rtas_pci_write_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where, int size, u32 val)
+{
+ struct device_node *busdn, *dn;
+
+ if (bus->self)
+ busdn = pci_device_to_OF_node(bus->self);
+ else
+ busdn = bus->sysdata; /* must be a phb */
+
+ /* Search only direct children of the bus */
+ for (dn = busdn->child; dn; dn = dn->sibling)
+ if (dn->devfn == devfn)
+ return rtas_write_config(dn, where, size, val);
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
struct pci_ops rtas_pci_ops = {
- rtas_pci_read_config_byte,
- rtas_pci_read_config_word,
- rtas_pci_read_config_dword,
- rtas_pci_write_config_byte,
- rtas_pci_write_config_word,
- rtas_pci_write_config_dword,
+ rtas_pci_read_config,
+ rtas_pci_write_config
};
/*
buid_vals = (int *) get_property(dev, "ibm,fw-phb-id", &len);
- if (buid_vals == NULL) {
+ if (buid_vals == NULL) {
phb->buid = 0;
} else {
struct pci_bus check;
if ((dev->resource[i].start == 0) && (dev->resource[i].end == 0)) {
continue;
}
+ if (dev->resource[i].start > dev->resource[i].end) {
+ /* Bogus resource. Just clear it out. */
+ dev->resource[i].start = dev->resource[i].end = 0;
+ continue;
+ }
if (dev->resource[i].flags & IORESOURCE_IO) {
if (is_eeh_implemented()) {
void
pSeries_pcibios_init_early(void)
{
- ppc_md.pcibios_read_config_byte = rtas_read_config_byte;
- ppc_md.pcibios_read_config_word = rtas_read_config_word;
- ppc_md.pcibios_read_config_dword = rtas_read_config_dword;
- ppc_md.pcibios_write_config_byte = rtas_write_config_byte;
- ppc_md.pcibios_write_config_word = rtas_write_config_word;
- ppc_md.pcibios_write_config_dword = rtas_write_config_dword;
+ ppc_md.pcibios_read_config = rtas_read_config;
+ ppc_md.pcibios_write_config = rtas_write_config;
}
-
/************************************************************************/
/* Get a char* of the device physical location(U0.3-P1-I8) */
/* See the Product Topology in the RS/6000 Architecture. */
*/
dma_window = (u32 *)get_property(busdn, "ibm,dma-window", 0);
if (dma_window) {
- /* Busno hasn't been copied yet.
+ /* Bussubno hasn't been copied yet.
* Do it now because getTceTableParmsPSeriesLP needs it.
*/
- busdn->busno = bus->number;
+ busdn->bussubno = bus->number;
create_pci_bus_tce_table((unsigned long)busdn);
} else
create_tce_tables_for_busesLP(&bus->children);
panic("PCI_DMA: getTceTableParmsPSeriesLP: device %s has no ibm,dma-window property!\n", dn->full_name);
}
- newTceTable->busNumber = dn->busno;
+ newTceTable->busNumber = dn->bussubno;
newTceTable->size = (((((unsigned long)dma_window[4] << 32) | (unsigned long)dma_window[5]) >> PAGE_SHIFT) << 3) >> PAGE_SHIFT;
newTceTable->startOffset = ((((unsigned long)dma_window[2] << 32) | (unsigned long)dma_window[3]) >> 12);
newTceTable->base = 0;
newTceTable->index = dma_window[0];
- PPCDBG(PPCDBG_TCEINIT, "getTceTableParmsPSeriesLP for bus 0x%lx:\n", dn->busno);
+ PPCDBG(PPCDBG_TCEINIT, "getTceTableParmsPSeriesLP for bus 0x%lx:\n", dn->bussubno);
PPCDBG(PPCDBG_TCEINIT, "\tDevice = %s\n", dn->full_name);
PPCDBG(PPCDBG_TCEINIT, "\tnewTceTable->index = 0x%lx\n", newTceTable->index);
PPCDBG(PPCDBG_TCEINIT, "\tnewTceTable->startOffset = 0x%lx\n", newTceTable->startOffset);
/* Client asked for way to much space. This is checked later anyway */
/* It is easier to debug here for the drivers than in the tce tables.*/
if(order >= NUM_TCE_LEVELS) {
- printk("PCI_DMA: pci_unmap_single size to large: 0x%lx \n",size);
+ printk("PCI_DMA: pci_unmap_single 0x%lx size to large: 0x%lx \n",dma_handle,size);
return;
}
PPCDBG(PPCDBG_TCE, "pci_unmap_sg:\n");
PPCDBG(PPCDBG_TCE, "\thwdev = 0x%16.16lx, sg = 0x%16.16lx, direction = 0x%16.16lx, nelms = 0x%16.16lx\n", hwdev, sg, direction, nelms);
- if ( direction == PCI_DMA_NONE )
+ if ( direction == PCI_DMA_NONE || nelms == 0 )
BUG();
dma_start_page = sg->dma_address & PAGE_MASK;
+ dma_end_page = 0;
for ( i=nelms; i>0; --i ) {
unsigned k = i - 1;
if ( sg[k].dma_length ) {
/* Client asked for way to much space. This is checked later anyway */
/* It is easier to debug here for the drivers than in the tce tables.*/
if(order >= NUM_TCE_LEVELS) {
+ printk("PCI_DMA: dma_start_page:0x%lx dma_end_page:0x%lx\n",dma_start_page,dma_end_page);
printk("PCI_DMA: pci_unmap_sg size to large: 0x%x \n",(numTces << PAGE_SHIFT));
return;
}
static void * __init
write_OF_bars(struct device_node *dn, void *data)
{
- int i;
- u32 oldbar, newbar, newbartest;
- u8 config_offset;
char *name = get_property(dn, "name", 0);
char *device_type = get_property(dn, "device_type", 0);
char devname[128];
return NULL;
}
-#ifndef CONFIG_PPC_ISERIES
+#ifndef CONFIG_PPC_ISERIES
+ int i;
+ u32 oldbar, newbar, newbartest;
+ u8 config_offset;
+
for (i = 0; i < dn->n_addrs; i++) {
newbar = dn->addrs[i].address;
config_offset = dn->addrs[i].space & 0xff;
- if (ppc_md.pcibios_read_config_dword(dn, config_offset, &oldbar) != PCIBIOS_SUCCESSFUL) {
+ if (ppc_md.pcibios_read_config(dn, config_offset, 4, &oldbar) != PCIBIOS_SUCCESSFUL) {
printk(KERN_WARNING "write_OF_bars %s: read BAR%d failed\n", devname, i);
continue;
}
/* Need to update this BAR. */
- if (ppc_md.pcibios_write_config_dword(dn, config_offset, newbar) != PCIBIOS_SUCCESSFUL) {
+ if (ppc_md.pcibios_write_config(dn, config_offset, 4, newbar) != PCIBIOS_SUCCESSFUL) {
printk(KERN_WARNING "write_OF_bars %s: write BAR%d with 0x%08x failed (old was 0x%08x)\n", devname, i, newbar, oldbar);
continue;
}
/* sanity check */
- if (ppc_md.pcibios_read_config_dword(dn, config_offset, &newbartest) != PCIBIOS_SUCCESSFUL) {
+ if (ppc_md.pcibios_read_config(dn, config_offset, 4, &newbartest) != PCIBIOS_SUCCESSFUL) {
printk(KERN_WARNING "write_OF_bars %s: sanity test read BAR%d failed?\n", devname, i);
continue;
}
return NULL;
}
-
/* Traversal func that looks for a <busno,devfcn> value.
* If found, the device_node is returned (thus terminating the traversal).
*/
{
int busno = ((unsigned long)data >> 8) & 0xff;
int devfn = ((unsigned long)data) & 0xff;
+
return (devfn == dn->devfn && busno == dn->busno) ? dn : NULL;
}