Commit 493626f2 authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai

ALSA: bebob: use address returned by kmalloc() instead of kernel stack for streaming DMA mapping

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: a2b2a779('ALSA: bebob: Send a cue to load firmware for M-Audio Firewire series')
Cc: <stable@vger.kernel.org> # v3.16+
Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent f7c50fa6
...@@ -96,17 +96,13 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit) ...@@ -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) ...@@ -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;
} }
......
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