Commit 923f92eb authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai

ALSA: firewire-lib: add new function to schedule a work for sound card registration

In former commit, ALSA dice driver postpone sound card registration after
IEEE 1394 bus is calm. This idea has advantages for the other drivers.

This commit adds a helper function for it to firewire-lib module. The
function is really for the specific purpose. Callers should initialize
delayed work structure with callback function.
Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 0eced45c
...@@ -20,8 +20,6 @@ MODULE_LICENSE("GPL v2"); ...@@ -20,8 +20,6 @@ MODULE_LICENSE("GPL v2");
#define WEISS_CATEGORY_ID 0x00 #define WEISS_CATEGORY_ID 0x00
#define LOUD_CATEGORY_ID 0x10 #define LOUD_CATEGORY_ID 0x10
#define PROBE_DELAY_MS (2 * MSEC_PER_SEC)
/* /*
* Some models support several isochronous channels, while these streams are not * Some models support several isochronous channels, while these streams are not
* always available. In this case, add the model name to this list. * 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,27 +233,12 @@ static void do_registration(struct work_struct *work)
error: error:
snd_dice_stream_destroy_duplex(dice); snd_dice_stream_destroy_duplex(dice);
snd_dice_transaction_destroy(dice); snd_dice_transaction_destroy(dice);
snd_dice_stream_destroy_duplex(dice);
snd_card_free(dice->card); snd_card_free(dice->card);
dev_info(&dice->unit->device, dev_info(&dice->unit->device,
"Sound card registration failed: %d\n", err); "Sound card registration failed: %d\n", err);
} }
static void schedule_registration(struct snd_dice *dice)
{
struct fw_card *fw_card = fw_parent_device(dice->unit)->card;
u64 now, delay;
now = get_jiffies_64();
delay = fw_card->reset_jiffies + msecs_to_jiffies(PROBE_DELAY_MS);
if (time_after64(delay, now))
delay -= now;
else
delay = 0;
mod_delayed_work(system_wq, &dice->dwork, delay);
}
static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
{ {
struct snd_dice *dice; struct snd_dice *dice;
...@@ -280,7 +263,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) ...@@ -280,7 +263,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
/* Allocate and register this sound card later. */ /* Allocate and register this sound card later. */
INIT_DEFERRABLE_WORK(&dice->dwork, do_registration); INIT_DEFERRABLE_WORK(&dice->dwork, do_registration);
schedule_registration(dice); snd_fw_schedule_registration(unit, &dice->dwork);
return 0; return 0;
} }
...@@ -311,7 +294,7 @@ static void dice_bus_reset(struct fw_unit *unit) ...@@ -311,7 +294,7 @@ static void dice_bus_reset(struct fw_unit *unit)
/* Postpone a workqueue for deferred registration. */ /* Postpone a workqueue for deferred registration. */
if (!dice->registered) if (!dice->registered)
schedule_registration(dice); snd_fw_schedule_registration(unit, &dice->dwork);
/* The handler address register becomes initialized. */ /* The handler address register becomes initialized. */
snd_dice_transaction_reinit(dice); snd_dice_transaction_reinit(dice);
......
...@@ -67,6 +67,38 @@ int snd_fw_transaction(struct fw_unit *unit, int tcode, ...@@ -67,6 +67,38 @@ int snd_fw_transaction(struct fw_unit *unit, int tcode,
} }
EXPORT_SYMBOL(snd_fw_transaction); EXPORT_SYMBOL(snd_fw_transaction);
#define PROBE_DELAY_MS (2 * MSEC_PER_SEC)
/**
* snd_fw_schedule_registration - schedule work for sound card registration
* @unit: an instance for unit on IEEE 1394 bus
* @dwork: delayed work with callback function
*
* This function is not designed for general purposes. When new unit is
* connected to IEEE 1394 bus, the bus is under bus-reset state because of
* topological change. In this state, units tend to fail both of asynchronous
* and isochronous communication. To avoid this problem, this function is used
* to postpone sound card registration after the state. The callers must
* set up instance of delayed work in advance.
*/
void snd_fw_schedule_registration(struct fw_unit *unit,
struct delayed_work *dwork)
{
u64 now, delay;
now = get_jiffies_64();
delay = fw_parent_device(unit)->card->reset_jiffies
+ msecs_to_jiffies(PROBE_DELAY_MS);
if (time_after64(delay, now))
delay -= now;
else
delay = 0;
mod_delayed_work(system_wq, dwork, delay);
}
EXPORT_SYMBOL(snd_fw_schedule_registration);
static void async_midi_port_callback(struct fw_card *card, int rcode, static void async_midi_port_callback(struct fw_card *card, int rcode,
void *data, size_t length, void *data, size_t length,
void *callback_data) void *callback_data)
......
...@@ -22,6 +22,9 @@ static inline bool rcode_is_permanent_error(int rcode) ...@@ -22,6 +22,9 @@ static inline bool rcode_is_permanent_error(int rcode)
return rcode == RCODE_TYPE_ERROR || rcode == RCODE_ADDRESS_ERROR; return rcode == RCODE_TYPE_ERROR || rcode == RCODE_ADDRESS_ERROR;
} }
void snd_fw_schedule_registration(struct fw_unit *unit,
struct delayed_work *dwork);
struct snd_fw_async_midi_port; struct snd_fw_async_midi_port;
typedef int (*snd_fw_async_midi_port_fill)( typedef int (*snd_fw_async_midi_port_fill)(
struct snd_rawmidi_substream *substream, struct snd_rawmidi_substream *substream,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment