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

Commit cd307124 authored by Dan Carpenter's avatar Dan Carpenter Committed by Thierry Reding
Browse files

firmware: tegra: Fix locking bugs in BPMP



There are a bunch of error paths were we don't unlock the bpmp->threaded
lock.  Also if __tegra_bpmp_channel_write() fails then we returned
success instead of an error code.

Fixes: 983de5f9 ("firmware: tegra: Add BPMP support")
Signed-off-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 2ea659a9
Loading
Loading
Loading
Loading
+18 −10
Original line number Diff line number Diff line
@@ -211,14 +211,17 @@ static ssize_t tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
	int index;

	index = tegra_bpmp_channel_get_thread_index(channel);
	if (index < 0)
		return index;
	if (index < 0) {
		err = index;
		goto unlock;
	}

	spin_lock_irqsave(&bpmp->lock, flags);
	err = __tegra_bpmp_channel_read(channel, data, size);
	clear_bit(index, bpmp->threaded.allocated);
	spin_unlock_irqrestore(&bpmp->lock, flags);

unlock:
	up(&bpmp->threaded.lock);

	return err;
@@ -256,18 +259,18 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq,

	index = find_first_zero_bit(bpmp->threaded.allocated, count);
	if (index == count) {
		channel = ERR_PTR(-EBUSY);
		err = -EBUSY;
		goto unlock;
	}

	channel = tegra_bpmp_channel_get_thread(bpmp, index);
	if (!channel) {
		channel = ERR_PTR(-EINVAL);
		err = -EINVAL;
		goto unlock;
	}

	if (!tegra_bpmp_master_free(channel)) {
		channel = ERR_PTR(-EBUSY);
		err = -EBUSY;
		goto unlock;
	}

@@ -275,16 +278,21 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq,

	err = __tegra_bpmp_channel_write(channel, mrq, MSG_ACK | MSG_RING,
					 data, size);
	if (err < 0) {
		clear_bit(index, bpmp->threaded.allocated);
		goto unlock;
	}
	if (err < 0)
		goto clear_allocated;

	set_bit(index, bpmp->threaded.busy);

unlock:
	spin_unlock_irqrestore(&bpmp->lock, flags);
	return channel;

clear_allocated:
	clear_bit(index, bpmp->threaded.allocated);
unlock:
	spin_unlock_irqrestore(&bpmp->lock, flags);
	up(&bpmp->threaded.lock);

	return ERR_PTR(err);
}

static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,