[alsa-devel] [PATCH 0/5 v4] ALSA: dice: improve card registration processing
Hi,
This patchset updates my previous one:
[alsa-devel] [PATCH 0/5 v3] ALSA: dice: improve card registration processing http://mailman.alsa-project.org/pipermail/alsa-devel/2015-December/102501.ht...
The patch 02 included a bug of missing 'end' tag. This v4 patchset includes fixes of the bug.
Additionally, this patchset adds to output information message when registration work encounters any errors.
Furthermore, I use mod_delayed_work() to queue and postpone work for sound card registration. I've reported system freeze in previous patchset, but I had a mistake not to use any actual workqueus as a first argument of the function.
Takashi Sakamoto (5): ALSA: dice: split subaddress check from category check ALSA: dice: postpone card registration ALSA: dice: ensure to release sound devices after sound card registration fails ALSA: dice: purge transaction initialization at timeout of Dice notification ALSA: dice: expand timeout to wait for Dice notification
sound/firewire/dice/dice-midi.c | 2 + sound/firewire/dice/dice-pcm.c | 2 + sound/firewire/dice/dice-transaction.c | 122 ++++++++++++-------- sound/firewire/dice/dice.c | 197 +++++++++++++++++---------------- sound/firewire/dice/dice.h | 5 + 5 files changed, 189 insertions(+), 139 deletions(-)
Before allocating an instance of sound card, ALSA dice driver checks chip_ID_hi in Bus information block of Config ROM, then also checks subaddresses. The former operation reads cache of Config ROM in Linux FireWire subsystem, while the latter operation sends read transaction. The latter can be merged into initialization of transaction system.
This commit splits these two operations to reduce needless transactions in probe processing.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/dice/dice-transaction.c | 89 ++++++++++++++++++++++++++-------- sound/firewire/dice/dice.c | 72 +++------------------------ 2 files changed, 77 insertions(+), 84 deletions(-)
diff --git a/sound/firewire/dice/dice-transaction.c b/sound/firewire/dice/dice-transaction.c index aee7461..75a2125 100644 --- a/sound/firewire/dice/dice-transaction.c +++ b/sound/firewire/dice/dice-transaction.c @@ -331,39 +331,59 @@ int snd_dice_transaction_reinit(struct snd_dice *dice) return register_notification_address(dice, false); }
-int snd_dice_transaction_init(struct snd_dice *dice) +static int get_subaddrs(struct snd_dice *dice) { - struct fw_address_handler *handler = &dice->notification_handler; + static const int min_values[10] = { + 10, 0x64 / 4, + 10, 0x18 / 4, + 10, 0x18 / 4, + 0, 0, + 0, 0, + }; __be32 *pointers; + u32 data; + unsigned int i; int err;
- /* Use the same way which dice_interface_check() does. */ - pointers = kmalloc(sizeof(__be32) * 10, GFP_KERNEL); + pointers = kmalloc_array(ARRAY_SIZE(min_values), sizeof(__be32), + GFP_KERNEL); if (pointers == NULL) return -ENOMEM;
- /* Get offsets for sub-addresses */ + /* + * Check that the sub address spaces exist and are located inside the + * private address space. The minimum values are chosen so that all + * minimally required registers are included. + */ err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, - DICE_PRIVATE_SPACE, - pointers, sizeof(__be32) * 10, 0); + DICE_PRIVATE_SPACE, pointers, + sizeof(__be32) * ARRAY_SIZE(min_values), 0); if (err < 0) goto end;
- /* Allocation callback in address space over host controller */ - handler->length = 4; - handler->address_callback = dice_notification; - handler->callback_data = dice; - err = fw_core_add_address_handler(handler, &fw_high_memory_region); - if (err < 0) { - handler->callback_data = NULL; - goto end; + for (i = 0; i < ARRAY_SIZE(min_values); ++i) { + data = be32_to_cpu(pointers[i]); + if (data < min_values[i] || data >= 0x40000) { + err = -ENODEV; + goto end; + } }
- /* Register the address space */ - err = register_notification_address(dice, true); - if (err < 0) { - fw_core_remove_address_handler(handler); - handler->callback_data = NULL; + /* + * Check that the implemented DICE driver specification major version + * number matches. + */ + err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST, + DICE_PRIVATE_SPACE + + be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION, + &data, sizeof(data), 0); + if (err < 0) + goto end; + + if ((data & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) { + dev_err(&dice->unit->device, + "unknown DICE version: 0x%08x\n", be32_to_cpu(data)); + err = -ENODEV; goto end; }
@@ -380,3 +400,32 @@ end: kfree(pointers); return err; } + +int snd_dice_transaction_init(struct snd_dice *dice) +{ + struct fw_address_handler *handler = &dice->notification_handler; + int err; + + err = get_subaddrs(dice); + if (err < 0) + return err; + + /* Allocation callback in address space over host controller */ + handler->length = 4; + handler->address_callback = dice_notification; + handler->callback_data = dice; + err = fw_core_add_address_handler(handler, &fw_high_memory_region); + if (err < 0) { + handler->callback_data = NULL; + return err; + } + + /* Register the address space */ + err = register_notification_address(dice, true); + if (err < 0) { + fw_core_remove_address_handler(handler); + handler->callback_data = NULL; + } + + return err; +} diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 0cda05c..26271cc 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -18,27 +18,12 @@ MODULE_LICENSE("GPL v2"); #define WEISS_CATEGORY_ID 0x00 #define LOUD_CATEGORY_ID 0x10
-static int dice_interface_check(struct fw_unit *unit) +static int check_dice_category(struct fw_unit *unit) { - static const int min_values[10] = { - 10, 0x64 / 4, - 10, 0x18 / 4, - 10, 0x18 / 4, - 0, 0, - 0, 0, - }; struct fw_device *device = fw_parent_device(unit); struct fw_csr_iterator it; - int key, val, vendor = -1, model = -1, err; - unsigned int category, i; - __be32 *pointers; - u32 value; - __be32 version; - - pointers = kmalloc_array(ARRAY_SIZE(min_values), sizeof(__be32), - GFP_KERNEL); - if (pointers == NULL) - return -ENOMEM; + int key, val, vendor = -1, model = -1; + unsigned int category;
/* * Check that GUID and unit directory are constructed according to DICE @@ -64,51 +49,10 @@ static int dice_interface_check(struct fw_unit *unit) else category = DICE_CATEGORY_ID; if (device->config_rom[3] != ((vendor << 8) | category) || - device->config_rom[4] >> 22 != model) { - err = -ENODEV; - goto end; - } - - /* - * Check that the sub address spaces exist and are located inside the - * private address space. The minimum values are chosen so that all - * minimally required registers are included. - */ - err = snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST, - DICE_PRIVATE_SPACE, pointers, - sizeof(__be32) * ARRAY_SIZE(min_values), 0); - if (err < 0) { - err = -ENODEV; - goto end; - } - for (i = 0; i < ARRAY_SIZE(min_values); ++i) { - value = be32_to_cpu(pointers[i]); - if (value < min_values[i] || value >= 0x40000) { - err = -ENODEV; - goto end; - } - } + device->config_rom[4] >> 22 != model) + return -ENODEV;
- /* - * Check that the implemented DICE driver specification major version - * number matches. - */ - err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, - DICE_PRIVATE_SPACE + - be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION, - &version, 4, 0); - if (err < 0) { - err = -ENODEV; - goto end; - } - if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) { - dev_err(&unit->device, - "unknown DICE version: 0x%08x\n", be32_to_cpu(version)); - err = -ENODEV; - goto end; - } -end: - return err; + return 0; }
static int highest_supported_mode_rate(struct snd_dice *dice, @@ -254,9 +198,9 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) struct snd_dice *dice; int err;
- err = dice_interface_check(unit); + err = check_dice_category(unit); if (err < 0) - goto end; + return -ENODEV;
err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*dice), &card);
On Sat, 26 Dec 2015 04:35:22 +0100, Takashi Sakamoto wrote:
Before allocating an instance of sound card, ALSA dice driver checks chip_ID_hi in Bus information block of Config ROM, then also checks subaddresses. The former operation reads cache of Config ROM in Linux FireWire subsystem, while the latter operation sends read transaction. The latter can be merged into initialization of transaction system.
This commit splits these two operations to reduce needless transactions in probe processing.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp
sound/firewire/dice/dice-transaction.c | 89 ++++++++++++++++++++++++++-------- sound/firewire/dice/dice.c | 72 +++------------------------ 2 files changed, 77 insertions(+), 84 deletions(-)
diff --git a/sound/firewire/dice/dice-transaction.c b/sound/firewire/dice/dice-transaction.c index aee7461..75a2125 100644 --- a/sound/firewire/dice/dice-transaction.c +++ b/sound/firewire/dice/dice-transaction.c @@ -331,39 +331,59 @@ int snd_dice_transaction_reinit(struct snd_dice *dice) return register_notification_address(dice, false); }
-int snd_dice_transaction_init(struct snd_dice *dice) +static int get_subaddrs(struct snd_dice *dice) {
- struct fw_address_handler *handler = &dice->notification_handler;
- static const int min_values[10] = {
10, 0x64 / 4,
10, 0x18 / 4,
10, 0x18 / 4,
0, 0,
0, 0,
- }; __be32 *pointers;
- u32 data;
- unsigned int i; int err;
- /* Use the same way which dice_interface_check() does. */
- pointers = kmalloc(sizeof(__be32) * 10, GFP_KERNEL);
- pointers = kmalloc_array(ARRAY_SIZE(min_values), sizeof(__be32),
if (pointers == NULL) return -ENOMEM;GFP_KERNEL);
- /* Get offsets for sub-addresses */
- /*
* Check that the sub address spaces exist and are located inside the
* private address space. The minimum values are chosen so that all
* minimally required registers are included.
err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,*/
DICE_PRIVATE_SPACE,
pointers, sizeof(__be32) * 10, 0);
DICE_PRIVATE_SPACE, pointers,
if (err < 0) goto end;sizeof(__be32) * ARRAY_SIZE(min_values), 0);
- /* Allocation callback in address space over host controller */
- handler->length = 4;
- handler->address_callback = dice_notification;
- handler->callback_data = dice;
- err = fw_core_add_address_handler(handler, &fw_high_memory_region);
- if (err < 0) {
handler->callback_data = NULL;
goto end;
- for (i = 0; i < ARRAY_SIZE(min_values); ++i) {
data = be32_to_cpu(pointers[i]);
if (data < min_values[i] || data >= 0x40000) {
err = -ENODEV;
goto end;
}}
- /* Register the address space */
- err = register_notification_address(dice, true);
- if (err < 0) {
fw_core_remove_address_handler(handler);
handler->callback_data = NULL;
- /*
* Check that the implemented DICE driver specification major version
* number matches.
*/
- err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
DICE_PRIVATE_SPACE +
be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
&data, sizeof(data), 0);
It's confusing to reuse a single variable as both u32 and be32. Use the specific variable like the original code instead.
thanks,
Takashi
- if (err < 0)
goto end;
- if ((data & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) {
dev_err(&dice->unit->device,
"unknown DICE version: 0x%08x\n", be32_to_cpu(data));
goto end; }err = -ENODEV;
@@ -380,3 +400,32 @@ end: kfree(pointers); return err; }
+int snd_dice_transaction_init(struct snd_dice *dice) +{
- struct fw_address_handler *handler = &dice->notification_handler;
- int err;
- err = get_subaddrs(dice);
- if (err < 0)
return err;
- /* Allocation callback in address space over host controller */
- handler->length = 4;
- handler->address_callback = dice_notification;
- handler->callback_data = dice;
- err = fw_core_add_address_handler(handler, &fw_high_memory_region);
- if (err < 0) {
handler->callback_data = NULL;
return err;
- }
- /* Register the address space */
- err = register_notification_address(dice, true);
- if (err < 0) {
fw_core_remove_address_handler(handler);
handler->callback_data = NULL;
- }
- return err;
+} diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 0cda05c..26271cc 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -18,27 +18,12 @@ MODULE_LICENSE("GPL v2"); #define WEISS_CATEGORY_ID 0x00 #define LOUD_CATEGORY_ID 0x10
-static int dice_interface_check(struct fw_unit *unit) +static int check_dice_category(struct fw_unit *unit) {
- static const int min_values[10] = {
10, 0x64 / 4,
10, 0x18 / 4,
10, 0x18 / 4,
0, 0,
0, 0,
- }; struct fw_device *device = fw_parent_device(unit); struct fw_csr_iterator it;
- int key, val, vendor = -1, model = -1, err;
- unsigned int category, i;
- __be32 *pointers;
- u32 value;
- __be32 version;
- pointers = kmalloc_array(ARRAY_SIZE(min_values), sizeof(__be32),
GFP_KERNEL);
- if (pointers == NULL)
return -ENOMEM;
int key, val, vendor = -1, model = -1;
unsigned int category;
/*
- Check that GUID and unit directory are constructed according to DICE
@@ -64,51 +49,10 @@ static int dice_interface_check(struct fw_unit *unit) else category = DICE_CATEGORY_ID; if (device->config_rom[3] != ((vendor << 8) | category) ||
device->config_rom[4] >> 22 != model) {
err = -ENODEV;
goto end;
- }
- /*
* Check that the sub address spaces exist and are located inside the
* private address space. The minimum values are chosen so that all
* minimally required registers are included.
*/
- err = snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST,
DICE_PRIVATE_SPACE, pointers,
sizeof(__be32) * ARRAY_SIZE(min_values), 0);
- if (err < 0) {
err = -ENODEV;
goto end;
- }
- for (i = 0; i < ARRAY_SIZE(min_values); ++i) {
value = be32_to_cpu(pointers[i]);
if (value < min_values[i] || value >= 0x40000) {
err = -ENODEV;
goto end;
}
- }
device->config_rom[4] >> 22 != model)
return -ENODEV;
- /*
* Check that the implemented DICE driver specification major version
* number matches.
*/
- err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
DICE_PRIVATE_SPACE +
be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
&version, 4, 0);
- if (err < 0) {
err = -ENODEV;
goto end;
- }
- if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) {
dev_err(&unit->device,
"unknown DICE version: 0x%08x\n", be32_to_cpu(version));
err = -ENODEV;
goto end;
- }
-end:
- return err;
- return 0;
}
static int highest_supported_mode_rate(struct snd_dice *dice, @@ -254,9 +198,9 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) struct snd_dice *dice; int err;
- err = dice_interface_check(unit);
- err = check_dice_category(unit); if (err < 0)
goto end;
return -ENODEV;
err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*dice), &card);
-- 2.5.0
On 2015年12月29日 17:54, Takashi Iwai wrote:
On Sat, 26 Dec 2015 04:35:22 +0100, Takashi Sakamoto wrote:
Before allocating an instance of sound card, ALSA dice driver checks chip_ID_hi in Bus information block of Config ROM, then also checks subaddresses. The former operation reads cache of Config ROM in Linux FireWire subsystem, while the latter operation sends read transaction. The latter can be merged into initialization of transaction system.
This commit splits these two operations to reduce needless transactions in probe processing.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp
sound/firewire/dice/dice-transaction.c | 89 ++++++++++++++++++++++++++-------- sound/firewire/dice/dice.c | 72 +++------------------------ 2 files changed, 77 insertions(+), 84 deletions(-)
diff --git a/sound/firewire/dice/dice-transaction.c b/sound/firewire/dice/dice-transaction.c index aee7461..75a2125 100644 --- a/sound/firewire/dice/dice-transaction.c +++ b/sound/firewire/dice/dice-transaction.c @@ -331,39 +331,59 @@ int snd_dice_transaction_reinit(struct snd_dice *dice) return register_notification_address(dice, false); }
-int snd_dice_transaction_init(struct snd_dice *dice) +static int get_subaddrs(struct snd_dice *dice) {
- struct fw_address_handler *handler = &dice->notification_handler;
- static const int min_values[10] = {
10, 0x64 / 4,
10, 0x18 / 4,
10, 0x18 / 4,
0, 0,
0, 0,
- }; __be32 *pointers;
- u32 data;
- unsigned int i; int err;
- /* Use the same way which dice_interface_check() does. */
- pointers = kmalloc(sizeof(__be32) * 10, GFP_KERNEL);
- pointers = kmalloc_array(ARRAY_SIZE(min_values), sizeof(__be32),
if (pointers == NULL) return -ENOMEM;GFP_KERNEL);
- /* Get offsets for sub-addresses */
- /*
* Check that the sub address spaces exist and are located inside the
* private address space. The minimum values are chosen so that all
* minimally required registers are included.
err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,*/
DICE_PRIVATE_SPACE,
pointers, sizeof(__be32) * 10, 0);
DICE_PRIVATE_SPACE, pointers,
if (err < 0) goto end;sizeof(__be32) * ARRAY_SIZE(min_values), 0);
- /* Allocation callback in address space over host controller */
- handler->length = 4;
- handler->address_callback = dice_notification;
- handler->callback_data = dice;
- err = fw_core_add_address_handler(handler, &fw_high_memory_region);
- if (err < 0) {
handler->callback_data = NULL;
goto end;
- for (i = 0; i < ARRAY_SIZE(min_values); ++i) {
data = be32_to_cpu(pointers[i]);
if (data < min_values[i] || data >= 0x40000) {
err = -ENODEV;
goto end;
}}
- /* Register the address space */
- err = register_notification_address(dice, true);
- if (err < 0) {
fw_core_remove_address_handler(handler);
handler->callback_data = NULL;
- /*
* Check that the implemented DICE driver specification major version
* number matches.
*/
- err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
DICE_PRIVATE_SPACE +
be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
&data, sizeof(data), 0);
It's confusing to reuse a single variable as both u32 and be32. Use the specific variable like the original code instead.
OK.
thanks,
Takashi
- if (err < 0)
goto end;
- if ((data & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) {
dev_err(&dice->unit->device,
"unknown DICE version: 0x%08x\n", be32_to_cpu(data));
goto end; }err = -ENODEV;
@@ -380,3 +400,32 @@ end: kfree(pointers); return err; }
+int snd_dice_transaction_init(struct snd_dice *dice) +{
- struct fw_address_handler *handler = &dice->notification_handler;
- int err;
- err = get_subaddrs(dice);
- if (err < 0)
return err;
- /* Allocation callback in address space over host controller */
- handler->length = 4;
- handler->address_callback = dice_notification;
- handler->callback_data = dice;
- err = fw_core_add_address_handler(handler, &fw_high_memory_region);
- if (err < 0) {
handler->callback_data = NULL;
return err;
- }
- /* Register the address space */
- err = register_notification_address(dice, true);
- if (err < 0) {
fw_core_remove_address_handler(handler);
handler->callback_data = NULL;
- }
- return err;
+} diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 0cda05c..26271cc 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -18,27 +18,12 @@ MODULE_LICENSE("GPL v2"); #define WEISS_CATEGORY_ID 0x00 #define LOUD_CATEGORY_ID 0x10
-static int dice_interface_check(struct fw_unit *unit) +static int check_dice_category(struct fw_unit *unit) {
- static const int min_values[10] = {
10, 0x64 / 4,
10, 0x18 / 4,
10, 0x18 / 4,
0, 0,
0, 0,
- }; struct fw_device *device = fw_parent_device(unit); struct fw_csr_iterator it;
- int key, val, vendor = -1, model = -1, err;
- unsigned int category, i;
- __be32 *pointers;
- u32 value;
- __be32 version;
- pointers = kmalloc_array(ARRAY_SIZE(min_values), sizeof(__be32),
GFP_KERNEL);
- if (pointers == NULL)
return -ENOMEM;
int key, val, vendor = -1, model = -1;
unsigned int category;
/*
- Check that GUID and unit directory are constructed according to DICE
@@ -64,51 +49,10 @@ static int dice_interface_check(struct fw_unit *unit) else category = DICE_CATEGORY_ID; if (device->config_rom[3] != ((vendor << 8) | category) ||
device->config_rom[4] >> 22 != model) {
err = -ENODEV;
goto end;
- }
- /*
* Check that the sub address spaces exist and are located inside the
* private address space. The minimum values are chosen so that all
* minimally required registers are included.
*/
- err = snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST,
DICE_PRIVATE_SPACE, pointers,
sizeof(__be32) * ARRAY_SIZE(min_values), 0);
- if (err < 0) {
err = -ENODEV;
goto end;
- }
- for (i = 0; i < ARRAY_SIZE(min_values); ++i) {
value = be32_to_cpu(pointers[i]);
if (value < min_values[i] || value >= 0x40000) {
err = -ENODEV;
goto end;
}
- }
device->config_rom[4] >> 22 != model)
return -ENODEV;
- /*
* Check that the implemented DICE driver specification major version
* number matches.
*/
- err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
DICE_PRIVATE_SPACE +
be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
&version, 4, 0);
- if (err < 0) {
err = -ENODEV;
goto end;
- }
- if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) {
dev_err(&unit->device,
"unknown DICE version: 0x%08x\n", be32_to_cpu(version));
err = -ENODEV;
goto end;
- }
-end:
- return err;
- return 0;
}
static int highest_supported_mode_rate(struct snd_dice *dice, @@ -254,9 +198,9 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) struct snd_dice *dice; int err;
- err = dice_interface_check(unit);
- err = check_dice_category(unit); if (err < 0)
goto end;
return -ENODEV;
err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*dice), &card);
-- 2.5.0
Some models based on ASIC for Dice II series (STD, CP) change their hardware configurations after appearing on IEEE 1394 bus. This is due to interactions of boot loader (RedBoot), firmwares (eCos) and vendor's configurations. This causes current ALSA dice driver to get wrong information about the hardware's capability because its probe function runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load the firmware after bootstrap. Just after loaded, the driver can get information about the unit. Then the hardware is initialized according to vendor's configurations. After, the got information becomes wrong. Between bootstrap, firmware loading and post configuration, some bus resets are observed.
This commit offloads most processing of probe function into workqueue and schedules the workqueue after successive bus resets. This has an effect to get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e. Dice II, Dice Jr., Dice Mini and Dice III. Due to the same reason, sound card instance is kept till .remove function even if some errors are detected in the workqueue.
I use a loose strategy to manage a race condition between the workqueue and the bus reset. This is due to a specification of dice transaction. When bus reset occurs, registered address for the transaction is cleared. Drivers must re-register their own address again. While, this operation is required for the workqueue because the workqueue includes to wait for the transaction. This commit uses no lock primitives for the race condition in bus reset handler. Instead, checking 'registered' member of 'struct snd_dice' avoid executing the workqueue several times.
When .remove callback is executed, the sound card is going to be released. The registration work should not be pending or executed in the releasing. This commit uses cancel_delayed_work_sync() in .remove callback and wait till the pending work finished. After .remove callback, .update callback is not executed, therefore no works are scheduled again.
Cc: Yoshifuji Hideaki hideaki@yoshifuji.org Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/dice/dice.c | 113 ++++++++++++++++++++++++++++++++------------- sound/firewire/dice/dice.h | 3 ++ 2 files changed, 85 insertions(+), 31 deletions(-)
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 26271cc..0bc7d08 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -18,6 +18,8 @@ MODULE_LICENSE("GPL v2"); #define WEISS_CATEGORY_ID 0x00 #define LOUD_CATEGORY_ID 0x10
+#define PROBE_DELAY_MS (2 * MSEC_PER_SEC) + static int check_dice_category(struct fw_unit *unit) { struct fw_device *device = fw_parent_device(unit); @@ -192,6 +194,59 @@ static void dice_card_free(struct snd_card *card) mutex_destroy(&dice->mutex); }
+static void do_registration(struct work_struct *work) +{ + struct snd_dice *dice = container_of(work, struct snd_dice, dwork.work); + int err; + + if (dice->card->shutdown || dice->registered) + return; + + err = snd_dice_transaction_init(dice); + if (err < 0) + goto end; + + err = dice_read_params(dice); + if (err < 0) + goto end; + + dice_card_strings(dice); + + err = snd_dice_create_pcm(dice); + if (err < 0) + goto end; + + err = snd_dice_create_midi(dice); + if (err < 0) + goto end; + + err = snd_card_register(dice->card); + if (err < 0) + goto end; + + dice->registered = true; +end: + if (err < 0) + dev_info(&dice->unit->device, + "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) { struct snd_card *card; @@ -205,29 +260,20 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*dice), &card); if (err < 0) - goto end; + return err;
dice = card->private_data; dice->card = card; dice->unit = fw_unit_get(unit); card->private_free = dice_card_free; + dev_set_drvdata(&unit->device, dice);
spin_lock_init(&dice->lock); mutex_init(&dice->mutex); init_completion(&dice->clock_accepted); init_waitqueue_head(&dice->hwdep_wait);
- err = snd_dice_transaction_init(dice); - if (err < 0) - goto error; - - err = dice_read_params(dice); - if (err < 0) - goto error; - - dice_card_strings(dice); - - err = snd_dice_create_pcm(dice); + err = snd_dice_stream_init_duplex(dice); if (err < 0) goto error;
@@ -237,23 +283,11 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
snd_dice_create_proc(dice);
- err = snd_dice_create_midi(dice); - if (err < 0) - goto error; - - err = snd_dice_stream_init_duplex(dice); - if (err < 0) - goto error; + /* Register this sound card later. */ + INIT_DEFERRABLE_WORK(&dice->dwork, do_registration); + schedule_registration(dice);
- err = snd_card_register(card); - if (err < 0) { - snd_dice_stream_destroy_duplex(dice); - goto error; - } - - dev_set_drvdata(&unit->device, dice); -end: - return err; + return 0; error: snd_card_free(card); return err; @@ -263,6 +297,13 @@ static void dice_remove(struct fw_unit *unit) { struct snd_dice *dice = dev_get_drvdata(&unit->device);
+ /* + * Confirm to stop the work for registration before the sound card is + * going to be released. The work is not scheduled again because bus + * reset handler is not called anymore. + */ + cancel_delayed_work_sync(&dice->dwork); + /* No need to wait for releasing card object in this context. */ snd_card_free_when_closed(dice->card); } @@ -271,12 +312,22 @@ static void dice_bus_reset(struct fw_unit *unit) { struct snd_dice *dice = dev_get_drvdata(&unit->device);
+ /* Postpone a workqueue for deferred registration. */ + if (!dice->registered) + schedule_registration(dice); + /* The handler address register becomes initialized. */ snd_dice_transaction_reinit(dice);
- mutex_lock(&dice->mutex); - snd_dice_stream_update_duplex(dice); - mutex_unlock(&dice->mutex); + /* + * After registration, userspace can start packet streaming, then this + * code block works fine. + */ + if (dice->registered) { + mutex_lock(&dice->mutex); + snd_dice_stream_update_duplex(dice); + mutex_unlock(&dice->mutex); + } }
#define DICE_INTERFACE 0x000001 diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index 101550ac..3d5ebeb 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h @@ -45,6 +45,9 @@ struct snd_dice { spinlock_t lock; struct mutex mutex;
+ bool registered; + struct delayed_work dwork; + /* Offsets for sub-addresses */ unsigned int global_offset; unsigned int rx_offset;
When work of sound card registration fails, bus reset on IEEE 1394 can schedule the work again. In this case, currently instances of PCM and RawMIDI devices are not released, but allocated and errors occurs.
This commit solves this issue. The allocated data is kept and released at any failures in the work.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/dice/dice-midi.c | 2 ++ sound/firewire/dice/dice-pcm.c | 2 ++ sound/firewire/dice/dice.c | 30 +++++++++++++++++++++--------- sound/firewire/dice/dice.h | 2 ++ 4 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/sound/firewire/dice/dice-midi.c b/sound/firewire/dice/dice-midi.c index 151b09f..908b43f 100644 --- a/sound/firewire/dice/dice-midi.c +++ b/sound/firewire/dice/dice-midi.c @@ -153,5 +153,7 @@ int snd_dice_create_midi(struct snd_dice *dice) if ((midi_out_ports > 0) && (midi_in_ports > 0)) rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
+ dice->rmidi_dev = rmidi; + return 0; } diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index 9b34319..6246ce3 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -426,5 +426,7 @@ int snd_dice_create_pcm(struct snd_dice *dice) if (playback > 0) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
+ dice->pcm_dev = pcm; + return 0; } diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 0bc7d08..21ad894 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -202,33 +202,45 @@ static void do_registration(struct work_struct *work) if (dice->card->shutdown || dice->registered) return;
+ dice->pcm_dev = NULL; + dice->rmidi_dev = NULL; + err = snd_dice_transaction_init(dice); if (err < 0) - goto end; + goto error;
err = dice_read_params(dice); if (err < 0) - goto end; + goto error;
dice_card_strings(dice);
err = snd_dice_create_pcm(dice); if (err < 0) - goto end; + goto error;
err = snd_dice_create_midi(dice); if (err < 0) - goto end; + goto error;
err = snd_card_register(dice->card); if (err < 0) - goto end; + goto error;
dice->registered = true; -end: - if (err < 0) - dev_info(&dice->unit->device, - "Sound card registration failed: %d\n", err); + + return; +error: + snd_dice_transaction_destroy(dice); + + if (dice->pcm_dev) + snd_device_free(dice->card, dice->pcm_dev); + + if (dice->rmidi_dev) + snd_device_free(dice->card, dice->rmidi_dev); + + dev_info(&dice->unit->device, + "Sound card registration failed: %d\n", err); }
static void schedule_registration(struct snd_dice *dice) diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index 3d5ebeb..d632ac1 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h @@ -47,6 +47,8 @@ struct snd_dice {
bool registered; struct delayed_work dwork; + struct snd_pcm *pcm_dev; + struct snd_rawmidi *rmidi_dev;
/* Offsets for sub-addresses */ unsigned int global_offset;
On Sat, 26 Dec 2015 04:35:24 +0100, Takashi Sakamoto wrote:
When work of sound card registration fails, bus reset on IEEE 1394 can schedule the work again. In this case, currently instances of PCM and RawMIDI devices are not released, but allocated and errors occurs.
This commit solves this issue. The allocated data is kept and released at any failures in the work.
Aren't they be released in snd_card_free() in the later error path?
Takashi
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp
sound/firewire/dice/dice-midi.c | 2 ++ sound/firewire/dice/dice-pcm.c | 2 ++ sound/firewire/dice/dice.c | 30 +++++++++++++++++++++--------- sound/firewire/dice/dice.h | 2 ++ 4 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/sound/firewire/dice/dice-midi.c b/sound/firewire/dice/dice-midi.c index 151b09f..908b43f 100644 --- a/sound/firewire/dice/dice-midi.c +++ b/sound/firewire/dice/dice-midi.c @@ -153,5 +153,7 @@ int snd_dice_create_midi(struct snd_dice *dice) if ((midi_out_ports > 0) && (midi_in_ports > 0)) rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
- dice->rmidi_dev = rmidi;
- return 0;
} diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index 9b34319..6246ce3 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -426,5 +426,7 @@ int snd_dice_create_pcm(struct snd_dice *dice) if (playback > 0) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
- dice->pcm_dev = pcm;
- return 0;
} diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 0bc7d08..21ad894 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -202,33 +202,45 @@ static void do_registration(struct work_struct *work) if (dice->card->shutdown || dice->registered) return;
- dice->pcm_dev = NULL;
- dice->rmidi_dev = NULL;
- err = snd_dice_transaction_init(dice); if (err < 0)
goto end;
goto error;
err = dice_read_params(dice); if (err < 0)
goto end;
goto error;
dice_card_strings(dice);
err = snd_dice_create_pcm(dice); if (err < 0)
goto end;
goto error;
err = snd_dice_create_midi(dice); if (err < 0)
goto end;
goto error;
err = snd_card_register(dice->card); if (err < 0)
goto end;
goto error;
dice->registered = true;
-end:
- if (err < 0)
dev_info(&dice->unit->device,
"Sound card registration failed: %d\n", err);
- return;
+error:
- snd_dice_transaction_destroy(dice);
- if (dice->pcm_dev)
snd_device_free(dice->card, dice->pcm_dev);
- if (dice->rmidi_dev)
snd_device_free(dice->card, dice->rmidi_dev);
- dev_info(&dice->unit->device,
"Sound card registration failed: %d\n", err);
}
static void schedule_registration(struct snd_dice *dice) diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index 3d5ebeb..d632ac1 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h @@ -47,6 +47,8 @@ struct snd_dice {
bool registered; struct delayed_work dwork;
struct snd_pcm *pcm_dev;
struct snd_rawmidi *rmidi_dev;
/* Offsets for sub-addresses */ unsigned int global_offset;
-- 2.5.0
On 2015年12月29日 18:00, Takashi Iwai wrote:
On Sat, 26 Dec 2015 04:35:24 +0100, Takashi Sakamoto wrote:
When work of sound card registration fails, bus reset on IEEE 1394 can schedule the work again. In this case, currently instances of PCM and RawMIDI devices are not released, but allocated and errors occurs.
This commit solves this issue. The allocated data is kept and released at any failures in the work.
Aren't they be released in snd_card_free() in the later error path?
Not in the error path, but indeed in card free processing. They're not released anymore. I should have used snd_pcm_free() and snd_rawmidi_free() for this purpose. (I misunderstand they should be used after calling snd_card_register().)
Thanks
Takashi Sakamoto
Takashi
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp
sound/firewire/dice/dice-midi.c | 2 ++ sound/firewire/dice/dice-pcm.c | 2 ++ sound/firewire/dice/dice.c | 30 +++++++++++++++++++++--------- sound/firewire/dice/dice.h | 2 ++ 4 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/sound/firewire/dice/dice-midi.c b/sound/firewire/dice/dice-midi.c index 151b09f..908b43f 100644 --- a/sound/firewire/dice/dice-midi.c +++ b/sound/firewire/dice/dice-midi.c @@ -153,5 +153,7 @@ int snd_dice_create_midi(struct snd_dice *dice) if ((midi_out_ports > 0) && (midi_in_ports > 0)) rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
- dice->rmidi_dev = rmidi;
- return 0;
} diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index 9b34319..6246ce3 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -426,5 +426,7 @@ int snd_dice_create_pcm(struct snd_dice *dice) if (playback > 0) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
- dice->pcm_dev = pcm;
- return 0;
} diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 0bc7d08..21ad894 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -202,33 +202,45 @@ static void do_registration(struct work_struct *work) if (dice->card->shutdown || dice->registered) return;
- dice->pcm_dev = NULL;
- dice->rmidi_dev = NULL;
- err = snd_dice_transaction_init(dice); if (err < 0)
goto end;
goto error;
err = dice_read_params(dice); if (err < 0)
goto end;
goto error;
dice_card_strings(dice);
err = snd_dice_create_pcm(dice); if (err < 0)
goto end;
goto error;
err = snd_dice_create_midi(dice); if (err < 0)
goto end;
goto error;
err = snd_card_register(dice->card); if (err < 0)
goto end;
goto error;
dice->registered = true;
-end:
- if (err < 0)
dev_info(&dice->unit->device,
"Sound card registration failed: %d\n", err);
- return;
+error:
- snd_dice_transaction_destroy(dice);
- if (dice->pcm_dev)
snd_device_free(dice->card, dice->pcm_dev);
- if (dice->rmidi_dev)
snd_device_free(dice->card, dice->rmidi_dev);
- dev_info(&dice->unit->device,
"Sound card registration failed: %d\n", err);
}
static void schedule_registration(struct snd_dice *dice) diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index 3d5ebeb..d632ac1 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h @@ -47,6 +47,8 @@ struct snd_dice {
bool registered; struct delayed_work dwork;
struct snd_pcm *pcm_dev;
struct snd_rawmidi *rmidi_dev;
/* Offsets for sub-addresses */ unsigned int global_offset;
-- 2.5.0
On 2015年12月29日 19:56, Takashi Sakamoto wrote:
On 2015年12月29日 18:00, Takashi Iwai wrote:
On Sat, 26 Dec 2015 04:35:24 +0100, Takashi Sakamoto wrote:
When work of sound card registration fails, bus reset on IEEE 1394 can schedule the work again. In this case, currently instances of PCM and RawMIDI devices are not released, but allocated and errors occurs.
This commit solves this issue. The allocated data is kept and released at any failures in the work.
Aren't they be released in snd_card_free() in the later error path?
Not in the error path, but indeed in card free processing. They're not released anymore. I should have used snd_pcm_free() and snd_rawmidi_free() for this purpose. (I misunderstand they should be used after calling snd_card_register().)
I realized that both of snd_rawmidi_free() and snd_pcm_free() are called by snd_device_free(), then all of allocated memory blocks are freed.
Which error pathes do you think to cause the problems?
Regards
Takashi Sakamoto
On Tue, 29 Dec 2015 12:37:06 +0100, Takashi Sakamoto wrote:
On 2015年12月29日 19:56, Takashi Sakamoto wrote:
On 2015年12月29日 18:00, Takashi Iwai wrote:
On Sat, 26 Dec 2015 04:35:24 +0100, Takashi Sakamoto wrote:
When work of sound card registration fails, bus reset on IEEE 1394 can schedule the work again. In this case, currently instances of PCM and RawMIDI devices are not released, but allocated and errors occurs.
This commit solves this issue. The allocated data is kept and released at any failures in the work.
Aren't they be released in snd_card_free() in the later error path?
Not in the error path, but indeed in card free processing. They're not released anymore. I should have used snd_pcm_free() and snd_rawmidi_free() for this purpose. (I misunderstand they should be used after calling snd_card_register().)
I realized that both of snd_rawmidi_free() and snd_pcm_free() are called by snd_device_free(), then all of allocated memory blocks are freed.
Which error pathes do you think to cause the problems?
I don't think it causing problems but just superfluous to call explicitly there. You (should) call snd_card_free*() in the error path, and these components are released there automatically.
In which code path did you see the leak? This already sounds strange.
Takashi
Hi,
On Dec 30 2015 17:09, Takashi Iwai wrote:
On Tue, 29 Dec 2015 12:37:06 +0100, Takashi Sakamoto wrote:
On 2015年12月29日 19:56, Takashi Sakamoto wrote:
On 2015年12月29日 18:00, Takashi Iwai wrote:
On Sat, 26 Dec 2015 04:35:24 +0100, Takashi Sakamoto wrote:
When work of sound card registration fails, bus reset on IEEE 1394 can schedule the work again. In this case, currently instances of PCM and RawMIDI devices are not released, but allocated and errors occurs.
This commit solves this issue. The allocated data is kept and released at any failures in the work.
Aren't they be released in snd_card_free() in the later error path?
Not in the error path, but indeed in card free processing. They're not released anymore. I should have used snd_pcm_free() and snd_rawmidi_free() for this purpose. (I misunderstand they should be used after calling snd_card_register().)
I realized that both of snd_rawmidi_free() and snd_pcm_free() are called by snd_device_free(), then all of allocated memory blocks are freed.
Which error pathes do you think to cause the problems?
I don't think it causing problems but just superfluous to call explicitly there. You (should) call snd_card_free*() in the error path, and these components are released there automatically.
I had two reason not to call snd_card_free() family in error path of the 'do_registration().
Originally, the 'do_registration()' and .remove() are on a race condition against sound card instance.
But now. remove() waits to finish a work of the sound card registration, therefore snd_card_free() can be called in error path of the work.
Another reason is the memory object for driver_data. Currently I use struct snd_dice allocated by snd_card_new(). If calling snd_card_new() in the work, I must allocate it in .probe() callback independently. I thought it a bit hard to maintain the memory object against the race condition between the work, .update() and .remove() and sound card free.
But the race condition becomes simpler when .remove() waits to finish the work.
OK. I'll modify and post the new patchset.
In which code path did you see the leak? This already sounds strange.
It was my misunderstanding a few days ago.
Thanks
Takashi Sakamoto
In previous commit, card registration is processed under situation with few bus reset. There's no need to add a workaround of transaction re-initialization at timeout.
This commit purges the re-initialization.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/dice/dice-transaction.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-)
diff --git a/sound/firewire/dice/dice-transaction.c b/sound/firewire/dice/dice-transaction.c index 75a2125..d5f7de7 100644 --- a/sound/firewire/dice/dice-transaction.c +++ b/sound/firewire/dice/dice-transaction.c @@ -65,16 +65,15 @@ static unsigned int get_clock_info(struct snd_dice *dice, __be32 *info) static int set_clock_info(struct snd_dice *dice, unsigned int rate, unsigned int source) { - unsigned int retries = 3; unsigned int i; __be32 info; u32 mask; u32 clock; int err; -retry: + err = get_clock_info(dice, &info); if (err < 0) - goto end; + return err;
clock = be32_to_cpu(info); if (source != UINT_MAX) { @@ -87,10 +86,8 @@ retry: if (snd_dice_rates[i] == rate) break; } - if (i == ARRAY_SIZE(snd_dice_rates)) { - err = -EINVAL; - goto end; - } + if (i == ARRAY_SIZE(snd_dice_rates)) + return -EINVAL;
mask = CLOCK_RATE_MASK; clock &= ~mask; @@ -104,25 +101,13 @@ retry: err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT, &info, 4); if (err < 0) - goto end; + return err;
- /* Timeout means it's invalid request, probably bus reset occurred. */ if (wait_for_completion_timeout(&dice->clock_accepted, - msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) { - if (retries-- == 0) { - err = -ETIMEDOUT; - goto end; - } - - err = snd_dice_transaction_reinit(dice); - if (err < 0) - goto end; + msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) + return -ETIMEDOUT;
- msleep(500); /* arbitrary */ - goto retry; - } -end: - return err; + return 0; }
int snd_dice_transaction_get_clock_source(struct snd_dice *dice,
Some users have reported that their Dice based models generate ETIMEDOUT when starting PCM playback. It means that current timeout (=100msec) is not enough for their models to transfer notifications.
This commit expands the timeout up to 2 sec. As a result, in a worst case, any operations to start AMDTP streams takes 2 sec or more. Then, in userspace, snd_pcm_hw_params(), snd_pcm_prepare(), snd_pcm_recover(), snd_rawmidi_open(), snd_seq_connect_from() and snd_seq_connect_to() may take the time.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/dice/dice-transaction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/firewire/dice/dice-transaction.c b/sound/firewire/dice/dice-transaction.c index d5f7de7..de5cd6c 100644 --- a/sound/firewire/dice/dice-transaction.c +++ b/sound/firewire/dice/dice-transaction.c @@ -9,7 +9,7 @@
#include "dice.h"
-#define NOTIFICATION_TIMEOUT_MS 100 +#define NOTIFICATION_TIMEOUT_MS (2 * MSEC_PER_SEC)
static u64 get_subaddr(struct snd_dice *dice, enum snd_dice_addr_type type, u64 offset)
participants (2)
-
Takashi Iwai
-
Takashi Sakamoto