X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=arch%2Fpowerpc%2Fplatforms%2Fpowermac%2Fpfunc_core.c;h=b117adbf957182251da8c1a5b4701ddc844879e8;hb=ba290ab7dace8b3339c0cc86c221d48eed21e956;hp=4baa75b1d36ff60a7cb9088a7e6ffa5d10301e0f;hpb=74293759002aa7db0179158c20676a034614577b;p=pandora-kernel.git diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index 4baa75b1d36f..b117adbf9571 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c @@ -5,12 +5,12 @@ * FIXME: LOCKING !!! */ -#include #include #include #include #include #include +#include #include #include @@ -545,7 +545,8 @@ struct pmf_device { }; static LIST_HEAD(pmf_devices); -static spinlock_t pmf_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(pmf_lock); +static DEFINE_MUTEX(pmf_irq_mutex); static void pmf_release_device(struct kref *kref) { @@ -864,16 +865,25 @@ int pmf_register_irq_client(struct device_node *target, spin_lock_irqsave(&pmf_lock, flags); func = __pmf_find_function(target, name, PMF_FLAGS_INT_GEN); - if (func == NULL) { - spin_unlock_irqrestore(&pmf_lock, flags); + if (func) + func = pmf_get_function(func); + spin_unlock_irqrestore(&pmf_lock, flags); + if (func == NULL) return -ENODEV; - } + + /* guard against manipulations of list */ + mutex_lock(&pmf_irq_mutex); if (list_empty(&func->irq_clients)) func->dev->handlers->irq_enable(func); + + /* guard against pmf_do_irq while changing list */ + spin_lock_irqsave(&pmf_lock, flags); list_add(&client->link, &func->irq_clients); - client->func = func; spin_unlock_irqrestore(&pmf_lock, flags); + client->func = func; + mutex_unlock(&pmf_irq_mutex); + return 0; } EXPORT_SYMBOL_GPL(pmf_register_irq_client); @@ -885,12 +895,19 @@ void pmf_unregister_irq_client(struct pmf_irq_client *client) BUG_ON(func == NULL); - spin_lock_irqsave(&pmf_lock, flags); + /* guard against manipulations of list */ + mutex_lock(&pmf_irq_mutex); client->func = NULL; + + /* guard against pmf_do_irq while changing list */ + spin_lock_irqsave(&pmf_lock, flags); list_del(&client->link); + spin_unlock_irqrestore(&pmf_lock, flags); + if (list_empty(&func->irq_clients)) func->dev->handlers->irq_disable(func); - spin_unlock_irqrestore(&pmf_lock, flags); + mutex_unlock(&pmf_irq_mutex); + pmf_put_function(func); } EXPORT_SYMBOL_GPL(pmf_unregister_irq_client);