Auto-update from upstream
authorKyle McMartin <kyle@parisc-linux.org>
Fri, 28 Oct 2005 16:18:07 +0000 (12:18 -0400)
committerKyle McMartin <kyle@parisc-linux.org>
Fri, 28 Oct 2005 16:18:07 +0000 (12:18 -0400)
1  2 
arch/parisc/kernel/pci-dma.c
drivers/parisc/ccio-dma.c
drivers/parisc/sba_iommu.c

index d9b447cb1a0d603b377cb3be17eb509692d468d8,844c2877a2e386a34169bc2e97b9bc42f866f950..ae6213d71670c4878affa60c0a8da6c7e6dbba00
@@@ -31,7 -31,7 +31,7 @@@
  #include <asm/page.h> /* get_order */
  #include <asm/pgalloc.h>
  #include <asm/uaccess.h>
 -
 +#include <asm/tlbflush.h>     /* for purge_tlb_*() macros */
  
  static struct proc_dir_entry * proc_gsc_root = NULL;
  static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length);
@@@ -333,33 -333,23 +333,33 @@@ pcxl_free_range(unsigned long vaddr, si
  static int __init
  pcxl_dma_init(void)
  {
 -    if (pcxl_dma_start == 0)
 -      return 0;
 +      if (pcxl_dma_start == 0)
 +              return 0;
  
 -    spin_lock_init(&pcxl_res_lock);
 -    pcxl_res_size = PCXL_DMA_MAP_SIZE >> (PAGE_SHIFT + 3);
 -    pcxl_res_hint = 0;
 -    pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL,
 +      spin_lock_init(&pcxl_res_lock);
 +      pcxl_res_size = PCXL_DMA_MAP_SIZE >> (PAGE_SHIFT + 3);
 +      pcxl_res_hint = 0;
 +      pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL,
                                            get_order(pcxl_res_size));
 -    memset(pcxl_res_map, 0, pcxl_res_size);
 -    proc_gsc_root = proc_mkdir("gsc", 0);
 -    create_proc_info_entry("dino", 0, proc_gsc_root, pcxl_proc_info);
 -    return 0;
 +      memset(pcxl_res_map, 0, pcxl_res_size);
 +      proc_gsc_root = proc_mkdir("gsc", 0);
 +      if (!proc_gsc_root)
 +              printk(KERN_WARNING
 +                      "pcxl_dma_init: Unable to create gsc /proc dir entry\n");
 +      else {
 +              struct proc_dir_entry* ent;
 +              ent = create_proc_info_entry("pcxl_dma", 0,
 +                              proc_gsc_root, pcxl_proc_info);
 +              if (!ent)
 +                      printk(KERN_WARNING
 +                              "pci-dma.c: Unable to create pcxl_dma /proc entry.\n");
 +      }
 +      return 0;
  }
  
  __initcall(pcxl_dma_init);
  
