Re: [PATCH v3 60/77] ncr5380: Implement new eh_abort_handler

2015-12-21 Thread Hannes Reinecke

On 12/22/2015 02:18 AM, Finn Thain wrote:

Introduce a new eh_abort_handler implementation. This one attempts to
follow all of the rules relating to EH handlers. There is still a known
bug: during selection, a command becomes invisible to the EH handlers
because it only appears in a pointer on the stack of a different thread.
This bug is addressed in a subsequent patch.

Signed-off-by: Finn Thain 

---
  drivers/scsi/NCR5380.c   |  155 ++
  drivers/scsi/atari_NCR5380.c |  157 
++-
  2 files changed, 282 insertions(+), 30 deletions(-)


Reviewed-by: Hannes Reinecke 

Cheers,

Hannes
--
Dr. Hannes Reinecke   zSeries & Storage
h...@suse.de  +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3 60/77] ncr5380: Implement new eh_abort_handler

2015-12-21 Thread Finn Thain
Introduce a new eh_abort_handler implementation. This one attempts to
follow all of the rules relating to EH handlers. There is still a known
bug: during selection, a command becomes invisible to the EH handlers
because it only appears in a pointer on the stack of a different thread.
This bug is addressed in a subsequent patch.

Signed-off-by: Finn Thain 

---
 drivers/scsi/NCR5380.c   |  155 ++
 drivers/scsi/atari_NCR5380.c |  157 ++-
 2 files changed, 282 insertions(+), 30 deletions(-)

Index: linux/drivers/scsi/atari_NCR5380.c
===
--- linux.orig/drivers/scsi/atari_NCR5380.c 2015-12-22 12:17:03.0 
+1100
+++ linux/drivers/scsi/atari_NCR5380.c  2015-12-22 12:17:05.0 +1100
@@ -2480,41 +2480,168 @@ static void NCR5380_reselect(struct Scsi
 }
 
 
-/*
- * Function : int NCR5380_abort (struct scsi_cmnd *cmd)
+/**
+ * list_find_cmd - test for presence of a command in a linked list
+ * @haystack: list of commands
+ * @needle: command to search for
+ */
+
+static bool list_find_cmd(struct list_head *haystack,
+  struct scsi_cmnd *needle)
+{
+   struct NCR5380_cmd *ncmd;
+
+   list_for_each_entry(ncmd, haystack, list)
+   if (NCR5380_to_scmd(ncmd) == needle)
+   return true;
+   return false;
+}
+
+/**
+ * list_remove_cmd - remove a command from linked list
+ * @haystack: list of commands
+ * @needle: command to remove
+ */
+
+static bool list_del_cmd(struct list_head *haystack,
+ struct scsi_cmnd *needle)
+{
+   if (list_find_cmd(haystack, needle)) {
+   struct NCR5380_cmd *ncmd = scsi_cmd_priv(needle);
+
+   list_del(>list);
+   return true;
+   }
+   return false;
+}
+
+/**
+ * NCR5380_abort - scsi host eh_abort_handler() method
+ * @cmd: the command to be aborted
  *
- * Purpose : abort a command
+ * Try to abort a given command by removing it from queues and/or sending
+ * the target an abort message. This may not succeed in causing a target
+ * to abort the command. Nonetheless, the low-level driver must forget about
+ * the command because the mid-layer reclaims it and it may be re-issued.
  *
- * Inputs : cmd - the scsi_cmnd to abort, code - code to set the
- * host byte of the result field to, if zero DID_ABORTED is
- * used.
+ * The normal path taken by a command is as follows. For EH we trace this
+ * same path to locate and abort the command.
  *
- * Returns : SUCCESS - success, FAILED on failure.
+ * unissued -> selecting -> [unissued -> selecting ->]... connected ->
+ * [disconnected -> connected ->]...
+ * [autosense -> connected ->] done
  *
- * XXX - there is no way to abort the command that is currently
- *  connected, you have to wait for it to complete.  If this is
- *  a problem, we could implement longjmp() / setjmp(), setjmp()
- *  called where the loop started in NCR5380_main().
+ * If cmd is unissued then just remove it.
+ * If cmd is disconnected, try to select the target.
+ * If cmd is connected, try to send an abort message.
+ * If cmd is waiting for autosense, give it a chance to complete but check
+ * that it isn't left connected.
+ * If cmd was not found at all then presumably it has already been completed,
+ * in which case return SUCCESS to try to avoid further EH measures.
+ * If the command has not completed yet, we must not fail to find it.
  */
 
