Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+18 -10
+18 -10
drivers/firmware/tegra/bpmp.c
··· 211 211 int index; 212 212 213 213 index = tegra_bpmp_channel_get_thread_index(channel); 214 - if (index < 0) 215 - return index; 214 + if (index < 0) { 215 + err = index; 216 + goto unlock; 217 + } 216 218 217 219 spin_lock_irqsave(&bpmp->lock, flags); 218 220 err = __tegra_bpmp_channel_read(channel, data, size); 219 221 clear_bit(index, bpmp->threaded.allocated); 220 222 spin_unlock_irqrestore(&bpmp->lock, flags); 221 223 224 + unlock: 222 225 up(&bpmp->threaded.lock); 223 226 224 227 return err; ··· 259 256 260 257 index = find_first_zero_bit(bpmp->threaded.allocated, count); 261 258 if (index == count) { 262 - channel = ERR_PTR(-EBUSY); 259 + err = -EBUSY; 263 260 goto unlock; 264 261 } 265 262 266 263 channel = tegra_bpmp_channel_get_thread(bpmp, index); 267 264 if (!channel) { 268 - channel = ERR_PTR(-EINVAL); 265 + err = -EINVAL; 269 266 goto unlock; 270 267 } 271 268 272 269 if (!tegra_bpmp_master_free(channel)) { 273 - channel = ERR_PTR(-EBUSY); 270 + err = -EBUSY; 274 271 goto unlock; 275 272 } 276 273 ··· 278 275 279 276 err = __tegra_bpmp_channel_write(channel, mrq, MSG_ACK | MSG_RING, 280 277 data, size); 281 - if (err < 0) { 282 - clear_bit(index, bpmp->threaded.allocated); 283 - goto unlock; 284 - } 278 + if (err < 0) 279 + goto clear_allocated; 285 280 286 281 set_bit(index, bpmp->threaded.busy); 287 282 288 - unlock: 289 283 spin_unlock_irqrestore(&bpmp->lock, flags); 290 284 return channel; 285 + 286 + clear_allocated: 287 + clear_bit(index, bpmp->threaded.allocated); 288 + unlock: 289 + spin_unlock_irqrestore(&bpmp->lock, flags); 290 + up(&bpmp->threaded.lock); 291 + 292 + return ERR_PTR(err); 291 293 } 292 294 293 295 static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,