Skip to contentSkip to conversation

lsilogic mpt fusion: mptctl: Fixed race condition around mptctl_id variable using mutexes

PATCH Superseded Mark Balantzyan 2 participants 2 messages Aug 14, 2019 – Aug 15, 2019

Subsystems (2)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 lsilogic mpt fusion: mptctl: Fixed race condition around mptctl_id variable using mutexes

Certain functions in the driver, such as mptctl_do_fw_download() and mptctl_do_mpt_command(), rely on the instance of mptctl_id, which does the id-ing. There is race condition possible when these functions operate in concurrency. Via, mutexes, the functions are mutually signalled to cooperate.

---
 drivers/message/fusion/mptctl.c | 39 ++++++++++++++++++++++++++-------
 1 file changed, 31 insertions(+), 8 deletions(-)
drivers/message/fusion/mptctl.c +31 -8
index 4470630d..f0b49a85 100644
@@ -816,12 +816,15 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
 
 		/*  Valid device. Get a message frame and construct the FW download message.
 	 	*/
+		mutex_lock(&mpctl_mutex);
 		if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
+			mutex_unlock(&mpctl_mutex);
 			return -EAGAIN;
 	}
-
+	mutex_lock(&mpctl_mutex);
 	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT
 	    "mptctl_do_fwdl called. mptctl_id = %xh.\n", iocp->name, mptctl_id));
+	mutex_unlock(&mpctl_mutex);
 	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.bufp  = %p\n",
 	    iocp->name, ufwbuf));
 	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.fwlen = %d\n",
@@ -943,7 +946,9 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
 	ReplyMsg = NULL;
 	SET_MGMT_MSG_CONTEXT(iocp->ioctl_cmds.msg_context, dlmsg->MsgContext);
 	INITIALIZE_MGMT_STATUS(iocp->ioctl_cmds.status)
+	mutex_lock(&mpctl_mutex);
 	mpt_put_msg_frame(mptctl_id, iocp, mf);
+	mutex_lock(&mpctl_mutex);
 
 	/* Now wait for the command to complete */
 retry_wait:
@@ -1889,7 +1894,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 
 	/* Get a free request frame and save the message context.
 	 */
+	mutex_lock(&mpctl_mutex);
         if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
+		mutex_unlock(&mpctl_mutex);
                 return -EAGAIN;
 
 	hdr = (MPIHeader_t *) mf;
@@ -2271,11 +2278,14 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 		DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
 
 		if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
-		    (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
+		    (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) {
+			mutex_lock(&mpctl_mutex);
 			mpt_put_msg_frame_hi_pri(mptctl_id, ioc, mf);
-		else {
-			rc =mpt_send_handshake_request(mptctl_id, ioc,
-				sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
+			mutex_unlock(&mpctl_mutex);
+		} else {
+			mutex_lock(&mpctl_mutex);
+			rc = mpt_send_handshake_request(mptctl_id, ioc, sizeof(SCSITaskMgmt_t), (u32 *)mf, CAN_SLEEP);
+			mutex_unlock(&mpctl_mutex);
 			if (rc != 0) {
 				dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
 				    "send_handshake FAILED! (ioc %p, mf %p)\n",
@@ -2287,8 +2297,11 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 			}
 		}
 
-	} else
+	} else {
+		mutex_lock(&mpctl_mutex);
 		mpt_put_msg_frame(mptctl_id, ioc, mf);
+		mutex_unlock(&mpctl_mutex);
+	}
 
 	/* Now wait for the command to complete */
 	timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
@@ -2563,7 +2576,9 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 	/* 
 	 * Gather ISTWI(Industry Standard Two Wire Interface) Data
 	 */
+	mutex_lock(&mpctl_mutex);
 	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+		mutex_unlock(&mpctl_mutex);
 		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
 			"%s, no msg frames!!\n", ioc->name, __func__));
 		goto out;
@@ -2593,7 +2608,9 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 	SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context,
 				IstwiRWRequest->MsgContext);
 	INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
+	mutex_lock(&mpctl_mutex);
 	mpt_put_msg_frame(mptctl_id, ioc, mf);
+	mutex_unlock(&mpctl_mutex);
 
 retry_wait:
 	timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