- static void * pa11_dma_alloc_consistent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flag)
+ static void * pa11_dma_alloc_consistent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)
  {
        unsigned long vaddr;
        unsigned long paddr;
@@@ -512,13 -502,13 +512,13 @@@ struct hppa_dma_ops pcxl_dma_ops = 
  };
  
  static void *fail_alloc_consistent(struct device *dev, size_t size,
-                                  dma_addr_t *dma_handle, int flag)
+                                  dma_addr_t *dma_handle, gfp_t flag)
  {
        return NULL;
  }
  
  static void *pa11_dma_alloc_noncoherent(struct device *dev, size_t size,
-                                         dma_addr_t *dma_handle, int flag)
+                                         dma_addr_t *dma_handle, gfp_t flag)
  {
        void *addr = NULL;
  
@@@ -555,16 -545,16 +555,16 @@@ struct hppa_dma_ops pcx_dma_ops = 
  
  static int pcxl_proc_info(char *buf, char **start, off_t offset, int len)
  {
 +#if 0
        u_long i = 0;
        unsigned long *res_ptr = (u_long *)pcxl_res_map;
 -      unsigned long total_pages = pcxl_res_size << 3;        /* 8 bits per byte */
 +#endif
 +      unsigned long total_pages = pcxl_res_size << 3;   /* 8 bits per byte */
  
 -      sprintf(buf, "\nDMA Mapping Area size    : %d bytes (%d pages)\n",
 -              PCXL_DMA_MAP_SIZE,
 -              (pcxl_res_size << 3) ); /* 1 bit per page */
 +      sprintf(buf, "\nDMA Mapping Area size    : %d bytes (%ld pages)\n",
 +              PCXL_DMA_MAP_SIZE, total_pages);
        
 -      sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", 
 -              buf, pcxl_res_size, pcxl_res_size << 3);   /* 8 bits per byte */
 +      sprintf(buf, "%sResource bitmap : %d bytes\n", buf, pcxl_res_size);
  
        strcat(buf,  "            total:    free:    used:   % used:\n");
        sprintf(buf, "%sblocks  %8d %8ld %8ld %8ld%%\n", buf, pcxl_res_size,
        sprintf(buf, "%spages   %8ld %8ld %8ld %8ld%%\n", buf, total_pages,
                total_pages - pcxl_used_pages, pcxl_used_pages,
                (pcxl_used_pages * 100 / total_pages));
 -      
 +
 +#if 0
        strcat(buf, "\nResource bitmap:");
  
        for(; i < (pcxl_res_size / sizeof(u_long)); ++i, ++res_ptr) {
                    strcat(buf,"\n   ");
                sprintf(buf, "%s %08lx", buf, *res_ptr);
        }
 +#endif
        strcat(buf, "\n");
        return strlen(buf);
  }
index f1c442ab9102e6b7ea82672ddcdff27b63537eda,a3bd91a618274672e31b30ff7913772ae34187f9..9e0229f7e25fbe3288e1bc12b51781868f2afa78
  #define DBG_RUN_SG(x...)
  #endif
  
 -#define CCIO_INLINE   /* inline */
 -#define WRITE_U32(value, addr) gsc_writel(value, (u32 *)(addr))
 -#define READ_U32(addr) gsc_readl((u32 *)(addr))
 +#define CCIO_INLINE   inline
 +#define WRITE_U32(value, addr) __raw_writel(value, addr)
 +#define READ_U32(addr) __raw_readl(addr)
  
  #define U2_IOA_RUNWAY 0x580
  #define U2_BC_GSC     0x501
  
  struct ioa_registers {
          /* Runway Supervisory Set */
 -        volatile int32_t    unused1[12];
 -        volatile uint32_t   io_command;             /* Offset 12 */
 -        volatile uint32_t   io_status;              /* Offset 13 */
 -        volatile uint32_t   io_control;             /* Offset 14 */
 -        volatile int32_t    unused2[1];
 +        int32_t    unused1[12];
 +        uint32_t   io_command;             /* Offset 12 */
 +        uint32_t   io_status;              /* Offset 13 */
 +        uint32_t   io_control;             /* Offset 14 */
 +        int32_t    unused2[1];
  
          /* Runway Auxiliary Register Set */
 -        volatile uint32_t   io_err_resp;            /* Offset  0 */
 -        volatile uint32_t   io_err_info;            /* Offset  1 */
 -        volatile uint32_t   io_err_req;             /* Offset  2 */
 -        volatile uint32_t   io_err_resp_hi;         /* Offset  3 */
 -        volatile uint32_t   io_tlb_entry_m;         /* Offset  4 */
 -        volatile uint32_t   io_tlb_entry_l;         /* Offset  5 */
 -        volatile uint32_t   unused3[1];
 -        volatile uint32_t   io_pdir_base;           /* Offset  7 */
 -        volatile uint32_t   io_io_low_hv;           /* Offset  8 */
 -        volatile uint32_t   io_io_high_hv;          /* Offset  9 */
 -        volatile uint32_t   unused4[1];
 -        volatile uint32_t   io_chain_id_mask;       /* Offset 11 */
 -        volatile uint32_t   unused5[2];
 -        volatile uint32_t   io_io_low;              /* Offset 14 */
 -        volatile uint32_t   io_io_high;             /* Offset 15 */
 +        uint32_t   io_err_resp;            /* Offset  0 */
 +        uint32_t   io_err_info;            /* Offset  1 */
 +        uint32_t   io_err_req;             /* Offset  2 */
 +        uint32_t   io_err_resp_hi;         /* Offset  3 */
 +        uint32_t   io_tlb_entry_m;         /* Offset  4 */
 +        uint32_t   io_tlb_entry_l;         /* Offset  5 */
 +        uint32_t   unused3[1];
 +        uint32_t   io_pdir_base;           /* Offset  7 */
 +        uint32_t   io_io_low_hv;           /* Offset  8 */
 +        uint32_t   io_io_high_hv;          /* Offset  9 */
 +        uint32_t   unused4[1];
 +        uint32_t   io_chain_id_mask;       /* Offset 11 */
 +        uint32_t   unused5[2];
 +        uint32_t   io_io_low;              /* Offset 14 */
 +        uint32_t   io_io_high;             /* Offset 15 */
  };
  
  /*
  */
  
  struct ioc {
 -      struct ioa_registers *ioc_hpa;  /* I/O MMU base address */
 +      struct ioa_registers __iomem *ioc_regs;  /* I/O MMU base address */
        u8  *res_map;                   /* resource map, bit == pdir entry */
        u64 *pdir_base;                 /* physical base address */
        u32 pdir_size;                  /* bytes, function of IOV Space size */
@@@ -595,7 -595,7 +595,7 @@@ ccio_io_pdir_entry(u64 *pdir_ptr, space
        ** Grab virtual index [0:11]
        ** Deposit virt_idx bits into I/O PDIR word
        */
 -      asm volatile ("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
 +      asm volatile ("lci %%r0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
        asm volatile ("extru %1,19,12,%0" : "+r" (ci) : "r" (ci));
        asm volatile ("depw  %1,15,12,%0" : "+r" (pa) : "r" (ci));
  
        ** the real mode coherence index generation of U2, the PDIR entry
        ** must be flushed to memory to retain coherence."
        */
 -      asm volatile("fdc 0(%0)" : : "r" (pdir_ptr));
 +      asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
        asm volatile("sync");
  }
  
@@@ -636,7 -636,7 +636,7 @@@ ccio_clear_io_tlb(struct ioc *ioc, dma_
        byte_cnt += chain_size;
  
        while(byte_cnt > chain_size) {
 -              WRITE_U32(CMD_TLB_PURGE | iovp, &ioc->ioc_hpa->io_command);
 +              WRITE_U32(CMD_TLB_PURGE | iovp, &ioc->ioc_regs->io_command);
                iovp += chain_size;
                byte_cnt -= chain_size;
        }
@@@ -684,7 -684,7 +684,7 @@@ ccio_mark_invalid(struct ioc *ioc, dma_
                ** Hopefully someone figures out how to patch (NOP) the
                ** FDC/SYNC out at boot time.
                */
 -              asm volatile("fdc 0(%0)" : : "r" (pdir_ptr[7]));
 +              asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr[7]));
  
                iovp     += IOVP_SIZE;
                byte_cnt -= IOVP_SIZE;
@@@ -836,7 -836,7 +836,7 @@@ ccio_unmap_single(struct device *dev, d
   * This function implements the pci_alloc_consistent function.
   */
  static void * 
- ccio_alloc_consistent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag)
+ ccio_alloc_consistent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)
  {
        void *ret;
  #if 0
@@@ -1251,7 -1251,7 +1251,7 @@@ static struct parisc_device_id ccio_tbl
  static int ccio_probe(struct parisc_device *dev);
  
  static struct parisc_driver ccio_driver = {
 -      .name =         "U2:Uturn",
 +      .name =         "ccio",
        .id_table =     ccio_tbl,
        .probe =        ccio_probe,
  };
@@@ -1314,13 -1314,14 +1314,13 @@@ ccio_ioc_init(struct ioc *ioc
  
        ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64);
  
 -      BUG_ON(ioc->pdir_size >= 4 * 1024 * 1024);   /* max pdir size < 4MB */
 +      BUG_ON(ioc->pdir_size > 8 * 1024 * 1024);   /* max pdir size <= 8MB */
  
        /* Verify it's a power of two */
        BUG_ON((1 << get_order(ioc->pdir_size)) != (ioc->pdir_size >> PAGE_SHIFT));
  
 -      DBG_INIT("%s() hpa 0x%lx mem %luMB IOV %dMB (%d bits)\n",
 -                      __FUNCTION__,
 -                      ioc->ioc_hpa,
 +      DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits)\n",
 +                      __FUNCTION__, ioc->ioc_regs,
                        (unsigned long) num_physpages >> (20 - PAGE_SHIFT),
                        iova_space_size>>20,
                        iov_order + PAGE_SHIFT);
        ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL, 
                                                 get_order(ioc->pdir_size));
        if(NULL == ioc->pdir_base) {
 -              panic("%s:%s() could not allocate I/O Page Table\n", __FILE__,
 -                    __FUNCTION__);
 +              panic("%s() could not allocate I/O Page Table\n", __FUNCTION__);
        }
        memset(ioc->pdir_base, 0, ioc->pdir_size);
  
        BUG_ON((((unsigned long)ioc->pdir_base) & PAGE_MASK) != (unsigned long)ioc->pdir_base);
 -      DBG_INIT(" base %p", ioc->pdir_base);
 +      DBG_INIT(" base %p\n", ioc->pdir_base);
  
        /* resource map size dictated by pdir_size */
        ioc->res_size = (ioc->pdir_size / sizeof(u64)) >> 3;
        ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL, 
                                              get_order(ioc->res_size));
        if(NULL == ioc->res_map) {
 -              panic("%s:%s() could not allocate resource map\n", __FILE__,
 -                    __FUNCTION__);
 +              panic("%s() could not allocate resource map\n", __FUNCTION__);
        }
        memset(ioc->res_map, 0, ioc->res_size);
  
        ** Initialize IOA hardware
        */
        WRITE_U32(CCIO_CHAINID_MASK << ioc->chainid_shift, 
 -                &ioc->ioc_hpa->io_chain_id_mask);
 +                &ioc->ioc_regs->io_chain_id_mask);
  
        WRITE_U32(virt_to_phys(ioc->pdir_base), 
 -                &ioc->ioc_hpa->io_pdir_base);
 +                &ioc->ioc_regs->io_pdir_base);
  
        /*
        ** Go to "Virtual Mode"
        */
 -      WRITE_U32(IOA_NORMAL_MODE, &ioc->ioc_hpa->io_control);
 +      WRITE_U32(IOA_NORMAL_MODE, &ioc->ioc_regs->io_control);
  
        /*
        ** Initialize all I/O TLB entries to 0 (Valid bit off).
        */
 -      WRITE_U32(0, &ioc->ioc_hpa->io_tlb_entry_m);
 -      WRITE_U32(0, &ioc->ioc_hpa->io_tlb_entry_l);
 +      WRITE_U32(0, &ioc->ioc_regs->io_tlb_entry_m);
 +      WRITE_U32(0, &ioc->ioc_regs->io_tlb_entry_l);
  
        for(i = 1 << CCIO_CHAINID_SHIFT; i ; i--) {
                WRITE_U32((CMD_TLB_DIRECT_WRITE | (i << ioc->chainid_shift)),
 -                        &ioc->ioc_hpa->io_command);
 +                        &ioc->ioc_regs->io_command);
        }
  }
  
  static void
 -ccio_init_resource(struct resource *res, char *name, unsigned long ioaddr)
 +ccio_init_resource(struct resource *res, char *name, void __iomem *ioaddr)
  {
        int result;
  
        res->parent = NULL;
        res->flags = IORESOURCE_MEM;
 -      res->start = (unsigned long)(signed) __raw_readl(ioaddr) << 16;
 -      res->end = (unsigned long)(signed) (__raw_readl(ioaddr + 4) << 16) - 1;
 +      /*
 +       * bracing ((signed) ...) are required for 64bit kernel because
 +       * we only want to sign extend the lower 16 bits of the register.
 +       * The upper 16-bits of range registers are hardcoded to 0xffff.
 +       */
 +      res->start = (unsigned long)((signed) READ_U32(ioaddr) << 16);
 +      res->end = (unsigned long)((signed) (READ_U32(ioaddr + 4) << 16) - 1);
        res->name = name;
 +      /*
 +       * Check if this MMIO range is disable
 +       */
        if (res->end + 1 == res->start)
                return;
 -      result = request_resource(&iomem_resource, res);
 +
 +      /* On some platforms (e.g. K-Class), we have already registered
 +       * resources for devices reported by firmware. Some are children
 +       * of ccio.
 +       * "insert" ccio ranges in the mmio hierarchy (/proc/iomem).
 +       */
 +      result = insert_resource(&iomem_resource, res);
        if (result < 0) {
 -              printk(KERN_ERR "%s: failed to claim CCIO bus address space (%08lx,%08lx)\n", 
 -                     __FILE__, res->start, res->end);
 +              printk(KERN_ERR "%s() failed to claim CCIO bus address space (%08lx,%08lx)\n", 
 +                      __FUNCTION__, res->start, res->end);
        }
  }
  
