diff mbox

[08/29] scsi: aacraid: Move code to wait for IO completion to shutdown func

Message ID 20171221173420.8213-9-RaghavaAditya.Renukunta@microsemi.com (mailing list archive)
State Superseded
Headers show

Commit Message

Raghava Aditya Renukunta Dec. 21, 2017, 5:33 p.m. UTC
Ideally driver needs to wait for IO to be submitted or responded to before
shutdown.

Move code to wait for IO completion into shutdown path

Signed-off-by: Raghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com>
---
 drivers/scsi/aacraid/comminit.c | 36 ++++++++++++++++++++++++++++++++++++
 drivers/scsi/aacraid/commsup.c  | 25 -------------------------
 2 files changed, 36 insertions(+), 25 deletions(-)

Comments

Bart Van Assche Dec. 21, 2017, 5:59 p.m. UTC | #1
On Thu, 2017-12-21 at 09:33 -0800, Raghava Aditya Renukunta wrote:
> +static void aac_wait_for_io_completion(struct aac_dev *aac)

> +{

> +	unsigned long flagv = 0;

> +	int i = 0;

> +

> +	for (i = 60; i; --i) {

> +		struct scsi_device *dev;

> +		struct scsi_cmnd *command;

> +		int active = 0;

> +

> +		__shost_for_each_device(dev, aac->scsi_host_ptr) {

> +			spin_lock_irqsave(&dev->list_lock, flagv);

> +			list_for_each_entry(command, &dev->cmd_list, list) {

> +				if (command->SCp.phase == AAC_OWNER_FIRMWARE) {

> +					active++;

> +					break;

> +				}

> +			}

> +			spin_unlock_irqrestore(&dev->list_lock, flagv);

> +			if (active)

> +				break;

> +

> +		}

> +		/*

> +		 * We can exit If all the commands are complete

> +		 */

> +		if (active == 0)

> +			break;

> +		ssleep(1);

> +	}

> +}


Have you considered to call scsi_target_block() and scsi_target_unblock() instead
of implementing functionality like the above in a SCSI LLD?

Thanks,

Bart.
Bart Van Assche Dec. 22, 2017, 4:26 p.m. UTC | #2
On Thu, 2017-12-21 at 17:59 +0000, Bart Van Assche wrote:
> On Thu, 2017-12-21 at 09:33 -0800, Raghava Aditya Renukunta wrote:

> > +static void aac_wait_for_io_completion(struct aac_dev *aac)

> > +{

> > +	unsigned long flagv = 0;

> > +	int i = 0;

> > +

> > +	for (i = 60; i; --i) {

> > +		struct scsi_device *dev;

> > +		struct scsi_cmnd *command;

> > +		int active = 0;

> > +

> > +		__shost_for_each_device(dev, aac->scsi_host_ptr) {

> > +			spin_lock_irqsave(&dev->list_lock, flagv);

> > +			list_for_each_entry(command, &dev->cmd_list, list) {

> > +				if (command->SCp.phase == AAC_OWNER_FIRMWARE) {

> > +					active++;

> > +					break;

> > +				}

> > +			}

> > +			spin_unlock_irqrestore(&dev->list_lock, flagv);

> > +			if (active)

> > +				break;

> > +

> > +		}

> > +		/*

> > +		 * We can exit If all the commands are complete

> > +		 */

> > +		if (active == 0)

> > +			break;

> > +		ssleep(1);

> > +	}

> > +}

> 

> Have you considered to call scsi_target_block() and scsi_target_unblock() instead

> of implementing functionality like the above in a SCSI LLD?


(replying to my own e-mail)

It seems like I misread your code - calling scsi_target_block() and
scsi_target_unblock() would not be sufficient. But calling blk_mq_freeze_queue()
and blk_mq_unfreeze_queue() should be sufficient. The following commit made these
functions work not only for scsi-mq but also for legacy scsi queues: commit
055f6e18e08f ("block: Make q_usage_counter also track legacy requests").

Bart.
Raghava Aditya Renukunta Dec. 27, 2017, 1:38 a.m. UTC | #3
> -----Original Message-----

> From: Bart Van Assche [mailto:Bart.VanAssche@wdc.com]

> Sent: Friday, December 22, 2017 8:27 AM

> To: jejb@linux.vnet.ibm.com; Raghava Aditya Renukunta

> <RaghavaAditya.Renukunta@microsemi.com>; linux-scsi@vger.kernel.org;

> martin.petersen@oracle.com

> Cc: dl-esc-Aacraid Linux Driver <aacraid@microsemi.com>;

> gpiccoli@linux.vnet.ibm.com; Tom White <tom.white@microsemi.com>;

> Scott Benesh <scott.benesh@microsemi.com>

> Subject: Re: [PATCH 08/29] scsi: aacraid: Move code to wait for IO completion

> to shutdown func

> 

> EXTERNAL EMAIL

> 

> 

