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

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
...@@ -211,14 +211,17 @@ static ssize_t tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel, ...@@ -211,14 +211,17 @@ static ssize_t tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
int index; int index;
index = tegra_bpmp_channel_get_thread_index(channel); index = tegra_bpmp_channel_get_thread_index(channel);
if (index < 0) if (index < 0) {
return index; err = index;
goto unlock;
}
spin_lock_irqsave(&bpmp->lock, flags); spin_lock_irqsave(&bpmp->lock, flags);
err = __tegra_bpmp_channel_read(channel, data, size); err = __tegra_bpmp_channel_read(channel, data, size);
clear_bit(index, bpmp->threaded.allocated); clear_bit(index, bpmp->threaded.allocated);
spin_unlock_irqrestore(&bpmp->lock, flags); spin_unlock_irqrestore(&bpmp->lock, flags);
unlock:
up(&bpmp->threaded.lock); up(&bpmp->threaded.lock);
return err; return err;
...@@ -256,18 +259,18 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq, ...@@ -256,18 +259,18 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq,
index = find_first_zero_bit(bpmp->threaded.allocated, count); index = find_first_zero_bit(bpmp->threaded.allocated, count);
if (index == count) { if (index == count) {
channel = ERR_PTR(-EBUSY); err = -EBUSY;
goto unlock; goto unlock;
} }
channel = tegra_bpmp_channel_get_thread(bpmp, index); channel = tegra_bpmp_channel_get_thread(bpmp, index);
if (!channel) { if (!channel) {
channel = ERR_PTR(-EINVAL); err = -EINVAL;
goto unlock; goto unlock;
} }
if (!tegra_bpmp_master_free(channel)) { if (!tegra_bpmp_master_free(channel)) {
channel = ERR_PTR(-EBUSY); err = -EBUSY;
goto unlock; goto unlock;
} }
...@@ -275,16 +278,21 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq, ...@@ -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, err = __tegra_bpmp_channel_write(channel, mrq, MSG_ACK | MSG_RING,
data, size); data, size);
if (err < 0) { if (err < 0)
clear_bit(index, bpmp->threaded.allocated); goto clear_allocated;
goto unlock;
}
set_bit(index, bpmp->threaded.busy); set_bit(index, bpmp->threaded.busy);
unlock:
spin_unlock_irqrestore(&bpmp->lock, flags); spin_unlock_irqrestore(&bpmp->lock, flags);
return channel; 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, static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
......
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