diff options
-rw-r--r-- | arch/sparc64/kernel/entry.S | 5 | ||||
-rw-r--r-- | arch/sparc64/kernel/irq.c | 131 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_common.c | 12 | ||||
-rw-r--r-- | include/asm-sparc64/dma-mapping.h | 42 | ||||
-rw-r--r-- | include/asm-sparc64/hypervisor.h | 8 | ||||
-rw-r--r-- | include/asm-sparc64/irq.h | 1 | ||||
-rw-r--r-- | include/asm-sparc64/parport.h | 5 |
7 files changed, 157 insertions, 47 deletions
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 7d1a11822a1..8059531bf0a 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -2357,8 +2357,9 @@ sun4v_ldc_unmap: nop .size sun4v_ldc_unmap, .-sun4v_ldc_unmap - /* %o0: cookie - * %o1: mte_cookie + /* %o0: channel + * %o1: cookie + * %o2: mte_cookie * * returns %o0: status */ diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index a36f8dd0c02..e60d283f60b 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -1,7 +1,6 @@ -/* $Id: irq.c,v 1.114 2002/01/11 08:45:38 davem Exp $ - * irq.c: UltraSparc IRQ handling/init/registry. +/* irq.c: UltraSparc IRQ handling/init/registry. * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net) * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) */ @@ -43,6 +42,7 @@ #include <asm/cpudata.h> #include <asm/auxio.h> #include <asm/head.h> +#include <asm/hypervisor.h> /* UPA nodes send interrupt packet to UltraSparc with first data reg * value low 5 (7 on Starfire) bits holding the IRQ identifier being @@ -380,6 +380,76 @@ static void sun4v_irq_end(unsigned int virt_irq) } } +static void sun4v_virq_enable(unsigned int virt_irq) +{ + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; + + if (likely(bucket)) { + unsigned long cpuid, dev_handle, dev_ino; + int err; + + cpuid = irq_choose_cpu(virt_irq); + + dev_handle = ino & IMAP_IGN; + dev_ino = ino & IMAP_INO; + + err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); + if (err != HV_EOK) + printk("sun4v_vintr_set_target(%lx,%lx,%lu): " + "err(%d)\n", + dev_handle, dev_ino, cpuid, err); + err = sun4v_vintr_set_state(dev_handle, dev_ino, + HV_INTR_ENABLED); + if (err != HV_EOK) + printk("sun4v_vintr_set_state(%lx,%lx," + "HV_INTR_ENABLED): err(%d)\n", + dev_handle, dev_ino, err); + } +} + +static void sun4v_virq_disable(unsigned int virt_irq) +{ + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; + + if (likely(bucket)) { + unsigned long dev_handle, dev_ino; + int err; + + dev_handle = ino & IMAP_IGN; + dev_ino = ino & IMAP_INO; + + err = sun4v_vintr_set_state(dev_handle, dev_ino, + HV_INTR_DISABLED); + if (err != HV_EOK) + printk("sun4v_vintr_set_state(%lx,%lx," + "HV_INTR_DISABLED): err(%d)\n", + dev_handle, dev_ino, err); + } +} + +static void sun4v_virq_end(unsigned int virt_irq) +{ + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; + + if (likely(bucket)) { + unsigned long dev_handle, dev_ino; + int err; + + dev_handle = ino & IMAP_IGN; + dev_ino = ino & IMAP_INO; + + err = sun4v_vintr_set_state(dev_handle, dev_ino, + HV_INTR_STATE_IDLE); + if (err != HV_EOK) + printk("sun4v_vintr_set_state(%lx,%lx," + "HV_INTR_STATE_IDLE): err(%d)\n", + dev_handle, dev_ino, err); + } +} + static void run_pre_handler(unsigned int virt_irq) { struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); @@ -434,6 +504,21 @@ static struct irq_chip sun4v_msi = { }; #endif +static struct irq_chip sun4v_virq = { + .typename = "vsun4v", + .enable = sun4v_virq_enable, + .disable = sun4v_virq_disable, + .end = sun4v_virq_end, +}; + +static struct irq_chip sun4v_virq_ack = { + .typename = "vsun4v+ack", + .enable = sun4v_virq_enable, + .disable = sun4v_virq_disable, + .ack = run_pre_handler, + .end = sun4v_virq_end, +}; + void irq_install_pre_handler(int virt_irq, void (*func)(unsigned int, void *, void *), void *arg1, void *arg2) @@ -447,7 +532,8 @@ void irq_install_pre_handler(int virt_irq, chip = get_irq_chip(virt_irq); if (chip == &sun4u_irq_ack || - chip == &sun4v_irq_ack + chip == &sun4v_irq_ack || + chip == &sun4v_virq_ack #ifdef CONFIG_PCI_MSI || chip == &sun4v_msi #endif @@ -455,7 +541,9 @@ void irq_install_pre_handler(int virt_irq, return; chip = (chip == &sun4u_irq ? - &sun4u_irq_ack : &sun4v_irq_ack); + &sun4u_irq_ack : + (chip == &sun4v_irq ? + &sun4v_irq_ack : &sun4v_virq_ack)); set_irq_chip(virt_irq, chip); } @@ -492,19 +580,18 @@ out: return bucket->virt_irq; } -unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) +static unsigned int sun4v_build_common(unsigned long sysino, + struct irq_chip *chip) { struct ino_bucket *bucket; struct irq_handler_data *data; - unsigned long sysino; BUG_ON(tlb_type != hypervisor); - sysino = sun4v_devino_to_sysino(devhandle, devino); bucket = &ivector_table[sysino]; if (!bucket->virt_irq) { bucket->virt_irq = virt_irq_alloc(__irq(bucket)); - set_irq_chip(bucket->virt_irq, &sun4v_irq); + set_irq_chip(bucket->virt_irq, chip); } data = get_irq_chip_data(bucket->virt_irq); @@ -529,6 +616,32 @@ out: return bucket->virt_irq; } +unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) +{ + unsigned long sysino = sun4v_devino_to_sysino(devhandle, devino); + + return sun4v_build_common(sysino, &sun4v_irq); +} + +unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) +{ + unsigned long sysino, hv_err; + + BUG_ON(devhandle & ~IMAP_IGN); + BUG_ON(devino & ~IMAP_INO); + + sysino = devhandle | devino; + + hv_err = sun4v_vintr_set_cookie(devhandle, devino, sysino); + if (hv_err) { + prom_printf("IRQ: Fatal, cannot set cookie for [%x:%x] " + "err=%lu\n", devhandle, devino, hv_err); + prom_halt(); + } + + return sun4v_build_common(sysino, &sun4v_virq); +} + #ifdef CONFIG_PCI_MSI unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p, unsigned int msi_start, unsigned int msi_end) diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index f974fefc3eb..4249214608a 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -291,8 +291,9 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) for (i = 0; i < num_pbm_ranges; i++) { const struct linux_prom_pci_ranges *pr = &pbm_ranges[i]; - unsigned long a; + unsigned long a, size; u32 parent_phys_hi, parent_phys_lo; + u32 size_hi, size_lo; int type; parent_phys_hi = pr->parent_phys_hi; @@ -300,9 +301,14 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) if (tlb_type == hypervisor) parent_phys_hi &= 0x0fffffff; + size_hi = pr->size_hi; + size_lo = pr->size_lo; + type = (pr->child_phys_hi >> 24) & 0x3; a = (((unsigned long)parent_phys_hi << 32UL) | ((unsigned long)parent_phys_lo << 0UL)); + size = (((unsigned long)size_hi << 32UL) | + ((unsigned long)size_lo << 0UL)); switch (type) { case 0: @@ -313,7 +319,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) case 1: /* 16-bit IO space, 16MB */ pbm->io_space.start = a; - pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL); + pbm->io_space.end = a + size - 1UL; pbm->io_space.flags = IORESOURCE_IO; saw_io = 1; break; @@ -321,7 +327,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) case 2: /* 32-bit MEM space, 2GB */ pbm->mem_space.start = a; - pbm->mem_space.end = a + (0x80000000UL - 1UL); + pbm->mem_space.end = a + size - 1UL; pbm->mem_space.flags = IORESOURCE_MEM; saw_mem = 1; break; diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h index 4e21c2f3065..c58ec1661df 100644 --- a/include/asm-sparc64/dma-mapping.h +++ b/include/asm-sparc64/dma-mapping.h @@ -15,8 +15,7 @@ static inline int dma_supported(struct device *dev, u64 mask) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); return pci_dma_supported(to_pci_dev(dev), mask); } @@ -24,8 +23,7 @@ dma_supported(struct device *dev, u64 mask) static inline int dma_set_mask(struct device *dev, u64 dma_mask) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); return pci_set_dma_mask(to_pci_dev(dev), dma_mask); } @@ -34,8 +32,7 @@ static inline void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); return pci_iommu_ops->alloc_consistent(to_pci_dev(dev), size, dma_handle, flag); } @@ -44,8 +41,7 @@ static inline void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle); } @@ -54,8 +50,7 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction); } @@ -64,8 +59,7 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction); } @@ -75,8 +69,7 @@ dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction); } @@ -85,8 +78,7 @@ static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction); } @@ -95,8 +87,7 @@ static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction); } @@ -105,8 +96,7 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction); } @@ -115,8 +105,7 @@ static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle, size, (int)direction); @@ -126,8 +115,7 @@ static inline void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle, size, (int)direction); @@ -137,8 +125,7 @@ static inline void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction); } @@ -147,8 +134,7 @@ static inline void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction direction) { - BUG_ON(dev->bus != &pci_bus_type && - dev->bus != &ebus_bus_type); + BUG_ON(dev->bus != &pci_bus_type); pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction); } diff --git a/include/asm-sparc64/hypervisor.h b/include/asm-sparc64/hypervisor.h index 5c2f9d4b9f0..db2130a95d6 100644 --- a/include/asm-sparc64/hypervisor.h +++ b/include/asm-sparc64/hypervisor.h @@ -2615,8 +2615,9 @@ struct ldc_mtable_entry { /* ldc_revoke() * TRAP: HV_FAST_TRAP * FUNCTION: HV_FAST_LDC_REVOKE - * ARG0: cookie - * ARG1: ldc_mtable_entry cookie + * ARG0: channel ID + * ARG1: cookie + * ARG2: ldc_mtable_entry cookie * RET0: status */ #define HV_FAST_LDC_REVOKE 0xef @@ -2663,7 +2664,8 @@ extern unsigned long sun4v_ldc_mapin(unsigned long channel, unsigned long *ra, unsigned long *perm); extern unsigned long sun4v_ldc_unmap(unsigned long ra); -extern unsigned long sun4v_ldc_revoke(unsigned long cookie, +extern unsigned long sun4v_ldc_revoke(unsigned long channel, + unsigned long cookie, unsigned long mte_cookie); #endif diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h index 5d233b42fe1..90781e34a95 100644 --- a/include/asm-sparc64/irq.h +++ b/include/asm-sparc64/irq.h @@ -46,6 +46,7 @@ extern void irq_install_pre_handler(int virt_irq, #define irq_canonicalize(irq) (irq) extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap); extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino); +extern unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino); extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p, unsigned int msi_devino_start, unsigned int msi_devino_end); diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h index 6340a5253a3..23cc63f049a 100644 --- a/include/asm-sparc64/parport.h +++ b/include/asm-sparc64/parport.h @@ -145,7 +145,7 @@ static int parport_isa_probe(int count) */ if (parport_pc_probe_port(base, base + 0x400, child->irq, PARPORT_DMA_NOFIFO, - child->bus->self)) + &child->bus->self->dev)) count++; } } @@ -199,7 +199,8 @@ static int parport_pc_find_nonpci_ports (int autoirq, int autodma) if (parport_pc_probe_port(base, base + 0x400, edev->irqs[0], - count, ebus->self)) + count, + &ebus->self->dev)) count++; } } |