Loading arch/powerpc/platforms/ps3/interrupt.c +166 −68 Original line number Diff line number Diff line Loading @@ -89,7 +89,18 @@ struct ps3_private { static DEFINE_PER_CPU(struct ps3_private, ps3_private); int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet, /** * ps3_virq_setup - virq related setup. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @outlet: The HV outlet from the various create outlet routines. * @virq: The assigned Linux virq. * * Calls irq_create_mapping() to get a virq and sets the chip data to * ps3_private data. */ int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet, unsigned int *virq) { int result; Loading @@ -111,17 +122,6 @@ int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet, goto fail_create; } /* Binds outlet to cpu + virq. */ result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0); if (result) { pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", __func__, __LINE__, ps3_result(result)); result = -EPERM; goto fail_connect; } pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__, outlet, cpu, *virq); Loading @@ -136,94 +136,118 @@ int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet, return result; fail_set: lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, *virq); fail_connect: irq_dispose_mapping(*virq); fail_create: return result; } EXPORT_SYMBOL_GPL(ps3_alloc_irq); int ps3_free_irq(unsigned int virq) /** * ps3_virq_destroy - virq related teardown. * @virq: The assigned Linux virq. * * Clears chip data and calls irq_dispose_mapping() for the virq. */ int ps3_virq_destroy(unsigned int virq) { int result; const struct ps3_private *pd = get_irq_chip_data(virq); pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, pd->node, pd->cpu, virq); result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq); if (result) pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", __func__, __LINE__, ps3_result(result)); set_irq_chip_data(virq, NULL); irq_dispose_mapping(virq); return result; pr_debug("%s:%d <-\n", __func__, __LINE__); return 0; } EXPORT_SYMBOL_GPL(ps3_free_irq); /** * ps3_alloc_io_irq - Assign a virq to a system bus device. * ps3_irq_plug_setup - Generic outlet and virq related setup. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @interrupt_id: The device interrupt id read from the system repository. * @outlet: The HV outlet from the various create outlet routines. * @virq: The assigned Linux virq. * * An io irq represents a non-virtualized device interrupt. interrupt_id * coresponds to the interrupt number of the interrupt controller. * Sets up virq and connects the irq plug. */ int ps3_alloc_io_irq(enum ps3_cpu_binding cpu, unsigned int interrupt_id, int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet, unsigned int *virq) { int result; unsigned long outlet; struct ps3_private *pd; result = lv1_construct_io_irq_outlet(interrupt_id, &outlet); result = ps3_virq_setup(cpu, outlet, virq); if (result) { pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n", pr_debug("%s:%d: ps3_virq_setup failed\n", __func__, __LINE__); goto fail_setup; } pd = get_irq_chip_data(*virq); /* Binds outlet to cpu + virq. */ result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0); if (result) { pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", __func__, __LINE__, ps3_result(result)); return result; result = -EPERM; goto fail_connect; } result = ps3_alloc_irq(cpu, outlet, virq); BUG_ON(result); return result; fail_connect: ps3_virq_destroy(*virq); fail_setup: return result; } EXPORT_SYMBOL_GPL(ps3_alloc_io_irq); EXPORT_SYMBOL_GPL(ps3_irq_plug_setup); int ps3_free_io_irq(unsigned int virq) /** * ps3_irq_plug_destroy - Generic outlet and virq related teardown. * @virq: The assigned Linux virq. * * Disconnects the irq plug and tears down virq. * Do not call for system bus event interrupts setup with * ps3_sb_event_receive_port_setup(). */ int ps3_irq_plug_destroy(unsigned int virq) { int result; const struct ps3_private *pd = get_irq_chip_data(virq); result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, pd->node, pd->cpu, virq); result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq); if (result) pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", __func__, __LINE__, ps3_result(result)); ps3_free_irq(virq); ps3_virq_destroy(virq); return result; } EXPORT_SYMBOL_GPL(ps3_free_io_irq); EXPORT_SYMBOL_GPL(ps3_irq_plug_destroy); /** * ps3_alloc_event_irq - Allocate a virq for use with a system event. * ps3_event_receive_port_setup - Setup an event receive port. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @virq: The assigned Linux virq. * * The virq can be used with lv1_connect_interrupt_event_receive_port() to * arrange to receive events, or with ps3_send_event_locally() to signal * events. * arrange to receive interrupts from system-bus devices, or with * ps3_send_event_locally() to signal events. */ int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq) int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq) { int result; unsigned long outlet; Loading @@ -237,17 +261,27 @@ int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq) return result; } result = ps3_alloc_irq(cpu, outlet, virq); result = ps3_irq_plug_setup(cpu, outlet, virq); BUG_ON(result); return result; } EXPORT_SYMBOL_GPL(ps3_event_receive_port_setup); /** * ps3_event_receive_port_destroy - Destroy an event receive port. * @virq: The assigned Linux virq. * * Since ps3_event_receive_port_destroy destroys the receive port outlet, * SB devices need to call disconnect_interrupt_event_receive_port() before * this. */ int ps3_free_event_irq(unsigned int virq) int ps3_event_receive_port_destroy(unsigned int virq) { int result; pr_debug(" -> %s:%d\n", __func__, __LINE__); pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq); result = lv1_destruct_event_receive_port(virq_to_hw(virq)); Loading @@ -255,11 +289,17 @@ int ps3_free_event_irq(unsigned int virq) pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", __func__, __LINE__, ps3_result(result)); ps3_free_irq(virq); /* lv1_destruct_event_receive_port() destroys the IRQ plug, * so don't call ps3_irq_plug_destroy() here. */ result = ps3_virq_destroy(virq); BUG_ON(result); pr_debug(" <- %s:%d\n", __func__, __LINE__); return result; } EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy); int ps3_send_event_locally(unsigned int virq) { Loading @@ -267,7 +307,7 @@ int ps3_send_event_locally(unsigned int virq) } /** * ps3_connect_event_irq - Assign a virq to a system bus device. * ps3_sb_event_receive_port_setup - Setup a system bus event receive port. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @did: The HV device identifier read from the system repository. Loading @@ -278,13 +318,15 @@ int ps3_send_event_locally(unsigned int virq) * coresponds to the software interrupt number. */ int ps3_connect_event_irq(enum ps3_cpu_binding cpu, int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, const struct ps3_device_id *did, unsigned int interrupt_id, unsigned int *virq) { /* this should go in system-bus.c */ int result; result = ps3_alloc_event_irq(cpu, virq); result = ps3_event_receive_port_setup(cpu, virq); if (result) return result; Loading @@ -296,7 +338,7 @@ int ps3_connect_event_irq(enum ps3_cpu_binding cpu, pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port" " failed: %s\n", __func__, __LINE__, ps3_result(result)); ps3_free_event_irq(*virq); ps3_event_receive_port_destroy(*virq); *virq = NO_IRQ; return result; } Loading @@ -306,10 +348,13 @@ int ps3_connect_event_irq(enum ps3_cpu_binding cpu, return 0; } EXPORT_SYMBOL(ps3_sb_event_receive_port_setup); int ps3_disconnect_event_irq(const struct ps3_device_id *did, int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did, unsigned int interrupt_id, unsigned int virq) { /* this should go in system-bus.c */ int result; pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, Loading @@ -323,14 +368,65 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did, " failed: %s\n", __func__, __LINE__, ps3_result(result)); ps3_free_event_irq(virq); result = ps3_event_receive_port_destroy(virq); BUG_ON(result); pr_debug(" <- %s:%d\n", __func__, __LINE__); return result; } EXPORT_SYMBOL(ps3_sb_event_receive_port_destroy); /** * ps3_io_irq_setup - Setup a system bus io irq. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @interrupt_id: The device interrupt id read from the system repository. * @virq: The assigned Linux virq. * * An io irq represents a non-virtualized device interrupt. interrupt_id * coresponds to the interrupt number of the interrupt controller. */ int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id, unsigned int *virq) { int result; unsigned long outlet; result = lv1_construct_io_irq_outlet(interrupt_id, &outlet); if (result) { pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n", __func__, __LINE__, ps3_result(result)); return result; } result = ps3_irq_plug_setup(cpu, outlet, virq); BUG_ON(result); return result; } EXPORT_SYMBOL_GPL(ps3_io_irq_setup); int ps3_io_irq_destroy(unsigned int virq) { int result; result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); if (result) pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", __func__, __LINE__, ps3_result(result)); result = ps3_irq_plug_destroy(virq); BUG_ON(result); return result; } EXPORT_SYMBOL_GPL(ps3_io_irq_destroy); /** * ps3_alloc_vuart_irq - Configure the system virtual uart virq. * ps3_vuart_irq_setup - Setup the system virtual uart virq. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap. Loading @@ -340,7 +436,7 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did, * freeing the interrupt will return a wrong state error. */ int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp, int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp, unsigned int *virq) { int result; Loading @@ -359,13 +455,13 @@ int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp, return result; } result = ps3_alloc_irq(cpu, outlet, virq); result = ps3_irq_plug_setup(cpu, outlet, virq); BUG_ON(result); return result; } int ps3_free_vuart_irq(unsigned int virq) int ps3_vuart_irq_destroy(unsigned int virq) { int result; Loading @@ -377,13 +473,14 @@ int ps3_free_vuart_irq(unsigned int virq) return result; } ps3_free_irq(virq); result = ps3_irq_plug_destroy(virq); BUG_ON(result); return result; } /** * ps3_alloc_spe_irq - Configure an spe virq. * ps3_spe_irq_setup - Setup an spe virq. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @spe_id: The spe_id returned from lv1_construct_logical_spe(). Loading @@ -392,7 +489,7 @@ int ps3_free_vuart_irq(unsigned int virq) * */ int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id, int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id, unsigned int class, unsigned int *virq) { int result; Loading @@ -408,15 +505,16 @@ int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id, return result; } result = ps3_alloc_irq(cpu, outlet, virq); result = ps3_irq_plug_setup(cpu, outlet, virq); BUG_ON(result); return result; } int ps3_free_spe_irq(unsigned int virq) int ps3_spe_irq_destroy(unsigned int virq) { ps3_free_irq(virq); int result = ps3_irq_plug_destroy(virq); BUG_ON(result); return 0; } Loading arch/powerpc/platforms/ps3/smp.c +4 −2 Original line number Diff line number Diff line Loading @@ -110,7 +110,7 @@ static void __init ps3_smp_setup_cpu(int cpu) BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); for (i = 0; i < MSG_COUNT; i++) { result = ps3_alloc_event_irq(cpu, &virqs[i]); result = ps3_event_receive_port_setup(cpu, &virqs[i]); if (result) continue; Loading @@ -134,11 +134,13 @@ void ps3_smp_cleanup_cpu(int cpu) int i; DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); for (i = 0; i < MSG_COUNT; i++) { ps3_free_event_irq(virqs[i]); free_irq(virqs[i], (void*)(long)i); ps3_event_receive_port_destroy(virqs[i]); virqs[i] = NO_IRQ; } DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); } Loading arch/powerpc/platforms/ps3/spu.c +8 −8 Original line number Diff line number Diff line Loading @@ -230,19 +230,19 @@ static int __init setup_interrupts(struct spu *spu) { int result; result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 0, &spu->irqs[0]); if (result) goto fail_alloc_0; result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 1, &spu->irqs[1]); if (result) goto fail_alloc_1; result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 2, &spu->irqs[2]); if (result) Loading @@ -251,9 +251,9 @@ static int __init setup_interrupts(struct spu *spu) return result; fail_alloc_2: ps3_free_spe_irq(spu->irqs[1]); ps3_spe_irq_destroy(spu->irqs[1]); fail_alloc_1: ps3_free_spe_irq(spu->irqs[0]); ps3_spe_irq_destroy(spu->irqs[0]); fail_alloc_0: spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; return result; Loading Loading @@ -301,9 +301,9 @@ static int ps3_destroy_spu(struct spu *spu) result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0); BUG_ON(result); ps3_free_spe_irq(spu->irqs[2]); ps3_free_spe_irq(spu->irqs[1]); ps3_free_spe_irq(spu->irqs[0]); ps3_spe_irq_destroy(spu->irqs[2]); ps3_spe_irq_destroy(spu->irqs[1]); ps3_spe_irq_destroy(spu->irqs[0]); spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; Loading drivers/ps3/vuart.c +4 −4 Original line number Diff line number Diff line Loading @@ -886,12 +886,12 @@ static int ps3_vuart_probe(struct device *_dev) if (++vuart_bus_priv.use_count == 1) { result = ps3_alloc_vuart_irq(PS3_BINDING_CPU_ANY, result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, (void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq); if (result) { dev_dbg(&dev->core, "%s:%d: ps3_alloc_vuart_irq failed (%d)\n", "%s:%d: ps3_vuart_irq_setup failed (%d)\n", __func__, __LINE__, result); result = -EPERM; goto fail_alloc_irq; Loading Loading @@ -937,7 +937,7 @@ static int ps3_vuart_probe(struct device *_dev) fail_probe: ps3_vuart_set_interrupt_mask(dev, 0); fail_request_irq: ps3_free_vuart_irq(vuart_bus_priv.virq); ps3_vuart_irq_destroy(vuart_bus_priv.virq); vuart_bus_priv.virq = NO_IRQ; fail_alloc_irq: --vuart_bus_priv.use_count; Loading Loading @@ -975,7 +975,7 @@ static int ps3_vuart_remove(struct device *_dev) if (--vuart_bus_priv.use_count == 0) { BUG(); free_irq(vuart_bus_priv.virq, &vuart_bus_priv); ps3_free_vuart_irq(vuart_bus_priv.virq); ps3_vuart_irq_destroy(vuart_bus_priv.virq); vuart_bus_priv.virq = NO_IRQ; } Loading drivers/usb/host/ehci-ps3.c +2 −2 Original line number Diff line number Diff line Loading @@ -104,7 +104,7 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev) dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__, __LINE__, dev->m_region->lpar_addr); result = ps3_alloc_io_irq(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq); result = ps3_io_irq_setup(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq); if (result) { dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n", Loading Loading @@ -162,7 +162,7 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev) fail_ioremap: usb_put_hcd(hcd); fail_create_hcd: ps3_free_io_irq(virq); ps3_io_irq_destroy(virq); fail_irq: ps3_free_mmio_region(dev->m_region); fail_mmio: Loading Loading
arch/powerpc/platforms/ps3/interrupt.c +166 −68 Original line number Diff line number Diff line Loading @@ -89,7 +89,18 @@ struct ps3_private { static DEFINE_PER_CPU(struct ps3_private, ps3_private); int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet, /** * ps3_virq_setup - virq related setup. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @outlet: The HV outlet from the various create outlet routines. * @virq: The assigned Linux virq. * * Calls irq_create_mapping() to get a virq and sets the chip data to * ps3_private data. */ int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet, unsigned int *virq) { int result; Loading @@ -111,17 +122,6 @@ int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet, goto fail_create; } /* Binds outlet to cpu + virq. */ result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0); if (result) { pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", __func__, __LINE__, ps3_result(result)); result = -EPERM; goto fail_connect; } pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__, outlet, cpu, *virq); Loading @@ -136,94 +136,118 @@ int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet, return result; fail_set: lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, *virq); fail_connect: irq_dispose_mapping(*virq); fail_create: return result; } EXPORT_SYMBOL_GPL(ps3_alloc_irq); int ps3_free_irq(unsigned int virq) /** * ps3_virq_destroy - virq related teardown. * @virq: The assigned Linux virq. * * Clears chip data and calls irq_dispose_mapping() for the virq. */ int ps3_virq_destroy(unsigned int virq) { int result; const struct ps3_private *pd = get_irq_chip_data(virq); pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, pd->node, pd->cpu, virq); result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq); if (result) pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", __func__, __LINE__, ps3_result(result)); set_irq_chip_data(virq, NULL); irq_dispose_mapping(virq); return result; pr_debug("%s:%d <-\n", __func__, __LINE__); return 0; } EXPORT_SYMBOL_GPL(ps3_free_irq); /** * ps3_alloc_io_irq - Assign a virq to a system bus device. * ps3_irq_plug_setup - Generic outlet and virq related setup. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @interrupt_id: The device interrupt id read from the system repository. * @outlet: The HV outlet from the various create outlet routines. * @virq: The assigned Linux virq. * * An io irq represents a non-virtualized device interrupt. interrupt_id * coresponds to the interrupt number of the interrupt controller. * Sets up virq and connects the irq plug. */ int ps3_alloc_io_irq(enum ps3_cpu_binding cpu, unsigned int interrupt_id, int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet, unsigned int *virq) { int result; unsigned long outlet; struct ps3_private *pd; result = lv1_construct_io_irq_outlet(interrupt_id, &outlet); result = ps3_virq_setup(cpu, outlet, virq); if (result) { pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n", pr_debug("%s:%d: ps3_virq_setup failed\n", __func__, __LINE__); goto fail_setup; } pd = get_irq_chip_data(*virq); /* Binds outlet to cpu + virq. */ result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0); if (result) { pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", __func__, __LINE__, ps3_result(result)); return result; result = -EPERM; goto fail_connect; } result = ps3_alloc_irq(cpu, outlet, virq); BUG_ON(result); return result; fail_connect: ps3_virq_destroy(*virq); fail_setup: return result; } EXPORT_SYMBOL_GPL(ps3_alloc_io_irq); EXPORT_SYMBOL_GPL(ps3_irq_plug_setup); int ps3_free_io_irq(unsigned int virq) /** * ps3_irq_plug_destroy - Generic outlet and virq related teardown. * @virq: The assigned Linux virq. * * Disconnects the irq plug and tears down virq. * Do not call for system bus event interrupts setup with * ps3_sb_event_receive_port_setup(). */ int ps3_irq_plug_destroy(unsigned int virq) { int result; const struct ps3_private *pd = get_irq_chip_data(virq); result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, pd->node, pd->cpu, virq); result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq); if (result) pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", __func__, __LINE__, ps3_result(result)); ps3_free_irq(virq); ps3_virq_destroy(virq); return result; } EXPORT_SYMBOL_GPL(ps3_free_io_irq); EXPORT_SYMBOL_GPL(ps3_irq_plug_destroy); /** * ps3_alloc_event_irq - Allocate a virq for use with a system event. * ps3_event_receive_port_setup - Setup an event receive port. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @virq: The assigned Linux virq. * * The virq can be used with lv1_connect_interrupt_event_receive_port() to * arrange to receive events, or with ps3_send_event_locally() to signal * events. * arrange to receive interrupts from system-bus devices, or with * ps3_send_event_locally() to signal events. */ int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq) int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq) { int result; unsigned long outlet; Loading @@ -237,17 +261,27 @@ int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq) return result; } result = ps3_alloc_irq(cpu, outlet, virq); result = ps3_irq_plug_setup(cpu, outlet, virq); BUG_ON(result); return result; } EXPORT_SYMBOL_GPL(ps3_event_receive_port_setup); /** * ps3_event_receive_port_destroy - Destroy an event receive port. * @virq: The assigned Linux virq. * * Since ps3_event_receive_port_destroy destroys the receive port outlet, * SB devices need to call disconnect_interrupt_event_receive_port() before * this. */ int ps3_free_event_irq(unsigned int virq) int ps3_event_receive_port_destroy(unsigned int virq) { int result; pr_debug(" -> %s:%d\n", __func__, __LINE__); pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq); result = lv1_destruct_event_receive_port(virq_to_hw(virq)); Loading @@ -255,11 +289,17 @@ int ps3_free_event_irq(unsigned int virq) pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", __func__, __LINE__, ps3_result(result)); ps3_free_irq(virq); /* lv1_destruct_event_receive_port() destroys the IRQ plug, * so don't call ps3_irq_plug_destroy() here. */ result = ps3_virq_destroy(virq); BUG_ON(result); pr_debug(" <- %s:%d\n", __func__, __LINE__); return result; } EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy); int ps3_send_event_locally(unsigned int virq) { Loading @@ -267,7 +307,7 @@ int ps3_send_event_locally(unsigned int virq) } /** * ps3_connect_event_irq - Assign a virq to a system bus device. * ps3_sb_event_receive_port_setup - Setup a system bus event receive port. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @did: The HV device identifier read from the system repository. Loading @@ -278,13 +318,15 @@ int ps3_send_event_locally(unsigned int virq) * coresponds to the software interrupt number. */ int ps3_connect_event_irq(enum ps3_cpu_binding cpu, int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, const struct ps3_device_id *did, unsigned int interrupt_id, unsigned int *virq) { /* this should go in system-bus.c */ int result; result = ps3_alloc_event_irq(cpu, virq); result = ps3_event_receive_port_setup(cpu, virq); if (result) return result; Loading @@ -296,7 +338,7 @@ int ps3_connect_event_irq(enum ps3_cpu_binding cpu, pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port" " failed: %s\n", __func__, __LINE__, ps3_result(result)); ps3_free_event_irq(*virq); ps3_event_receive_port_destroy(*virq); *virq = NO_IRQ; return result; } Loading @@ -306,10 +348,13 @@ int ps3_connect_event_irq(enum ps3_cpu_binding cpu, return 0; } EXPORT_SYMBOL(ps3_sb_event_receive_port_setup); int ps3_disconnect_event_irq(const struct ps3_device_id *did, int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did, unsigned int interrupt_id, unsigned int virq) { /* this should go in system-bus.c */ int result; pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, Loading @@ -323,14 +368,65 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did, " failed: %s\n", __func__, __LINE__, ps3_result(result)); ps3_free_event_irq(virq); result = ps3_event_receive_port_destroy(virq); BUG_ON(result); pr_debug(" <- %s:%d\n", __func__, __LINE__); return result; } EXPORT_SYMBOL(ps3_sb_event_receive_port_destroy); /** * ps3_io_irq_setup - Setup a system bus io irq. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @interrupt_id: The device interrupt id read from the system repository. * @virq: The assigned Linux virq. * * An io irq represents a non-virtualized device interrupt. interrupt_id * coresponds to the interrupt number of the interrupt controller. */ int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id, unsigned int *virq) { int result; unsigned long outlet; result = lv1_construct_io_irq_outlet(interrupt_id, &outlet); if (result) { pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n", __func__, __LINE__, ps3_result(result)); return result; } result = ps3_irq_plug_setup(cpu, outlet, virq); BUG_ON(result); return result; } EXPORT_SYMBOL_GPL(ps3_io_irq_setup); int ps3_io_irq_destroy(unsigned int virq) { int result; result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); if (result) pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", __func__, __LINE__, ps3_result(result)); result = ps3_irq_plug_destroy(virq); BUG_ON(result); return result; } EXPORT_SYMBOL_GPL(ps3_io_irq_destroy); /** * ps3_alloc_vuart_irq - Configure the system virtual uart virq. * ps3_vuart_irq_setup - Setup the system virtual uart virq. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap. Loading @@ -340,7 +436,7 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did, * freeing the interrupt will return a wrong state error. */ int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp, int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp, unsigned int *virq) { int result; Loading @@ -359,13 +455,13 @@ int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp, return result; } result = ps3_alloc_irq(cpu, outlet, virq); result = ps3_irq_plug_setup(cpu, outlet, virq); BUG_ON(result); return result; } int ps3_free_vuart_irq(unsigned int virq) int ps3_vuart_irq_destroy(unsigned int virq) { int result; Loading @@ -377,13 +473,14 @@ int ps3_free_vuart_irq(unsigned int virq) return result; } ps3_free_irq(virq); result = ps3_irq_plug_destroy(virq); BUG_ON(result); return result; } /** * ps3_alloc_spe_irq - Configure an spe virq. * ps3_spe_irq_setup - Setup an spe virq. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. * @spe_id: The spe_id returned from lv1_construct_logical_spe(). Loading @@ -392,7 +489,7 @@ int ps3_free_vuart_irq(unsigned int virq) * */ int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id, int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id, unsigned int class, unsigned int *virq) { int result; Loading @@ -408,15 +505,16 @@ int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id, return result; } result = ps3_alloc_irq(cpu, outlet, virq); result = ps3_irq_plug_setup(cpu, outlet, virq); BUG_ON(result); return result; } int ps3_free_spe_irq(unsigned int virq) int ps3_spe_irq_destroy(unsigned int virq) { ps3_free_irq(virq); int result = ps3_irq_plug_destroy(virq); BUG_ON(result); return 0; } Loading
arch/powerpc/platforms/ps3/smp.c +4 −2 Original line number Diff line number Diff line Loading @@ -110,7 +110,7 @@ static void __init ps3_smp_setup_cpu(int cpu) BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); for (i = 0; i < MSG_COUNT; i++) { result = ps3_alloc_event_irq(cpu, &virqs[i]); result = ps3_event_receive_port_setup(cpu, &virqs[i]); if (result) continue; Loading @@ -134,11 +134,13 @@ void ps3_smp_cleanup_cpu(int cpu) int i; DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); for (i = 0; i < MSG_COUNT; i++) { ps3_free_event_irq(virqs[i]); free_irq(virqs[i], (void*)(long)i); ps3_event_receive_port_destroy(virqs[i]); virqs[i] = NO_IRQ; } DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); } Loading
arch/powerpc/platforms/ps3/spu.c +8 −8 Original line number Diff line number Diff line Loading @@ -230,19 +230,19 @@ static int __init setup_interrupts(struct spu *spu) { int result; result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 0, &spu->irqs[0]); if (result) goto fail_alloc_0; result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 1, &spu->irqs[1]); if (result) goto fail_alloc_1; result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 2, &spu->irqs[2]); if (result) Loading @@ -251,9 +251,9 @@ static int __init setup_interrupts(struct spu *spu) return result; fail_alloc_2: ps3_free_spe_irq(spu->irqs[1]); ps3_spe_irq_destroy(spu->irqs[1]); fail_alloc_1: ps3_free_spe_irq(spu->irqs[0]); ps3_spe_irq_destroy(spu->irqs[0]); fail_alloc_0: spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; return result; Loading Loading @@ -301,9 +301,9 @@ static int ps3_destroy_spu(struct spu *spu) result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0); BUG_ON(result); ps3_free_spe_irq(spu->irqs[2]); ps3_free_spe_irq(spu->irqs[1]); ps3_free_spe_irq(spu->irqs[0]); ps3_spe_irq_destroy(spu->irqs[2]); ps3_spe_irq_destroy(spu->irqs[1]); ps3_spe_irq_destroy(spu->irqs[0]); spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; Loading
drivers/ps3/vuart.c +4 −4 Original line number Diff line number Diff line Loading @@ -886,12 +886,12 @@ static int ps3_vuart_probe(struct device *_dev) if (++vuart_bus_priv.use_count == 1) { result = ps3_alloc_vuart_irq(PS3_BINDING_CPU_ANY, result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, (void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq); if (result) { dev_dbg(&dev->core, "%s:%d: ps3_alloc_vuart_irq failed (%d)\n", "%s:%d: ps3_vuart_irq_setup failed (%d)\n", __func__, __LINE__, result); result = -EPERM; goto fail_alloc_irq; Loading Loading @@ -937,7 +937,7 @@ static int ps3_vuart_probe(struct device *_dev) fail_probe: ps3_vuart_set_interrupt_mask(dev, 0); fail_request_irq: ps3_free_vuart_irq(vuart_bus_priv.virq); ps3_vuart_irq_destroy(vuart_bus_priv.virq); vuart_bus_priv.virq = NO_IRQ; fail_alloc_irq: --vuart_bus_priv.use_count; Loading Loading @@ -975,7 +975,7 @@ static int ps3_vuart_remove(struct device *_dev) if (--vuart_bus_priv.use_count == 0) { BUG(); free_irq(vuart_bus_priv.virq, &vuart_bus_priv); ps3_free_vuart_irq(vuart_bus_priv.virq); ps3_vuart_irq_destroy(vuart_bus_priv.virq); vuart_bus_priv.virq = NO_IRQ; } Loading
drivers/usb/host/ehci-ps3.c +2 −2 Original line number Diff line number Diff line Loading @@ -104,7 +104,7 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev) dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__, __LINE__, dev->m_region->lpar_addr); result = ps3_alloc_io_irq(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq); result = ps3_io_irq_setup(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq); if (result) { dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n", Loading Loading @@ -162,7 +162,7 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev) fail_ioremap: usb_put_hcd(hcd); fail_create_hcd: ps3_free_io_irq(virq); ps3_io_irq_destroy(virq); fail_irq: ps3_free_mmio_region(dev->m_region); fail_mmio: Loading