[POWERPC] PS3: Interrupt routine fixups.
Fixups for the ps3 interrupt routines to support all HV device in a generic way. Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Родитель
1282885663
Коммит
dc4f60c25a
|
@ -89,7 +89,18 @@ struct ps3_private {
|
||||||
|
|
||||||
static DEFINE_PER_CPU(struct ps3_private, 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)
|
unsigned int *virq)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
@ -111,17 +122,6 @@ int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet,
|
||||||
goto fail_create;
|
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__,
|
pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__,
|
||||||
outlet, cpu, *virq);
|
outlet, cpu, *virq);
|
||||||
|
|
||||||
|
@ -136,15 +136,87 @@ int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet,
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
fail_set:
|
fail_set:
|
||||||
lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, *virq);
|
|
||||||
fail_connect:
|
|
||||||
irq_dispose_mapping(*virq);
|
irq_dispose_mapping(*virq);
|
||||||
fail_create:
|
fail_create:
|
||||||
return result;
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
set_irq_chip_data(virq, NULL);
|
||||||
|
irq_dispose_mapping(virq);
|
||||||
|
|
||||||
|
pr_debug("%s:%d <-\n", __func__, __LINE__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ps3_irq_plug_setup - Generic outlet and 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.
|
||||||
|
*
|
||||||
|
* Sets up virq and connects the irq plug.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
|
||||||
|
unsigned int *virq)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
struct ps3_private *pd;
|
||||||
|
|
||||||
|
result = ps3_virq_setup(cpu, outlet, virq);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
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));
|
||||||
|
result = -EPERM;
|
||||||
|
goto fail_connect;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
fail_connect:
|
||||||
|
ps3_virq_destroy(*virq);
|
||||||
|
fail_setup:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(ps3_irq_plug_setup);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
int result;
|
||||||
const struct ps3_private *pd = get_irq_chip_data(virq);
|
const struct ps3_private *pd = get_irq_chip_data(virq);
|
||||||
|
@ -158,72 +230,24 @@ int ps3_free_irq(unsigned int virq)
|
||||||
pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
|
pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
|
||||||
__func__, __LINE__, ps3_result(result));
|
__func__, __LINE__, ps3_result(result));
|
||||||
|
|
||||||
set_irq_chip_data(virq, NULL);
|
ps3_virq_destroy(virq);
|
||||||
irq_dispose_mapping(virq);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ps3_free_irq);
|
EXPORT_SYMBOL_GPL(ps3_irq_plug_destroy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ps3_alloc_io_irq - Assign a virq to a system bus device.
|
* ps3_event_receive_port_setup - Setup an event receive port.
|
||||||
* @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_alloc_io_irq(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_alloc_irq(cpu, outlet, virq);
|
|
||||||
BUG_ON(result);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(ps3_alloc_io_irq);
|
|
||||||
|
|
||||||
int ps3_free_io_irq(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));
|
|
||||||
|
|
||||||
ps3_free_irq(virq);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(ps3_free_io_irq);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ps3_alloc_event_irq - Allocate a virq for use with a system event.
|
|
||||||
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
|
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
|
||||||
* serviced on.
|
* serviced on.
|
||||||
* @virq: The assigned Linux virq.
|
* @virq: The assigned Linux virq.
|
||||||
*
|
*
|
||||||
* The virq can be used with lv1_connect_interrupt_event_receive_port() to
|
* 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
|
* arrange to receive interrupts from system-bus devices, or with
|
||||||
* events.
|
* 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;
|
int result;
|
||||||
unsigned long outlet;
|
unsigned long outlet;
|
||||||
|
@ -237,17 +261,27 @@ int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ps3_alloc_irq(cpu, outlet, virq);
|
result = ps3_irq_plug_setup(cpu, outlet, virq);
|
||||||
BUG_ON(result);
|
BUG_ON(result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(ps3_event_receive_port_setup);
|
||||||
|
|
||||||
int ps3_free_event_irq(unsigned int virq)
|
/**
|
||||||
|
* 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_event_receive_port_destroy(unsigned int virq)
|
||||||
{
|
{
|
||||||
int result;
|
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));
|
result = lv1_destruct_event_receive_port(virq_to_hw(virq));
|
||||||
|
|
||||||
|
@ -255,11 +289,17 @@ int ps3_free_event_irq(unsigned int virq)
|
||||||
pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
|
pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
|
||||||
__func__, __LINE__, ps3_result(result));
|
__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__);
|
pr_debug(" <- %s:%d\n", __func__, __LINE__);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy);
|
||||||
|
|
||||||
int ps3_send_event_locally(unsigned int virq)
|
int ps3_send_event_locally(unsigned int virq)
|
||||||
{
|
{
|
||||||
|
@ -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
|
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
|
||||||
* serviced on.
|
* serviced on.
|
||||||
* @did: The HV device identifier read from the system repository.
|
* @did: The HV device identifier read from the system repository.
|
||||||
|
@ -278,13 +318,15 @@ int ps3_send_event_locally(unsigned int virq)
|
||||||
* coresponds to the software interrupt number.
|
* 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,
|
const struct ps3_device_id *did, unsigned int interrupt_id,
|
||||||
unsigned int *virq)
|
unsigned int *virq)
|
||||||
{
|
{
|
||||||
|
/* this should go in system-bus.c */
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
result = ps3_alloc_event_irq(cpu, virq);
|
result = ps3_event_receive_port_setup(cpu, virq);
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
@ -296,7 +338,7 @@ int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
|
||||||
pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
|
pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
|
||||||
" failed: %s\n", __func__, __LINE__,
|
" failed: %s\n", __func__, __LINE__,
|
||||||
ps3_result(result));
|
ps3_result(result));
|
||||||
ps3_free_event_irq(*virq);
|
ps3_event_receive_port_destroy(*virq);
|
||||||
*virq = NO_IRQ;
|
*virq = NO_IRQ;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -306,10 +348,13 @@ int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
|
||||||
|
|
||||||
return 0;
|
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)
|
unsigned int interrupt_id, unsigned int virq)
|
||||||
{
|
{
|
||||||
|
/* this should go in system-bus.c */
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
|
pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
|
||||||
|
@ -323,14 +368,65 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did,
|
||||||
" failed: %s\n", __func__, __LINE__,
|
" failed: %s\n", __func__, __LINE__,
|
||||||
ps3_result(result));
|
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__);
|
pr_debug(" <- %s:%d\n", __func__, __LINE__);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(ps3_sb_event_receive_port_destroy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ps3_alloc_vuart_irq - Configure the system virtual uart virq.
|
* 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_vuart_irq_setup - Setup the system virtual uart virq.
|
||||||
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
|
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
|
||||||
* serviced on.
|
* serviced on.
|
||||||
* @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap.
|
* @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap.
|
||||||
|
@ -340,7 +436,7 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did,
|
||||||
* freeing the interrupt will return a wrong state error.
|
* 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)
|
unsigned int *virq)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
@ -359,13 +455,13 @@ int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ps3_alloc_irq(cpu, outlet, virq);
|
result = ps3_irq_plug_setup(cpu, outlet, virq);
|
||||||
BUG_ON(result);
|
BUG_ON(result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ps3_free_vuart_irq(unsigned int virq)
|
int ps3_vuart_irq_destroy(unsigned int virq)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
|
@ -377,13 +473,14 @@ int ps3_free_vuart_irq(unsigned int virq)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ps3_free_irq(virq);
|
result = ps3_irq_plug_destroy(virq);
|
||||||
|
BUG_ON(result);
|
||||||
|
|
||||||
return 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
|
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
|
||||||
* serviced on.
|
* serviced on.
|
||||||
* @spe_id: The spe_id returned from lv1_construct_logical_spe().
|
* @spe_id: The spe_id returned from lv1_construct_logical_spe().
|
||||||
|
@ -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)
|
unsigned int class, unsigned int *virq)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
@ -408,15 +505,16 @@ int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ps3_alloc_irq(cpu, outlet, virq);
|
result = ps3_irq_plug_setup(cpu, outlet, virq);
|
||||||
BUG_ON(result);
|
BUG_ON(result);
|
||||||
|
|
||||||
return 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ static void __init ps3_smp_setup_cpu(int cpu)
|
||||||
BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3);
|
BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3);
|
||||||
|
|
||||||
for (i = 0; i < MSG_COUNT; i++) {
|
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)
|
if (result)
|
||||||
continue;
|
continue;
|
||||||
|
@ -134,11 +134,13 @@ void ps3_smp_cleanup_cpu(int cpu)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
|
DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
|
||||||
|
|
||||||
for (i = 0; i < MSG_COUNT; i++) {
|
for (i = 0; i < MSG_COUNT; i++) {
|
||||||
ps3_free_event_irq(virqs[i]);
|
|
||||||
free_irq(virqs[i], (void*)(long)i);
|
free_irq(virqs[i], (void*)(long)i);
|
||||||
|
ps3_event_receive_port_destroy(virqs[i]);
|
||||||
virqs[i] = NO_IRQ;
|
virqs[i] = NO_IRQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
|
DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -230,19 +230,19 @@ static int __init setup_interrupts(struct spu *spu)
|
||||||
{
|
{
|
||||||
int result;
|
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]);
|
0, &spu->irqs[0]);
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
goto fail_alloc_0;
|
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]);
|
1, &spu->irqs[1]);
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
goto fail_alloc_1;
|
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]);
|
2, &spu->irqs[2]);
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
|
@ -251,9 +251,9 @@ static int __init setup_interrupts(struct spu *spu)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
fail_alloc_2:
|
fail_alloc_2:
|
||||||
ps3_free_spe_irq(spu->irqs[1]);
|
ps3_spe_irq_destroy(spu->irqs[1]);
|
||||||
fail_alloc_1:
|
fail_alloc_1:
|
||||||
ps3_free_spe_irq(spu->irqs[0]);
|
ps3_spe_irq_destroy(spu->irqs[0]);
|
||||||
fail_alloc_0:
|
fail_alloc_0:
|
||||||
spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ;
|
spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ;
|
||||||
return result;
|
return result;
|
||||||
|
@ -301,9 +301,9 @@ static int ps3_destroy_spu(struct spu *spu)
|
||||||
result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0);
|
result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0);
|
||||||
BUG_ON(result);
|
BUG_ON(result);
|
||||||
|
|
||||||
ps3_free_spe_irq(spu->irqs[2]);
|
ps3_spe_irq_destroy(spu->irqs[2]);
|
||||||
ps3_free_spe_irq(spu->irqs[1]);
|
ps3_spe_irq_destroy(spu->irqs[1]);
|
||||||
ps3_free_spe_irq(spu->irqs[0]);
|
ps3_spe_irq_destroy(spu->irqs[0]);
|
||||||
|
|
||||||
spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ;
|
spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ;
|
||||||
|
|
||||||
|
|
|
@ -886,12 +886,12 @@ static int ps3_vuart_probe(struct device *_dev)
|
||||||
|
|
||||||
if (++vuart_bus_priv.use_count == 1) {
|
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);
|
(void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
dev_dbg(&dev->core,
|
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);
|
__func__, __LINE__, result);
|
||||||
result = -EPERM;
|
result = -EPERM;
|
||||||
goto fail_alloc_irq;
|
goto fail_alloc_irq;
|
||||||
|
@ -937,7 +937,7 @@ static int ps3_vuart_probe(struct device *_dev)
|
||||||
fail_probe:
|
fail_probe:
|
||||||
ps3_vuart_set_interrupt_mask(dev, 0);
|
ps3_vuart_set_interrupt_mask(dev, 0);
|
||||||
fail_request_irq:
|
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;
|
vuart_bus_priv.virq = NO_IRQ;
|
||||||
fail_alloc_irq:
|
fail_alloc_irq:
|
||||||
--vuart_bus_priv.use_count;
|
--vuart_bus_priv.use_count;
|
||||||
|
@ -975,7 +975,7 @@ static int ps3_vuart_remove(struct device *_dev)
|
||||||
if (--vuart_bus_priv.use_count == 0) {
|
if (--vuart_bus_priv.use_count == 0) {
|
||||||
BUG();
|
BUG();
|
||||||
free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
|
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;
|
vuart_bus_priv.virq = NO_IRQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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__,
|
dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
|
||||||
__LINE__, dev->m_region->lpar_addr);
|
__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) {
|
if (result) {
|
||||||
dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
|
dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
|
||||||
|
@ -162,7 +162,7 @@ fail_add_hcd:
|
||||||
fail_ioremap:
|
fail_ioremap:
|
||||||
usb_put_hcd(hcd);
|
usb_put_hcd(hcd);
|
||||||
fail_create_hcd:
|
fail_create_hcd:
|
||||||
ps3_free_io_irq(virq);
|
ps3_io_irq_destroy(virq);
|
||||||
fail_irq:
|
fail_irq:
|
||||||
ps3_free_mmio_region(dev->m_region);
|
ps3_free_mmio_region(dev->m_region);
|
||||||
fail_mmio:
|
fail_mmio:
|
||||||
|
|
|
@ -107,7 +107,7 @@ static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
|
||||||
dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
|
dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
|
||||||
__LINE__, dev->m_region->lpar_addr);
|
__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) {
|
if (result) {
|
||||||
dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
|
dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
|
||||||
|
@ -165,7 +165,7 @@ fail_add_hcd:
|
||||||
fail_ioremap:
|
fail_ioremap:
|
||||||
usb_put_hcd(hcd);
|
usb_put_hcd(hcd);
|
||||||
fail_create_hcd:
|
fail_create_hcd:
|
||||||
ps3_free_io_irq(virq);
|
ps3_io_irq_destroy(virq);
|
||||||
fail_irq:
|
fail_irq:
|
||||||
ps3_free_mmio_region(dev->m_region);
|
ps3_free_mmio_region(dev->m_region);
|
||||||
fail_mmio:
|
fail_mmio:
|
||||||
|
|
|
@ -885,8 +885,8 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
ps3fb.dev = dev;
|
ps3fb.dev = dev;
|
||||||
error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
|
error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
|
||||||
&ps3fb.irq_no);
|
&ps3fb.irq_no);
|
||||||
if (error) {
|
if (error) {
|
||||||
printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __FUNCTION__,
|
printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __FUNCTION__,
|
||||||
error);
|
error);
|
||||||
|
@ -898,7 +898,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
|
||||||
if (error) {
|
if (error) {
|
||||||
printk(KERN_ERR "%s: request_irq failed %d\n", __FUNCTION__,
|
printk(KERN_ERR "%s: request_irq failed %d\n", __FUNCTION__,
|
||||||
error);
|
error);
|
||||||
ps3_free_irq(ps3fb.irq_no);
|
ps3_irq_plug_destroy(ps3fb.irq_no);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1059,7 +1059,7 @@ err_framebuffer_release:
|
||||||
framebuffer_release(info);
|
framebuffer_release(info);
|
||||||
err_free_irq:
|
err_free_irq:
|
||||||
free_irq(ps3fb.irq_no, ps3fb.dev);
|
free_irq(ps3fb.irq_no, ps3fb.dev);
|
||||||
ps3_free_irq(ps3fb.irq_no);
|
ps3_irq_plug_destroy(ps3fb.irq_no);
|
||||||
err_iounmap_dinfo:
|
err_iounmap_dinfo:
|
||||||
iounmap((u8 __iomem *)ps3fb.dinfo);
|
iounmap((u8 __iomem *)ps3fb.dinfo);
|
||||||
err_gpu_context_free:
|
err_gpu_context_free:
|
||||||
|
@ -1075,7 +1075,7 @@ static void ps3fb_shutdown(struct platform_device *dev)
|
||||||
ps3fb_flip_ctl(0); /* flip off */
|
ps3fb_flip_ctl(0); /* flip off */
|
||||||
ps3fb.dinfo->irq.mask = 0;
|
ps3fb.dinfo->irq.mask = 0;
|
||||||
free_irq(ps3fb.irq_no, ps3fb.dev);
|
free_irq(ps3fb.irq_no, ps3fb.dev);
|
||||||
ps3_free_irq(ps3fb.irq_no);
|
ps3_irq_plug_destroy(ps3fb.irq_no);
|
||||||
iounmap((u8 __iomem *)ps3fb.dinfo);
|
iounmap((u8 __iomem *)ps3fb.dinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1085,7 +1085,7 @@ void ps3fb_cleanup(void)
|
||||||
|
|
||||||
if (ps3fb.irq_no) {
|
if (ps3fb.irq_no) {
|
||||||
free_irq(ps3fb.irq_no, ps3fb.dev);
|
free_irq(ps3fb.irq_no, ps3fb.dev);
|
||||||
ps3_free_irq(ps3fb.irq_no);
|
ps3_irq_plug_destroy(ps3fb.irq_no);
|
||||||
}
|
}
|
||||||
iounmap((u8 __iomem *)ps3fb.dinfo);
|
iounmap((u8 __iomem *)ps3fb.dinfo);
|
||||||
|
|
||||||
|
|
|
@ -167,26 +167,31 @@ enum ps3_cpu_binding {
|
||||||
PS3_BINDING_CPU_1 = 1,
|
PS3_BINDING_CPU_1 = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
int ps3_alloc_io_irq(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
|
int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
|
||||||
unsigned int *virq);
|
unsigned int *virq);
|
||||||
int ps3_free_io_irq(unsigned int virq);
|
int ps3_virq_destroy(unsigned int virq);
|
||||||
int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq);
|
int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
|
||||||
int ps3_free_event_irq(unsigned int virq);
|
unsigned int *virq);
|
||||||
|
int ps3_irq_plug_destroy(unsigned int virq);
|
||||||
|
int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq);
|
||||||
|
int ps3_event_receive_port_destroy(unsigned int virq);
|
||||||
int ps3_send_event_locally(unsigned int virq);
|
int ps3_send_event_locally(unsigned int virq);
|
||||||
int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
|
|
||||||
|
int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
|
||||||
|
unsigned int *virq);
|
||||||
|
int ps3_io_irq_destroy(unsigned int virq);
|
||||||
|
int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
|
||||||
|
unsigned int *virq);
|
||||||
|
int ps3_vuart_irq_destroy(unsigned int virq);
|
||||||
|
int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
|
||||||
|
unsigned int class, unsigned int *virq);
|
||||||
|
int ps3_spe_irq_destroy(unsigned int virq);
|
||||||
|
|
||||||
|
int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
|
||||||
const struct ps3_device_id *did, unsigned int interrupt_id,
|
const struct ps3_device_id *did, unsigned int interrupt_id,
|
||||||
unsigned int *virq);
|
unsigned int *virq);
|
||||||
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);
|
unsigned int interrupt_id, unsigned int virq);
|
||||||
int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
|
|
||||||
unsigned int *virq);
|
|
||||||
int ps3_free_vuart_irq(unsigned int virq);
|
|
||||||
int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id,
|
|
||||||
unsigned int class, unsigned int *virq);
|
|
||||||
int ps3_free_spe_irq(unsigned int virq);
|
|
||||||
int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet,
|
|
||||||
unsigned int *virq);
|
|
||||||
int ps3_free_irq(unsigned int virq);
|
|
||||||
|
|
||||||
/* lv1 result codes */
|
/* lv1 result codes */
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче