Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+14 −10
Original line number Diff line number Diff line
@@ -96,17 +96,13 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit)
	struct fw_device *device = fw_parent_device(unit);
	int err, rcode;
	u64 date;
	__le32 cues[3] = {
		cpu_to_le32(MAUDIO_BOOTLOADER_CUE1),
		cpu_to_le32(MAUDIO_BOOTLOADER_CUE2),
		cpu_to_le32(MAUDIO_BOOTLOADER_CUE3)
	};
	__le32 *cues;

	/* check date of software used to build */
	err = snd_bebob_read_block(unit, INFO_OFFSET_SW_DATE,
				   &date, sizeof(u64));
	if (err < 0)
		goto end;
		return err;
	/*
	 * firmware version 5058 or later has date later than "20070401", but
	 * 'date' is not null-terminated.
@@ -114,20 +110,28 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit)
	if (date < 0x3230303730343031LL) {
		dev_err(&unit->device,
			"Use firmware version 5058 or later\n");
		err = -ENOSYS;
		goto end;
		return -ENXIO;
	}

	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,
				   device->node_id, device->generation,
				   device->max_speed, BEBOB_ADDR_REG_REQ,
				   cues, sizeof(cues));
				   cues, 3 * sizeof(*cues));
	kfree(cues);
	if (rcode != RCODE_COMPLETE) {
		dev_err(&unit->device,
			"Failed to send a cue to load firmware\n");
		err = -EIO;
	}
end:

	return err;
}