-static
-int NCR5380_abort(struct scsi_cmnd *cmd)
+static int NCR5380_abort(struct scsi_cmnd *cmd)
 {
struct Scsi_Host *instance = cmd->device->host;
struct NCR5380_hostdata *hostdata = shost_priv(instance);
unsigned long flags;
+   int result = SUCCESS;
 
spin_lock_irqsave(>lock, flags);
 
 #if (NDEBUG & NDEBUG_ANY)
-   scmd_printk(KERN_INFO, cmd, "aborting command\n");
+   scmd_printk(KERN_INFO, cmd, __func__);
 #endif
NCR5380_dprint(NDEBUG_ANY, instance);
NCR5380_dprint_phase(NDEBUG_ANY, instance);
 
+   if (list_del_cmd(>unissued, cmd)) {
+   dsprintk(NDEBUG_ABORT, instance,
+"abort: removed %p from issue queue\n", cmd);
+   cmd->result = DID_ABORT << 16;
+   cmd->scsi_done(cmd); /* No tag or busy flag to worry about */
+   }
+
+   if (list_del_cmd(>disconnected, cmd)) {
+   dsprintk(NDEBUG_ABORT, instance,
+"abort: removed %p from disconnected list\n", cmd);
+   cmd->result = DID_ERROR << 16;
+   if (!hostdata->connected)
+   NCR5380_select(instance, cmd);
+   if (hostdata->connected != cmd) {
+   complete_cmd(instance, cmd);
+   result = FAILED;
+   goto out;
+   }
+   }
+
+   if (hostdata->connected == cmd) {

[PATCH v3 60/77] ncr5380: Implement new eh_abort_handler

2015-12-21 Thread Finn Thain
Introduce a new eh_abort_handler implementation. This one attempts to
follow all of the rules relating to EH handlers. There is still a known
bug: during selection, a command becomes invisible to the EH handlers
because it only appears in a pointer on the stack of a different thread.
This bug is addressed in a subsequent patch.

Signed-off-by: Finn Thain 

---
 drivers/scsi/NCR5380.c   |  155 ++
 drivers/scsi/atari_NCR5380.c |  157 ++-
 2 files changed, 282 insertions(+), 30 deletions(-)

Index: linux/drivers/scsi/atari_NCR5380.c
===
--- linux.orig/drivers/scsi/atari_NCR5380.c 2015-12-22 12:17:03.0 
+1100
+++ linux/drivers/scsi/atari_NCR5380.c  2015-12-22 12:17:05.0 +1100
@@ -2480,41 +2480,168 @@ static void NCR5380_reselect(struct Scsi
 }
 
 
-/*
- * Function : int NCR5380_abort (struct scsi_cmnd *cmd)
+/**
+ * list_find_cmd - test for presence of a command in a linked list
+ * @haystack: list of commands
+ * @needle: command to search for
+ */
+
+static bool list_find_cmd(struct list_head *haystack,
+  struct scsi_cmnd *needle)
+{
+   struct NCR5380_cmd *ncmd;
+
+   list_for_each_entry(ncmd, haystack, list)
+   if (NCR5380_to_scmd(ncmd) == needle)
+   return true;
+   return false;
+}
+
+/**
+ * list_remove_cmd - remove a command from linked list
+ * @haystack: list of commands
+ * @needle: command to remove
+ */
+
+static bool list_del_cmd(struct list_head *haystack,
+ struct scsi_cmnd *needle)
+{
+   if (list_find_cmd(haystack, needle)) {
+   struct NCR5380_cmd *ncmd = scsi_cmd_priv(needle);
+
+   list_del(>list);
+   return true;
+   }
+   return false;
+}
+
+/**
+ * NCR5380_abort - scsi host eh_abort_handler() method
+ * @cmd: the command to be aborted
  *
- * Purpose : abort a command
+ * Try to abort a given command by removing it from queues and/or sending
+ * the target an abort message. This may not succeed in causing a target
+ * to abort the command. Nonetheless, the low-level driver must forget about
+ * the command because the mid-layer reclaims it and it may be re-issued.
  *
- * Inputs : cmd - the scsi_cmnd to abort, code - code to set the
- * host byte of the result field to, if zero DID_ABORTED is
- * used.
+ * The normal path taken by a command is as follows. For EH we trace this
+ * same path to locate and abort the command.
  *
- * Returns : SUCCESS - success, FAILED on failure.
+ * unissued -> selecting -> [unissued -> selecting ->]... connected ->
+ * [disconnected -> connected ->]...
+ * [autosense -> connected ->] done
  *
- * XXX - there is no way to abort the command that is currently
- *  connected, you have to wait for it to complete.  If this is
- *  a problem, we could implement longjmp() / setjmp(), setjmp()
- *  called where the loop started in NCR5380_main().
+ * If cmd is unissued then just remove it.
+ * If cmd is disconnected, try to select the target.
+ * If cmd is connected, try to send an abort message.
+ * If cmd is waiting for autosense, give it a chance to complete but check
+ * that it isn't left connected.
+ * If cmd was not found at all then presumably it has already been completed,
+ * in which case return SUCCESS to try to avoid further EH measures.
+ * If the command has not completed yet, we must not fail to find it.
  */
 
-static
-int NCR5380_abort(struct scsi_cmnd *cmd)
+static int NCR5380_abort(struct scsi_cmnd *cmd)
 {
struct Scsi_Host *instance = cmd->device->host;
struct NCR5380_hostdata *hostdata = shost_priv(instance);
unsigned long flags;
+   int result = SUCCESS;
 
spin_lock_irqsave(>lock, flags);
 
 #if (NDEBUG & NDEBUG_ANY)
-   scmd_printk(KERN_INFO, cmd, "aborting command\n");
+   scmd_printk(KERN_INFO, cmd, __func__);
 #endif
NCR5380_dprint(NDEBUG_ANY, instance);
NCR5380_dprint_phase(NDEBUG_ANY, instance);
 
+   if (list_del_cmd(>unissued, cmd)) {
+   dsprintk(NDEBUG_ABORT, instance,
+"abort: removed %p from issue queue\n", cmd);
+   cmd->result = DID_ABORT << 16;
+   cmd->scsi_done(cmd); /* No tag or busy flag to worry about */
+   }
+
+   if (list_del_cmd(>disconnected, cmd)) {
+   dsprintk(NDEBUG_ABORT, instance,
+"abort: removed %p from disconnected list\n", cmd);
+   cmd->result = DID_ERROR << 16;
+   if (!hostdata->connected)
+   NCR5380_select(instance, cmd);
+   if (hostdata->connected != cmd) {
+   complete_cmd(instance, cmd);
+   result = FAILED;
+   goto out;
+   }
+   }
+
+   if 

Re: [PATCH v3 60/77] ncr5380: Implement new eh_abort_handler

2015-12-21 Thread Hannes Reinecke

On 12/22/2015 02:18 AM, Finn Thain wrote:

Introduce a new eh_abort_handler implementation. This one attempts to
follow all of the rules relating to EH handlers. There is still a known
bug: during selection, a command becomes invisible to the EH handlers
because it only appears in a pointer on the stack of a different thread.
This bug is addressed in a subsequent patch.

Signed-off-by: Finn Thain 

---
  drivers/scsi/NCR5380.c   |  155 ++
  drivers/scsi/atari_NCR5380.c |  157 
++-
  2 files changed, 282 insertions(+), 30 deletions(-)


Reviewed-by: Hannes Reinecke 

Cheers,

Hannes
--
Dr. Hannes Reinecke   zSeries & Storage
h...@suse.de  +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/