diff options
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/commproc.c | 20 | ||||
-rw-r--r-- | arch/powerpc/sysdev/cpm2_common.c | 2 | ||||
-rw-r--r-- | arch/powerpc/sysdev/dart_iommu.c | 4 | ||||
-rw-r--r-- | arch/powerpc/sysdev/dcr.c | 4 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_soc.c | 13 | ||||
-rw-r--r-- | arch/powerpc/sysdev/indirect_pci.c | 4 | ||||
-rw-r--r-- | arch/powerpc/sysdev/tsi108_pci.c | 4 | ||||
-rw-r--r-- | arch/powerpc/sysdev/uic.c | 66 |
8 files changed, 94 insertions, 23 deletions
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c index 4f67b89ba1d..e8e79f83d19 100644 --- a/arch/powerpc/sysdev/commproc.c +++ b/arch/powerpc/sysdev/commproc.c @@ -45,10 +45,10 @@ #define CPM_MAP_SIZE (0x4000) static void m8xx_cpm_dpinit(void); -static uint host_buffer; /* One page of host buffer */ -static uint host_end; /* end + 1 */ -cpm8xx_t *cpmp; /* Pointer to comm processor space */ -cpic8xx_t *cpic_reg; +static uint host_buffer; /* One page of host buffer */ +static uint host_end; /* end + 1 */ +cpm8xx_t *cpmp; /* Pointer to comm processor space */ +cpic8xx_t *cpic_reg; static struct device_node *cpm_pic_node; static struct irq_host *cpm_pic_host; @@ -115,7 +115,7 @@ static int cpm_pic_host_map(struct irq_host *h, unsigned int virq, * and return. This is a no-op function so we don't need any special * tests in the interrupt handler. */ -static irqreturn_t cpm_error_interrupt(int irq, void *dev) +static irqreturn_t cpm_error_interrupt(int irq, void *dev) { return IRQ_HANDLED; } @@ -181,7 +181,7 @@ unsigned int cpm_pic_init(void) printk(KERN_ERR "CPM PIC init: can not find cpm node\n"); goto end; } - eirq= irq_of_parse_and_map(np, 0); + eirq = irq_of_parse_and_map(np, 0); if (eirq == NO_IRQ) goto end; @@ -197,15 +197,15 @@ end: void cpm_reset(void) { - cpm8xx_t *commproc; - sysconf8xx_t *siu_conf; + cpm8xx_t *commproc; + sysconf8xx_t *siu_conf; commproc = (cpm8xx_t *)ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE); #ifdef CONFIG_UCODE_PATCH /* Perform a reset. */ - out_be16(&commproc->cp_cpcr, CPM_CR_RST | CPM_CR_FLG); + out_be16(&commproc->cp_cpcr, CPM_CR_RST | CPM_CR_FLG); /* Wait for it. */ @@ -307,7 +307,7 @@ static rh_block_t cpm_boot_dpmem_rh_block[16]; static rh_info_t cpm_dpmem_info; #define CPM_DPMEM_ALIGNMENT 8 -static u8* dpram_vbase; +static u8 *dpram_vbase; static uint dpram_pbase; void m8xx_cpm_dpinit(void) diff --git a/arch/powerpc/sysdev/cpm2_common.c b/arch/powerpc/sysdev/cpm2_common.c index c827715a509..3bf89b32476 100644 --- a/arch/powerpc/sysdev/cpm2_common.c +++ b/arch/powerpc/sysdev/cpm2_common.c @@ -201,7 +201,7 @@ int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode) } if (mode == CPM_CLK_RX) - shift +=3; + shift += 3; for (i=0; i<24; i++) { if (clk_map[i][0] == target && clk_map[i][1] == clock) { diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index a1d2042bb30..e0e24b01e3a 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -204,7 +204,7 @@ static void dart_free(struct iommu_table *tbl, long index, long npages) } -static int dart_init(struct device_node *dart_node) +static int __init dart_init(struct device_node *dart_node) { unsigned int i; unsigned long tmp, base, size; @@ -313,7 +313,7 @@ static void pci_dma_bus_setup_dart(struct pci_bus *bus) PCI_DN(dn)->iommu_table = &iommu_table_dart; } -void iommu_init_early_dart(void) +void __init iommu_init_early_dart(void) { struct device_node *dn; diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c index 574b6ef44e0..e82d54de8a8 100644 --- a/arch/powerpc/sysdev/dcr.c +++ b/arch/powerpc/sysdev/dcr.c @@ -33,6 +33,7 @@ unsigned int dcr_resource_start(struct device_node *np, unsigned int index) return dr[index * 2]; } +EXPORT_SYMBOL_GPL(dcr_resource_start); unsigned int dcr_resource_len(struct device_node *np, unsigned int index) { @@ -44,6 +45,7 @@ unsigned int dcr_resource_len(struct device_node *np, unsigned int index) return dr[index * 2 + 1]; } +EXPORT_SYMBOL_GPL(dcr_resource_len); #ifndef CONFIG_PPC_DCR_NATIVE @@ -122,6 +124,7 @@ dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, ret.token -= dcr_n * ret.stride; return ret; } +EXPORT_SYMBOL_GPL(dcr_map); void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c) { @@ -133,5 +136,6 @@ void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c) iounmap(h.token); h.token = NULL; } +EXPORT_SYMBOL_GPL(dcr_unmap); #endif /* !defined(CONFIG_PPC_DCR_NATIVE) */ diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 1cf29c9d440..f3abce11bea 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -321,21 +321,26 @@ static struct i2c_driver_device i2c_devices[] __initdata = { {"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",}, }; -static int __init of_find_i2c_driver(struct device_node *node, struct i2c_board_info *info) +static int __init of_find_i2c_driver(struct device_node *node, + struct i2c_board_info *info) { int i; for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) { if (!of_device_is_compatible(node, i2c_devices[i].of_device)) continue; - strncpy(info->driver_name, i2c_devices[i].i2c_driver, KOBJ_NAME_LEN); - strncpy(info->type, i2c_devices[i].i2c_type, I2C_NAME_SIZE); + if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver, + KOBJ_NAME_LEN) >= KOBJ_NAME_LEN || + strlcpy(info->type, i2c_devices[i].i2c_type, + I2C_NAME_SIZE) >= I2C_NAME_SIZE) + return -ENOMEM; return 0; } return -ENODEV; } -static void __init of_register_i2c_devices(struct device_node *adap_node, int bus_num) +static void __init of_register_i2c_devices(struct device_node *adap_node, + int bus_num) { struct device_node *node = NULL; diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c index 5294560c7b0..b5d068204aa 100644 --- a/arch/powerpc/sysdev/indirect_pci.c +++ b/arch/powerpc/sysdev/indirect_pci.c @@ -144,8 +144,8 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, static struct pci_ops indirect_pci_ops = { - indirect_read_config, - indirect_write_config + .read = indirect_read_config, + .write = indirect_write_config, }; void __init diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c index 90db8a720fe..cf0bfbd7340 100644 --- a/arch/powerpc/sysdev/tsi108_pci.c +++ b/arch/powerpc/sysdev/tsi108_pci.c @@ -193,8 +193,8 @@ void tsi108_clear_pci_cfg_error(void) } static struct pci_ops tsi108_direct_pci_ops = { - tsi108_direct_read_config, - tsi108_direct_write_config + .read = tsi108_direct_read_config, + .write = tsi108_direct_write_config, }; int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary) diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c index 89059895a20..47180b3fca5 100644 --- a/arch/powerpc/sysdev/uic.c +++ b/arch/powerpc/sysdev/uic.c @@ -24,6 +24,7 @@ #include <linux/spinlock.h> #include <linux/irq.h> #include <linux/interrupt.h> +#include <linux/kernel_stat.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/prom.h> @@ -142,7 +143,7 @@ static int uic_set_irq_type(unsigned int virq, unsigned int flow_type) desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; - if (trigger) + if (!trigger) desc->status |= IRQ_LEVEL; spin_unlock_irqrestore(&uic->lock, flags); @@ -159,6 +160,64 @@ static struct irq_chip uic_irq_chip = { .set_type = uic_set_irq_type, }; +/** + * handle_uic_irq - irq flow handler for UIC + * @irq: the interrupt number + * @desc: the interrupt description structure for this irq + * + * This is modified version of the generic handle_level_irq() suitable + * for the UIC. On the UIC, acking (i.e. clearing the SR bit) a level + * irq will have no effect if the interrupt is still asserted by the + * device, even if the interrupt is already masked. Therefore, unlike + * the standard handle_level_irq(), we must ack the interrupt *after* + * invoking the ISR (which should have de-asserted the interrupt in + * the external source). For edge interrupts we ack at the beginning + * instead of the end, to keep the window in which we can miss an + * interrupt as small as possible. + */ +void fastcall handle_uic_irq(unsigned int irq, struct irq_desc *desc) +{ + unsigned int cpu = smp_processor_id(); + struct irqaction *action; + irqreturn_t action_ret; + + spin_lock(&desc->lock); + if (desc->status & IRQ_LEVEL) + desc->chip->mask(irq); + else + desc->chip->mask_ack(irq); + + if (unlikely(desc->status & IRQ_INPROGRESS)) + goto out_unlock; + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + kstat_cpu(cpu).irqs[irq]++; + + /* + * If its disabled or no action available + * keep it masked and get out of here + */ + action = desc->action; + if (unlikely(!action || (desc->status & IRQ_DISABLED))) { + desc->status |= IRQ_PENDING; + goto out_unlock; + } + + desc->status |= IRQ_INPROGRESS; + desc->status &= ~IRQ_PENDING; + spin_unlock(&desc->lock); + + action_ret = handle_IRQ_event(irq, action); + + spin_lock(&desc->lock); + desc->status &= ~IRQ_INPROGRESS; + if (desc->status & IRQ_LEVEL) + desc->chip->ack(irq); + if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) + desc->chip->unmask(irq); +out_unlock: + spin_unlock(&desc->lock); +} + static int uic_host_match(struct irq_host *h, struct device_node *node) { struct uic *uic = h->host_data; @@ -173,7 +232,7 @@ static int uic_host_map(struct irq_host *h, unsigned int virq, set_irq_chip_data(virq, uic); /* Despite the name, handle_level_irq() works for both level * and edge irqs on UIC. FIXME: check this is correct */ - set_irq_chip_and_handler(virq, &uic_irq_chip, handle_level_irq); + set_irq_chip_and_handler(virq, &uic_irq_chip, handle_uic_irq); /* Set default irq type */ set_irq_type(virq, IRQ_TYPE_NONE); @@ -207,6 +266,9 @@ irqreturn_t uic_cascade(int virq, void *data) int subvirq; msr = mfdcr(uic->dcrbase + UIC_MSR); + if (!msr) /* spurious interrupt */ + return IRQ_HANDLED; + src = 32 - ffs(msr); subvirq = irq_linear_revmap(uic->irqhost, src); |