| .. | .. | 
|---|
| 10 | 10 |  #include <linux/slab.h> | 
|---|
| 11 | 11 |  #include <linux/spinlock.h> | 
|---|
| 12 | 12 |  #include <linux/mm.h> | 
|---|
| 13 |  | -#include <linux/highmem.h>	/* pte_offset_map => kmap_atomic */  | 
|---|
| 14 | 13 |  #include <linux/bitops.h> | 
|---|
| 15 |  | -#include <linux/scatterlist.h>  | 
|---|
 | 14 | +#include <linux/dma-map-ops.h>  | 
|---|
| 16 | 15 |  #include <linux/of.h> | 
|---|
| 17 | 16 |  #include <linux/of_device.h> | 
|---|
| 18 | 17 |   | 
|---|
| 19 |  | -#include <asm/pgalloc.h>  | 
|---|
| 20 |  | -#include <asm/pgtable.h>  | 
|---|
| 21 | 18 |  #include <asm/io.h> | 
|---|
| 22 | 19 |  #include <asm/io-unit.h> | 
|---|
| 23 | 20 |  #include <asm/mxcc.h> | 
|---|
| .. | .. | 
|---|
| 37 | 34 |   | 
|---|
| 38 | 35 |  #define IOPERM        (IOUPTE_CACHE | IOUPTE_WRITE | IOUPTE_VALID) | 
|---|
| 39 | 36 |  #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM) | 
|---|
 | 37 | +  | 
|---|
 | 38 | +static const struct dma_map_ops iounit_dma_ops;  | 
|---|
| 40 | 39 |   | 
|---|
| 41 | 40 |  static void __init iounit_iommu_init(struct platform_device *op) | 
|---|
| 42 | 41 |  { | 
|---|
| .. | .. | 
|---|
| 70 | 69 |  	xptend = iounit->page_table + (16 * PAGE_SIZE) / sizeof(iopte_t); | 
|---|
| 71 | 70 |  	for (; xpt < xptend; xpt++) | 
|---|
| 72 | 71 |  		sbus_writel(0, xpt); | 
|---|
 | 72 | +  | 
|---|
 | 73 | +	op->dev.dma_ops = &iounit_dma_ops;  | 
|---|
| 73 | 74 |  } | 
|---|
| 74 | 75 |   | 
|---|
| 75 | 76 |  static int __init iounit_init(void) | 
|---|
| .. | .. | 
|---|
| 140 | 141 |  	return vaddr; | 
|---|
| 141 | 142 |  } | 
|---|
| 142 | 143 |   | 
|---|
| 143 |  | -static __u32 iounit_get_scsi_one(struct device *dev, char *vaddr, unsigned long len)  | 
|---|
 | 144 | +static dma_addr_t iounit_map_page(struct device *dev, struct page *page,  | 
|---|
 | 145 | +		unsigned long offset, size_t len, enum dma_data_direction dir,  | 
|---|
 | 146 | +		unsigned long attrs)  | 
|---|
| 144 | 147 |  { | 
|---|
 | 148 | +	void *vaddr = page_address(page) + offset;  | 
|---|
| 145 | 149 |  	struct iounit_struct *iounit = dev->archdata.iommu; | 
|---|
| 146 | 150 |  	unsigned long ret, flags; | 
|---|
| 147 | 151 |  	 | 
|---|
 | 152 | +	/* XXX So what is maxphys for us and how do drivers know it? */  | 
|---|
 | 153 | +	if (!len || len > 256 * 1024)  | 
|---|
 | 154 | +		return DMA_MAPPING_ERROR;  | 
|---|
 | 155 | +  | 
|---|
| 148 | 156 |  	spin_lock_irqsave(&iounit->lock, flags); | 
|---|
| 149 | 157 |  	ret = iounit_get_area(iounit, (unsigned long)vaddr, len); | 
|---|
| 150 | 158 |  	spin_unlock_irqrestore(&iounit->lock, flags); | 
|---|
| 151 | 159 |  	return ret; | 
|---|
| 152 | 160 |  } | 
|---|
| 153 | 161 |   | 
|---|
| 154 |  | -static void iounit_get_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz)  | 
|---|
 | 162 | +static int iounit_map_sg(struct device *dev, struct scatterlist *sgl, int nents,  | 
|---|
 | 163 | +		enum dma_data_direction dir, unsigned long attrs)  | 
