diff options
author | Mark Maule <maule@sgi.com> | 2005-04-25 14:26:03 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2005-04-25 14:26:03 -0400 |
commit | e955d82543fea76b02aa243b182e782f71bda82c (patch) | |
tree | 58dc9df5161f47bca69c8dc9c819495f15694352 | |
parent | 25ee7e3832951cf5896b194f6cd929a44863f419 (diff) |
[IA64-SGI] sn2-pci-dma-abstraction.patch
Provide an abstraction of the altix pci dma runtime layer so that multiple
pci-based bridges can be supported.
Signed-off-by: Mark Maule <maule@sgi.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r-- | arch/ia64/sn/include/pci/pcibr_provider.h | 6 | ||||
-rw-r--r-- | arch/ia64/sn/include/pci/pcibus_provider_defs.h | 12 | ||||
-rw-r--r-- | arch/ia64/sn/include/pci/pcidev.h | 4 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/io_init.c | 72 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pci_dma.c | 35 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pcibr/pcibr_dma.c | 103 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pcibr/pcibr_provider.c | 20 |
7 files changed, 173 insertions, 79 deletions
diff --git a/arch/ia64/sn/include/pci/pcibr_provider.h b/arch/ia64/sn/include/pci/pcibr_provider.h index b1f05ffec70b..1cd291d8badd 100644 --- a/arch/ia64/sn/include/pci/pcibr_provider.h +++ b/arch/ia64/sn/include/pci/pcibr_provider.h | |||
@@ -123,9 +123,11 @@ pcibr_lock(struct pcibus_info *pcibus_info) | |||
123 | } | 123 | } |
124 | #define pcibr_unlock(pcibus_info, flag) spin_unlock_irqrestore(&pcibus_info->pbi_lock, flag) | 124 | #define pcibr_unlock(pcibus_info, flag) spin_unlock_irqrestore(&pcibus_info->pbi_lock, flag) |
125 | 125 | ||
126 | extern int pcibr_init_provider(void); | ||
126 | extern void *pcibr_bus_fixup(struct pcibus_bussoft *); | 127 | extern void *pcibr_bus_fixup(struct pcibus_bussoft *); |
127 | extern uint64_t pcibr_dma_map(struct pcidev_info *, unsigned long, size_t, unsigned int); | 128 | extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t); |
128 | extern void pcibr_dma_unmap(struct pcidev_info *, dma_addr_t, int); | 129 | extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t); |
130 | extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int); | ||
129 | 131 | ||
130 | /* | 132 | /* |
131 | * prototypes for the bridge asic register access routines in pcibr_reg.c | 133 | * prototypes for the bridge asic register access routines in pcibr_reg.c |
diff --git a/arch/ia64/sn/include/pci/pcibus_provider_defs.h b/arch/ia64/sn/include/pci/pcibus_provider_defs.h index 07065615bbea..f546b4ece33c 100644 --- a/arch/ia64/sn/include/pci/pcibus_provider_defs.h +++ b/arch/ia64/sn/include/pci/pcibus_provider_defs.h | |||
@@ -18,6 +18,8 @@ | |||
18 | #define PCIIO_ASIC_TYPE_PIC 2 | 18 | #define PCIIO_ASIC_TYPE_PIC 2 |
19 | #define PCIIO_ASIC_TYPE_TIOCP 3 | 19 | #define PCIIO_ASIC_TYPE_TIOCP 3 |
20 | 20 | ||
21 | #define PCIIO_ASIC_MAX_TYPES 4 | ||
22 | |||
21 | /* | 23 | /* |
22 | * Common pciio bus provider data. There should be one of these as the | 24 | * Common pciio bus provider data. There should be one of these as the |
23 | * first field in any pciio based provider soft structure (e.g. pcibr_soft | 25 | * first field in any pciio based provider soft structure (e.g. pcibr_soft |
@@ -35,9 +37,15 @@ struct pcibus_bussoft { | |||
35 | }; | 37 | }; |
36 | 38 | ||
37 | /* | 39 | /* |
38 | * DMA mapping flags | 40 | * SN pci bus indirection |
39 | */ | 41 | */ |
40 | 42 | ||
41 | #define SN_PCIDMA_CONSISTENT 0x0001 | 43 | struct sn_pcibus_provider { |
44 | dma_addr_t (*dma_map)(struct pci_dev *, unsigned long, size_t); | ||
45 | dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t); | ||
46 | void (*dma_unmap)(struct pci_dev *, dma_addr_t, int); | ||
47 | void * (*bus_fixup)(struct pcibus_bussoft *); | ||
48 | }; | ||
42 | 49 | ||
50 | extern struct sn_pcibus_provider *sn_pci_provider[]; | ||
43 | #endif /* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */ | 51 | #endif /* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */ |
diff --git a/arch/ia64/sn/include/pci/pcidev.h b/arch/ia64/sn/include/pci/pcidev.h index 81eb95d3bf47..ed4031d80811 100644 --- a/arch/ia64/sn/include/pci/pcidev.h +++ b/arch/ia64/sn/include/pci/pcidev.h | |||
@@ -32,6 +32,9 @@ extern struct sn_irq_info **sn_irq; | |||
32 | #define SN_PCIDEV_BUSSOFT(pci_dev) \ | 32 | #define SN_PCIDEV_BUSSOFT(pci_dev) \ |
33 | (SN_PCIDEV_INFO(pci_dev)->pdi_host_pcidev_info->pdi_pcibus_info) | 33 | (SN_PCIDEV_INFO(pci_dev)->pdi_host_pcidev_info->pdi_pcibus_info) |
34 | 34 | ||
35 | #define SN_PCIDEV_BUSPROVIDER(pci_dev) \ | ||
36 | (SN_PCIDEV_INFO(pci_dev)->pdi_provider) | ||
37 | |||
35 | #define PCIIO_BUS_NONE 255 /* bus 255 reserved */ | 38 | #define PCIIO_BUS_NONE 255 /* bus 255 reserved */ |
36 | #define PCIIO_SLOT_NONE 255 | 39 | #define PCIIO_SLOT_NONE 255 |
37 | #define PCIIO_FUNC_NONE 255 | 40 | #define PCIIO_FUNC_NONE 255 |
@@ -46,6 +49,7 @@ struct pcidev_info { | |||
46 | struct pci_dev *pdi_linux_pcidev; /* Kernel pci_dev */ | 49 | struct pci_dev *pdi_linux_pcidev; /* Kernel pci_dev */ |
47 | 50 | ||
48 | struct sn_irq_info *pdi_sn_irq_info; | 51 | struct sn_irq_info *pdi_sn_irq_info; |
52 | struct sn_pcibus_provider *pdi_provider; /* sn pci ops */ | ||
49 | }; | 53 | }; |
50 | 54 | ||
51 | extern void sn_irq_fixup(struct pci_dev *pci_dev, | 55 | extern void sn_irq_fixup(struct pci_dev *pci_dev, |
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 001880812b7c..3e5e4a901302 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c | |||
@@ -34,6 +34,37 @@ struct brick { | |||
34 | 34 | ||
35 | int sn_ioif_inited = 0; /* SN I/O infrastructure initialized? */ | 35 | int sn_ioif_inited = 0; /* SN I/O infrastructure initialized? */ |
36 | 36 | ||
37 | struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ | ||
38 | |||
39 | /* | ||
40 | * Hooks and struct for unsupported pci providers | ||
41 | */ | ||
42 | |||
43 | static dma_addr_t | ||
44 | sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size) | ||
45 | { | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static void | ||
50 | sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction) | ||
51 | { | ||
52 | return; | ||
53 | } | ||
54 | |||
55 | static void * | ||
56 | sn_default_pci_bus_fixup(struct pcibus_bussoft *soft) | ||
57 | { | ||
58 | return NULL; | ||
59 | } | ||
60 | |||
61 | static struct sn_pcibus_provider sn_pci_default_provider = { | ||
62 | .dma_map = sn_default_pci_map, | ||
63 | .dma_map_consistent = sn_default_pci_map, | ||
64 | .dma_unmap = sn_default_pci_unmap, | ||
65 | .bus_fixup = sn_default_pci_bus_fixup, | ||
66 | }; | ||
67 | |||
37 | /* | 68 | /* |
38 | * Retrieve the DMA Flush List given nasid. This list is needed | 69 | * Retrieve the DMA Flush List given nasid. This list is needed |
39 | * to implement the WAR - Flush DMA data on PIO Reads. | 70 | * to implement the WAR - Flush DMA data on PIO Reads. |
@@ -201,6 +232,7 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) | |||
201 | struct sn_irq_info *sn_irq_info; | 232 | struct sn_irq_info *sn_irq_info; |
202 | struct pci_dev *host_pci_dev; | 233 | struct pci_dev *host_pci_dev; |
203 | int status = 0; | 234 | int status = 0; |
235 | struct pcibus_bussoft *bs; | ||
204 | 236 | ||
205 | dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL); | 237 | dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL); |
206 | if (SN_PCIDEV_INFO(dev) <= 0) | 238 | if (SN_PCIDEV_INFO(dev) <= 0) |
@@ -241,6 +273,7 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) | |||
241 | } | 273 | } |
242 | 274 | ||
243 | /* set up host bus linkages */ | 275 | /* set up host bus linkages */ |
276 | bs = SN_PCIBUS_BUSSOFT(dev->bus); | ||
244 | host_pci_dev = | 277 | host_pci_dev = |
245 | pci_find_slot(SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32, | 278 | pci_find_slot(SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32, |
246 | SN_PCIDEV_INFO(dev)-> | 279 | SN_PCIDEV_INFO(dev)-> |
@@ -248,10 +281,16 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) | |||
248 | SN_PCIDEV_INFO(dev)->pdi_host_pcidev_info = | 281 | SN_PCIDEV_INFO(dev)->pdi_host_pcidev_info = |
249 | SN_PCIDEV_INFO(host_pci_dev); | 282 | SN_PCIDEV_INFO(host_pci_dev); |
250 | SN_PCIDEV_INFO(dev)->pdi_linux_pcidev = dev; | 283 | SN_PCIDEV_INFO(dev)->pdi_linux_pcidev = dev; |
251 | SN_PCIDEV_INFO(dev)->pdi_pcibus_info = SN_PCIBUS_BUSSOFT(dev->bus); | 284 | SN_PCIDEV_INFO(dev)->pdi_pcibus_info = bs; |
285 | |||
286 | if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) { | ||
287 | SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type]; | ||
288 | } else { | ||
289 | SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider; | ||
290 | } | ||
252 | 291 | ||
253 | /* Only set up IRQ stuff if this device has a host bus context */ | 292 | /* Only set up IRQ stuff if this device has a host bus context */ |
254 | if (SN_PCIDEV_BUSSOFT(dev) && sn_irq_info->irq_irq) { | 293 | if (bs && sn_irq_info->irq_irq) { |
255 | SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = sn_irq_info; | 294 | SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = sn_irq_info; |
256 | dev->irq = SN_PCIDEV_INFO(dev)->pdi_sn_irq_info->irq_irq; | 295 | dev->irq = SN_PCIDEV_INFO(dev)->pdi_sn_irq_info->irq_irq; |
257 | sn_irq_fixup(dev, sn_irq_info); | 296 | sn_irq_fixup(dev, sn_irq_info); |
@@ -271,6 +310,7 @@ static void sn_pci_controller_fixup(int segment, int busnum) | |||
271 | struct pcibus_bussoft *prom_bussoft_ptr; | 310 | struct pcibus_bussoft *prom_bussoft_ptr; |
272 | struct hubdev_info *hubdev_info; | 311 | struct hubdev_info *hubdev_info; |
273 | void *provider_soft; | 312 | void *provider_soft; |
313 | struct sn_pcibus_provider *provider; | ||
274 | 314 | ||
275 | status = | 315 | status = |
276 | sal_get_pcibus_info((u64) segment, (u64) busnum, | 316 | sal_get_pcibus_info((u64) segment, (u64) busnum, |
@@ -291,16 +331,22 @@ static void sn_pci_controller_fixup(int segment, int busnum) | |||
291 | /* | 331 | /* |
292 | * Per-provider fixup. Copies the contents from prom to local | 332 | * Per-provider fixup. Copies the contents from prom to local |
293 | * area and links SN_PCIBUS_BUSSOFT(). | 333 | * area and links SN_PCIBUS_BUSSOFT(). |
294 | * | ||
295 | * Note: Provider is responsible for ensuring that prom_bussoft_ptr | ||
296 | * represents an asic-type that it can handle. | ||
297 | */ | 334 | */ |
298 | 335 | ||
299 | if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB) { | 336 | if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) { |
300 | return; /* no further fixup necessary */ | 337 | return; /* unsupported asic type */ |
338 | } | ||
339 | |||
340 | provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type]; | ||
341 | if (provider == NULL) { | ||
342 | return; /* no provider registerd for this asic */ | ||
343 | } | ||
344 | |||
345 | provider_soft = NULL; | ||
346 | if (provider->bus_fixup) { | ||
347 | provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr); | ||
301 | } | 348 | } |
302 | 349 | ||
303 | provider_soft = pcibr_bus_fixup(prom_bussoft_ptr); | ||
304 | if (provider_soft == NULL) { | 350 | if (provider_soft == NULL) { |
305 | return; /* fixup failed or not applicable */ | 351 | return; /* fixup failed or not applicable */ |
306 | } | 352 | } |
@@ -339,6 +385,16 @@ static int __init sn_pci_init(void) | |||
339 | return 0; | 385 | return 0; |
340 | 386 | ||
341 | /* | 387 | /* |
388 | * prime sn_pci_provider[]. Individial provider init routines will | ||
389 | * override their respective default entries. | ||
390 | */ | ||
391 | |||
392 | for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++) | ||
393 | sn_pci_provider[i] = &sn_pci_default_provider; | ||
394 | |||
395 | pcibr_init_provider(); | ||
396 | |||
397 | /* | ||
342 | * This is needed to avoid bounce limit checks in the blk layer | 398 | * This is needed to avoid bounce limit checks in the blk layer |
343 | */ | 399 | */ |
344 | ia64_max_iommu_merge_mask = ~PAGE_MASK; | 400 | ia64_max_iommu_merge_mask = ~PAGE_MASK; |
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index f680824f819d..c2b92b94c563 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <asm/sn/sn_sal.h> | 14 | #include <asm/sn/sn_sal.h> |
15 | #include "pci/pcibus_provider_defs.h" | 15 | #include "pci/pcibus_provider_defs.h" |
16 | #include "pci/pcidev.h" | 16 | #include "pci/pcidev.h" |
17 | #include "pci/pcibr_provider.h" | ||
18 | 17 | ||
19 | #define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset) | 18 | #define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset) |
20 | #define SG_ENT_PHYS_ADDRESS(SG) virt_to_phys(SG_ENT_VIRT_ADDRESS(SG)) | 19 | #define SG_ENT_PHYS_ADDRESS(SG) virt_to_phys(SG_ENT_VIRT_ADDRESS(SG)) |
@@ -79,7 +78,8 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size, | |||
79 | { | 78 | { |
80 | void *cpuaddr; | 79 | void *cpuaddr; |
81 | unsigned long phys_addr; | 80 | unsigned long phys_addr; |
82 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev)); | 81 | struct pci_dev *pdev = to_pci_dev(dev); |
82 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); | ||
83 | 83 | ||
84 | BUG_ON(dev->bus != &pci_bus_type); | 84 | BUG_ON(dev->bus != &pci_bus_type); |
85 | 85 | ||
@@ -102,8 +102,7 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size, | |||
102 | * resources. | 102 | * resources. |
103 | */ | 103 | */ |
104 | 104 | ||
105 | *dma_handle = pcibr_dma_map(pcidev_info, phys_addr, size, | 105 | *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size); |
106 | SN_PCIDMA_CONSISTENT); | ||
107 | if (!*dma_handle) { | 106 | if (!*dma_handle) { |
108 | printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); | 107 | printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); |
109 | free_pages((unsigned long)cpuaddr, get_order(size)); | 108 | free_pages((unsigned long)cpuaddr, get_order(size)); |
@@ -127,11 +126,12 @@ EXPORT_SYMBOL(sn_dma_alloc_coherent); | |||
127 | void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, | 126 | void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, |
128 | dma_addr_t dma_handle) | 127 | dma_addr_t dma_handle) |
129 | { | 128 | { |
130 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev)); | 129 | struct pci_dev *pdev = to_pci_dev(dev); |
130 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); | ||
131 | 131 | ||
132 | BUG_ON(dev->bus != &pci_bus_type); | 132 | BUG_ON(dev->bus != &pci_bus_type); |
133 | 133 | ||
134 | pcibr_dma_unmap(pcidev_info, dma_handle, 0); | 134 | provider->dma_unmap(pdev, dma_handle, 0); |
135 | free_pages((unsigned long)cpu_addr, get_order(size)); | 135 | free_pages((unsigned long)cpu_addr, get_order(size)); |
136 | } | 136 | } |
137 | EXPORT_SYMBOL(sn_dma_free_coherent); | 137 | EXPORT_SYMBOL(sn_dma_free_coherent); |
@@ -159,12 +159,13 @@ dma_addr_t sn_dma_map_single(struct device *dev, void *cpu_addr, size_t size, | |||
159 | { | 159 | { |
160 | dma_addr_t dma_addr; | 160 | dma_addr_t dma_addr; |
161 | unsigned long phys_addr; | 161 | unsigned long phys_addr; |
162 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev)); | 162 | struct pci_dev *pdev = to_pci_dev(dev); |
163 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); | ||
163 | 164 | ||
164 | BUG_ON(dev->bus != &pci_bus_type); | 165 | BUG_ON(dev->bus != &pci_bus_type); |
165 | 166 | ||
166 | phys_addr = __pa(cpu_addr); | 167 | phys_addr = __pa(cpu_addr); |
167 | dma_addr = pcibr_dma_map(pcidev_info, phys_addr, size, 0); | 168 | dma_addr = provider->dma_map(pdev, phys_addr, size); |
168 | if (!dma_addr) { | 169 | if (!dma_addr) { |
169 | printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); | 170 | printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); |
170 | return 0; | 171 | return 0; |
@@ -187,10 +188,12 @@ EXPORT_SYMBOL(sn_dma_map_single); | |||
187 | void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | 188 | void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, |
188 | int direction) | 189 | int direction) |
189 | { | 190 | { |
190 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev)); | 191 | struct pci_dev *pdev = to_pci_dev(dev); |
192 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); | ||
191 | 193 | ||
192 | BUG_ON(dev->bus != &pci_bus_type); | 194 | BUG_ON(dev->bus != &pci_bus_type); |
193 | pcibr_dma_unmap(pcidev_info, dma_addr, direction); | 195 | |
196 | provider->dma_unmap(pdev, dma_addr, direction); | ||
194 | } | 197 | } |
195 | EXPORT_SYMBOL(sn_dma_unmap_single); | 198 | EXPORT_SYMBOL(sn_dma_unmap_single); |
196 | 199 | ||
@@ -207,12 +210,13 @@ void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sg, | |||
207 | int nhwentries, int direction) | 210 | int nhwentries, int direction) |
208 | { | 211 | { |
209 | int i; | 212 | int i; |
210 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev)); | 213 | struct pci_dev *pdev = to_pci_dev(dev); |
214 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); | ||
211 | 215 | ||
212 | BUG_ON(dev->bus != &pci_bus_type); | 216 | BUG_ON(dev->bus != &pci_bus_type); |
213 | 217 | ||
214 | for (i = 0; i < nhwentries; i++, sg++) { | 218 | for (i = 0; i < nhwentries; i++, sg++) { |
215 | pcibr_dma_unmap(pcidev_info, sg->dma_address, direction); | 219 | provider->dma_unmap(pdev, sg->dma_address, direction); |
216 | sg->dma_address = (dma_addr_t) NULL; | 220 | sg->dma_address = (dma_addr_t) NULL; |
217 | sg->dma_length = 0; | 221 | sg->dma_length = 0; |
218 | } | 222 | } |
@@ -233,7 +237,8 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | |||
233 | { | 237 | { |
234 | unsigned long phys_addr; | 238 | unsigned long phys_addr; |
235 | struct scatterlist *saved_sg = sg; | 239 | struct scatterlist *saved_sg = sg; |
236 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev)); | 240 | struct pci_dev *pdev = to_pci_dev(dev); |
241 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); | ||
237 | int i; | 242 | int i; |
238 | 243 | ||
239 | BUG_ON(dev->bus != &pci_bus_type); | 244 | BUG_ON(dev->bus != &pci_bus_type); |
@@ -243,8 +248,8 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | |||
243 | */ | 248 | */ |
244 | for (i = 0; i < nhwentries; i++, sg++) { | 249 | for (i = 0; i < nhwentries; i++, sg++) { |
245 | phys_addr = SG_ENT_PHYS_ADDRESS(sg); | 250 | phys_addr = SG_ENT_PHYS_ADDRESS(sg); |
246 | sg->dma_address = pcibr_dma_map(pcidev_info, phys_addr, | 251 | sg->dma_address = provider->dma_map(pdev, |
247 | sg->length, 0); | 252 | phys_addr, sg->length); |
248 | 253 | ||
249 | if (!sg->dma_address) { | 254 | if (!sg->dma_address) { |
250 | printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); | 255 | printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index b1d66ac065c8..3c305f46417f 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c | |||
@@ -40,7 +40,7 @@ extern int sn_ioif_inited; | |||
40 | * we do not have to allocate entries in the PMU. | 40 | * we do not have to allocate entries in the PMU. |
41 | */ | 41 | */ |
42 | 42 | ||
43 | static uint64_t | 43 | static dma_addr_t |
44 | pcibr_dmamap_ate32(struct pcidev_info *info, | 44 | pcibr_dmamap_ate32(struct pcidev_info *info, |
45 | uint64_t paddr, size_t req_size, uint64_t flags) | 45 | uint64_t paddr, size_t req_size, uint64_t flags) |
46 | { | 46 | { |
@@ -109,7 +109,7 @@ pcibr_dmamap_ate32(struct pcidev_info *info, | |||
109 | return pci_addr; | 109 | return pci_addr; |
110 | } | 110 | } |
111 | 111 | ||
112 | static uint64_t | 112 | static dma_addr_t |
113 | pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, | 113 | pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, |
114 | uint64_t dma_attributes) | 114 | uint64_t dma_attributes) |
115 | { | 115 | { |
@@ -141,7 +141,7 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, | |||
141 | 141 | ||
142 | } | 142 | } |
143 | 143 | ||
144 | static uint64_t | 144 | static dma_addr_t |
145 | pcibr_dmatrans_direct32(struct pcidev_info * info, | 145 | pcibr_dmatrans_direct32(struct pcidev_info * info, |
146 | uint64_t paddr, size_t req_size, uint64_t flags) | 146 | uint64_t paddr, size_t req_size, uint64_t flags) |
147 | { | 147 | { |
@@ -180,11 +180,11 @@ pcibr_dmatrans_direct32(struct pcidev_info * info, | |||
180 | * DMA mappings for Direct 64 and 32 do not have any DMA maps. | 180 | * DMA mappings for Direct 64 and 32 do not have any DMA maps. |
181 | */ | 181 | */ |
182 | void | 182 | void |
183 | pcibr_dma_unmap(struct pcidev_info *pcidev_info, dma_addr_t dma_handle, | 183 | pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle, int direction) |
184 | int direction) | ||
185 | { | 184 | { |
186 | struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> | 185 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev); |
187 | pdi_pcibus_info; | 186 | struct pcibus_info *pcibus_info = |
187 | (struct pcibus_info *)pcidev_info->pdi_pcibus_info; | ||
188 | 188 | ||
189 | if (IS_PCI32_MAPPED(dma_handle)) { | 189 | if (IS_PCI32_MAPPED(dma_handle)) { |
190 | int ate_index; | 190 | int ate_index; |
@@ -316,64 +316,63 @@ void sn_dma_flush(uint64_t addr) | |||
316 | } | 316 | } |
317 | 317 | ||
318 | /* | 318 | /* |
319 | * Wrapper DMA interface. Called from pci_dma.c routines. | 319 | * DMA interfaces. Called from pci_dma.c routines. |
320 | */ | 320 | */ |
321 | 321 | ||
322 | uint64_t | 322 | dma_addr_t |
323 | pcibr_dma_map(struct pcidev_info * pcidev_info, unsigned long phys_addr, | 323 | pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size) |
324 | size_t size, unsigned int flags) | ||
325 | { | 324 | { |
326 | dma_addr_t dma_handle; | 325 | dma_addr_t dma_handle; |
327 | struct pci_dev *pcidev = pcidev_info->pdi_linux_pcidev; | 326 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev); |
328 | |||
329 | if (flags & SN_PCIDMA_CONSISTENT) { | ||
330 | /* sn_pci_alloc_consistent interfaces */ | ||
331 | if (pcidev->dev.coherent_dma_mask == ~0UL) { | ||
332 | dma_handle = | ||
333 | pcibr_dmatrans_direct64(pcidev_info, phys_addr, | ||
334 | PCI64_ATTR_BAR); | ||
335 | } else { | ||
336 | dma_handle = | ||
337 | (dma_addr_t) pcibr_dmamap_ate32(pcidev_info, | ||
338 | phys_addr, size, | ||
339 | PCI32_ATE_BAR); | ||
340 | } | ||
341 | } else { | ||
342 | /* map_sg/map_single interfaces */ | ||
343 | 327 | ||
344 | /* SN cannot support DMA addresses smaller than 32 bits. */ | 328 | /* SN cannot support DMA addresses smaller than 32 bits. */ |
345 | if (pcidev->dma_mask < 0x7fffffff) { | 329 | if (hwdev->dma_mask < 0x7fffffff) { |
346 | return 0; | 330 | return 0; |
347 | } | 331 | } |
348 | 332 | ||
349 | if (pcidev->dma_mask == ~0UL) { | 333 | if (hwdev->dma_mask == ~0UL) { |
334 | /* | ||
335 | * Handle the most common case: 64 bit cards. This | ||
336 | * call should always succeed. | ||
337 | */ | ||
338 | |||
339 | dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr, | ||
340 | PCI64_ATTR_PREF); | ||
341 | } else { | ||
342 | /* Handle 32-63 bit cards via direct mapping */ | ||
343 | dma_handle = pcibr_dmatrans_direct32(pcidev_info, phys_addr, | ||
344 | size, 0); | ||
345 | if (!dma_handle) { | ||
350 | /* | 346 | /* |
351 | * Handle the most common case: 64 bit cards. This | 347 | * It is a 32 bit card and we cannot do direct mapping, |
352 | * call should always succeed. | 348 | * so we use an ATE. |
353 | */ | 349 | */ |
354 | 350 | ||
355 | dma_handle = | 351 | dma_handle = pcibr_dmamap_ate32(pcidev_info, phys_addr, |
356 | pcibr_dmatrans_direct64(pcidev_info, phys_addr, | 352 | size, PCI32_ATE_PREF); |
357 | PCI64_ATTR_PREF); | ||
358 | } else { | ||
359 | /* Handle 32-63 bit cards via direct mapping */ | ||
360 | dma_handle = | ||
361 | pcibr_dmatrans_direct32(pcidev_info, phys_addr, | ||
362 | size, 0); | ||
363 | if (!dma_handle) { | ||
364 | /* | ||
365 | * It is a 32 bit card and we cannot do direct mapping, | ||
366 | * so we use an ATE. | ||
367 | */ | ||
368 | |||
369 | dma_handle = | ||
370 | pcibr_dmamap_ate32(pcidev_info, phys_addr, | ||
371 | size, PCI32_ATE_PREF); | ||
372 | } | ||
373 | } | 353 | } |
374 | } | 354 | } |
375 | 355 | ||
376 | return dma_handle; | 356 | return dma_handle; |
377 | } | 357 | } |
378 | 358 | ||
359 | dma_addr_t | ||
360 | pcibr_dma_map_consistent(struct pci_dev * hwdev, unsigned long phys_addr, | ||
361 | size_t size) | ||
362 | { | ||
363 | dma_addr_t dma_handle; | ||
364 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev); | ||
365 | |||
366 | if (hwdev->dev.coherent_dma_mask == ~0UL) { | ||
367 | dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr, | ||
368 | PCI64_ATTR_BAR); | ||
369 | } else { | ||
370 | dma_handle = (dma_addr_t) pcibr_dmamap_ate32(pcidev_info, | ||
371 | phys_addr, size, | ||
372 | PCI32_ATE_BAR); | ||
373 | } | ||
374 | |||
375 | return dma_handle; | ||
376 | } | ||
377 | |||
379 | EXPORT_SYMBOL(sn_dma_flush); | 378 | EXPORT_SYMBOL(sn_dma_flush); |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 92bd278cf7ff..539ab1fdab21 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c | |||
@@ -168,3 +168,23 @@ void pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info) | |||
168 | pcibr_force_interrupt(sn_irq_info); | 168 | pcibr_force_interrupt(sn_irq_info); |
169 | } | 169 | } |
170 | } | 170 | } |
171 | |||
172 | /* | ||
173 | * Provider entries for PIC/CP | ||
174 | */ | ||
175 | |||
176 | struct sn_pcibus_provider pcibr_provider = { | ||
177 | .dma_map = pcibr_dma_map, | ||
178 | .dma_map_consistent = pcibr_dma_map_consistent, | ||
179 | .dma_unmap = pcibr_dma_unmap, | ||
180 | .bus_fixup = pcibr_bus_fixup, | ||
181 | }; | ||
182 | |||
183 | int | ||
184 | pcibr_init_provider(void) | ||
185 | { | ||
186 | sn_pci_provider[PCIIO_ASIC_TYPE_PIC] = &pcibr_provider; | ||
187 | sn_pci_provider[PCIIO_ASIC_TYPE_TIOCP] = &pcibr_provider; | ||
188 | |||
189 | return 0; | ||
190 | } | ||