diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h index 8d7a63b..3b742b2 100644 --- a/arch/mips/include/asm/pci/bridge.h +++ b/arch/mips/include/asm/pci/bridge.h @@ -14,6 +14,8 @@ #include #include +#include + #include /* generic widget header */ #include @@ -842,6 +844,7 @@ struct bridge_controller { unsigned int irq_cpu; u64 baddr; unsigned int pci_int[8]; + spinlock_t lock; }; #define BRIDGE_CONTROLLER(bus) \ diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index d1531ba..a4b2cd9 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -46,12 +46,13 @@ extern struct pci_ops bridge_pci_ops; /* Increments for each additional bridge. */ static int num_bridges = 0; -int bridge_probe(nasid_t nasid, int widget_id, int masterwid) +int bridge_probe(nasid_t nasid, xwidgetnum_t widget_id, xwidgetnum_t masterwid) { + int slot; + unsigned long flags; unsigned long offset = NODE_OFFSET(nasid); - struct bridge_controller *bc; bridge_t *bridge; - int slot; + struct bridge_controller *bc; pci_set_flags(PCI_PROBE_ONLY); @@ -63,6 +64,10 @@ int bridge_probe(nasid_t nasid, int widget_id, int masterwid) bc = &bridges[num_bridges]; + /* Init a spinlock. */ + spin_lock_init(&bc->lock); + spin_lock_irqsave(&bc->lock, flags); + bc->pc.pci_ops = &bridge_pci_ops; bc->pc.mem_resource = &bc->mem; bc->pc.io_resource = &bc->io; @@ -93,10 +98,10 @@ int bridge_probe(nasid_t nasid, int widget_id, int masterwid) bc->widget_id = widget_id; bc->nasid = nasid; - bc->baddr = (u64)masterwid << 60 | PCI64_ATTR_BAR; + bc->baddr = ((u64)masterwid << PCI64_ATTR_TARG_SHFT); /* - * point to this bridge + * Point to this bridge */ bridge = (bridge_t *) RAW_NODE_SWIN_BASE(nasid, widget_id); @@ -125,22 +130,30 @@ int bridge_probe(nasid_t nasid, int widget_id, int masterwid) * Hmm... IRIX sets additional bits in the address which * are documented as reserved in the bridge docs. */ - bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); + bridge->b_wid_int_upper = 0x8000 | (masterwid << WIDGET_TARGET_ID_SHFT); bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ - bridge->b_dir_map = (masterwid << 20); /* DMA */ + + /* Configure direct-mapped DMA */ + bridge->b_dir_map = (masterwid << BRIDGE_DIRMAP_W_ID_SHFT); bridge->b_int_enable = 0; - for (slot = 0; slot < 8; slot ++) { - bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; + for (slot = 0; slot < BRIDGE_DEV_CNT; slot++) { + bridge->b_device[slot].reg |= (BRIDGE_DEV_SWAP_DIR | + BRIDGE_DEV_ERR_LOCK_EN | + BRIDGE_DEV_D64_BITS); bc->pci_int[slot] = -1; } - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + + /* Wait until Bridge PIO complete */ + while(bridge->b_wid_tflush) + cpu_relax(); bc->base = bridge; register_pci_controller(&bc->pc); num_bridges++; + spin_unlock_irqrestore(&bc->lock, flags); return 0; }