diff options
-rw-r--r-- | sound/firewire/dice/dice.c | 23 | ||||
-rw-r--r-- | sound/firewire/lib.c | 32 | ||||
-rw-r--r-- | sound/firewire/lib.h | 3 |
3 files changed, 38 insertions, 20 deletions
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 53ca441ea9b9..96fe68f42e5d 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c | |||
@@ -20,8 +20,6 @@ MODULE_LICENSE("GPL v2"); | |||
20 | #define WEISS_CATEGORY_ID 0x00 | 20 | #define WEISS_CATEGORY_ID 0x00 |
21 | #define LOUD_CATEGORY_ID 0x10 | 21 | #define LOUD_CATEGORY_ID 0x10 |
22 | 22 | ||
23 | #define PROBE_DELAY_MS (2 * MSEC_PER_SEC) | ||
24 | |||
25 | /* | 23 | /* |
26 | * Some models support several isochronous channels, while these streams are not | 24 | * Some models support several isochronous channels, while these streams are not |
27 | * always available. In this case, add the model name to this list. | 25 | * always available. In this case, add the model name to this list. |
@@ -235,27 +233,12 @@ static void do_registration(struct work_struct *work) | |||
235 | error: | 233 | error: |
236 | snd_dice_stream_destroy_duplex(dice); | 234 | snd_dice_stream_destroy_duplex(dice); |
237 | snd_dice_transaction_destroy(dice); | 235 | snd_dice_transaction_destroy(dice); |
236 | snd_dice_stream_destroy_duplex(dice); | ||
238 | snd_card_free(dice->card); | 237 | snd_card_free(dice->card); |
239 | dev_info(&dice->unit->device, | 238 | dev_info(&dice->unit->device, |
240 | "Sound card registration failed: %d\n", err); | 239 | "Sound card registration failed: %d\n", err); |
241 | } | 240 | } |
242 | 241 | ||
243 | static void schedule_registration(struct snd_dice *dice) | ||
244 | { | ||
245 | struct fw_card *fw_card = fw_parent_device(dice->unit)->card; | ||
246 | u64 now, delay; | ||
247 | |||
248 | now = get_jiffies_64(); | ||
249 | delay = fw_card->reset_jiffies + msecs_to_jiffies(PROBE_DELAY_MS); | ||
250 | |||
251 | if (time_after64(delay, now)) | ||
252 | delay -= now; | ||
253 | else | ||
254 | delay = 0; | ||
255 | |||
256 | mod_delayed_work(system_wq, &dice->dwork, delay); | ||
257 | } | ||
258 | |||
259 | static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) | 242 | static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) |
260 | { | 243 | { |
261 | struct snd_dice *dice; | 244 | struct snd_dice *dice; |
@@ -280,7 +263,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) | |||
280 | 263 | ||
281 | /* Allocate and register this sound card later. */ | 264 | /* Allocate and register this sound card later. */ |
282 | INIT_DEFERRABLE_WORK(&dice->dwork, do_registration); | 265 | INIT_DEFERRABLE_WORK(&dice->dwork, do_registration); |
283 | schedule_registration(dice); | 266 | snd_fw_schedule_registration(unit, &dice->dwork); |
284 | 267 | ||
285 | return 0; | 268 | return 0; |
286 | } | 269 | } |
@@ -311,7 +294,7 @@ static void dice_bus_reset(struct fw_unit *unit) | |||
311 | 294 | ||
312 | /* Postpone a workqueue for deferred registration. */ | 295 | /* Postpone a workqueue for deferred registration. */ |
313 | if (!dice->registered) | 296 | if (!dice->registered) |
314 | schedule_registration(dice); | 297 | snd_fw_schedule_registration(unit, &dice->dwork); |
315 | 298 | ||
316 | /* The handler address register becomes initialized. */ | 299 | /* The handler address register becomes initialized. */ |
317 | snd_dice_transaction_reinit(dice); | 300 | snd_dice_transaction_reinit(dice); |
diff --git a/sound/firewire/lib.c b/sound/firewire/lib.c index f80aafa44c89..ca4dfcf43175 100644 --- a/sound/firewire/lib.c +++ b/sound/firewire/lib.c | |||
@@ -67,6 +67,38 @@ int snd_fw_transaction(struct fw_unit *unit, int tcode, | |||
67 | } | 67 | } |
68 | EXPORT_SYMBOL(snd_fw_transaction); | 68 | EXPORT_SYMBOL(snd_fw_transaction); |
69 | 69 | ||
70 | #define PROBE_DELAY_MS (2 * MSEC_PER_SEC) | ||
71 | |||
72 | /** | ||
73 | * snd_fw_schedule_registration - schedule work for sound card registration | ||
74 | * @unit: an instance for unit on IEEE 1394 bus | ||
75 | * @dwork: delayed work with callback function | ||
76 | * | ||
77 | * This function is not designed for general purposes. When new unit is | ||
78 | * connected to IEEE 1394 bus, the bus is under bus-reset state because of | ||
79 | * topological change. In this state, units tend to fail both of asynchronous | ||
80 | * and isochronous communication. To avoid this problem, this function is used | ||
81 | * to postpone sound card registration after the state. The callers must | ||
82 | * set up instance of delayed work in advance. | ||
83 | */ | ||
84 | void snd_fw_schedule_registration(struct fw_unit *unit, | ||
85 | struct delayed_work *dwork) | ||
86 | { | ||
87 | u64 now, delay; | ||
88 | |||
89 | now = get_jiffies_64(); | ||
90 | delay = fw_parent_device(unit)->card->reset_jiffies | ||
91 | + msecs_to_jiffies(PROBE_DELAY_MS); | ||
92 | |||
93 | if (time_after64(delay, now)) | ||
94 | delay -= now; | ||
95 | else | ||
96 | delay = 0; | ||
97 | |||
98 | mod_delayed_work(system_wq, dwork, delay); | ||
99 | } | ||
100 | EXPORT_SYMBOL(snd_fw_schedule_registration); | ||
101 | |||
70 | static void async_midi_port_callback(struct fw_card *card, int rcode, | 102 | static void async_midi_port_callback(struct fw_card *card, int rcode, |
71 | void *data, size_t length, | 103 | void *data, size_t length, |
72 | void *callback_data) | 104 | void *callback_data) |
diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h index f3f6f84c48d6..f6769312ebfc 100644 --- a/sound/firewire/lib.h +++ b/sound/firewire/lib.h | |||
@@ -22,6 +22,9 @@ static inline bool rcode_is_permanent_error(int rcode) | |||
22 | return rcode == RCODE_TYPE_ERROR || rcode == RCODE_ADDRESS_ERROR; | 22 | return rcode == RCODE_TYPE_ERROR || rcode == RCODE_ADDRESS_ERROR; |
23 | } | 23 | } |
24 | 24 | ||
25 | void snd_fw_schedule_registration(struct fw_unit *unit, | ||
26 | struct delayed_work *dwork); | ||
27 | |||
25 | struct snd_fw_async_midi_port; | 28 | struct snd_fw_async_midi_port; |
26 | typedef int (*snd_fw_async_midi_port_fill)( | 29 | typedef int (*snd_fw_async_midi_port_fill)( |
27 | struct snd_rawmidi_substream *substream, | 30 | struct snd_rawmidi_substream *substream, |