|---|
| 155 | 164 |  { | 
|---|
| 156 | 165 |  	struct iounit_struct *iounit = dev->archdata.iommu; | 
|---|
 | 166 | +	struct scatterlist *sg;  | 
|---|
| 157 | 167 |  	unsigned long flags; | 
|---|
 | 168 | +	int i;  | 
|---|
| 158 | 169 |   | 
|---|
| 159 | 170 |  	/* FIXME: Cache some resolved pages - often several sg entries are to the same page */ | 
|---|
| 160 | 171 |  	spin_lock_irqsave(&iounit->lock, flags); | 
|---|
| 161 |  | -	while (sz != 0) {  | 
|---|
| 162 |  | -		--sz;  | 
|---|
 | 172 | +	for_each_sg(sgl, sg, nents, i) {  | 
|---|
| 163 | 173 |  		sg->dma_address = iounit_get_area(iounit, (unsigned long) sg_virt(sg), sg->length); | 
|---|
| 164 | 174 |  		sg->dma_length = sg->length; | 
|---|
| 165 |  | -		sg = sg_next(sg);  | 
|---|
| 166 | 175 |  	} | 
|---|
| 167 | 176 |  	spin_unlock_irqrestore(&iounit->lock, flags); | 
|---|
 | 177 | +	return nents;  | 
|---|
| 168 | 178 |  } | 
|---|
| 169 | 179 |   | 
|---|
| 170 |  | -static void iounit_release_scsi_one(struct device *dev, __u32 vaddr, unsigned long len)  | 
|---|
 | 180 | +static void iounit_unmap_page(struct device *dev, dma_addr_t vaddr, size_t len,  | 
|---|
 | 181 | +		enum dma_data_direction dir, unsigned long attrs)  | 
|---|
| 171 | 182 |  { | 
|---|
| 172 | 183 |  	struct iounit_struct *iounit = dev->archdata.iommu; | 
|---|
| 173 | 184 |  	unsigned long flags; | 
|---|
| .. | .. | 
|---|
| 181 | 192 |  	spin_unlock_irqrestore(&iounit->lock, flags); | 
|---|
| 182 | 193 |  } | 
|---|
| 183 | 194 |   | 
|---|
| 184 |  | -static void iounit_release_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz)  | 
|---|
 | 195 | +static void iounit_unmap_sg(struct device *dev, struct scatterlist *sgl,  | 
|---|
 | 196 | +		int nents, enum dma_data_direction dir, unsigned long attrs)  | 
|---|
| 185 | 197 |  { | 
|---|
| 186 | 198 |  	struct iounit_struct *iounit = dev->archdata.iommu; | 
|---|
| 187 |  | -	unsigned long flags;  | 
|---|
| 188 |  | -	unsigned long vaddr, len;  | 
|---|
 | 199 | +	unsigned long flags, vaddr, len;  | 
|---|
 | 200 | +	struct scatterlist *sg;  | 
|---|
 | 201 | +	int i;  | 
|---|
| 189 | 202 |   | 
|---|
| 190 | 203 |  	spin_lock_irqsave(&iounit->lock, flags); | 
|---|
| 191 |  | -	while (sz != 0) {  | 
|---|
| 192 |  | -		--sz;  | 
|---|
 | 204 | +	for_each_sg(sgl, sg, nents, i) {  | 
|---|
| 193 | 205 |  		len = ((sg->dma_address & ~PAGE_MASK) + sg->length + (PAGE_SIZE-1)) >> PAGE_SHIFT; | 
|---|
| 194 | 206 |  		vaddr = (sg->dma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT; | 
|---|
| 195 | 207 |  		IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr)); | 
|---|
| 196 | 208 |  		for (len += vaddr; vaddr < len; vaddr++) | 
|---|
| 197 | 209 |  			clear_bit(vaddr, iounit->bmap); | 
|---|
| 198 |  | -		sg = sg_next(sg);  | 
|---|
| 199 | 210 |  	} | 
|---|
| 200 | 211 |  	spin_unlock_irqrestore(&iounit->lock, flags); | 
|---|
| 201 | 212 |  } | 
|---|
| 202 | 213 |   | 
|---|
| 203 | 214 |  #ifdef CONFIG_SBUS | 
|---|
| 204 |  | -static int iounit_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va, unsigned long addr, int len)  | 
|---|
 | 215 | +static void *iounit_alloc(struct device *dev, size_t len,  | 
|---|
 | 216 | +		dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)  | 
