summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/firewire/digi00x/digi00x-transaction.c7
-rw-r--r--sound/firewire/digi00x/digi00x.c107
-rw-r--r--sound/firewire/digi00x/digi00x.h3
3 files changed, 85 insertions, 32 deletions
diff --git a/sound/firewire/digi00x/digi00x-transaction.c b/sound/firewire/digi00x/digi00x-transaction.c
index 554324d8c602..735d35640807 100644
--- a/sound/firewire/digi00x/digi00x-transaction.c
+++ b/sound/firewire/digi00x/digi00x-transaction.c
@@ -126,12 +126,17 @@ int snd_dg00x_transaction_register(struct snd_dg00x *dg00x)
126 return err; 126 return err;
127error: 127error:
128 fw_core_remove_address_handler(&dg00x->async_handler); 128 fw_core_remove_address_handler(&dg00x->async_handler);
129 dg00x->async_handler.address_callback = NULL; 129 dg00x->async_handler.callback_data = NULL;
130 return err; 130 return err;
131} 131}
132 132
133void snd_dg00x_transaction_unregister(struct snd_dg00x *dg00x) 133void snd_dg00x_transaction_unregister(struct snd_dg00x *dg00x)
134{ 134{
135 if (dg00x->async_handler.callback_data == NULL)
136 return;
137
135 snd_fw_async_midi_port_destroy(&dg00x->out_control); 138 snd_fw_async_midi_port_destroy(&dg00x->out_control);
136 fw_core_remove_address_handler(&dg00x->async_handler); 139 fw_core_remove_address_handler(&dg00x->async_handler);
140
141 dg00x->async_handler.callback_data = NULL;
137} 142}
diff --git a/sound/firewire/digi00x/digi00x.c b/sound/firewire/digi00x/digi00x.c
index 1f33b7a1fca4..cc4776c6ded3 100644
--- a/sound/firewire/digi00x/digi00x.c
+++ b/sound/firewire/digi00x/digi00x.c
@@ -40,10 +40,8 @@ static int name_card(struct snd_dg00x *dg00x)
40 return 0; 40 return 0;
41} 41}
42 42
43static void dg00x_card_free(struct snd_card *card) 43static void dg00x_free(struct snd_dg00x *dg00x)
44{ 44{
45 struct snd_dg00x *dg00x = card->private_data;
46
47 snd_dg00x_stream_destroy_duplex(dg00x); 45 snd_dg00x_stream_destroy_duplex(dg00x);
48 snd_dg00x_transaction_unregister(dg00x); 46 snd_dg00x_transaction_unregister(dg00x);
49 47
@@ -52,28 +50,24 @@ static void dg00x_card_free(struct snd_card *card)
52 mutex_destroy(&dg00x->mutex); 50 mutex_destroy(&dg00x->mutex);
53} 51}
54 52
55static int snd_dg00x_probe(struct fw_unit *unit, 53static void dg00x_card_free(struct snd_card *card)
56 const struct ieee1394_device_id *entry)
57{ 54{
58 struct snd_card *card; 55 dg00x_free(card->private_data);
59 struct snd_dg00x *dg00x; 56}
60 int err;
61 57
62 /* create card */ 58static void do_registration(struct work_struct *work)
63 err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, 59{
64 sizeof(struct snd_dg00x), &card); 60 struct snd_dg00x *dg00x =
65 if (err < 0) 61 container_of(work, struct snd_dg00x, dwork.work);
66 return err; 62 int err;
67 card->private_free = dg00x_card_free;
68 63
69 /* initialize myself */ 64 if (dg00x->registered)
70 dg00x = card->private_data; 65 return;
71 dg00x->card = card;
72 dg00x->unit = fw_unit_get(unit);
73 66
74 mutex_init(&dg00x->mutex); 67 err = snd_card_new(&dg00x->unit->device, -1, NULL, THIS_MODULE, 0,
75 spin_lock_init(&dg00x->lock); 68 &dg00x->card);
76 init_waitqueue_head(&dg00x->hwdep_wait); 69 if (err < 0)
70 return;
77 71
78 err = name_card(dg00x); 72 err = name_card(dg00x);
79 if (err < 0) 73 if (err < 0)
@@ -101,35 +95,86 @@ static int snd_dg00x_probe(struct fw_unit *unit,
101 if (err < 0) 95 if (err < 0)
102 goto error; 96 goto error;
103 97
104 err = snd_card_register(card); 98 err = snd_card_register(dg00x->card);
105 if (err < 0) 99 if (err < 0)
106 goto error; 100 goto error;
107 101
108 dev_set_drvdata(&unit->device, dg00x); 102 dg00x->card->private_free = dg00x_card_free;
103 dg00x->card->private_data = dg00x;
104 dg00x->registered = true;
109 105
110 return err; 106 return;
111error: 107error:
112 snd_card_free(card); 108 snd_dg00x_transaction_unregister(dg00x);
113 return err; 109 snd_dg00x_stream_destroy_duplex(dg00x);
110 snd_card_free(dg00x->card);
111 dev_info(&dg00x->unit->device,
112 "Sound card registration failed: %d\n", err);
113}
114
115static int snd_dg00x_probe(struct fw_unit *unit,
116 const struct ieee1394_device_id *entry)
117{
118 struct snd_dg00x *dg00x;
119
120 /* Allocate this independent of sound card instance. */
121 dg00x = kzalloc(sizeof(struct snd_dg00x), GFP_KERNEL);
122 if (dg00x == NULL)
123 return -ENOMEM;
124
125 dg00x->unit = fw_unit_get(unit);
126 dev_set_drvdata(&unit->device, dg00x);
127
128 mutex_init(&dg00x->mutex);
129 spin_lock_init(&dg00x->lock);
130 init_waitqueue_head(&dg00x->hwdep_wait);
131
132 /* Allocate and register this sound card later. */
133 INIT_DEFERRABLE_WORK(&dg00x->dwork, do_registration);
134 snd_fw_schedule_registration(unit, &dg00x->dwork);
135
136 return 0;
114} 137}
115 138
116static void snd_dg00x_update(struct fw_unit *unit) 139static void snd_dg00x_update(struct fw_unit *unit)
117{ 140{
118 struct snd_dg00x *dg00x = dev_get_drvdata(&unit->device); 141 struct snd_dg00x *dg00x = dev_get_drvdata(&unit->device);
119 142
143 /* Postpone a workqueue for deferred registration. */
144 if (!dg00x->registered)
145 snd_fw_schedule_registration(unit, &dg00x->dwork);
146
120 snd_dg00x_transaction_reregister(dg00x); 147 snd_dg00x_transaction_reregister(dg00x);
121 148
122 mutex_lock(&dg00x->mutex); 149 /*
123 snd_dg00x_stream_update_duplex(dg00x); 150 * After registration, userspace can start packet streaming, then this
124 mutex_unlock(&dg00x->mutex); 151 * code block works fine.
152 */
153 if (dg00x->registered) {
154 mutex_lock(&dg00x->mutex);
155 snd_dg00x_stream_update_duplex(dg00x);
156 mutex_unlock(&dg00x->mutex);
157 }
125} 158}
126 159
127static void snd_dg00x_remove(struct fw_unit *unit) 160static void snd_dg00x_remove(struct fw_unit *unit)
128{ 161{
129 struct snd_dg00x *dg00x = dev_get_drvdata(&unit->device); 162 struct snd_dg00x *dg00x = dev_get_drvdata(&unit->device);
130 163
131 /* No need to wait for releasing card object in this context. */ 164 /*
132 snd_card_free_when_closed(dg00x->card); 165 * Confirm to stop the work for registration before the sound card is
166 * going to be released. The work is not scheduled again because bus
167 * reset handler is not called anymore.
168 */
169 cancel_delayed_work_sync(&dg00x->dwork);
170
171 if (dg00x->registered) {
172 /* No need to wait for releasing card object in this context. */
173 snd_card_free_when_closed(dg00x->card);
174 } else {
175 /* Don't forget this case. */
176 dg00x_free(dg00x);
177 }
133} 178}
134 179
135static const struct ieee1394_device_id snd_dg00x_id_table[] = { 180static const struct ieee1394_device_id snd_dg00x_id_table[] = {
diff --git a/sound/firewire/digi00x/digi00x.h b/sound/firewire/digi00x/digi00x.h
index 907e73993677..2cd465c0caae 100644
--- a/sound/firewire/digi00x/digi00x.h
+++ b/sound/firewire/digi00x/digi00x.h
@@ -37,6 +37,9 @@ struct snd_dg00x {
37 struct mutex mutex; 37 struct mutex mutex;
38 spinlock_t lock; 38 spinlock_t lock;
39 39
40 bool registered;
41 struct delayed_work dwork;
42
40 struct amdtp_stream tx_stream; 43 struct amdtp_stream tx_stream;
41 struct fw_iso_resources tx_resources; 44 struct fw_iso_resources tx_resources;
42 45