ALSA: bebob: use address returned by kmalloc() instead of kernel stack for streaming DMA mapping
commit 493626f2d87a74e6dbea1686499ed6e7e600484e upstream. When executing 'fw_run_transaction()' with 'TCODE_WRITE_BLOCK_REQUEST', an address of 'payload' argument is used for streaming DMA mapping by 'firewire_ohci' module if 'size' argument is larger than 8 byte. Although in this case the address should not be on kernel stack, current implementation of ALSA bebob driver uses data in kernel stack for a cue to boot M-Audio devices. This often brings unexpected result, especially for a case of CONFIG_VMAP_STACK=y. This commit fixes the bug. Reference: https://bugzilla.kernel.org/show_bug.cgi?id=201021 Reference: https://forum.manjaro.org/t/firewire-m-audio-410-driver-wont-load-firmware/51165 Fixes: a2b2a7798fb6('ALSA: bebob: Send a cue to load firmware for M-Audio Firewire series') Cc: <stable@vger.kernel.org> # v3.16+ Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
68d542be69
commit
1da7fa6383
1 changed files with 14 additions and 10 deletions
|
@ -96,17 +96,13 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit)
|
||||||
struct fw_device *device = fw_parent_device(unit);
|
struct fw_device *device = fw_parent_device(unit);
|
||||||
int err, rcode;
|
int err, rcode;
|
||||||
u64 date;
|
u64 date;
|
||||||
__le32 cues[3] = {
|
__le32 *cues;
|
||||||
cpu_to_le32(MAUDIO_BOOTLOADER_CUE1),
|
|
||||||
cpu_to_le32(MAUDIO_BOOTLOADER_CUE2),
|
|
||||||
cpu_to_le32(MAUDIO_BOOTLOADER_CUE3)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* check date of software used to build */
|
/* check date of software used to build */
|
||||||
err = snd_bebob_read_block(unit, INFO_OFFSET_SW_DATE,
|
err = snd_bebob_read_block(unit, INFO_OFFSET_SW_DATE,
|
||||||
&date, sizeof(u64));
|
&date, sizeof(u64));
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto end;
|
return err;
|
||||||
/*
|
/*
|
||||||
* firmware version 5058 or later has date later than "20070401", but
|
* firmware version 5058 or later has date later than "20070401", but
|
||||||
* 'date' is not null-terminated.
|
* 'date' is not null-terminated.
|
||||||
|
@ -114,20 +110,28 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit)
|
||||||
if (date < 0x3230303730343031LL) {
|
if (date < 0x3230303730343031LL) {
|
||||||
dev_err(&unit->device,
|
dev_err(&unit->device,
|
||||||
"Use firmware version 5058 or later\n");
|
"Use firmware version 5058 or later\n");
|
||||||
err = -ENOSYS;
|
return -ENXIO;
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cues = kmalloc_array(3, sizeof(*cues), GFP_KERNEL);
|
||||||
|
if (!cues)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
cues[0] = cpu_to_le32(MAUDIO_BOOTLOADER_CUE1);
|
||||||
|
cues[1] = cpu_to_le32(MAUDIO_BOOTLOADER_CUE2);
|
||||||
|
cues[2] = cpu_to_le32(MAUDIO_BOOTLOADER_CUE3);
|
||||||
|
|
||||||
rcode = fw_run_transaction(device->card, TCODE_WRITE_BLOCK_REQUEST,
|
rcode = fw_run_transaction(device->card, TCODE_WRITE_BLOCK_REQUEST,
|
||||||
device->node_id, device->generation,
|
device->node_id, device->generation,
|
||||||
device->max_speed, BEBOB_ADDR_REG_REQ,
|
device->max_speed, BEBOB_ADDR_REG_REQ,
|
||||||
cues, sizeof(cues));
|
cues, 3 * sizeof(*cues));
|
||||||
|
kfree(cues);
|
||||||
if (rcode != RCODE_COMPLETE) {
|
if (rcode != RCODE_COMPLETE) {
|
||||||
dev_err(&unit->device,
|
dev_err(&unit->device,
|
||||||
"Failed to send a cue to load firmware\n");
|
"Failed to send a cue to load firmware\n");
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
}
|
}
|
||||||
end:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue