diff options
Diffstat (limited to 'arch/ia64/sn')
-rw-r--r-- | arch/ia64/sn/kernel/io_init.c | 153 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/ptc_deadlock.S | 8 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/sn2_smp.c | 2 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pcibr/pcibr_reg.c | 48 | ||||
-rw-r--r-- | arch/ia64/sn/pci/tioca_provider.c | 12 |
5 files changed, 168 insertions, 55 deletions
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 05e4ea8..318087e 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved. */ #include <linux/bootmem.h> @@ -147,6 +147,24 @@ sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, } /* + * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified + * device. + */ +inline struct pcidev_info * +sn_pcidev_info_get(struct pci_dev *dev) +{ + struct pcidev_info *pcidev; + + list_for_each_entry(pcidev, + &(SN_PCI_CONTROLLER(dev)->pcidev_info), pdi_list) { + if (pcidev->pdi_linux_pcidev == dev) { + return pcidev; + } + } + return NULL; +} + +/* * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for * each node in the system. */ @@ -229,6 +247,50 @@ static void sn_fixup_ionodes(void) } +/* + * sn_pci_window_fixup() - Create a pci_window for each device resource. + * Until ACPI support is added, we need this code + * to setup pci_windows for use by + * pcibios_bus_to_resource(), + * pcibios_resource_to_bus(), etc. + */ +static void +sn_pci_window_fixup(struct pci_dev *dev, unsigned int count, + int64_t * pci_addrs) +{ + struct pci_controller *controller = PCI_CONTROLLER(dev->bus); + unsigned int i; + unsigned int idx; + unsigned int new_count; + struct pci_window *new_window; + + if (count == 0) + return; + idx = controller->windows; + new_count = controller->windows + count; + new_window = kcalloc(new_count, sizeof(struct pci_window), GFP_KERNEL); + if (new_window == NULL) + BUG(); + if (controller->window) { + memcpy(new_window, controller->window, + sizeof(struct pci_window) * controller->windows); + kfree(controller->window); + } + + /* Setup a pci_window for each device resource. */ + for (i = 0; i <= PCI_ROM_RESOURCE; i++) { + if (pci_addrs[i] == -1) + continue; + + new_window[idx].offset = dev->resource[i].start - pci_addrs[i]; + new_window[idx].resource = dev->resource[i]; + idx++; + } + + controller->windows = new_count; + controller->window = new_window; +} + void sn_pci_unfixup_slot(struct pci_dev *dev) { struct pci_dev *host_pci_dev = SN_PCIDEV_INFO(dev)->host_pci_dev; @@ -246,21 +308,23 @@ void sn_pci_unfixup_slot(struct pci_dev *dev) */ void sn_pci_fixup_slot(struct pci_dev *dev) { + unsigned int count = 0; int idx; int segment = pci_domain_nr(dev->bus); int status = 0; struct pcibus_bussoft *bs; struct pci_bus *host_pci_bus; struct pci_dev *host_pci_dev; + struct pcidev_info *pcidev_info; + int64_t pci_addrs[PCI_ROM_RESOURCE + 1]; struct sn_irq_info *sn_irq_info; unsigned long size; unsigned int bus_no, devfn; pci_dev_get(dev); /* for the sysdata pointer */ - dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL); - if (SN_PCIDEV_INFO(dev) <= 0) + pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL); + if (pcidev_info <= 0) BUG(); /* Cannot afford to run out of memory */ - memset(SN_PCIDEV_INFO(dev), 0, sizeof(struct pcidev_info)); sn_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_KERNEL); if (sn_irq_info <= 0) @@ -270,22 +334,34 @@ void sn_pci_fixup_slot(struct pci_dev *dev) /* Call to retrieve pci device information needed by kernel. */ status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, dev->devfn, - (u64) __pa(SN_PCIDEV_INFO(dev)), + (u64) __pa(pcidev_info), (u64) __pa(sn_irq_info)); if (status) BUG(); /* Cannot get platform pci device information */ + /* Add pcidev_info to list in sn_pci_controller struct */ + list_add_tail(&pcidev_info->pdi_list, + &(SN_PCI_CONTROLLER(dev->bus)->pcidev_info)); + /* Copy over PIO Mapped Addresses */ for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) { unsigned long start, end, addr; - if (!SN_PCIDEV_INFO(dev)->pdi_pio_mapped_addr[idx]) + if (!pcidev_info->pdi_pio_mapped_addr[idx]) { + pci_addrs[idx] = -1; continue; + } start = dev->resource[idx].start; end = dev->resource[idx].end; size = end - start; - addr = SN_PCIDEV_INFO(dev)->pdi_pio_mapped_addr[idx]; + if (size == 0) { + pci_addrs[idx] = -1; + continue; + } + pci_addrs[idx] = start; + count++; + addr = pcidev_info->pdi_pio_mapped_addr[idx]; addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET; dev->resource[idx].start = addr; dev->resource[idx].end = addr + size; @@ -294,23 +370,27 @@ void sn_pci_fixup_slot(struct pci_dev *dev) else dev->resource[idx].parent = &iomem_resource; } + /* Create a pci_window in the pci_controller struct for + * each device resource. + */ + if (count > 0) + sn_pci_window_fixup(dev, count, pci_addrs); /* * Using the PROMs values for the PCI host bus, get the Linux * PCI host_pci_dev struct and set up host bus linkages */ - bus_no = (SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32) & 0xff; - devfn = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle & 0xffffffff; + bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff; + devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff; host_pci_bus = pci_find_bus(segment, bus_no); host_pci_dev = pci_get_slot(host_pci_bus, devfn); - SN_PCIDEV_INFO(dev)->host_pci_dev = host_pci_dev; - SN_PCIDEV_INFO(dev)->pdi_host_pcidev_info = - SN_PCIDEV_INFO(host_pci_dev); - SN_PCIDEV_INFO(dev)->pdi_linux_pcidev = dev; + pcidev_info->host_pci_dev = host_pci_dev; + pcidev_info->pdi_linux_pcidev = dev; + pcidev_info->pdi_host_pcidev_info = SN_PCIDEV_INFO(host_pci_dev); bs = SN_PCIBUS_BUSSOFT(dev->bus); - SN_PCIDEV_INFO(dev)->pdi_pcibus_info = bs; + pcidev_info->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]; @@ -320,11 +400,11 @@ void sn_pci_fixup_slot(struct pci_dev *dev) /* Only set up IRQ stuff if this device has a host bus context */ 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; + pcidev_info->pdi_sn_irq_info = sn_irq_info; + dev->irq = pcidev_info->pdi_sn_irq_info->irq_irq; sn_irq_fixup(dev, sn_irq_info); } else { - SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = NULL; + pcidev_info->pdi_sn_irq_info = NULL; kfree(sn_irq_info); } } @@ -338,6 +418,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) int status = 0; int nasid, cnode; struct pci_controller *controller; + struct sn_pci_controller *sn_controller; struct pcibus_bussoft *prom_bussoft_ptr; struct hubdev_info *hubdev_info; void *provider_soft = NULL; @@ -349,10 +430,15 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) return; /*bus # does not exist */ prom_bussoft_ptr = __va(prom_bussoft_ptr); - controller = kzalloc(sizeof(struct pci_controller), GFP_KERNEL); + /* Allocate a sn_pci_controller, which has a pci_controller struct + * as the first member. + */ + sn_controller = kzalloc(sizeof(struct sn_pci_controller), GFP_KERNEL); + if (!sn_controller) + BUG(); + INIT_LIST_HEAD(&sn_controller->pcidev_info); + controller = &sn_controller->pci_controller; controller->segment = segment; - if (!controller) - BUG(); if (bus == NULL) { bus = pci_scan_bus(busnum, &pci_root_ops, controller); @@ -390,6 +476,29 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) } /* + * Setup pci_windows for legacy IO and MEM space. + * (Temporary until ACPI support is in place.) + */ + controller->window = kcalloc(2, sizeof(struct pci_window), GFP_KERNEL); + if (controller->window == NULL) + BUG(); + controller->window[0].offset = prom_bussoft_ptr->bs_legacy_io; + controller->window[0].resource.name = "legacy_io"; + controller->window[0].resource.flags = IORESOURCE_IO; + controller->window[0].resource.start = prom_bussoft_ptr->bs_legacy_io; + controller->window[0].resource.end = + controller->window[0].resource.start + 0xffff; + controller->window[0].resource.parent = &ioport_resource; + controller->window[1].offset = prom_bussoft_ptr->bs_legacy_mem; + controller->window[1].resource.name = "legacy_mem"; + controller->window[1].resource.flags = IORESOURCE_MEM; + controller->window[1].resource.start = prom_bussoft_ptr->bs_legacy_mem; + controller->window[1].resource.end = + controller->window[1].resource.start + (1024 * 1024) - 1; + controller->window[1].resource.parent = &iomem_resource; + controller->windows = 2; + + /* * Generic bus fixup goes here. Don't reference prom_bussoft_ptr * after this point. */ @@ -421,7 +530,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) error_return: - kfree(controller); + kfree(sn_controller); return; } @@ -434,7 +543,7 @@ void sn_bus_store_sysdata(struct pci_dev *dev) dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__); return; } - element->sysdata = dev->sysdata; + element->sysdata = SN_PCIDEV_INFO(dev); list_add(&element->entry, &sn_sysdata_list); } diff --git a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S index 3fa9506..bebbcc4 100644 --- a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S +++ b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S @@ -39,9 +39,13 @@ sn2_ptc_deadlock_recovery_core: mov r8=r0 1: + cmp.ne p8,p9=r0,ptc1 // Test for shub type (ptc1 non-null on shub1) + // p8 = 1 if shub1, p9 = 1 if shub2 + add scr2=ALIAS_OFFSET,piowc // Address of WRITE_STATUS alias register - ;; - ld8.acq scr1=[scr2];; + mov scr1=7;; // Clear DEADLOCK, WRITE_ERROR, MULTI_WRITE_ERROR +(p8) st8.rel [scr2]=scr1;; +(p9) ld8.acq scr1=[scr2];; 5: ld8.acq scr1=[piowc];; // Wait for PIOs to complete. hint @pause diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 5d54f5f..471bbaa 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -202,7 +202,7 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long nbits) { int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0; - int mymm = (mm == current->active_mm); + int mymm = (mm == current->active_mm && current->mm); volatile unsigned long *ptc0, *ptc1; unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value; short nasids[MAX_NUMNODES], nix; diff --git a/arch/ia64/sn/pci/pcibr/pcibr_reg.c b/arch/ia64/sn/pci/pcibr/pcibr_reg.c index 5d53409..79fdb91 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_reg.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_reg.c @@ -25,7 +25,7 @@ union br_ptr { */ void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) { - union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; + union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -38,14 +38,14 @@ void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) default: panic ("pcireg_control_bit_clr: unknown bridgetype bridge 0x%p", - (void *)ptr); + ptr); } } } void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) { - union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; + union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -58,7 +58,7 @@ void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) default: panic ("pcireg_control_bit_set: unknown bridgetype bridge 0x%p", - (void *)ptr); + ptr); } } } @@ -68,7 +68,7 @@ void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) */ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info) { - union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; + union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; uint64_t ret = 0; if (pcibus_info) { @@ -82,7 +82,7 @@ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info) default: panic ("pcireg_tflush_get: unknown bridgetype bridge 0x%p", - (void *)ptr); + ptr); } } @@ -98,7 +98,7 @@ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info) */ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info) { - union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; + union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; uint64_t ret = 0; if (pcibus_info) { @@ -112,7 +112,7 @@ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info) default: panic ("pcireg_intr_status_get: unknown bridgetype bridge 0x%p", - (void *)ptr); + ptr); } } return ret; @@ -123,7 +123,7 @@ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info) */ void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) { - union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; + union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -136,14 +136,14 @@ void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) default: panic ("pcireg_intr_enable_bit_clr: unknown bridgetype bridge 0x%p", - (void *)ptr); + ptr); } } } void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) { - union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; + union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -156,7 +156,7 @@ void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) default: panic ("pcireg_intr_enable_bit_set: unknown bridgetype bridge 0x%p", - (void *)ptr); + ptr); } } } @@ -167,7 +167,7 @@ void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n, uint64_t addr) { - union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; + union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -186,7 +186,7 @@ void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n, default: panic ("pcireg_intr_addr_addr_get: unknown bridgetype bridge 0x%p", - (void *)ptr); + ptr); } } } @@ -196,7 +196,7 @@ void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n, */ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n) { - union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; + union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -209,7 +209,7 @@ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n) default: panic ("pcireg_force_intr_set: unknown bridgetype bridge 0x%p", - (void *)ptr); + ptr); } } } @@ -219,7 +219,7 @@ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n) */ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) { - union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; + union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; uint64_t ret = 0; if (pcibus_info) { @@ -233,7 +233,7 @@ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) __sn_readq_relaxed(&ptr->pic.p_wr_req_buf[device]); break; default: - panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", (void *)ptr); + panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", ptr); } } @@ -244,7 +244,7 @@ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index, uint64_t val) { - union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; + union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -257,15 +257,15 @@ void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index, default: panic ("pcireg_int_ate_set: unknown bridgetype bridge 0x%p", - (void *)ptr); + ptr); } } } -uint64_t *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) +uint64_t __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) { - union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; - uint64_t *ret = (uint64_t *) 0; + union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; + uint64_t __iomem *ret = NULL; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -278,7 +278,7 @@ uint64_t *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) default: panic ("pcireg_int_ate_addr: unknown bridgetype bridge 0x%p", - (void *)ptr); + ptr); } } return ret; diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 46b646a..27aa184 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -38,10 +38,10 @@ tioca_gart_init(struct tioca_kernel *tioca_kern) uint64_t offset; struct page *tmp; struct tioca_common *tioca_common; - struct tioca *ca_base; + struct tioca __iomem *ca_base; tioca_common = tioca_kern->ca_common; - ca_base = (struct tioca *)tioca_common->ca_common.bs_base; + ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base; if (list_empty(tioca_kern->ca_devices)) return 0; @@ -215,7 +215,7 @@ tioca_fastwrite_enable(struct tioca_kernel *tioca_kern) { int cap_ptr; uint32_t reg; - struct tioca *tioca_base; + struct tioca __iomem *tioca_base; struct pci_dev *pdev; struct tioca_common *common; @@ -257,7 +257,7 @@ tioca_fastwrite_enable(struct tioca_kernel *tioca_kern) * Set ca's fw to match */ - tioca_base = (struct tioca *)common->ca_common.bs_base; + tioca_base = (struct tioca __iomem*)common->ca_common.bs_base; __sn_setq_relaxed(&tioca_base->ca_control1, CA_AGP_FW_ENABLE); } @@ -322,7 +322,7 @@ static uint64_t tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr) { struct tioca_common *tioca_common; - struct tioca *ca_base; + struct tioca __iomem *ca_base; uint64_t ct_addr; dma_addr_t bus_addr; uint32_t node_upper; @@ -330,7 +330,7 @@ tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr) struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev); tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info; - ca_base = (struct tioca *)tioca_common->ca_common.bs_base; + ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base; ct_addr = PHYS_TO_TIODMA(paddr); if (!ct_addr) |