> On Thu, 2017-12-21 at 17:59 +0000, Bart Van Assche wrote:

> > On Thu, 2017-12-21 at 09:33 -0800, Raghava Aditya Renukunta wrote:

> > > +static void aac_wait_for_io_completion(struct aac_dev *aac)

> > > +{

> > > +   unsigned long flagv = 0;

> > > +   int i = 0;

> > > +

> > > +   for (i = 60; i; --i) {

> > > +           struct scsi_device *dev;

> > > +           struct scsi_cmnd *command;

> > > +           int active = 0;

> > > +

> > > +           __shost_for_each_device(dev, aac->scsi_host_ptr) {

> > > +                   spin_lock_irqsave(&dev->list_lock, flagv);

> > > +                   list_for_each_entry(command, &dev->cmd_list, list) {

> > > +                           if (command->SCp.phase == AAC_OWNER_FIRMWARE) {

> > > +                                   active++;

> > > +                                   break;

> > > +                           }

> > > +                   }

> > > +                   spin_unlock_irqrestore(&dev->list_lock, flagv);

> > > +                   if (active)

> > > +                           break;

> > > +

> > > +           }

> > > +           /*

> > > +            * We can exit If all the commands are complete

> > > +            */

> > > +           if (active == 0)

> > > +                   break;

> > > +           ssleep(1);

> > > +   }

> > > +}

> >

> > Have you considered to call scsi_target_block() and scsi_target_unblock()

> instead

> > of implementing functionality like the above in a SCSI LLD?

> 

> (replying to my own e-mail)

> 

> It seems like I misread your code - calling scsi_target_block() and

> scsi_target_unblock() would not be sufficient. But calling

> blk_mq_freeze_queue()

> and blk_mq_unfreeze_queue() should be sufficient. The following commit

> made these

> functions work not only for scsi-mq but also for legacy scsi queues: commit

> 055f6e18e08f ("block: Make q_usage_counter also track legacy requests").


Hi Bart,
That piece of code is very much legacy  that I removed and placed in a function that would benefit all code paths that shutdown the controller. The 2 functions you mentioned are a god send but I think I will hold off on this patchset and do a full refactor with them in the next patchset. ( I suspect that I will have to touch a bunch of different code paths and perform extensive testing to be fully confident)

Regards,
Raghava Aditya

> Bart.
diff mbox

Patch

diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 9eff246..0dc7b5a 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -42,6 +42,8 @@ 
 #include <linux/completion.h>
 #include <linux/mm.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
 
 #include "aacraid.h"
 
@@ -284,6 +286,38 @@  static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem,
 	q->entries = qsize;
 }
 
+static void aac_wait_for_io_completion(struct aac_dev *aac)
+{
+	unsigned long flagv = 0;
+	int i = 0;
+
+	for (i = 60; i; --i) {
+		struct scsi_device *dev;
+		struct scsi_cmnd *command;
+		int active = 0;
+
+		__shost_for_each_device(dev, aac->scsi_host_ptr) {
+			spin_lock_irqsave(&dev->list_lock, flagv);
+			list_for_each_entry(command, &dev->cmd_list, list) {
+				if (command->SCp.phase == AAC_OWNER_FIRMWARE) {
+					active++;
+					break;
+				}
+			}
+			spin_unlock_irqrestore(&dev->list_lock, flagv);
+			if (active)
+				break;
+
+		}
+		/*
+		 * We can exit If all the commands are complete
+		 */
+		if (active == 0)
+			break;
+		ssleep(1);
+	}
+}
+
 /**
  *	aac_send_shutdown		-	shutdown an adapter
  *	@dev: Adapter to shutdown
@@ -306,6 +340,8 @@  int aac_send_shutdown(struct aac_dev * dev)
 		mutex_unlock(&dev->ioctl_mutex);
 	}
 
+	aac_wait_for_io_completion(dev);
+
 	fibctx = aac_fib_alloc(dev);
 	if (!fibctx)
 		return -ENOMEM;
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 32b8bdb..9840bd3 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -1701,31 +1701,6 @@  int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
 	 */
 	host = aac->scsi_host_ptr;
 	scsi_block_requests(host);
-	if (forced < 2) for (retval = 60; retval; --retval) {
-		struct scsi_device * dev;
-		struct scsi_cmnd * command;
-		int active = 0;
-
-		__shost_for_each_device(dev, host) {
-			spin_lock_irqsave(&dev->list_lock, flagv);
-			list_for_each_entry(command, &dev->cmd_list, list) {
-				if (command->SCp.phase == AAC_OWNER_FIRMWARE) {
-					active++;
-					break;
-				}
-			}
-			spin_unlock_irqrestore(&dev->list_lock, flagv);
-			if (active)
-				break;
-
-		}
-		/*
-		 * We can exit If all the commands are complete
-		 */
-		if (active == 0)
-			break;
-		ssleep(1);
-	}
 
 	/* Quiesce build, flush cache, write through mode */
 	if (forced < 2)