@@@ -1425,8 -1414,9 +1425,8 @@@ static void __init ccio_init_resources(
  
        sprintf(name, "GSC Bus [%d/]", ioc->hw_path);
  
 -      ccio_init_resource(res, name, (unsigned long)&ioc->ioc_hpa->io_io_low);
 -      ccio_init_resource(res + 1, name,
 -                      (unsigned long)&ioc->ioc_hpa->io_io_low_hv);
 +      ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low);
 +      ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv);
  }
  
  static int new_ioc_area(struct resource *res, unsigned long size,
  
        res->start = (max - size + 1) &~ (align - 1);
        res->end = res->start + size;
 -      if (!request_resource(&iomem_resource, res))
 +      
 +      /* We might be trying to expand the MMIO range to include
 +       * a child device that has already registered it's MMIO space.
 +       * Use "insert" instead of request_resource().
 +       */
 +      if (!insert_resource(&iomem_resource, res))
                return 0;
  
        return new_ioc_area(res, size, min, max - size, align);
@@@ -1501,15 -1486,15 +1501,15 @@@ int ccio_allocate_resource(const struc
  
        if (!expand_ioc_area(parent, size, min, max, align)) {
                __raw_writel(((parent->start)>>16) | 0xffff0000,
 -                           (unsigned long)&(ioc->ioc_hpa->io_io_low));
 +                           &ioc->ioc_regs->io_io_low);
                __raw_writel(((parent->end)>>16) | 0xffff0000,
 -                           (unsigned long)&(ioc->ioc_hpa->io_io_high));
 +                           &ioc->ioc_regs->io_io_high);
        } else if (!expand_ioc_area(parent + 1, size, min, max, align)) {
                parent++;
                __raw_writel(((parent->start)>>16) | 0xffff0000,
 -                           (unsigned long)&(ioc->ioc_hpa->io_io_low_hv));
 +                           &ioc->ioc_regs->io_io_low_hv);
                __raw_writel(((parent->end)>>16) | 0xffff0000,
 -                           (unsigned long)&(ioc->ioc_hpa->io_io_high_hv));
 +                           &ioc->ioc_regs->io_io_high_hv);
        } else {
                return -EBUSY;
        }
