| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2004 Hewlett-Packard Development Company, L.P. | 
					
						
							|  |  |  |  *   Contributed by David Mosberger-Tang <davidm@hpl.hp.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This is a pseudo I/O MMU which dispatches to the hardware I/O MMU | 
					
						
							|  |  |  |  * whenever possible.  We assume that the hardware I/O MMU requires | 
					
						
							|  |  |  |  * full 32-bit addressability, as is the case, e.g., for HP zx1-based | 
					
						
							|  |  |  |  * systems (there, the I/O MMU window is mapped at 3-4GB).  If a | 
					
						
							|  |  |  |  * device doesn't provide full 32-bit addressability, we fall back on | 
					
						
							|  |  |  |  * the sw I/O TLB.  This is good enough to let us support broken | 
					
						
							|  |  |  |  * hardware such as soundcards which have a DMA engine that can | 
					
						
							|  |  |  |  * address only 28 bits. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/device.h>
 | 
					
						
							| 
									
										
										
										
											2009-01-05 23:36:08 +09:00
										 |  |  | #include <linux/dma-mapping.h>
 | 
					
						
							| 
									
										
										
										
											2008-10-29 14:17:59 -07:00
										 |  |  | #include <linux/swiotlb.h>
 | 
					
						
							| 
									
										
										
										
											2011-07-31 18:33:21 -04:00
										 |  |  | #include <linux/export.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <asm/machvec.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-05 23:59:02 +09:00
										 |  |  | extern struct dma_map_ops sba_dma_ops, swiotlb_dma_ops; | 
					
						
							| 
									
										
										
										
											2009-01-05 23:36:17 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* swiotlb declarations & definitions: */ | 
					
						
							| 
									
										
										
										
											2005-09-06 11:20:49 -06:00
										 |  |  | extern int swiotlb_late_init_with_default_size (size_t size); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Note: we need to make the determination of whether or not to use | 
					
						
							|  |  |  |  * the sw I/O TLB based purely on the device structure.  Anything else | 
					
						
							|  |  |  |  * would be unreliable or would be too intrusive. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-01-05 23:36:17 +09:00
										 |  |  | static inline int use_swiotlb(struct device *dev) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-05 23:36:17 +09:00
										 |  |  | 	return dev && dev->dma_mask && | 
					
						
							| 
									
										
										
										
											2009-01-05 23:59:02 +09:00
										 |  |  | 		!sba_dma_ops.dma_supported(dev, *dev->dma_mask); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-05 23:59:02 +09:00
										 |  |  | struct dma_map_ops *hwsw_dma_get_ops(struct device *dev) | 
					
						
							| 
									
										
										
										
											2009-01-05 23:36:17 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (use_swiotlb(dev)) | 
					
						
							|  |  |  | 		return &swiotlb_dma_ops; | 
					
						
							|  |  |  | 	return &sba_dma_ops; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | EXPORT_SYMBOL(hwsw_dma_get_ops); | 
					
						
							| 
									
										
										
										
											2009-01-05 23:36:12 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-10 11:57:58 -07:00
										 |  |  | void __init | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | hwsw_init (void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* default to a smallish 2MB sw I/O TLB */ | 
					
						
							| 
									
										
										
										
											2005-09-06 11:20:49 -06:00
										 |  |  | 	if (swiotlb_late_init_with_default_size (2 * (1<<20)) != 0) { | 
					
						
							|  |  |  | #ifdef CONFIG_IA64_GENERIC
 | 
					
						
							|  |  |  | 		/* Better to have normal DMA than panic */ | 
					
						
							|  |  |  | 		printk(KERN_WARNING "%s: Failed to initialize software I/O TLB," | 
					
						
							| 
									
										
										
										
											2008-03-04 15:15:00 -08:00
										 |  |  | 		       " reverting to hpzx1 platform vector\n", __func__); | 
					
						
							| 
									
										
										
										
											2005-09-06 11:20:49 -06:00
										 |  |  | 		machvec_init("hpzx1"); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		panic("Unable to initialize software I/O TLB services"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } |