diff options
Diffstat (limited to 'arch/ia64/sn/kernel/io_init.c')
-rw-r--r-- | arch/ia64/sn/kernel/io_init.c | 78 |
1 files changed, 68 insertions, 10 deletions
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 001880812b7c..18160a06a8c9 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c | |||
@@ -11,14 +11,15 @@ | |||
11 | #include <asm/sn/types.h> | 11 | #include <asm/sn/types.h> |
12 | #include <asm/sn/sn_sal.h> | 12 | #include <asm/sn/sn_sal.h> |
13 | #include <asm/sn/addrs.h> | 13 | #include <asm/sn/addrs.h> |
14 | #include "pci/pcibus_provider_defs.h" | 14 | #include <asm/sn/pcibus_provider_defs.h> |
15 | #include "pci/pcidev.h" | 15 | #include <asm/sn/pcidev.h> |
16 | #include "pci/pcibr_provider.h" | 16 | #include "pci/pcibr_provider.h" |
17 | #include "xtalk/xwidgetdev.h" | 17 | #include "xtalk/xwidgetdev.h" |
18 | #include <asm/sn/geo.h> | 18 | #include <asm/sn/geo.h> |
19 | #include "xtalk/hubdev.h" | 19 | #include "xtalk/hubdev.h" |
20 | #include <asm/sn/io.h> | 20 | #include <asm/sn/io.h> |
21 | #include <asm/sn/simulator.h> | 21 | #include <asm/sn/simulator.h> |
22 | #include <asm/sn/tioca_provider.h> | ||
22 | 23 | ||
23 | char master_baseio_wid; | 24 | char master_baseio_wid; |
24 | nasid_t master_nasid = INVALID_NASID; /* Partition Master */ | 25 | nasid_t master_nasid = INVALID_NASID; /* Partition Master */ |
@@ -34,6 +35,37 @@ struct brick { | |||
34 | 35 | ||
35 | int sn_ioif_inited = 0; /* SN I/O infrastructure initialized? */ | 36 | int sn_ioif_inited = 0; /* SN I/O infrastructure initialized? */ |
36 | 37 | ||
38 | struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ | ||
39 | |||
40 | /* | ||
41 | * Hooks and struct for unsupported pci providers | ||
42 | */ | ||
43 | |||
44 | static dma_addr_t | ||
45 | sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size) | ||
46 | { | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static void | ||
51 | sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction) | ||
52 | { | ||
53 | return; | ||
54 | } | ||
55 | |||
56 | static void * | ||
57 | sn_default_pci_bus_fixup(struct pcibus_bussoft *soft) | ||
58 | { | ||
59 | return NULL; | ||
60 | } | ||
61 | |||
62 | static struct sn_pcibus_provider sn_pci_default_provider = { | ||
63 | .dma_map = sn_default_pci_map, | ||
64 | .dma_map_consistent = sn_default_pci_map, | ||
65 | .dma_unmap = sn_default_pci_unmap, | ||
66 | .bus_fixup = sn_default_pci_bus_fixup, | ||
67 | }; | ||
68 | |||
37 | /* | 69 | /* |
38 | * Retrieve the DMA Flush List given nasid. This list is needed | 70 | * Retrieve the DMA Flush List given nasid. This list is needed |
39 | * to implement the WAR - Flush DMA data on PIO Reads. | 71 | * to implement the WAR - Flush DMA data on PIO Reads. |
@@ -201,6 +233,7 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) | |||
201 | struct sn_irq_info *sn_irq_info; | 233 | struct sn_irq_info *sn_irq_info; |
202 | struct pci_dev *host_pci_dev; | 234 | struct pci_dev *host_pci_dev; |
203 | int status = 0; | 235 | int status = 0; |
236 | struct pcibus_bussoft *bs; | ||
204 | 237 | ||
205 | dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL); | 238 | dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL); |
206 | if (SN_PCIDEV_INFO(dev) <= 0) | 239 | if (SN_PCIDEV_INFO(dev) <= 0) |
@@ -241,6 +274,7 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) | |||
241 | } | 274 | } |
242 | 275 | ||
243 | /* set up host bus linkages */ | 276 | /* set up host bus linkages */ |
277 | bs = SN_PCIBUS_BUSSOFT(dev->bus); | ||
244 | host_pci_dev = | 278 | host_pci_dev = |
245 | pci_find_slot(SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32, | 279 | pci_find_slot(SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32, |
246 | SN_PCIDEV_INFO(dev)-> | 280 | SN_PCIDEV_INFO(dev)-> |
@@ -248,10 +282,16 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) | |||
248 | SN_PCIDEV_INFO(dev)->pdi_host_pcidev_info = | 282 | SN_PCIDEV_INFO(dev)->pdi_host_pcidev_info = |
249 | SN_PCIDEV_INFO(host_pci_dev); | 283 | SN_PCIDEV_INFO(host_pci_dev); |
250 | SN_PCIDEV_INFO(dev)->pdi_linux_pcidev = dev; | 284 | SN_PCIDEV_INFO(dev)->pdi_linux_pcidev = dev; |
251 | SN_PCIDEV_INFO(dev)->pdi_pcibus_info = SN_PCIBUS_BUSSOFT(dev->bus); | 285 | SN_PCIDEV_INFO(dev)->pdi_pcibus_info = bs; |
286 | |||
287 | if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) { | ||
288 | SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type]; | ||
289 | } else { | ||
290 | SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider; | ||
291 | } | ||
252 | 292 | ||
253 | /* Only set up IRQ stuff if this device has a host bus context */ | 293 | /* Only set up IRQ stuff if this device has a host bus context */ |
254 | if (SN_PCIDEV_BUSSOFT(dev) && sn_irq_info->irq_irq) { | 294 | if (bs && sn_irq_info->irq_irq) { |
255 | SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = sn_irq_info; | 295 | SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = sn_irq_info; |
256 | dev->irq = SN_PCIDEV_INFO(dev)->pdi_sn_irq_info->irq_irq; | 296 | dev->irq = SN_PCIDEV_INFO(dev)->pdi_sn_irq_info->irq_irq; |
257 | sn_irq_fixup(dev, sn_irq_info); | 297 | sn_irq_fixup(dev, sn_irq_info); |
@@ -271,6 +311,7 @@ static void sn_pci_controller_fixup(int segment, int busnum) | |||
271 | struct pcibus_bussoft *prom_bussoft_ptr; | 311 | struct pcibus_bussoft *prom_bussoft_ptr; |
272 | struct hubdev_info *hubdev_info; | 312 | struct hubdev_info *hubdev_info; |
273 | void *provider_soft; | 313 | void *provider_soft; |
314 | struct sn_pcibus_provider *provider; | ||
274 | 315 | ||
275 | status = | 316 | status = |
276 | sal_get_pcibus_info((u64) segment, (u64) busnum, | 317 | sal_get_pcibus_info((u64) segment, (u64) busnum, |
@@ -291,16 +332,22 @@ static void sn_pci_controller_fixup(int segment, int busnum) | |||
291 | /* | 332 | /* |
292 | * Per-provider fixup. Copies the contents from prom to local | 333 | * Per-provider fixup. Copies the contents from prom to local |
293 | * area and links SN_PCIBUS_BUSSOFT(). | 334 | * 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 | */ | 335 | */ |
298 | 336 | ||
299 | if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB) { | 337 | if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) { |
300 | return; /* no further fixup necessary */ | 338 | return; /* unsupported asic type */ |
339 | } | ||
340 | |||
341 | provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type]; | ||
342 | if (provider == NULL) { | ||
343 | return; /* no provider registerd for this asic */ | ||
344 | } | ||
345 | |||
346 | provider_soft = NULL; | ||
347 | if (provider->bus_fixup) { | ||
348 | provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr); | ||
301 | } | 349 | } |
302 | 350 | ||
303 | provider_soft = pcibr_bus_fixup(prom_bussoft_ptr); | ||
304 | if (provider_soft == NULL) { | 351 | if (provider_soft == NULL) { |
305 | return; /* fixup failed or not applicable */ | 352 | return; /* fixup failed or not applicable */ |
306 | } | 353 | } |
@@ -339,6 +386,17 @@ static int __init sn_pci_init(void) | |||
339 | return 0; | 386 | return 0; |
340 | 387 | ||
341 | /* | 388 | /* |
389 | * prime sn_pci_provider[]. Individial provider init routines will | ||
390 | * override their respective default entries. | ||
391 | */ | ||
392 | |||
393 | for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++) | ||
394 | sn_pci_provider[i] = &sn_pci_default_provider; | ||
395 | |||
396 | pcibr_init_provider(); | ||
397 | tioca_init_provider(); | ||
398 | |||
399 | /* | ||
342 | * This is needed to avoid bounce limit checks in the blk layer | 400 | * This is needed to avoid bounce limit checks in the blk layer |
343 | */ | 401 | */ |
344 | ia64_max_iommu_merge_mask = ~PAGE_MASK; | 402 | ia64_max_iommu_merge_mask = ~PAGE_MASK; |