From d9f26a6689a3e4ae643fca9c2acda3148b717e63 Mon Sep 17 00:00:00 2001
From: Kevin McKinney <klmckinney1@gmail.com>
Date: Tue, 22 Nov 2011 20:25:57 -0500
Subject: [PATCH] Staging: bcm: Fix semaphore locking error when downloading
 firmware.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch releases semaphore locks when
an error occurrs while attempting to
download firmware for the bcm driver.
When downloading firmware for this driver,
a process is expected to call
the following ioctl's in this order:
(1)IOCTL_BCM_BUFFER_DOWNLOAD_START,
(2)IOCTL_BCM_BUFFER_DOWNLOAD, and (3)
IOCTL_BCM_BUFFER_DOWNLOAD_STOP.
Semaphore, “Adapter->fw_download_sema” is
expected to be acquired in the first ioctl,
IOCTL_BCM_BUFFER_DOWNLOAD_START, and it should
block until IOCTL_BCM_BUFFER_DOWNLOAD_STOP
is called.  In this case, if an error
occurred before STOP finished, the semaphore
"Adapter->fw_download_sema" was not being released.

Signed-off-by: Kevin McKinney <klmckinney1@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/staging/bcm/Bcmchar.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
index 5a3e7c846a3e..d0a0b10c5d4e 100644
--- a/drivers/staging/bcm/Bcmchar.c
+++ b/drivers/staging/bcm/Bcmchar.c
@@ -802,27 +802,36 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 		}
 
 		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
+			up(&Adapter->fw_download_sema);
 			return -EFAULT;
+		}
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
 				"Length for FW DLD is : %lx\n", IoBuffer.InputLength);
 
-		if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO))
+		if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) {
+			up(&Adapter->fw_download_sema);
 			return -EINVAL;
+		}
 
 		psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL);
-		if (!psFwInfo)
+		if (!psFwInfo) {
+			up(&Adapter->fw_download_sema);
 			return -ENOMEM;
+		}
 
-		if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength))
+		if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
+			up(&Adapter->fw_download_sema);
 			return -EFAULT;
+		}
 
 		if (!psFwInfo->pvMappedFirmwareAddress ||
 			(psFwInfo->u32FirmwareLength == 0)) {
 
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n",
 					psFwInfo->u32FirmwareLength);
+			up(&Adapter->fw_download_sema);
 			Status = -EINVAL;
 			break;
 		}
-- 
GitLab