]> git.hungrycats.org Git - linux/commitdiff
ppc64: new pci config methods, from Todd Inglett
authorAnton Blanchard <anton@samba.org>
Sat, 14 Sep 2002 07:27:30 +0000 (17:27 +1000)
committerAnton Blanchard <anton@samba.org>
Sat, 14 Sep 2002 07:27:30 +0000 (17:27 +1000)
arch/ppc64/kernel/pSeries_pci.c
arch/ppc64/kernel/pci_dma.c
arch/ppc64/kernel/pci_dn.c
include/asm-ppc64/machdep.h
include/asm-ppc64/prom.h

index f546516e12f643cd7138f93ea9831e1d991c1ec5..62167be892b93daf9b115c809b31a650389ccf46 100644 (file)
@@ -63,85 +63,85 @@ static int ibm_write_pci_config;
 
 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
 };
 
 /*
@@ -563,7 +563,7 @@ alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words)
 
        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;
@@ -651,6 +651,11 @@ fixup_resources(struct pci_dev *dev)
                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()) {
@@ -776,14 +781,9 @@ pSeries_pcibios_init(void)
 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.                */
index b54c549e0c6a1f38f7e729d8d552921798868dbc..5f859dc2527ea1d422ea5b4cd6b8523bddc68e49 100644 (file)
@@ -708,10 +708,10 @@ void create_tce_tables_for_busesLP(struct list_head *bus_list)
                 */
                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);
@@ -966,12 +966,12 @@ static void getTceTableParmsPSeriesLP(struct pci_controller *phb,
                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);
@@ -1121,7 +1121,7 @@ void pci_unmap_single( struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size
        /* 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;
        }
        
@@ -1377,10 +1377,11 @@ void pci_unmap_sg( struct pci_dev *hwdev, struct scatterlist *sg, int nelms, int
        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 ) {
@@ -1396,6 +1397,7 @@ void pci_unmap_sg( struct pci_dev *hwdev, struct scatterlist *sg, int nelms, int
        /* 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;
        }
index fd2a8ed4ce79bab7edc5763c90e88a468c23f916..0bc45cac00c6bb815cd89594a4f1dea5c007b9d8 100644 (file)
@@ -74,9 +74,6 @@ update_dn_pci_info(struct device_node *dn, void *data)
 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];
@@ -95,21 +92,25 @@ write_OF_bars(struct device_node *dn, void *data)
                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;
                }
@@ -214,7 +215,6 @@ void *traverse_all_pci_devices(traverse_func pre)
        return NULL;
 }
 
-
 /* Traversal func that looks for a <busno,devfcn> value.
  * If found, the device_node is returned (thus terminating the traversal).
  */
@@ -223,6 +223,7 @@ is_devfn_node(struct device_node *dn, void *data)
 {
        int busno = ((unsigned long)data >> 8) & 0xff;
        int devfn = ((unsigned long)data) & 0xff;
+
        return (devfn == dn->devfn && busno == dn->busno) ? dn : NULL;
 }
 
index 391c9a4125debc66a8ddfa7b58225d4ec11c8b46..2765573302d7b8dbd657bdfe255fb36cdfbb745b 100644 (file)
@@ -31,9 +31,6 @@ struct smp_ops_t {
 #endif
 
 struct machdep_calls {
-       /* High use functions in the first cachelines, low use functions
-        * follow.  DRENG collect profile data.
-        */
        void            (*hpte_invalidate)(unsigned long slot,
                                           unsigned long va,
                                           int large,
@@ -104,12 +101,8 @@ struct machdep_calls {
        int             (*udbg_getc_poll)(void);
 
        /* PCI interfaces */
-       int (*pcibios_read_config_byte)(struct device_node *dn, int offset, u8 *val);
-       int (*pcibios_read_config_word)(struct device_node *dn, int offset, u16 *val);
-       int (*pcibios_read_config_dword)(struct device_node *dn, int offset, u32 *val);
-       int (*pcibios_write_config_byte)(struct device_node *dn, int offset, u8 val);
-       int (*pcibios_write_config_word)(struct device_node *dn, int offset, u16 val);
-       int (*pcibios_write_config_dword)(struct device_node *dn, int offset, u32 val);
+       int (*pcibios_read_config)(struct device_node *dn, int where, int size, u32 *val);
+       int (*pcibios_write_config)(struct device_node *dn, int where, int size, u32 val);
 
        /* Called after scanning the bus, before allocating
         * resources
index cc7dc0324c519357827d6b02cf81ba08a4725a0a..212c13436f75a57e4f40d1a53890f17d00f03891 100644 (file)
@@ -126,6 +126,7 @@ struct device_node {
        struct  interrupt_info *intrs;
        char    *full_name;
        int     busno;                  /* for pci devices */
+       int     bussubno;               /* for pci devices */
        int     devfn;                  /* for pci devices */
        struct  pci_controller *phb;    /* for pci devices */
        struct  TceTable *tce_table;    /* for phb's or bridges */