@@@ -1536,12 -1521,7 +1536,12 @@@ int ccio_request_resource(const struct 
                return -EBUSY;
        }
  
 -      return request_resource(parent, res);
 +      /* "transparent" bus bridges need to register MMIO resources
 +       * firmware assigned them. e.g. children of hppb.c (e.g. K-class)
 +       * registered their resources in the PDC "bus walk" (See
 +       * arch/parisc/kernel/inventory.c).
 +       */
 +      return insert_resource(parent, res);
  }
  
  /**
@@@ -1566,7 -1546,7 +1566,7 @@@ static int ccio_probe(struct parisc_dev
  
        ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn";
  
 -      printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa);
 +      printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa.start);
  
        for (i = 0; i < ioc_count; i++) {
                ioc_p = &(*ioc_p)->next;
        *ioc_p = ioc;
  
        ioc->hw_path = dev->hw_path;
 -      ioc->ioc_hpa = (struct ioa_registers *)dev->hpa;
 +      ioc->ioc_regs = ioremap(dev->hpa.start, 4096);
        ccio_ioc_init(ioc);
        ccio_init_resources(ioc);
        hppa_dma_ops = &ccio_ops;
index 48591badd4ceb243a02040cf9281e27cd2009cab,bd8b3e5a5cd76ebf79e6056fc852555f8ee6f03a..c85653f315aad47be0b758863356e95b53c27b60
@@@ -91,8 -91,8 +91,8 @@@ extern struct proc_dir_entry * proc_mck
  #define DBG_RES(x...)
  #endif
  
 -#if defined(__LP64__) && !defined(CONFIG_PDC_NARROW)
 -/* "low end" PA8800 machines use ZX1 chipset */
 +#if defined(CONFIG_64BIT)
 +/* "low end" PA8800 machines use ZX1 chipset: PAT PDC and only run 64-bit */
  #define ZX1_SUPPORT
  #endif
  