@@ -3010,9 +3027,11 @@ static int __init mptctl_init(void)
 	 *  Install our handler
 	 */
 	++where;
+	mutex_lock(&mpctl_mutex);
 	mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER,
 	    "mptctl_reply");
 	if (!mptctl_id || mptctl_id >= MPT_MAX_PROTOCOL_DRIVERS) {
+		mutex_unlock(&mpctl_mutex);
 		printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n");
 		misc_deregister(&mptctl_miscdev);
 		err = -EBUSY;
@@ -3022,13 +3041,14 @@ static int __init mptctl_init(void)
 	mptctl_taskmgmt_id = mpt_register(mptctl_taskmgmt_reply, MPTCTL_DRIVER,
 	    "mptctl_taskmgmt_reply");
 	if (!mptctl_taskmgmt_id || mptctl_taskmgmt_id >= MPT_MAX_PROTOCOL_DRIVERS) {
+		mutex_unlock(&mpctl_mutex);
 		printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n");
 		mpt_deregister(mptctl_id);
 		misc_deregister(&mptctl_miscdev);
 		err = -EBUSY;
 		goto out_fail;
 	}
-
+	mutex_unlock(&mpctl_mutex);
 	mpt_reset_register(mptctl_id, mptctl_ioc_reset);
 	mpt_event_register(mptctl_id, mptctl_event_process);
 
@@ -3044,13 +3064,14 @@ out_fail:
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static void mptctl_exit(void)
 {
+	mutex_lock(&mpctl_mutex);
 	misc_deregister(&mptctl_miscdev);
 	printk(KERN_INFO MYNAM ": Deregistered /dev/%s @ (major,minor=%d,%d)\n",
 			 mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor);
 
 	/* De-register event handler from base module */
 	mpt_event_deregister(mptctl_id);
-
+
 	/* De-register reset handler from base module */
 	mpt_reset_deregister(mptctl_id);
 
@@ -3058,6 +3079,8 @@ static void mptctl_exit(void)
 	mpt_deregister(mptctl_taskmgmt_id);
 	mpt_deregister(mptctl_id);
 
+	mutex_unlock(&mpctl_mutex);
+
         mpt_device_driver_deregister(MPTCTL_DRIVER);
 
 }
Signature · 1 line
2.17.1
#1 lore raw
Thank you for the patch! Perhaps something to improve:

Hi Mark,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[cannot apply to v5.3-rc4 next-20190814]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Mark-Balantzyan/lsilogic-mpt-fusion-mptctl-Fixed-race-condition-around-mptctl_id-variable-using-mutexes/20190815-115822
config: x86_64-lkp (attached as .config)
compiler: gcc-7 (Debian 7.4.0-10) 7.4.0 reproduce:

        # save the attached .config to linux build tree
        make ARCH=x86_64 

If you fix the issue, kindly add following tag

All warnings (new ones prefixed by >>):

drivers/message/fusion/mptctl.c: In function 'mptctl_do_fw_download':

>> drivers/message/fusion/mptctl.c:820:3: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
      if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
      ^~
   drivers/message/fusion/mptctl.c:822:4: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
       return -EAGAIN;
       ^~~~~~
   drivers/message/fusion/mptctl.c: In function 'mptctl_do_mpt_command':
   drivers/message/fusion/mptctl.c:1898:9: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
            if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
            ^~
   drivers/message/fusion/mptctl.c:1900:17: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
                    return -EAGAIN;
                    ^~~~~~

vim +/if +820 drivers/message/fusion/mptctl.c

^1da177e4c3f41 Linus Torvalds  2005-04-16   771  
^1da177e4c3f41 Linus Torvalds  2005-04-16   772  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
^1da177e4c3f41 Linus Torvalds  2005-04-16   773  /*
^1da177e4c3f41 Linus Torvalds  2005-04-16   774   * FW Download engine.
^1da177e4c3f41 Linus Torvalds  2005-04-16   775   * Outputs:	None.
^1da177e4c3f41 Linus Torvalds  2005-04-16   776   * Return:	0 if successful
^1da177e4c3f41 Linus Torvalds  2005-04-16   777   *		-EFAULT if data unavailable
^1da177e4c3f41 Linus Torvalds  2005-04-16   778   *		-ENXIO  if no such device
^1da177e4c3f41 Linus Torvalds  2005-04-16   779   *		-EAGAIN if resource problem
^1da177e4c3f41 Linus Torvalds  2005-04-16   780   *		-ENOMEM if no memory for SGE
^1da177e4c3f41 Linus Torvalds  2005-04-16   781   *		-EMLINK if too many chain buffers required
^1da177e4c3f41 Linus Torvalds  2005-04-16   782   *		-EBADRQC if adapter does not support FW download
^1da177e4c3f41 Linus Torvalds  2005-04-16   783   *		-EBUSY if adapter is busy
^1da177e4c3f41 Linus Torvalds  2005-04-16   784   *		-ENOMSG if FW upload returned bad status
^1da177e4c3f41 Linus Torvalds  2005-04-16   785   */
^1da177e4c3f41 Linus Torvalds  2005-04-16   786  static int
^1da177e4c3f41 Linus Torvalds  2005-04-16   787  mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
^1da177e4c3f41 Linus Torvalds  2005-04-16   788  {
^1da177e4c3f41 Linus Torvalds  2005-04-16   789  	FWDownload_t		*dlmsg;
^1da177e4c3f41 Linus Torvalds  2005-04-16   790  	MPT_FRAME_HDR		*mf;
^1da177e4c3f41 Linus Torvalds  2005-04-16   791  	MPT_ADAPTER		*iocp;
^1da177e4c3f41 Linus Torvalds  2005-04-16   792  	FWDownloadTCSGE_t	*ptsge;
^1da177e4c3f41 Linus Torvalds  2005-04-16   793  	MptSge_t		*sgl, *sgIn;
^1da177e4c3f41 Linus Torvalds  2005-04-16   794  	char			*sgOut;
^1da177e4c3f41 Linus Torvalds  2005-04-16   795  	struct buflist		*buflist;
^1da177e4c3f41 Linus Torvalds  2005-04-16   796  	struct buflist		*bl;
^1da177e4c3f41 Linus Torvalds  2005-04-16   797  	dma_addr_t		 sgl_dma;
^1da177e4c3f41 Linus Torvalds  2005-04-16   798  	int			 ret;
^1da177e4c3f41 Linus Torvalds  2005-04-16   799  	int			 numfrags = 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16   800  	int			 maxfrags;
^1da177e4c3f41 Linus Torvalds  2005-04-16   801  	int			 n = 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16   802  	u32			 sgdir;
^1da177e4c3f41 Linus Torvalds  2005-04-16   803  	u32			 nib;
^1da177e4c3f41 Linus Torvalds  2005-04-16   804  	int			 fw_bytes_copied = 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16   805  	int			 i;
^1da177e4c3f41 Linus Torvalds  2005-04-16   806  	int			 sge_offset = 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16   807  	u16			 iocstat;
^1da177e4c3f41 Linus Torvalds  2005-04-16   808  	pFWDownloadReply_t	 ReplyMsg = NULL;
ea2a788de4ce5e Kashyap, Desai  2009-05-29   809  	unsigned long		 timeleft;
^1da177e4c3f41 Linus Torvalds  2005-04-16   810  
946cbf040adb9d Moore, Eric     2006-02-02   811  	if (mpt_verify_adapter(ioc, &iocp) < 0) {
29dd3609f2fc70 Eric Moore      2007-09-14   812  		printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n",
29dd3609f2fc70 Eric Moore      2007-09-14   813  				 ioc);
^1da177e4c3f41 Linus Torvalds  2005-04-16   814  		return -ENODEV; /* (-6) No such device or address */
946cbf040adb9d Moore, Eric     2006-02-02   815  	} else {
^1da177e4c3f41 Linus Torvalds  2005-04-16   816  
^1da177e4c3f41 Linus Torvalds  2005-04-16   817  		/*  Valid device. Get a message frame and construct the FW download message.
^1da177e4c3f41 Linus Torvalds  2005-04-16   818  	 	*/
b07cb166c26273 Mark Balantzyan 2019-08-14   819  		mutex_lock(&mpctl_mutex);
^1da177e4c3f41 Linus Torvalds  2005-04-16  @820  		if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
b07cb166c26273 Mark Balantzyan 2019-08-14   821  			mutex_unlock(&mpctl_mutex);
^1da177e4c3f41 Linus Torvalds  2005-04-16   822  			return -EAGAIN;
946cbf040adb9d Moore, Eric     2006-02-02   823  	}
b07cb166c26273 Mark Balantzyan 2019-08-14   824  	mutex_lock(&mpctl_mutex);
09120a8cd38dbd Prakash, Sathya 2007-07-24   825  	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT
09120a8cd38dbd Prakash, Sathya 2007-07-24   826  	    "mptctl_do_fwdl called. mptctl_id = %xh.\n", iocp->name, mptctl_id));
b07cb166c26273 Mark Balantzyan 2019-08-14   827  	mutex_unlock(&mpctl_mutex);
09120a8cd38dbd Prakash, Sathya 2007-07-24   828  	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.bufp  = %p\n",
09120a8cd38dbd Prakash, Sathya 2007-07-24   829  	    iocp->name, ufwbuf));
09120a8cd38dbd Prakash, Sathya 2007-07-24   830  	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.fwlen = %d\n",
09120a8cd38dbd Prakash, Sathya 2007-07-24   831  	    iocp->name, (int)fwlen));
09120a8cd38dbd Prakash, Sathya 2007-07-24   832  	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.ioc   = %04xh\n",
09120a8cd38dbd Prakash, Sathya 2007-07-24   833  	    iocp->name, ioc));
09120a8cd38dbd Prakash, Sathya 2007-07-24   834  
^1da177e4c3f41 Linus Torvalds  2005-04-16   835  	dlmsg = (FWDownload_t*) mf;
^1da177e4c3f41 Linus Torvalds  2005-04-16   836  	ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
^1da177e4c3f41 Linus Torvalds  2005-04-16   837  	sgOut = (char *) (ptsge + 1);
^1da177e4c3f41 Linus Torvalds  2005-04-16   838  
^1da177e4c3f41 Linus Torvalds  2005-04-16   839  	/*
^1da177e4c3f41 Linus Torvalds  2005-04-16   840  	 * Construct f/w download request
^1da177e4c3f41 Linus Torvalds  2005-04-16   841  	 */
^1da177e4c3f41 Linus Torvalds  2005-04-16   842  	dlmsg->ImageType = MPI_FW_DOWNLOAD_ITYPE_FW;
^1da177e4c3f41 Linus Torvalds  2005-04-16   843  	dlmsg->Reserved = 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16   844  	dlmsg->ChainOffset = 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16   845  	dlmsg->Function = MPI_FUNCTION_FW_DOWNLOAD;
^1da177e4c3f41 Linus Torvalds  2005-04-16   846  	dlmsg->Reserved1[0] = dlmsg->Reserved1[1] = dlmsg->Reserved1[2] = 0;
946cbf040adb9d Moore, Eric     2006-02-02   847  	if (iocp->facts.MsgVersion >= MPI_VERSION_01_05)
946cbf040adb9d Moore, Eric     2006-02-02   848  		dlmsg->MsgFlags = MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT;
946cbf040adb9d Moore, Eric     2006-02-02   849  	else
^1da177e4c3f41 Linus Torvalds  2005-04-16   850  		dlmsg->MsgFlags = 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16   851  
946cbf040adb9d Moore, Eric     2006-02-02   852  
^1da177e4c3f41 Linus Torvalds  2005-04-16   853  	/* Set up the Transaction SGE.
^1da177e4c3f41 Linus Torvalds  2005-04-16   854  	 */
^1da177e4c3f41 Linus Torvalds  2005-04-16   855  	ptsge->Reserved = 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16   856  	ptsge->ContextSize = 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16   857  	ptsge->DetailsLength = 12;
^1da177e4c3f41 Linus Torvalds  2005-04-16   858  	ptsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
^1da177e4c3f41 Linus Torvalds  2005-04-16   859  	ptsge->Reserved_0100_Checksum = 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16   860  	ptsge->ImageOffset = 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16   861  	ptsge->ImageSize = cpu_to_le32(fwlen);
^1da177e4c3f41 Linus Torvalds  2005-04-16   862  
^1da177e4c3f41 Linus Torvalds  2005-04-16   863  	/* Add the SGL
^1da177e4c3f41 Linus Torvalds  2005-04-16   864  	 */
^1da177e4c3f41 Linus Torvalds  2005-04-16   865  
^1da177e4c3f41 Linus Torvalds  2005-04-16   866  	/*
^1da177e4c3f41 Linus Torvalds  2005-04-16   867  	 * Need to kmalloc area(s) for holding firmware image bytes.
^1da177e4c3f41 Linus Torvalds  2005-04-16   868  	 * But we need to do it piece meal, using a proper
^1da177e4c3f41 Linus Torvalds  2005-04-16   869  	 * scatter gather list (with 128kB MAX hunks).
^1da177e4c3f41 Linus Torvalds  2005-04-16   870  	 *
^1da177e4c3f41 Linus Torvalds  2005-04-16   871  	 * A practical limit here might be # of sg hunks that fit into
^1da177e4c3f41 Linus Torvalds  2005-04-16   872  	 * a single IOC request frame; 12 or 8 (see below), so:
^1da177e4c3f41 Linus Torvalds  2005-04-16   873  	 * For FC9xx: 12 x 128kB == 1.5 mB (max)
^1da177e4c3f41 Linus Torvalds  2005-04-16   874  	 * For C1030:  8 x 128kB == 1   mB (max)
^1da177e4c3f41 Linus Torvalds  2005-04-16   875  	 * We could support chaining, but things get ugly(ier:)
^1da177e4c3f41 Linus Torvalds  2005-04-16   876  	 *
^1da177e4c3f41 Linus Torvalds  2005-04-16   877  	 * Set the sge_offset to the start of the sgl (bytes).
^1da177e4c3f41 Linus Torvalds  2005-04-16   878  	 */
^1da177e4c3f41 Linus Torvalds  2005-04-16   879  	sgdir = 0x04000000;		/* IOC will READ from sys mem */
^1da177e4c3f41 Linus Torvalds  2005-04-16   880  	sge_offset = sizeof(MPIHeader_t) + sizeof(FWDownloadTCSGE_t);
^1da177e4c3f41 Linus Torvalds  2005-04-16   881  	if ((sgl = kbuf_alloc_2_sgl(fwlen, sgdir, sge_offset,
^1da177e4c3f41 Linus Torvalds  2005-04-16   882  				    &numfrags, &buflist, &sgl_dma, iocp)) == NULL)
^1da177e4c3f41 Linus Torvalds  2005-04-16   883  		return -ENOMEM;
^1da177e4c3f41 Linus Torvalds  2005-04-16   884  
^1da177e4c3f41 Linus Torvalds  2005-04-16   885  	/*
^1da177e4c3f41 Linus Torvalds  2005-04-16   886  	 * We should only need SGL with 2 simple_32bit entries (up to 256 kB)
^1da177e4c3f41 Linus Torvalds  2005-04-16   887  	 * for FC9xx f/w image, but calculate max number of sge hunks
^1da177e4c3f41 Linus Torvalds  2005-04-16   888  	 * we can fit into a request frame, and limit ourselves to that.
^1da177e4c3f41 Linus Torvalds  2005-04-16   889  	 * (currently no chain support)
^1da177e4c3f41 Linus Torvalds  2005-04-16   890  	 * maxfrags = (Request Size - FWdownload Size ) / Size of 32 bit SGE
^1da177e4c3f41 Linus Torvalds  2005-04-16   891  	 *	Request		maxfrags
^1da177e4c3f41 Linus Torvalds  2005-04-16   892  	 *	128		12
^1da177e4c3f41 Linus Torvalds  2005-04-16   893  	 *	96		8
^1da177e4c3f41 Linus Torvalds  2005-04-16   894  	 *	64		4
^1da177e4c3f41 Linus Torvalds  2005-04-16   895  	 */
14d0f0b063f536 Kashyap, Desai  2009-05-29   896  	maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) -
14d0f0b063f536 Kashyap, Desai  2009-05-29   897  			sizeof(FWDownloadTCSGE_t))
14d0f0b063f536 Kashyap, Desai  2009-05-29   898  			/ iocp->SGE_size;
^1da177e4c3f41 Linus Torvalds  2005-04-16   899  	if (numfrags > maxfrags) {
^1da177e4c3f41 Linus Torvalds  2005-04-16   900  		ret = -EMLINK;
^1da177e4c3f41 Linus Torvalds  2005-04-16   901  		goto fwdl_out;
^1da177e4c3f41 Linus Torvalds  2005-04-16   902  	}
^1da177e4c3f41 Linus Torvalds  2005-04-16   903  
09120a8cd38dbd Prakash, Sathya 2007-07-24   904  	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: sgl buffer = %p, sgfrags = %d\n",
09120a8cd38dbd Prakash, Sathya 2007-07-24   905  	    iocp->name, sgl, numfrags));
^1da177e4c3f41 Linus Torvalds  2005-04-16   906  
^1da177e4c3f41 Linus Torvalds  2005-04-16   907  	/*
^1da177e4c3f41 Linus Torvalds  2005-04-16   908  	 * Parse SG list, copying sgl itself,
^1da177e4c3f41 Linus Torvalds  2005-04-16   909  	 * plus f/w image hunks from user space as we go...
^1da177e4c3f41 Linus Torvalds  2005-04-16   910  	 */
^1da177e4c3f41 Linus Torvalds  2005-04-16   911  	ret = -EFAULT;
^1da177e4c3f41 Linus Torvalds  2005-04-16   912  	sgIn = sgl;
^1da177e4c3f41 Linus Torvalds  2005-04-16   913  	bl = buflist;
^1da177e4c3f41 Linus Torvalds  2005-04-16   914  	for (i=0; i < numfrags; i++) {
^1da177e4c3f41 Linus Torvalds  2005-04-16   915  
^1da177e4c3f41 Linus Torvalds  2005-04-16   916  		/* Get the SGE type: 0 - TCSGE, 3 - Chain, 1 - Simple SGE
^1da177e4c3f41 Linus Torvalds  2005-04-16   917  		 * Skip everything but Simple. If simple, copy from
^1da177e4c3f41 Linus Torvalds  2005-04-16   918  		 *	user space into kernel space.
^1da177e4c3f41 Linus Torvalds  2005-04-16   919  		 * Note: we should not have anything but Simple as
^1da177e4c3f41 Linus Torvalds  2005-04-16   920  		 *	Chain SGE are illegal.
^1da177e4c3f41 Linus Torvalds  2005-04-16   921  		 */
^1da177e4c3f41 Linus Torvalds  2005-04-16   922  		nib = (sgIn->FlagsLength & 0x30000000) >> 28;
^1da177e4c3f41 Linus Torvalds  2005-04-16   923  		if (nib == 0 || nib == 3) {
^1da177e4c3f41 Linus Torvalds  2005-04-16   924  			;
^1da177e4c3f41 Linus Torvalds  2005-04-16   925  		} else if (sgIn->Address) {
14d0f0b063f536 Kashyap, Desai  2009-05-29   926  			iocp->add_sge(sgOut, sgIn->FlagsLength, sgIn->Address);
^1da177e4c3f41 Linus Torvalds  2005-04-16   927  			n++;
^1da177e4c3f41 Linus Torvalds  2005-04-16   928  			if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
29dd3609f2fc70 Eric Moore      2007-09-14   929  				printk(MYIOC_s_ERR_FMT "%s@%d::_ioctl_fwdl - "
^1da177e4c3f41 Linus Torvalds  2005-04-16   930  					"Unable to copy f/w buffer hunk#%d @ %p\n",
29dd3609f2fc70 Eric Moore      2007-09-14   931  					iocp->name, __FILE__, __LINE__, n, ufwbuf);
^1da177e4c3f41 Linus Torvalds  2005-04-16   932  				goto fwdl_out;
^1da177e4c3f41 Linus Torvalds  2005-04-16   933  			}
^1da177e4c3f41 Linus Torvalds  2005-04-16   934  			fw_bytes_copied += bl->len;
^1da177e4c3f41 Linus Torvalds  2005-04-16   935  		}
^1da177e4c3f41 Linus Torvalds  2005-04-16   936  		sgIn++;
^1da177e4c3f41 Linus Torvalds  2005-04-16   937  		bl++;
14d0f0b063f536 Kashyap, Desai  2009-05-29   938  		sgOut += iocp->SGE_size;
^1da177e4c3f41 Linus Torvalds  2005-04-16   939  	}
^1da177e4c3f41 Linus Torvalds  2005-04-16   940  
09120a8cd38dbd Prakash, Sathya 2007-07-24   941  	DBG_DUMP_FW_DOWNLOAD(iocp, (u32 *)mf, numfrags);
^1da177e4c3f41 Linus Torvalds  2005-04-16   942  
^1da177e4c3f41 Linus Torvalds  2005-04-16   943  	/*
^1da177e4c3f41 Linus Torvalds  2005-04-16   944  	 * Finally, perform firmware download.
^1da177e4c3f41 Linus Torvalds  2005-04-16   945  	 */
946cbf040adb9d Moore, Eric     2006-02-02   946  	ReplyMsg = NULL;
ea2a788de4ce5e Kashyap, Desai  2009-05-29   947  	SET_MGMT_MSG_CONTEXT(iocp->ioctl_cmds.msg_context, dlmsg->MsgContext);
ea2a788de4ce5e Kashyap, Desai  2009-05-29   948  	INITIALIZE_MGMT_STATUS(iocp->ioctl_cmds.status)
b07cb166c26273 Mark Balantzyan 2019-08-14   949  	mutex_lock(&mpctl_mutex);
^1da177e4c3f41 Linus Torvalds  2005-04-16   950  	mpt_put_msg_frame(mptctl_id, iocp, mf);
b07cb166c26273 Mark Balantzyan 2019-08-14   951  	mutex_lock(&mpctl_mutex);
^1da177e4c3f41 Linus Torvalds  2005-04-16   952  
^1da177e4c3f41 Linus Torvalds  2005-04-16   953  	/* Now wait for the command to complete */
ea2a788de4ce5e Kashyap, Desai  2009-05-29   954  retry_wait:
ea2a788de4ce5e Kashyap, Desai  2009-05-29   955  	timeleft = wait_for_completion_timeout(&iocp->ioctl_cmds.done, HZ*60);
ea2a788de4ce5e Kashyap, Desai  2009-05-29   956  	if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
ea2a788de4ce5e Kashyap, Desai  2009-05-29   957  		ret = -ETIME;
ea2a788de4ce5e Kashyap, Desai  2009-05-29   958  		printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __func__);
ea2a788de4ce5e Kashyap, Desai  2009-05-29   959  		if (iocp->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
ea2a788de4ce5e Kashyap, Desai  2009-05-29   960  			mpt_free_msg_frame(iocp, mf);
ea2a788de4ce5e Kashyap, Desai  2009-05-29   961  			goto fwdl_out;
ea2a788de4ce5e Kashyap, Desai  2009-05-29   962  		}
97009a29e8c999 Kei Tokunaga    2010-06-22   963  		if (!timeleft) {
97009a29e8c999 Kei Tokunaga    2010-06-22   964  			printk(MYIOC_s_WARN_FMT
97009a29e8c999 Kei Tokunaga    2010-06-22   965  			       "FW download timeout, doorbell=0x%08x\n",
97009a29e8c999 Kei Tokunaga    2010-06-22   966  			       iocp->name, mpt_GetIocState(iocp, 0));
ea2a788de4ce5e Kashyap, Desai  2009-05-29   967  			mptctl_timeout_expired(iocp, mf);
97009a29e8c999 Kei Tokunaga    2010-06-22   968  		} else
ea2a788de4ce5e Kashyap, Desai  2009-05-29   969  			goto retry_wait;
ea2a788de4ce5e Kashyap, Desai  2009-05-29   970  		goto fwdl_out;
ea2a788de4ce5e Kashyap, Desai  2009-05-29   971  	}
^1da177e4c3f41 Linus Torvalds  2005-04-16   972  
ea2a788de4ce5e Kashyap, Desai  2009-05-29   973  	if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
ea2a788de4ce5e Kashyap, Desai  2009-05-29   974  		printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __func__);
ea2a788de4ce5e Kashyap, Desai  2009-05-29   975  		mpt_free_msg_frame(iocp, mf);
^1da177e4c3f41 Linus Torvalds  2005-04-16   976  		ret = -ENODATA;
^1da177e4c3f41 Linus Torvalds  2005-04-16   977  		goto fwdl_out;
^1da177e4c3f41 Linus Torvalds  2005-04-16   978  	}
^1da177e4c3f41 Linus Torvalds  2005-04-16   979  
^1da177e4c3f41 Linus Torvalds  2005-04-16   980  	if (sgl)
^1da177e4c3f41 Linus Torvalds  2005-04-16   981  		kfree_sgl(sgl, sgl_dma, buflist, iocp);
^1da177e4c3f41 Linus Torvalds  2005-04-16   982  
ea2a788de4ce5e Kashyap, Desai  2009-05-29   983  	ReplyMsg = (pFWDownloadReply_t)iocp->ioctl_cmds.reply;
^1da177e4c3f41 Linus Torvalds  2005-04-16   984  	iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
^1da177e4c3f41 Linus Torvalds  2005-04-16   985  	if (iocstat == MPI_IOCSTATUS_SUCCESS) {
25985edcedea63 Lucas De Marchi 2011-03-30   986  		printk(MYIOC_s_INFO_FMT "F/W update successful!\n", iocp->name);
^1da177e4c3f41 Linus Torvalds  2005-04-16   987  		return 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16   988  	} else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) {
29dd3609f2fc70 Eric Moore      2007-09-14   989  		printk(MYIOC_s_WARN_FMT "Hmmm...  F/W download not supported!?!\n",
29dd3609f2fc70 Eric Moore      2007-09-14   990  			iocp->name);
29dd3609f2fc70 Eric Moore      2007-09-14   991  		printk(MYIOC_s_WARN_FMT "(time to go bang on somebodies door)\n",
^1da177e4c3f41 Linus Torvalds  2005-04-16   992  			iocp->name);
^1da177e4c3f41 Linus Torvalds  2005-04-16   993  		return -EBADRQC;
^1da177e4c3f41 Linus Torvalds  2005-04-16   994  	} else if (iocstat == MPI_IOCSTATUS_BUSY) {
29dd3609f2fc70 Eric Moore      2007-09-14   995  		printk(MYIOC_s_WARN_FMT "IOC_BUSY!\n", iocp->name);
29dd3609f2fc70 Eric Moore      2007-09-14   996  		printk(MYIOC_s_WARN_FMT "(try again later?)\n", iocp->name);
^1da177e4c3f41 Linus Torvalds  2005-04-16   997  		return -EBUSY;
^1da177e4c3f41 Linus Torvalds  2005-04-16   998  	} else {
29dd3609f2fc70 Eric Moore      2007-09-14   999  		printk(MYIOC_s_WARN_FMT "ioctl_fwdl() returned [bad] status = %04xh\n",
^1da177e4c3f41 Linus Torvalds  2005-04-16  1000  			iocp->name, iocstat);
29dd3609f2fc70 Eric Moore      2007-09-14  1001  		printk(MYIOC_s_WARN_FMT "(bad VooDoo)\n", iocp->name);
^1da177e4c3f41 Linus Torvalds  2005-04-16  1002  		return -ENOMSG;
^1da177e4c3f41 Linus Torvalds  2005-04-16  1003  	}
^1da177e4c3f41 Linus Torvalds  2005-04-16  1004  	return 0;
^1da177e4c3f41 Linus Torvalds  2005-04-16  1005  
^1da177e4c3f41 Linus Torvalds  2005-04-16  1006  fwdl_out:
ea2a788de4ce5e Kashyap, Desai  2009-05-29  1007  
ea2a788de4ce5e Kashyap, Desai  2009-05-29  1008  	CLEAR_MGMT_STATUS(iocp->ioctl_cmds.status);
ea2a788de4ce5e Kashyap, Desai  2009-05-29  1009  	SET_MGMT_MSG_CONTEXT(iocp->ioctl_cmds.msg_context, 0);
^1da177e4c3f41 Linus Torvalds  2005-04-16  1010          kfree_sgl(sgl, sgl_dma, buflist, iocp);
^1da177e4c3f41 Linus Torvalds  2005-04-16  1011  	return ret;
^1da177e4c3f41 Linus Torvalds  2005-04-16  1012  }
^1da177e4c3f41 Linus Torvalds  2005-04-16  1013  

:::::: The code at line 820 was first introduced by commit :::::: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Linux-2.6.12-rc2

:::::: TO: Linus Torvalds <[email protected]> :::::: CC: Linus Torvalds <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation