summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/firewire/dice/dice.c23
-rw-r--r--sound/firewire/lib.c32
-rw-r--r--sound/firewire/lib.h3
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)
235error: 233error:
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
243static 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
259static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) 242static 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}
68EXPORT_SYMBOL(snd_fw_transaction); 68EXPORT_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 */
84void 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}
100EXPORT_SYMBOL(snd_fw_schedule_registration);
101
70static void async_midi_port_callback(struct fw_card *card, int rcode, 102static 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
25void snd_fw_schedule_registration(struct fw_unit *unit,
26 struct delayed_work *dwork);
27
25struct snd_fw_async_midi_port; 28struct snd_fw_async_midi_port;
26typedef int (*snd_fw_async_midi_port_fill)( 29typedef int (*snd_fw_async_midi_port_fill)(
27 struct snd_rawmidi_substream *substream, 30 struct snd_rawmidi_substream *substream,