@@@ -231,7 -231,7 +231,7 @@@ struct ioc 
        spinlock_t      res_lock;
        unsigned int    res_bitshift;   /* from the LEFT! */
        unsigned int    res_size;       /* size of resource map in bytes */
 -#if SBA_HINT_SUPPORT
 +#ifdef SBA_HINT_SUPPORT
  /* FIXME : DMA HINTs not used */
        unsigned long   hint_mask_pdir; /* bits used for DMA hints */
        unsigned int    hint_shift_pdir;
@@@ -294,7 -294,7 +294,7 @@@ static unsigned long piranha_bad_128k 
  /* Looks nice and keeps the compiler happy */
  #define SBA_DEV(d) ((struct sba_device *) (d))
  
 -#if SBA_AGP_SUPPORT
 +#ifdef SBA_AGP_SUPPORT
  static int reserve_sba_gart = 1;
  #endif
  
  #define WRITE_REG32(val, addr) __raw_writel(cpu_to_le32(val), addr)
  #define WRITE_REG64(val, addr) __raw_writeq(cpu_to_le64(val), addr)
  
 -#ifdef __LP64__
 +#ifdef CONFIG_64BIT
  #define READ_REG(addr)                READ_REG64(addr)
  #define WRITE_REG(value, addr)        WRITE_REG64(value, addr)
  #else
  
  #ifdef DEBUG_SBA_INIT
  
 -/* NOTE: When __LP64__ isn't defined, READ_REG64() is two 32-bit reads */
 +/* NOTE: When CONFIG_64BIT isn't defined, READ_REG64() is two 32-bit reads */
  
  /**
   * sba_dump_ranges - debugging only - print ranges assigned to this IOA
@@@ -364,7 -364,7 +364,7 @@@ static void sba_dump_tlb(void __iomem *
  #else
  #define sba_dump_ranges(x)
  #define sba_dump_tlb(x)
 -#endif
 +#endif        /* DEBUG_SBA_INIT */
  
  
  #ifdef ASSERT_PDIR_SANITY
