diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2008-05-24 16:50:22 +0200 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2008-07-14 13:06:03 +0200 |
commit | 459f79235d8faa0050180c7e0c7bb4b2b52cbdfd (patch) | |
tree | 97847b1b06ded6c136cdba73bc961a46a3e39a30 /drivers/firewire/fw-card.c | |
parent | 2147ef204f57191e0fff6d5d3d1a0336afa6cfae (diff) |
firewire: clean up fw_card reference counting
This is a functionally equivalent replacement of the current reference
counting of struct fw_card instances. It only converts it to common
idioms as suggested by Kristian Høgsberg:
- struct kref replaces atomic_t as the counter.
- wait_for_completion is used to wait for all card users to complete.
BTW, it may make sense to count card->flush_timer and card->work as
card users too.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/fw-card.c')
-rw-r--r-- | drivers/firewire/fw-card.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 1332b66ae0b3..da873d795aad 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -16,12 +16,15 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <linux/module.h> -#include <linux/errno.h> +#include <linux/completion.h> +#include <linux/crc-itu-t.h> #include <linux/delay.h> #include <linux/device.h> +#include <linux/errno.h> +#include <linux/kref.h> +#include <linux/module.h> #include <linux/mutex.h> -#include <linux/crc-itu-t.h> + #include "fw-transaction.h" #include "fw-topology.h" #include "fw-device.h" @@ -396,7 +399,6 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, { static atomic_t index = ATOMIC_INIT(-1); - atomic_set(&card->device_count, 0); card->index = atomic_inc_return(&index); card->driver = driver; card->device = device; @@ -405,6 +407,8 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, card->color = 0; card->broadcast_channel = BROADCAST_CHANNEL_INITIAL; + kref_init(&card->kref); + init_completion(&card->done); INIT_LIST_HEAD(&card->transaction_list); spin_lock_init(&card->lock); setup_timer(&card->flush_timer, @@ -507,6 +511,14 @@ static struct fw_card_driver dummy_driver = { }; void +fw_card_release(struct kref *kref) +{ + struct fw_card *card = container_of(kref, struct fw_card, kref); + + complete(&card->done); +} + +void fw_core_remove_card(struct fw_card *card) { card->driver->update_phy_reg(card, 4, @@ -521,12 +533,10 @@ fw_core_remove_card(struct fw_card *card) card->driver = &dummy_driver; fw_destroy_nodes(card); - /* - * Wait for all device workqueue jobs to finish. Otherwise the - * firewire-core module could be unloaded before the jobs ran. - */ - while (atomic_read(&card->device_count) > 0) - msleep(100); + + /* Wait for all users, especially device workqueue jobs, to finish. */ + fw_card_put(card); + wait_for_completion(&card->done); cancel_delayed_work_sync(&card->work); fw_flush_transactions(card); |