diff options
author | Mark Maule <maule@sgi.com> | 2005-04-25 11:26:03 -0700 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2005-04-25 11:26:03 -0700 |
commit | e955d82543fea76b02aa243b182e782f71bda82c (patch) | |
tree | 58dc9df5161f47bca69c8dc9c819495f15694352 /arch/ia64/sn/kernel/io_init.c | |
parent | 25ee7e3832951cf5896b194f6cd929a44863f419 (diff) | |
download | op-kernel-dev-e955d82543fea76b02aa243b182e782f71bda82c.zip op-kernel-dev-e955d82543fea76b02aa243b182e782f71bda82c.tar.gz |
[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/io_init.c')
-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 0018808..3e5e4a9 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -34,6 +34,37 @@ struct brick { int sn_ioif_inited = 0; /* SN I/O infrastructure initialized? */ +struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ + +/* + * Hooks and struct for unsupported pci providers + */ + +static dma_addr_t +sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size) +{ + return 0; +} + +static void +sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction) +{ + return; +} + +static void * +sn_default_pci_bus_fixup(struct pcibus_bussoft *soft) +{ + return NULL; +} + +static struct sn_pcibus_provider sn_pci_default_provider = { + .dma_map = sn_default_pci_map, + .dma_map_consistent = sn_default_pci_map, + .dma_unmap = sn_default_pci_unmap, + .bus_fixup = sn_default_pci_bus_fixup, +}; + /* * Retrieve the DMA Flush List given nasid. This list is needed * to implement the WAR - Flush DMA data on PIO Reads. @@ -201,6 +232,7 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) struct sn_irq_info *sn_irq_info; struct pci_dev *host_pci_dev; int status = 0; + struct pcibus_bussoft *bs; dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL); if (SN_PCIDEV_INFO(dev) <= 0) @@ -241,6 +273,7 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) } /* set up host bus linkages */ + bs = SN_PCIBUS_BUSSOFT(dev->bus); host_pci_dev = pci_find_slot(SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32, SN_PCIDEV_INFO(dev)-> @@ -248,10 +281,16 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) SN_PCIDEV_INFO(dev)->pdi_host_pcidev_info = SN_PCIDEV_INFO(host_pci_dev); SN_PCIDEV_INFO(dev)->pdi_linux_pcidev = dev; - SN_PCIDEV_INFO(dev)->pdi_pcibus_info = SN_PCIBUS_BUSSOFT(dev->bus); + SN_PCIDEV_INFO(dev)->pdi_pcibus_info = bs; + + if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) { + SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type]; + } else { + SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider; + } /* Only set up IRQ stuff if this device has a host bus context */ - if (SN_PCIDEV_BUSSOFT(dev) && sn_irq_info->irq_irq) { + if (bs && sn_irq_info->irq_irq) { SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = sn_irq_info; dev->irq = SN_PCIDEV_INFO(dev)->pdi_sn_irq_info->irq_irq; sn_irq_fixup(dev, sn_irq_info); @@ -271,6 +310,7 @@ static void sn_pci_controller_fixup(int segment, int busnum) struct pcibus_bussoft *prom_bussoft_ptr; struct hubdev_info *hubdev_info; void *provider_soft; + struct sn_pcibus_provider *provider; status = sal_get_pcibus_info((u64) segment, (u64) busnum, @@ -291,16 +331,22 @@ static void sn_pci_controller_fixup(int segment, int busnum) /* * Per-provider fixup. Copies the contents from prom to local * area and links SN_PCIBUS_BUSSOFT(). - * - * Note: Provider is responsible for ensuring that prom_bussoft_ptr - * represents an asic-type that it can handle. */ - if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB) { - return; /* no further fixup necessary */ + if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) { + return; /* unsupported asic type */ + } + + provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type]; + if (provider == NULL) { + return; /* no provider registerd for this asic */ + } + + provider_soft = NULL; + if (provider->bus_fixup) { + provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr); } - provider_soft = pcibr_bus_fixup(prom_bussoft_ptr); if (provider_soft == NULL) { return; /* fixup failed or not applicable */ } @@ -339,6 +385,16 @@ static int __init sn_pci_init(void) return 0; /* + * prime sn_pci_provider[]. Individial provider init routines will + * override their respective default entries. + */ + + for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++) + sn_pci_provider[i] = &sn_pci_default_provider; + + pcibr_init_provider(); + + /* * This is needed to avoid bounce limit checks in the blk layer */ ia64_max_iommu_merge_mask = ~PAGE_MASK; |