[alsa-devel] [PATCH 1/5] ALSA: dice: split subaddress check from category check
Takashi Sakamoto
o-takashi at sakamocchi.jp
Tue Dec 29 10:33:07 CET 2015
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 at 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);
>
> 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));
>> + 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);
>> --
>> 2.5.0
More information about the Alsa-devel
mailing list