aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn/pci
diff options
context:
space:
mode:
authorMark Maule <maule@sgi.com>2005-04-25 14:26:03 -0400
committerTony Luck <tony.luck@intel.com>2005-04-25 14:26:03 -0400
commite955d82543fea76b02aa243b182e782f71bda82c (patch)
tree58dc9df5161f47bca69c8dc9c819495f15694352 /arch/ia64/sn/pci
parent25ee7e3832951cf5896b194f6cd929a44863f419 (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>
Diffstat (limited to 'arch/ia64/sn/pci')
-rw-r--r--arch/ia64/sn/pci/pci_dma.c35
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_dma.c103
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c20
3 files changed, 91 insertions, 67 deletions
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);
127void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, 126void 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}
137EXPORT_SYMBOL(sn_dma_free_coherent); 137EXPORT_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);
187void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, 188void 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}
195EXPORT_SYMBOL(sn_dma_unmap_single); 198EXPORT_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
43static uint64_t 43static dma_addr_t
44pcibr_dmamap_ate32(struct pcidev_info *info, 44pcibr_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
112static uint64_t 112static dma_addr_t
113pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, 113pcibr_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
144static uint64_t 144static dma_addr_t
145pcibr_dmatrans_direct32(struct pcidev_info * info, 145pcibr_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 */
182void 182void
183pcibr_dma_unmap(struct pcidev_info *pcidev_info, dma_addr_t dma_handle, 183pcibr_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
322uint64_t 322dma_addr_t
323pcibr_dma_map(struct pcidev_info * pcidev_info, unsigned long phys_addr, 323pcibr_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
359dma_addr_t
360pcibr_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
379EXPORT_SYMBOL(sn_dma_flush); 378EXPORT_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
176struct 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
183int
184pcibr_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}