diff options
Diffstat (limited to 'drivers/parisc/sba_iommu.c')
| -rw-r--r-- | drivers/parisc/sba_iommu.c | 179 |
1 files changed, 97 insertions, 82 deletions
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 8c4d2c13d5f..1ff1b67e8b2 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -39,10 +39,12 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <linux/module.h> #include <asm/ropes.h> #include <asm/mckinley.h> /* for proc_mckinley_root */ #include <asm/runway.h> /* for proc_runway_root */ +#include <asm/page.h> /* for PAGE0 */ #include <asm/pdc.h> /* for PDC_MODEL_* */ #include <asm/pdcpat.h> /* for is_pdc_pat() */ #include <asm/parisc-device.h> @@ -384,7 +386,7 @@ sba_search_bitmap(struct ioc *ioc, struct device *dev, } mask = RESMAP_MASK(bits_wanted) >> bitshiftcnt; - DBG_RES("%s() o %ld %p", __FUNCTION__, o, res_ptr); + DBG_RES("%s() o %ld %p", __func__, o, res_ptr); while(res_ptr < res_end) { DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr); @@ -454,7 +456,7 @@ sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size) #endif DBG_RES("%s(%x) %d -> %lx hint %x/%x\n", - __FUNCTION__, size, pages_needed, pide, + __func__, size, pages_needed, pide, (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map), ioc->res_bitshift ); @@ -497,7 +499,7 @@ sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size) unsigned long m = RESMAP_MASK(bits_not_wanted) >> (pide & (BITS_PER_LONG - 1)); DBG_RES("%s( ,%x,%x) %x/%lx %x %p %lx\n", - __FUNCTION__, (uint) iova, size, + __func__, (uint) iova, size, bits_not_wanted, m, pide, res_ptr, *res_ptr); #ifdef SBA_COLLECT_STATS @@ -561,7 +563,7 @@ typedef unsigned long space_t; * IOMMU uses little endian for the pdir. */ -void SBA_INLINE +static void SBA_INLINE sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, unsigned long hint) { @@ -573,7 +575,7 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, mtsp(sid,1); asm("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba)); - pa |= (ci >> 12) & 0xff; /* move CI (8 bits) into lowest byte */ + pa |= (ci >> PAGE_SHIFT) & 0xff; /* move CI (8 bits) into lowest byte */ pa |= SBA_PDIR_VALID_BIT; /* set "valid" bit */ *pdir_ptr = cpu_to_le64(pa); /* swap and store into I/O Pdir */ @@ -668,7 +670,7 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) * @dev: instance of PCI owned by the driver that's asking * @mask: number of address bits this PCI device can handle * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static int sba_dma_supported( struct device *dev, u64 mask) { @@ -680,8 +682,8 @@ static int sba_dma_supported( struct device *dev, u64 mask) return(0); } - /* Documentation/DMA-mapping.txt tells drivers to try 64-bit first, - * then fall back to 32-bit if that fails. + /* Documentation/DMA-API-HOWTO.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. */ @@ -706,7 +708,7 @@ static int sba_dma_supported( struct device *dev, u64 mask) * @size: number of bytes to map in driver buffer. * @direction: R/W or both. * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static dma_addr_t sba_map_single(struct device *dev, void *addr, size_t size, @@ -740,7 +742,7 @@ sba_map_single(struct device *dev, void *addr, size_t size, iovp = (dma_addr_t) pide << IOVP_SHIFT; DBG_RUN("%s() 0x%p -> 0x%lx\n", - __FUNCTION__, addr, (long) iovp | offset); + __func__, addr, (long) iovp | offset); pdir_start = &(ioc->pdir_base[pide]); @@ -785,7 +787,7 @@ sba_map_single(struct device *dev, void *addr, size_t size, * @size: number of bytes mapped in driver buffer. * @direction: R/W or both. * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, @@ -798,7 +800,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, unsigned long flags; dma_addr_t offset; - DBG_RUN("%s() iovp 0x%lx/%x\n", __FUNCTION__, (long) iova, size); + DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long) iova, size); ioc = GET_IOC(dev); offset = iova & ~IOVP_MASK; @@ -861,7 +863,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, * @size: number of bytes mapped in driver buffer. * @dma_handle: IOVA of new buffer. * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static void *sba_alloc_consistent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t gfp) @@ -892,7 +894,7 @@ static void *sba_alloc_consistent(struct device *hwdev, size_t size, * @vaddr: virtual address IOVA of "consistent" buffer. * @dma_handler: IO virtual address of "consistent" buffer. * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static void sba_free_consistent(struct device *hwdev, size_t size, void *vaddr, @@ -927,7 +929,7 @@ int dump_run_sg = 0; * @nents: number of entries in list * @direction: R/W or both. * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, @@ -937,7 +939,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int coalesced, filled = 0; unsigned long flags; - DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents); + DBG_RUN_SG("%s() START %d entries\n", __func__, nents); ioc = GET_IOC(dev); @@ -998,7 +1000,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, spin_unlock_irqrestore(&ioc->res_lock, flags); - DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled); + DBG_RUN_SG("%s() DONE %d mappings\n", __func__, filled); return filled; } @@ -1011,7 +1013,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, * @nents: number of entries in list * @direction: R/W or both. * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static void sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, @@ -1023,7 +1025,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, #endif DBG_RUN_SG("%s() START %d entries, %p,%x\n", - __FUNCTION__, nents, sg_virt_addr(sglist), sglist->length); + __func__, nents, sg_virt_addr(sglist), sglist->length); ioc = GET_IOC(dev); @@ -1047,7 +1049,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, ++sglist; } - DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__, nents); + DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents); #ifdef ASSERT_PDIR_SANITY spin_lock_irqsave(&ioc->res_lock, flags); @@ -1118,7 +1120,7 @@ sba_alloc_pdir(unsigned int pdir_size) pdir_base = __get_free_pages(GFP_KERNEL, pdir_order); if (NULL == (void *) pdir_base) { panic("%s() could not allocate I/O Page Table\n", - __FUNCTION__); + __func__); } /* If this is not PA8700 (PCX-W2) @@ -1206,31 +1208,49 @@ sba_alloc_pdir(unsigned int pdir_size) return (void *) pdir_base; } -static struct device *next_device(struct klist_iter *i) +struct ibase_data_struct { + struct ioc *ioc; + int ioc_num; +}; + +static int setup_ibase_imask_callback(struct device *dev, void *data) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ + extern void lba_set_iregs(struct parisc_device *, u32, u32); + struct parisc_device *lba = to_parisc_device(dev); + struct ibase_data_struct *ibd = data; + int rope_num = (lba->hpa.start >> 13) & 0xf; + if (rope_num >> 3 == ibd->ioc_num) + lba_set_iregs(lba, ibd->ioc->ibase, ibd->ioc->imask); + return 0; } /* setup Mercury or Elroy IBASE/IMASK registers. */ 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 */ - extern void lba_set_iregs(struct parisc_device *, u32, u32); - struct device *dev; - struct klist_iter i; - - 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.start >> 13) & 0xf; - if (rope_num >> 3 == ioc_num) - lba_set_iregs(lba, ioc->ibase, ioc->imask); - } - klist_iter_exit(&i); + struct ibase_data_struct ibase_data = { + .ioc = ioc, + .ioc_num = ioc_num, + }; + + device_for_each_child(&sba->dev, &ibase_data, + setup_ibase_imask_callback); } +#ifdef SBA_AGP_SUPPORT +static int +sba_ioc_find_quicksilver(struct device *dev, void *data) +{ + int *agp_found = data; + struct parisc_device *lba = to_parisc_device(dev); + + if (IS_QUICKSILVER(lba)) + *agp_found = 1; + return 0; +} +#endif + static void sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { @@ -1261,7 +1281,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64); DBG_INIT("%s() hpa 0x%p IOV %dMB (%d bits)\n", - __FUNCTION__, ioc->ioc_hpa, iova_space_size >> 20, + __func__, ioc->ioc_hpa, iova_space_size >> 20, iov_order + PAGE_SHIFT); ioc->pdir_base = (void *) __get_free_pages(GFP_KERNEL, @@ -1272,7 +1292,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) memset(ioc->pdir_base, 0, ioc->pdir_size); DBG_INIT("%s() pdir %p size %x\n", - __FUNCTION__, ioc->pdir_base, ioc->pdir_size); + __func__, ioc->pdir_base, ioc->pdir_size); #ifdef SBA_HINT_SUPPORT ioc->hint_shift_pdir = iov_order + PAGE_SHIFT; @@ -1332,9 +1352,6 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM); #ifdef SBA_AGP_SUPPORT -{ - struct klist_iter i; - struct device *dev = NULL; /* ** If an AGP device is present, only use half of the IOV space @@ -1344,30 +1361,22 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ** We program the next pdir index after we stop w/ a key for ** the GART code to handshake on. */ - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *lba = to_parisc_device(dev); - if (IS_QUICKSILVER(lba)) - agp_found = 1; - } - klist_iter_exit(&i); + device_for_each_child(&sba->dev, &agp_found, sba_ioc_find_quicksilver); if (agp_found && sba_reserve_agpgart) { printk(KERN_INFO "%s: reserving %dMb of IOVA space for agpgart\n", - __FUNCTION__, (iova_space_size/2) >> 20); + __func__, (iova_space_size/2) >> 20); ioc->pdir_size /= 2; ioc->pdir_base[PDIR_INDEX(iova_space_size/2)] = SBA_AGPGART_COOKIE; } -} #endif /*SBA_AGP_SUPPORT*/ - } static void sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { u32 iova_space_size, iova_space_mask; - unsigned int pdir_size, iov_order; + unsigned int pdir_size, iov_order, tcnfg; /* ** Determine IOVA Space size from memory size. @@ -1383,7 +1392,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ** for DMA hints - ergo only 30 bits max. */ - iova_space_size = (u32) (num_physpages/global_ioc_cnt); + iova_space_size = (u32) (totalram_pages/global_ioc_cnt); /* limit IOVA space size to 1MB-1GB */ if (iova_space_size < (1 << (20 - PAGE_SHIFT))) { @@ -1406,16 +1415,16 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64); DBG_INIT("%s() hpa 0x%lx mem %ldMB IOV %dMB (%d bits)\n", - __FUNCTION__, + __func__, ioc->ioc_hpa, - (unsigned long) num_physpages >> (20 - PAGE_SHIFT), + (unsigned long) totalram_pages >> (20 - PAGE_SHIFT), iova_space_size>>20, iov_order + PAGE_SHIFT); ioc->pdir_base = sba_alloc_pdir(pdir_size); DBG_INIT("%s() pdir %p size %x\n", - __FUNCTION__, ioc->pdir_base, pdir_size); + __func__, ioc->pdir_base, pdir_size); #ifdef SBA_HINT_SUPPORT /* FIXME : DMA HINTs not used */ @@ -1443,7 +1452,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) #endif DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n", - __FUNCTION__, ioc->ibase, ioc->imask); + __func__, ioc->ibase, ioc->imask); /* ** FIXME: Hint registers are programmed with default hint @@ -1459,8 +1468,19 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa+IOC_IBASE); WRITE_REG(ioc->imask, ioc->ioc_hpa+IOC_IMASK); - /* Set I/O PDIR Page size to 4K */ - WRITE_REG(0, ioc->ioc_hpa+IOC_TCNFG); + /* Set I/O PDIR Page size to system page size */ + switch (PAGE_SHIFT) { + case 12: tcnfg = 0; break; /* 4K */ + case 13: tcnfg = 1; break; /* 8K */ + case 14: tcnfg = 2; break; /* 16K */ + case 16: tcnfg = 3; break; /* 64K */ + default: + panic(__FILE__ "Unsupported system page size %d", + 1 << PAGE_SHIFT); + break; + } + /* Set I/O PDIR Page size to PAGE_SIZE (4k/16k/...) */ + WRITE_REG(tcnfg, ioc->ioc_hpa+IOC_TCNFG); /* ** Clear I/O TLB of any possible entries. @@ -1470,7 +1490,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->ibase = 0; /* used by SBA_IOVA and related macros */ - DBG_INIT("%s() DONE\n", __FUNCTION__); + DBG_INIT("%s() DONE\n", __func__); } @@ -1544,7 +1564,7 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa, if (!IS_PLUTO(sba_dev->dev)) { ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL); DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->", - __FUNCTION__, sba_dev->sba_hpa, ioc_ctl); + __func__, sba_dev->sba_hpa, ioc_ctl); ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC | IOC_CTRL_CE); ioc_ctl |= IOC_CTRL_DD | IOC_CTRL_D4 | IOC_CTRL_TC; /* j6700 v1.6 firmware sets 0x294f */ @@ -1675,7 +1695,7 @@ sba_common_init(struct sba_device *sba_dev) res_size >>= 3; /* convert bit count to byte count */ DBG_INIT("%s() res_size 0x%x\n", - __FUNCTION__, res_size); + __func__, res_size); sba_dev->ioc[i].res_size = res_size; sba_dev->ioc[i].res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size)); @@ -1688,7 +1708,7 @@ sba_common_init(struct sba_device *sba_dev) if (NULL == sba_dev->ioc[i].res_map) { panic("%s:%s() could not allocate resource map\n", - __FILE__, __FUNCTION__ ); + __FILE__, __func__ ); } memset(sba_dev->ioc[i].res_map, 0, res_size); @@ -1725,7 +1745,7 @@ sba_common_init(struct sba_device *sba_dev) #endif DBG_INIT("%s() %d res_map %x %p\n", - __FUNCTION__, i, res_size, sba_dev->ioc[i].res_map); + __func__, i, res_size, sba_dev->ioc[i].res_map); } spin_lock_init(&sba_dev->sba_lock); @@ -1874,7 +1894,7 @@ static struct parisc_device_id sba_tbl[] = { { 0, } }; -int sba_driver_callback(struct parisc_device *); +static int sba_driver_callback(struct parisc_device *); static struct parisc_driver sba_driver = { .name = MODULE_NAME, @@ -1887,15 +1907,16 @@ static struct parisc_driver sba_driver = { ** If so, initialize the chip and tell other partners in crime they ** have work to do. */ -int -sba_driver_callback(struct parisc_device *dev) +static int sba_driver_callback(struct parisc_device *dev) { struct sba_device *sba_dev; u32 func_class; int i; char *version; void __iomem *sba_addr = ioremap_nocache(dev->hpa.start, SBA_FUNC_SIZE); - struct proc_dir_entry *info_entry, *bitmap_entry, *root; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *root; +#endif sba_dump_ranges(sba_addr); @@ -1973,18 +1994,10 @@ sba_driver_callback(struct parisc_device *dev) break; } - info_entry = create_proc_entry("sba_iommu", 0, root); - bitmap_entry = create_proc_entry("sba_iommu-bitmap", 0, root); - - if (info_entry) - info_entry->proc_fops = &sba_proc_fops; - - if (bitmap_entry) - bitmap_entry->proc_fops = &sba_proc_bitmap_fops; + proc_create("sba_iommu", 0, root, &sba_proc_fops); + proc_create("sba_iommu-bitmap", 0, root, &sba_proc_bitmap_fops); #endif - parisc_vmerge_boundary = IOVP_SIZE; - parisc_vmerge_max_size = IOVP_SIZE * BITS_PER_LONG; parisc_has_iommu(); return 0; } @@ -2010,7 +2023,7 @@ void __init sba_init(void) void * sba_get_iommu(struct parisc_device *pci_hba) { struct parisc_device *sba_dev = parisc_parent(pci_hba); - struct sba_device *sba = sba_dev->dev.driver_data; + struct sba_device *sba = dev_get_drvdata(&sba_dev->dev); char t = sba_dev->id.hw_type; int iocnum = (pci_hba->hw_path >> 3); /* rope # */ @@ -2031,7 +2044,7 @@ void * sba_get_iommu(struct parisc_device *pci_hba) void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) { struct parisc_device *sba_dev = parisc_parent(pci_hba); - struct sba_device *sba = sba_dev->dev.driver_data; + struct sba_device *sba = dev_get_drvdata(&sba_dev->dev); char t = sba_dev->id.hw_type; int i; int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */ @@ -2057,6 +2070,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) r->start = (base & ~1UL) | PCI_F_EXTEND; size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK); r->end = r->start + size; + r->flags = IORESOURCE_MEM; } } @@ -2073,7 +2087,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r ) { struct parisc_device *sba_dev = parisc_parent(pci_hba); - struct sba_device *sba = sba_dev->dev.driver_data; + struct sba_device *sba = dev_get_drvdata(&sba_dev->dev); char t = sba_dev->id.hw_type; int base, size; int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */ @@ -2093,4 +2107,5 @@ void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r ) size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC; r->start += rope * (size + 1); /* adjust base for this rope */ r->end = r->start + size; + r->flags = IORESOURCE_MEM; } |
