Re: [PATCH v3 60/77] ncr5380: Implement new eh_abort_handler
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
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
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
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/