summary refs log tree commit diff
path: root/drivers/firmware/tegra
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2017-06-18 21:01:15 -0700
committerOlof Johansson <olof@lixom.net>2017-06-18 21:01:15 -0700
commit43e68aa7b58f0f2d9abb79ca03c397f4f00d9238 (patch)
tree1b7b6c107b5afe73088bda4e8bf4687ad9015bed /drivers/firmware/tegra
parentf39b24e0b4d812da9658033621d3992959ae6d32 (diff)
parentcd307124ad9bb01019920c2053696218d161f4a1 (diff)
downloadlinux-43e68aa7b58f0f2d9abb79ca03c397f4f00d9238.tar.gz
Merge tag 'tegra-for-4.13-firmware' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into next/drivers
firmware: tegra: Changes for v4.13-rc1

This contains a fix for missing semaphore release in error paths as well
as a bogus error code return in the BPMP firmware implementation.

* tag 'tegra-for-4.13-firmware' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  firmware: tegra: Fix locking bugs in BPMP

Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/firmware/tegra')
-rw-r--r--drivers/firmware/tegra/bpmp.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index f11c7025b4a1..b25179517cc5 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -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,