|---|
| 205 | 217 |  { | 
|---|
| 206 | 218 |  	struct iounit_struct *iounit = dev->archdata.iommu; | 
|---|
| 207 |  | -	unsigned long page, end;  | 
|---|
 | 219 | +	unsigned long va, addr, page, end, ret;  | 
|---|
| 208 | 220 |  	pgprot_t dvma_prot; | 
|---|
| 209 | 221 |  	iopte_t __iomem *iopte; | 
|---|
| 210 | 222 |   | 
|---|
| 211 |  | -	*pba = addr;  | 
|---|
 | 223 | +	/* XXX So what is maxphys for us and how do drivers know it? */  | 
|---|
 | 224 | +	if (!len || len > 256 * 1024)  | 
|---|
 | 225 | +		return NULL;  | 
|---|
 | 226 | +  | 
|---|
 | 227 | +	len = PAGE_ALIGN(len);  | 
|---|
 | 228 | +	va = __get_free_pages(gfp | __GFP_ZERO, get_order(len));  | 
|---|
 | 229 | +	if (!va)  | 
|---|
 | 230 | +		return NULL;  | 
|---|
 | 231 | +  | 
|---|
 | 232 | +	addr = ret = sparc_dma_alloc_resource(dev, len);  | 
|---|
 | 233 | +	if (!addr)  | 
|---|
 | 234 | +		goto out_free_pages;  | 
|---|
 | 235 | +	*dma_handle = addr;  | 
|---|
| 212 | 236 |   | 
|---|
| 213 | 237 |  	dvma_prot = __pgprot(SRMMU_CACHE | SRMMU_ET_PTE | SRMMU_PRIV); | 
|---|
| 214 | 238 |  	end = PAGE_ALIGN((addr + len)); | 
|---|
| 215 | 239 |  	while(addr < end) { | 
|---|
| 216 | 240 |  		page = va; | 
|---|
| 217 | 241 |  		{ | 
|---|
| 218 |  | -			pgd_t *pgdp;  | 
|---|
| 219 | 242 |  			pmd_t *pmdp; | 
|---|
| 220 | 243 |  			pte_t *ptep; | 
|---|
| 221 | 244 |  			long i; | 
|---|
| 222 | 245 |   | 
|---|
| 223 |  | -			pgdp = pgd_offset(&init_mm, addr);  | 
|---|
| 224 |  | -			pmdp = pmd_offset(pgdp, addr);  | 
|---|
 | 246 | +			pmdp = pmd_off_k(addr);  | 
|---|
| 225 | 247 |  			ptep = pte_offset_map(pmdp, addr); | 
|---|
| 226 | 248 |   | 
|---|
| 227 | 249 |  			set_pte(ptep, mk_pte(virt_to_page(page), dvma_prot)); | 
|---|
| 228 |  | -			  | 
|---|
 | 250 | +  | 
|---|
| 229 | 251 |  			i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT); | 
|---|
| 230 | 252 |   | 
|---|
| 231 | 253 |  			iopte = iounit->page_table + i; | 
|---|
| .. | .. | 
|---|
| 237 | 259 |  	flush_cache_all(); | 
|---|
| 238 | 260 |  	flush_tlb_all(); | 
|---|
| 239 | 261 |   | 
|---|
| 240 |  | -	return 0;  | 
|---|
 | 262 | +	return (void *)ret;  | 
|---|
 | 263 | +  | 
|---|
 | 264 | +out_free_pages:  | 
|---|
 | 265 | +	free_pages(va, get_order(len));  | 
|---|
 | 266 | +	return NULL;  | 
|---|
| 241 | 267 |  } | 
|---|
| 242 | 268 |   | 
|---|
| 243 |  | -static void iounit_unmap_dma_area(struct device *dev, unsigned long addr, int len)  | 
|---|
 | 269 | +static void iounit_free(struct device *dev, size_t size, void *cpu_addr,  | 
|---|
 | 270 | +		dma_addr_t dma_addr, unsigned long attrs)  | 
|---|
| 244 | 271 |  { | 
|---|
| 245 | 272 |  	/* XXX Somebody please fill this in */ | 
|---|
| 246 | 273 |  } | 
|---|
| 247 | 274 |  #endif | 
|---|
| 248 | 275 |   | 
|---|
| 249 |  | -static const struct sparc32_dma_ops iounit_dma_ops = {  | 
|---|
| 250 |  | -	.get_scsi_one		= iounit_get_scsi_one,  | 
|---|
| 251 |  | -	.get_scsi_sgl		= iounit_get_scsi_sgl,  | 
|---|
| 252 |  | -	.release_scsi_one	= iounit_release_scsi_one,  | 
|---|
| 253 |  | -	.release_scsi_sgl	= iounit_release_scsi_sgl,  | 
|---|
 | 276 | +static const struct dma_map_ops iounit_dma_ops = {  | 
|---|
| 254 | 277 |  #ifdef CONFIG_SBUS | 
|---|
| 255 |  | -	.map_dma_area		= iounit_map_dma_area,  | 
|---|
| 256 |  | -	.unmap_dma_area		= iounit_unmap_dma_area,  | 
|---|
 | 278 | +	.alloc			= iounit_alloc,  | 
|---|
 | 279 | +	.free			= iounit_free,  | 
|---|
| 257 | 280 |  #endif | 
|---|
 | 281 | +	.map_page		= iounit_map_page,  | 
|---|
 | 282 | +	.unmap_page		= iounit_unmap_page,  | 
|---|
 | 283 | +	.map_sg			= iounit_map_sg,  | 
|---|
 | 284 | +	.unmap_sg		= iounit_unmap_sg,  | 
|---|
| 258 | 285 |  }; | 
|---|
| 259 |  | -  | 
|---|
| 260 |  | -void __init ld_mmu_iounit(void)  | 
|---|
| 261 |  | -{  | 
|---|
| 262 |  | -	sparc32_dma_ops = &iounit_dma_ops;  | 
|---|
| 263 |  | -}  | 
|---|