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 /arch/ia64/sn/kernel | |
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>
Diffstat (limited to 'arch/ia64/sn/kernel')
-rw-r--r-- | arch/ia64/sn/kernel/io_init.c | 72 |
1 files changed, 64 insertions, 8 deletions
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; |