@@@ -674,7 -674,7 +674,7 @@@ sba_free_range(struct ioc *ioc, dma_add
  *
  ***************************************************************/
  
 -#if SBA_HINT_SUPPORT
 +#ifdef SBA_HINT_SUPPORT
  #define SBA_DMA_HINT(ioc, val) ((val) << (ioc)->hint_shift_pdir)
  #endif
  
@@@ -743,8 -743,9 +743,8 @@@ sba_io_pdir_entry(u64 *pdir_ptr, space_
         * (bit #61, big endian), we have to flush and sync every time
         * IO-PDIR is changed in Ike/Astro.
         */
 -      if (ioc_needs_fdc) {
 -              asm volatile("fdc 0(%%sr1,%0)\n\tsync" : : "r" (pdir_ptr));
 -      }
 +      if (ioc_needs_fdc)
 +              asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
  }
  
  
@@@ -768,57 -769,42 +768,57 @@@ static SBA_INLINE voi
  sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
  {
        u32 iovp = (u32) SBA_IOVP(ioc,iova);
 -
 -      /* Even though this is a big-endian machine, the entries
 -      ** in the iopdir are little endian. That's why we clear the byte
 -      ** at +7 instead of at +0.
 -      */
 -      int off = PDIR_INDEX(iovp)*sizeof(u64)+7;
 +      u64 *pdir_ptr = &ioc->pdir_base[PDIR_INDEX(iovp)];
  
  #ifdef ASSERT_PDIR_SANITY
 -      /* Assert first pdir entry is set */
 -      if (0x80 != (((u8 *) ioc->pdir_base)[off])) {
 +      /* Assert first pdir entry is set.
 +      **
 +      ** Even though this is a big-endian machine, the entries
 +      ** in the iopdir are little endian. That's why we look at
 +      ** the byte at +7 instead of at +0.
 +      */
 +      if (0x80 != (((u8 *) pdir_ptr)[7])) {
                sba_dump_pdir_entry(ioc,"sba_mark_invalid()", PDIR_INDEX(iovp));
        }
  #endif
  
 -      if (byte_cnt <= IOVP_SIZE)
 +      if (byte_cnt > IOVP_SIZE)
        {
 -              iovp |= IOVP_SHIFT;     /* set "size" field for PCOM */
 +#if 0
 +              unsigned long entries_per_cacheline = ioc_needs_fdc ?
 +                              L1_CACHE_ALIGN(((unsigned long) pdir_ptr))
 +                                      - (unsigned long) pdir_ptr;
 +                              : 262144;
 +#endif
  
 -              /*
 -              ** clear I/O PDIR entry "valid" bit
 -              ** Do NOT clear the rest - save it for debugging.
 -              ** We should only clear bits that have previously
 -              ** been enabled.
 -              */
 -              ((u8 *)(ioc->pdir_base))[off] = 0;
 -      } else {
 -              u32 t = get_order(byte_cnt) + PAGE_SHIFT;
 +              /* set "size" field for PCOM */
 +              iovp |= get_order(byte_cnt) + PAGE_SHIFT;
  
 -              iovp |= t;
                do {
                        /* clear I/O Pdir entry "valid" bit first */
 -                      ((u8 *)(ioc->pdir_base))[off] = 0;
 -                      off += sizeof(u64);
 +                      ((u8 *) pdir_ptr)[7] = 0;
 +                      if (ioc_needs_fdc) {
 +                              asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
 +#if 0
 +                              entries_per_cacheline = L1_CACHE_SHIFT - 3;
 +#endif
 +                      }
 +                      pdir_ptr++;
                        byte_cnt -= IOVP_SIZE;
 -              } while (byte_cnt > 0);
 -      }
 +              } while (byte_cnt > IOVP_SIZE);
 +      } else
 +              iovp |= IOVP_SHIFT;     /* set "size" field for PCOM */
 +
 +      /*
 +      ** clear I/O PDIR entry "valid" bit.
 +      ** We have to R/M/W the cacheline regardless how much of the
 +      ** pdir entry that we clobber.
 +      ** The rest of the entry would be useful for debugging if we
 +      ** could dump core on HPMC.
 +      */
 +      ((u8 *) pdir_ptr)[7] = 0;
 +      if (ioc_needs_fdc)
 +              asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
  
        WRITE_REG( SBA_IOVA(ioc, iovp, 0, 0), ioc->ioc_hpa+IOC_PCOM);
  }
  static int sba_dma_supported( struct device *dev, u64 mask)
  {
        struct ioc *ioc;
 +
        if (dev == NULL) {
                printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n");
                BUG();
                return(0);
        }
  
 -      ioc = GET_IOC(dev);
 +      /* Documentation/DMA-mapping.txt tells drivers to try 64-bit first,
 +       * then fall back to 32-bit if that fails.
 +       * We are just "encouraging" 32-bit DMA masks here since we can
 +       * never allow IOMMU bypass unless we add special support for ZX1.
 +       */
 +      if (mask > ~0U)
 +              return 0;
  
 -      /* check if mask is > than the largest IO Virt Address */
 +      ioc = GET_IOC(dev);
  
 -      return((int) (mask >= (ioc->ibase +
 -                              (ioc->pdir_size / sizeof(u64) * IOVP_SIZE) )));
 +      /*
 +       * check if mask is >= than the current max IO Virt Address
 +       * The max IO Virt address will *always* < 30 bits.
 +       */
 +      return((int)(mask >= (ioc->ibase - 1 +
 +                      (ioc->pdir_size / sizeof(u64) * IOVP_SIZE) )));
  }
  
  
@@@ -923,17 -898,11 +923,17 @@@ sba_map_single(struct device *dev, voi
                size -= IOVP_SIZE;
                pdir_start++;
        }
 -      /* form complete address */
 +
 +      /* force FDC ops in io_pdir_entry() to be visible to IOMMU */
 +      if (ioc_needs_fdc)
 +              asm volatile("sync" : : );
 +
  #ifdef ASSERT_PDIR_SANITY
        sba_check_pdir(ioc,"Check after sba_map_single()");
  #endif
        spin_unlock_irqrestore(&ioc->res_lock, flags);
 +
 +      /* form complete address */
        return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG);
  }
  
