Commands subject to exception handling are to be returned to the scsi
mid-layer. Make sure that the various command pointers and command lists
in the low-level driver are correctly cleansed of affected commands.

This fixes some bugs that I accidentally introduced in v4.5-rc1 including
the removal of INIT_LIST_HEAD for the 'autosense' and 'disconnected'
command lists, and the possible NULL pointer dereference in
NCR5380_bus_reset() that was reported by Dan Carpenter.

hostdata->sensing may also point to an affected command so this pointer
also has to be cleared. The abort handler calls complete_cmd() to take
care of this; let's have the bus reset handler do the same.

The issue queue may also contain an affected command. If so, remove it.
This also follows the abort handler logic.

Reported-by: Dan Carpenter <dan.carpen...@oracle.com>
Fixes: 62717f537e1b ("ncr5380: Implement new eh_bus_reset_handler")
Tested-by: Michael Schmitz <schmitz...@gmail.com>
Signed-off-by: Finn Thain <fth...@telegraphics.com.au>

---
 drivers/scsi/NCR5380.c       |   19 ++++++++++++-------
 drivers/scsi/atari_NCR5380.c |   19 ++++++++++++-------
 2 files changed, 24 insertions(+), 14 deletions(-)

Index: linux/drivers/scsi/NCR5380.c
===================================================================
--- linux.orig/drivers/scsi/NCR5380.c   2016-02-23 10:06:56.000000000 +1100
+++ linux/drivers/scsi/NCR5380.c        2016-02-23 10:06:56.000000000 +1100
@@ -2450,7 +2450,16 @@ static int NCR5380_bus_reset(struct scsi
         * commands!
         */
 
-       hostdata->selecting = NULL;
+       if (list_del_cmd(&hostdata->unissued, cmd)) {
+               cmd->result = DID_RESET << 16;
+               cmd->scsi_done(cmd);
+       }
+
+       if (hostdata->selecting) {
+               hostdata->selecting->result = DID_RESET << 16;
+               complete_cmd(instance, hostdata->selecting);
+               hostdata->selecting = NULL;
+       }
 
        list_for_each_entry(ncmd, &hostdata->disconnected, list) {
                struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
@@ -2458,6 +2467,7 @@ static int NCR5380_bus_reset(struct scsi
                set_host_byte(cmd, DID_RESET);
                cmd->scsi_done(cmd);
        }
+       INIT_LIST_HEAD(&hostdata->disconnected);
 
        list_for_each_entry(ncmd, &hostdata->autosense, list) {
                struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
@@ -2465,6 +2475,7 @@ static int NCR5380_bus_reset(struct scsi
                set_host_byte(cmd, DID_RESET);
                cmd->scsi_done(cmd);
        }
+       INIT_LIST_HEAD(&hostdata->autosense);
 
        if (hostdata->connected) {
                set_host_byte(hostdata->connected, DID_RESET);
@@ -2472,12 +2483,6 @@ static int NCR5380_bus_reset(struct scsi
                hostdata->connected = NULL;
        }
 
-       if (hostdata->sensing) {
-               set_host_byte(hostdata->connected, DID_RESET);
-               complete_cmd(instance, hostdata->sensing);
-               hostdata->sensing = NULL;
-       }
-
        for (i = 0; i < 8; ++i)
                hostdata->busy[i] = 0;
 #ifdef REAL_DMA
Index: linux/drivers/scsi/atari_NCR5380.c
===================================================================
--- linux.orig/drivers/scsi/atari_NCR5380.c     2016-02-23 10:06:56.000000000 
+1100
+++ linux/drivers/scsi/atari_NCR5380.c  2016-02-23 10:06:56.000000000 +1100
@@ -2646,7 +2646,16 @@ static int NCR5380_bus_reset(struct scsi
         * commands!
         */
 
-       hostdata->selecting = NULL;
+       if (list_del_cmd(&hostdata->unissued, cmd)) {
+               cmd->result = DID_RESET << 16;
+               cmd->scsi_done(cmd);
+       }
+
+       if (hostdata->selecting) {
+               hostdata->selecting->result = DID_RESET << 16;
+               complete_cmd(instance, hostdata->selecting);
+               hostdata->selecting = NULL;
+       }
 
        list_for_each_entry(ncmd, &hostdata->disconnected, list) {
                struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
@@ -2654,6 +2663,7 @@ static int NCR5380_bus_reset(struct scsi
                set_host_byte(cmd, DID_RESET);
                cmd->scsi_done(cmd);
        }
+       INIT_LIST_HEAD(&hostdata->disconnected);
 
        list_for_each_entry(ncmd, &hostdata->autosense, list) {
                struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
@@ -2661,6 +2671,7 @@ static int NCR5380_bus_reset(struct scsi
                set_host_byte(cmd, DID_RESET);
                cmd->scsi_done(cmd);
        }
+       INIT_LIST_HEAD(&hostdata->autosense);
 
        if (hostdata->connected) {
                set_host_byte(hostdata->connected, DID_RESET);
@@ -2668,12 +2679,6 @@ static int NCR5380_bus_reset(struct scsi
                hostdata->connected = NULL;
        }
 
-       if (hostdata->sensing) {
-               set_host_byte(hostdata->connected, DID_RESET);
-               complete_cmd(instance, hostdata->sensing);
-               hostdata->sensing = NULL;
-       }
-
 #ifdef SUPPORT_TAGS
        free_all_tags(hostdata);
 #endif


--
To unsubscribe from this list: send the line "unsubscribe linux-m68k" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to