X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fparisc%2Fccio-dma.c;h=a5d826237b265a0b683e0b2bbea513c33e11cc34;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=c4f348241227327c4f4e7a4beaa5e399be208701;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index c4f348241..a5d826237 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -40,11 +40,12 @@ #include #include #include +#include +#include #include #include /* for L1_CACHE_BYTES */ #include -#include #include #include #include @@ -101,9 +102,9 @@ #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 @@ -116,28 +117,28 @@ 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 */ }; /* @@ -227,7 +228,7 @@ struct ioa_registers { */ 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 */ @@ -263,8 +264,6 @@ struct ioc { struct resource mmio_region[2]; /* The "routed" MMIO regions */ }; -/* Ratio of Host MEM to IOV Space size */ -static unsigned long ccio_mem_ratio = 4; static struct ioc *ioc_list; static int ioc_count; @@ -560,7 +559,7 @@ void CCIO_INLINE ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, unsigned long hints) { - register unsigned long pa = (volatile unsigned long) vba; + register unsigned long pa; register unsigned long ci; /* coherent index */ /* We currently only support kernel addresses */ @@ -598,7 +597,7 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, ** 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)); @@ -616,7 +615,7 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, ** 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"); } @@ -639,7 +638,7 @@ ccio_clear_io_tlb(struct ioc *ioc, dma_addr_t iovp, size_t byte_cnt) 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; } @@ -687,7 +686,7 @@ ccio_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) ** 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; @@ -839,7 +838,7 @@ ccio_unmap_single(struct device *dev, dma_addr_t iova, size_t size, * 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 @@ -1022,62 +1021,33 @@ static struct hppa_dma_ops ccio_ops = { }; #ifdef CONFIG_PROC_FS -static int proc_append(char *src, int len, char **dst, off_t *offset, int *max) +static int ccio_proc_info(struct seq_file *m, void *p) { - if (len < *offset) { - *offset -= len; - return 0; - } - if (*offset > 0) { - src += *offset; - len -= *offset; - *offset = 0; - } - if (len > *max) { - len = *max; - } - memcpy(*dst, src, len); - *dst += len; - *max -= len; - return (*max == 0); -} - -static int ccio_proc_info(char *buf, char **start, off_t offset, int count, - int *eof, void *data) -{ - int max = count; - char tmp[80]; /* width of an ANSI-standard terminal */ + int len = 0; struct ioc *ioc = ioc_list; while (ioc != NULL) { unsigned int total_pages = ioc->res_size << 3; unsigned long avg = 0, min, max; - int j, len; + int j; - len = sprintf(tmp, "%s\n", ioc->name); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, "%s\n", ioc->name); - len = sprintf(tmp, "Cujo 2.0 bug : %s\n", - (ioc->cujo20_bug ? "yes" : "no")); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, "Cujo 2.0 bug : %s\n", + (ioc->cujo20_bug ? "yes" : "no")); - len = sprintf(tmp, "IO PDIR size : %d bytes (%d entries)\n", - total_pages * 8, total_pages); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, "IO PDIR size : %d bytes (%d entries)\n", + total_pages * 8, total_pages); + #ifdef CCIO_MAP_STATS - len = sprintf(tmp, "IO PDIR entries : %ld free %ld used (%d%%)\n", - total_pages - ioc->used_pages, ioc->used_pages, - (int)(ioc->used_pages * 100 / total_pages)); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, "IO PDIR entries : %ld free %ld used (%d%%)\n", + total_pages - ioc->used_pages, ioc->used_pages, + (int)(ioc->used_pages * 100 / total_pages)); #endif - len = sprintf(tmp, "Resource bitmap : %d bytes (%d pages)\n", - ioc->res_size, total_pages); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + + len += seq_printf(m, "Resource bitmap : %d bytes (%d pages)\n", + ioc->res_size, total_pages); + #ifdef CCIO_SEARCH_TIME min = max = ioc->avg_search[0]; for(j = 0; j < CCIO_SEARCH_SAMPLE; ++j) { @@ -1088,70 +1058,83 @@ static int ccio_proc_info(char *buf, char **start, off_t offset, int count, min = ioc->avg_search[j]; } avg /= CCIO_SEARCH_SAMPLE; - len = sprintf(tmp, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", - min, avg, max); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", + min, avg, max); #endif #ifdef CCIO_MAP_STATS - len = sprintf(tmp, "pci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n", - ioc->msingle_calls, ioc->msingle_pages, - (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls)); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; - + len += seq_printf(m, "pci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n", + ioc->msingle_calls, ioc->msingle_pages, + (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls)); /* KLUGE - unmap_sg calls unmap_single for each mapped page */ min = ioc->usingle_calls - ioc->usg_calls; max = ioc->usingle_pages - ioc->usg_pages; - len = sprintf(tmp, "pci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n", - min, max, (int)((max * 1000)/min)); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, "pci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n", + min, max, (int)((max * 1000)/min)); - len = sprintf(tmp, "pci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n", - ioc->msg_calls, ioc->msg_pages, - (int)((ioc->msg_pages * 1000)/ioc->msg_calls)); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; - len = sprintf(tmp, "pci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n\n\n", - ioc->usg_calls, ioc->usg_pages, - (int)((ioc->usg_pages * 1000)/ioc->usg_calls)); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, "pci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n", + ioc->msg_calls, ioc->msg_pages, + (int)((ioc->msg_pages * 1000)/ioc->msg_calls)); + + len += seq_printf(m, "pci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n\n\n", + ioc->usg_calls, ioc->usg_pages, + (int)((ioc->usg_pages * 1000)/ioc->usg_calls)); #endif /* CCIO_MAP_STATS */ + ioc = ioc->next; } - if (count == 0) { - *eof = 1; - } - return (max - count); + return 0; } -static int ccio_resource_map(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int ccio_proc_info_open(struct inode *inode, struct file *file) { + return single_open(file, &ccio_proc_info, NULL); +} + +static struct file_operations ccio_proc_info_fops = { + .owner = THIS_MODULE, + .open = ccio_proc_info_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int ccio_proc_bitmap_info(struct seq_file *m, void *p) +{ + int len = 0; struct ioc *ioc = ioc_list; - buf[0] = '\0'; while (ioc != NULL) { u32 *res_ptr = (u32 *)ioc->res_map; int j; for (j = 0; j < (ioc->res_size / sizeof(u32)); j++) { if ((j & 7) == 0) - strcat(buf,"\n "); - sprintf(buf, "%s %08x", buf, *res_ptr); + len += seq_puts(m, "\n "); + len += seq_printf(m, "%08x", *res_ptr); res_ptr++; } - strcat(buf, "\n\n"); + len += seq_puts(m, "\n\n"); ioc = ioc->next; break; /* XXX - remove me */ } - return strlen(buf); + return 0; } + +static int ccio_proc_bitmap_open(struct inode *inode, struct file *file) +{ + return single_open(file, &ccio_proc_bitmap_info, NULL); +} + +static struct file_operations ccio_proc_bitmap_fops = { + .owner = THIS_MODULE, + .open = ccio_proc_bitmap_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; #endif /** @@ -1199,9 +1182,10 @@ void * ccio_get_iommu(const struct parisc_device *dev) * to/from certain pages. To avoid this happening, we mark these pages * as `used', and ensure that nothing will try to allocate from them. */ -void ccio_cujo20_fixup(struct parisc_device *dev, u32 iovp) +void ccio_cujo20_fixup(struct parisc_device *cujo, u32 iovp) { unsigned int idx; + struct parisc_device *dev = parisc_parent(cujo); struct ioc *ioc = ccio_get_iommu(dev); u8 *res_ptr; @@ -1243,6 +1227,21 @@ ccio_get_iotlb_size(struct parisc_device *dev) #define CCIO_CHAINID_MASK 0xff #endif /* 0 */ +/* We *can't* support JAVA (T600). Venture there at your own risk. */ +static struct parisc_device_id ccio_tbl[] = { + { HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */ + { HPHW_IOA, HVERSION_REV_ANY_ID, UTURN_IOA_RUNWAY, 0xb }, /* UTurn */ + { 0, } +}; + +static int ccio_probe(struct parisc_device *dev); + +static struct parisc_driver ccio_driver = { + .name = "ccio", + .id_table = ccio_tbl, + .probe = ccio_probe, +}; + /** * ccio_ioc_init - Initalize the I/O Controller * @ioc: The I/O Controller. @@ -1254,9 +1253,9 @@ ccio_get_iotlb_size(struct parisc_device *dev) static void ccio_ioc_init(struct ioc *ioc) { - int i, iov_order; + int i; + unsigned int iov_order; u32 iova_space_size; - unsigned long physmem; /* ** Determine IOVA Space size from memory size. @@ -1269,17 +1268,16 @@ ccio_ioc_init(struct ioc *ioc) ** Hot-Plug/Removal of PCI cards. (aka PCI OLARD). */ + iova_space_size = (u32) (num_physpages / count_parisc_driver(&ccio_driver)); + /* limit IOVA space size to 1MB-1GB */ - physmem = num_physpages << PAGE_SHIFT; - if(physmem < (ccio_mem_ratio * 1024 * 1024)) { - iova_space_size = 1024 * 1024; + if (iova_space_size < (1 << (20 - PAGE_SHIFT))) { + iova_space_size = 1 << (20 - PAGE_SHIFT); #ifdef __LP64__ - } else if(physmem > (ccio_mem_ratio * 512 * 1024 * 1024)) { - iova_space_size = 512 * 1024 * 1024; + } else if (iova_space_size > (1 << (30 - PAGE_SHIFT))) { + iova_space_size = 1 << (30 - PAGE_SHIFT); #endif - } else { - iova_space_size = (u32)(physmem / ccio_mem_ratio); } /* @@ -1295,32 +1293,33 @@ ccio_ioc_init(struct ioc *ioc) ** this is the case under linux." */ - iov_order = get_order(iova_space_size) >> (IOVP_SHIFT - PAGE_SHIFT); - BUG_ON(iov_order > (30 - IOVP_SHIFT)); /* iova_space_size <= 1GB */ - BUG_ON(iov_order < (20 - IOVP_SHIFT)); /* iova_space_size >= 1MB */ - iova_space_size = 1 << (iov_order + IOVP_SHIFT); + iov_order = get_order(iova_space_size << PAGE_SHIFT); + + /* iova_space_size is now bytes, not pages */ + iova_space_size = 1 << (iov_order + PAGE_SHIFT); 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%p mem %luMB IOV %dMB (%d bits) PDIR size 0x%0x", - __FUNCTION__, ioc->ioc_hpa, physmem>>20, iova_space_size>>20, - iov_order + PAGE_SHIFT, ioc->pdir_size); + 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; @@ -1329,8 +1328,7 @@ ccio_ioc_init(struct ioc *ioc) 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); @@ -1351,44 +1349,58 @@ ccio_ioc_init(struct ioc *ioc) ** 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); } } @@ -1397,11 +1409,10 @@ static void __init ccio_init_resources(struct ioc *ioc) struct resource *res = ioc->mmio_region; char *name = kmalloc(14, GFP_KERNEL); - sprintf(name, "GSC Bus [%d/]", ioc->hw_path); + snprintf(name, 14, "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, @@ -1412,7 +1423,12 @@ 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); @@ -1471,15 +1487,15 @@ int ccio_allocate_resource(const struct parisc_device *dev, 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; } @@ -1506,7 +1522,12 @@ int ccio_request_resource(const struct parisc_device *dev, 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); } /** @@ -1521,17 +1542,17 @@ static int ccio_probe(struct parisc_device *dev) { int i; struct ioc *ioc, **ioc_p = &ioc_list; + struct proc_dir_entry *info_entry, *bitmap_entry; - ioc = kmalloc(sizeof(struct ioc), GFP_KERNEL); + ioc = kzalloc(sizeof(struct ioc), GFP_KERNEL); if (ioc == NULL) { printk(KERN_ERR MODULE_NAME ": memory allocation failure\n"); return 1; } - memset(ioc, 0, sizeof(struct ioc)); 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; @@ -1539,43 +1560,34 @@ static int ccio_probe(struct parisc_device *dev) *ioc_p = ioc; ioc->hw_path = dev->hw_path; - ioc->ioc_hpa = (struct ioa_registers *)dev->hpa; + ioc->ioc_regs = ioremap_nocache(dev->hpa.start, 4096); ccio_ioc_init(ioc); ccio_init_resources(ioc); hppa_dma_ops = &ccio_ops; - dev->dev.platform_data = kmalloc(sizeof(struct pci_hba_data), GFP_KERNEL); + dev->dev.platform_data = kzalloc(sizeof(struct pci_hba_data), GFP_KERNEL); /* if this fails, no I/O cards will work, so may as well bug */ BUG_ON(dev->dev.platform_data == NULL); HBA_DATA(dev->dev.platform_data)->iommu = ioc; - if (ioc_count == 0) { - /* FIXME: Create separate entries for each ioc */ - create_proc_read_entry(MODULE_NAME, S_IRWXU, proc_runway_root, - ccio_proc_info, NULL); - create_proc_read_entry(MODULE_NAME"-bitmap", S_IRWXU, - proc_runway_root, ccio_resource_map, NULL); + info_entry = create_proc_entry(MODULE_NAME, 0, proc_runway_root); + if (info_entry) + info_entry->proc_fops = &ccio_proc_info_fops; + + bitmap_entry = create_proc_entry(MODULE_NAME"-bitmap", 0, proc_runway_root); + if (bitmap_entry) + bitmap_entry->proc_fops = &ccio_proc_bitmap_fops; } + + ioc_count++; + parisc_vmerge_boundary = IOVP_SIZE; parisc_vmerge_max_size = BITS_PER_LONG * IOVP_SIZE; - ioc_count++; + parisc_has_iommu(); return 0; } -/* We *can't* support JAVA (T600). Venture there at your own risk. */ -static struct parisc_device_id ccio_tbl[] = { - { HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */ - { HPHW_IOA, HVERSION_REV_ANY_ID, UTURN_IOA_RUNWAY, 0xb }, /* UTurn */ - { 0, } -}; - -static struct parisc_driver ccio_driver = { - .name = "U2:Uturn", - .id_table = ccio_tbl, - .probe = ccio_probe, -}; - /** * ccio_init - ccio initalization procedure. *