@@@ -989,19 -958,12 +989,19 @@@ sba_unmap_single(struct device *dev, dm
                        d--;
                }
                ioc->saved_cnt = 0;
 +
                READ_REG(ioc->ioc_hpa+IOC_PCOM);        /* flush purges */
        }
  #else /* DELAYED_RESOURCE_CNT == 0 */
        sba_free_range(ioc, iova, size);
 +
 +      /* If fdc's were issued, force fdc's to be visible now */
 +      if (ioc_needs_fdc)
 +              asm volatile("sync" : : );
 +
        READ_REG(ioc->ioc_hpa+IOC_PCOM);        /* flush purges */
  #endif /* DELAYED_RESOURCE_CNT == 0 */
 +
        spin_unlock_irqrestore(&ioc->res_lock, flags);
  
        /* XXX REVISIT for 2.5 Linux - need syncdma for zero-copy support.
   * See Documentation/DMA-mapping.txt
   */
  static void *sba_alloc_consistent(struct device *hwdev, size_t size,
-                                       dma_addr_t *dma_handle, int gfp)
+                                       dma_addr_t *dma_handle, gfp_t gfp)
  {
        void *ret;
  
@@@ -1144,10 -1106,6 +1144,10 @@@ sba_map_sg(struct device *dev, struct s
        */
        filled = iommu_fill_pdir(ioc, sglist, nents, 0, sba_io_pdir_entry);
  
 +      /* force FDC ops in io_pdir_entry() to be visible to IOMMU */
 +      if (ioc_needs_fdc)
 +              asm volatile("sync" : : );
 +
  #ifdef ASSERT_PDIR_SANITY
        if (sba_check_pdir(ioc,"Check after sba_map_sg()"))
        {
@@@ -1276,10 -1234,8 +1276,10 @@@ sba_alloc_pdir(unsigned int pdir_size
        unsigned long pdir_order = get_order(pdir_size);
  
        pdir_base = __get_free_pages(GFP_KERNEL, pdir_order);
 -      if (NULL == (void *) pdir_base)
 -              panic("sba_ioc_init() could not allocate I/O Page Table\n");
 +      if (NULL == (void *) pdir_base) {
 +              panic("%s() could not allocate I/O Page Table\n",
 +                      __FUNCTION__);
 +      }
  
        /* If this is not PA8700 (PCX-W2)
        **      OR newer than ver 2.2
        return (void *) pdir_base;
  }
  
 +static struct device *next_device(struct klist_iter *i)
 +{
 +        struct klist_node * n = klist_next(i);
 +        return n ? container_of(n, struct device, knode_parent) : NULL;
 +}
 +
  /* setup Mercury or Elroy IBASE/IMASK registers. */
 -static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
 +static void 
 +setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
  {
 -        /* lba_set_iregs() is in drivers/parisc/lba_pci.c */
 +      /* lba_set_iregs() is in drivers/parisc/lba_pci.c */
          extern void lba_set_iregs(struct parisc_device *, u32, u32);
        struct device *dev;
 +      struct klist_iter i;
  
 -      list_for_each_entry(dev, &sba->dev.children, node) {
 +      klist_iter_init(&sba->dev.klist_children, &i);
 +      while ((dev = next_device(&i))) {
                struct parisc_device *lba = to_parisc_device(dev);
 -              int rope_num = (lba->hpa >> 13) & 0xf;
 +              int rope_num = (lba->hpa.start >> 13) & 0xf;
                if (rope_num >> 3 == ioc_num)
                        lba_set_iregs(lba, ioc->ibase, ioc->imask);
        }
 +      klist_iter_exit(&i);
  }
  
  static void
@@@ -1397,7 -1343,7 +1397,7 @@@ sba_ioc_init_pluto(struct parisc_devic
        u32 iova_space_mask;
        u32 iova_space_size;
        int iov_order, tcnfg;
 -#if SBA_AGP_SUPPORT
 +#ifdef SBA_AGP_SUPPORT
        int agp_found = 0;
  #endif
        /*
        DBG_INIT("%s() pdir %p size %x\n",
                        __FUNCTION__, ioc->pdir_base, ioc->pdir_size);
  
 -#if SBA_HINT_SUPPORT
 +#ifdef SBA_HINT_SUPPORT
        ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
        ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
  
  
        WRITE_REG(ioc->imask, ioc->ioc_hpa + IOC_IMASK);
  
 -#ifdef __LP64__
 +#ifdef CONFIG_64BIT
        /*
        ** Setting the upper bits makes checking for bypass addresses
        ** a little faster later on.
        */
        WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM);
  
 -#if SBA_AGP_SUPPORT
 +#ifdef SBA_AGP_SUPPORT
        /*
        ** If an AGP device is present, only use half of the IOV space
        ** for PCI DMA.  Unfortunately we can't know ahead of time
@@@ -1543,9 -1489,11 +1543,9 @@@ sba_ioc_init(struct parisc_device *sba
        if (iova_space_size < (1 << (20 - PAGE_SHIFT))) {
                iova_space_size = 1 << (20 - PAGE_SHIFT);
        }
 -#ifdef __LP64__
        else if (iova_space_size > (1 << (30 - PAGE_SHIFT))) {
                iova_space_size = 1 << (30 - PAGE_SHIFT);
        }
 -#endif
  
        /*
        ** iova space must be log2() in size.
        DBG_INIT("%s() pdir %p size %x\n",
                        __FUNCTION__, ioc->pdir_base, pdir_size);
  
 -#if SBA_HINT_SUPPORT
 +#ifdef SBA_HINT_SUPPORT
        /* FIXME : DMA HINTs not used */
        ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
        ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
  
  static void __iomem *ioc_remap(struct sba_device *sba_dev, int offset)
  {
 -      return ioremap(sba_dev->dev->hpa + offset, SBA_FUNC_SIZE);
 +      return ioremap(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE);
  }
  
  static void sba_hw_init(struct sba_device *sba_dev)
@@@ -2020,7 -1968,7 +2020,7 @@@ sba_driver_callback(struct parisc_devic
        u32 func_class;
        int i;
        char *version;
 -      void __iomem *sba_addr = ioremap(dev->hpa, SBA_FUNC_SIZE);
 +      void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE);
  
        sba_dump_ranges(sba_addr);
  
        }
  
        printk(KERN_INFO "%s found %s at 0x%lx\n",
 -              MODULE_NAME, version, dev->hpa);
 +              MODULE_NAME, version, dev->hpa.start);
  
        sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
        if (!sba_dev) {