summaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-card.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire/fw-card.c')
-rw-r--r--drivers/firewire/fw-card.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index 5b4c0d9f517..da873d795aa 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,14 +399,16 @@ 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;
card->current_tlabel = 0;
card->tlabel_mask = 0;
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,
@@ -496,7 +501,6 @@ dummy_enable_phys_dma(struct fw_card *card,
}
static struct fw_card_driver dummy_driver = {
- .name = "dummy",
.enable = dummy_enable,
.update_phy_reg = dummy_update_phy_reg,
.set_config_rom = dummy_set_config_rom,
@@ -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);