Skip to content

Commit 10f5aa0

Browse files
hreineckemartinkpetersen
authored andcommitted
scsi: aic7xxx: Do not reference SCSI command when resetting device
When sending a device reset we should not take a reference to the SCSI command. Signed-off-by: Hannes Reinecke <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Johannes Thumshirn <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 958230b commit 10f5aa0

File tree

1 file changed

+57
-51
lines changed

1 file changed

+57
-51
lines changed

drivers/scsi/aic7xxx/aic7xxx_osm.c

Lines changed: 57 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
366366
struct scsi_cmnd *cmd);
367367
static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
368368
static void ahc_linux_release_simq(struct ahc_softc *ahc);
369-
static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
369+
static int ahc_linux_queue_recovery_cmd(struct scsi_device *sdev,
370+
struct scsi_cmnd *cmd);
370371
static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
371372
static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
372373
struct ahc_devinfo *devinfo);
@@ -728,7 +729,7 @@ ahc_linux_abort(struct scsi_cmnd *cmd)
728729
{
729730
int error;
730731

731-
error = ahc_linux_queue_recovery_cmd(cmd, SCB_ABORT);
732+
error = ahc_linux_queue_recovery_cmd(cmd->device, cmd);
732733
if (error != SUCCESS)
733734
printk("aic7xxx_abort returns 0x%x\n", error);
734735
return (error);
@@ -742,7 +743,7 @@ ahc_linux_dev_reset(struct scsi_cmnd *cmd)
742743
{
743744
int error;
744745

745-
error = ahc_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);
746+
error = ahc_linux_queue_recovery_cmd(cmd->device, NULL);
746747
if (error != SUCCESS)
747748
printk("aic7xxx_dev_reset returns 0x%x\n", error);
748749
return (error);
@@ -2036,11 +2037,12 @@ ahc_linux_release_simq(struct ahc_softc *ahc)
20362037
}
20372038

20382039
static int
2039-
ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
2040+
ahc_linux_queue_recovery_cmd(struct scsi_device *sdev,
2041+
struct scsi_cmnd *cmd)
20402042
{
20412043
struct ahc_softc *ahc;
20422044
struct ahc_linux_device *dev;
2043-
struct scb *pending_scb;
2045+
struct scb *pending_scb = NULL, *scb;
20442046
u_int saved_scbptr;
20452047
u_int active_scb_index;
20462048
u_int last_phase;
@@ -2053,18 +2055,19 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
20532055
int disconnected;
20542056
unsigned long flags;
20552057

2056-
pending_scb = NULL;
20572058
paused = FALSE;
20582059
wait = FALSE;
2059-
ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
2060+
ahc = *(struct ahc_softc **)sdev->host->hostdata;
20602061

2061-
scmd_printk(KERN_INFO, cmd, "Attempting to queue a%s message\n",
2062-
flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
2062+
sdev_printk(KERN_INFO, sdev, "Attempting to queue a%s message\n",
2063+
cmd ? "n ABORT" : " TARGET RESET");
20632064

2064-
printk("CDB:");
2065-
for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
2066-
printk(" 0x%x", cmd->cmnd[cdb_byte]);
2067-
printk("\n");
2065+
if (cmd) {
2066+
printk("CDB:");
2067+
for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
2068+
printk(" 0x%x", cmd->cmnd[cdb_byte]);
2069+
printk("\n");
2070+
}
20682071

20692072
ahc_lock(ahc, &flags);
20702073

@@ -2075,21 +2078,20 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
20752078
* at all, and the system wanted us to just abort the
20762079
* command, return success.
20772080
*/
2078-
dev = scsi_transport_device_data(cmd->device);
2081+
dev = scsi_transport_device_data(sdev);
20792082

20802083
if (dev == NULL) {
20812084
/*
20822085
* No target device for this command exists,
20832086
* so we must not still own the command.
20842087
*/
20852088
printk("%s:%d:%d:%d: Is not an active device\n",
2086-
ahc_name(ahc), cmd->device->channel, cmd->device->id,
2087-
(u8)cmd->device->lun);
2089+
ahc_name(ahc), sdev->channel, sdev->id, (u8)sdev->lun);
20882090
retval = SUCCESS;
20892091
goto no_cmd;
20902092
}
20912093

2092-
if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
2094+
if (cmd && (dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
20932095
&& ahc_search_untagged_queues(ahc, cmd, cmd->device->id,
20942096
cmd->device->channel + 'A',
20952097
(u8)cmd->device->lun,
@@ -2104,25 +2106,28 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
21042106
/*
21052107
* See if we can find a matching cmd in the pending list.
21062108
*/
2107-
LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) {
2108-
if (pending_scb->io_ctx == cmd)
2109-
break;
2110-
}
2111-
2112-
if (pending_scb == NULL && flag == SCB_DEVICE_RESET) {
2113-
2109+
if (cmd) {
2110+
LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) {
2111+
if (scb->io_ctx == cmd) {
2112+
pending_scb = scb;
2113+
break;
2114+
}
2115+
}
2116+
} else {
21142117
/* Any SCB for this device will do for a target reset */
2115-
LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) {
2116-
if (ahc_match_scb(ahc, pending_scb, scmd_id(cmd),
2117-
scmd_channel(cmd) + 'A',
2118+
LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) {
2119+
if (ahc_match_scb(ahc, scb, sdev->id,
2120+
sdev->channel + 'A',
21182121
CAM_LUN_WILDCARD,
2119-
SCB_LIST_NULL, ROLE_INITIATOR))
2122+
SCB_LIST_NULL, ROLE_INITIATOR)) {
2123+
pending_scb = scb;
21202124
break;
2125+
}
21212126
}
21222127
}
21232128

21242129
if (pending_scb == NULL) {
2125-
scmd_printk(KERN_INFO, cmd, "Command not found\n");
2130+
sdev_printk(KERN_INFO, sdev, "Command not found\n");
21262131
goto no_cmd;
21272132
}
21282133

@@ -2153,22 +2158,22 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
21532158
ahc_dump_card_state(ahc);
21542159

21552160
disconnected = TRUE;
2156-
if (flag == SCB_ABORT) {
2157-
if (ahc_search_qinfifo(ahc, cmd->device->id,
2158-
cmd->device->channel + 'A',
2159-
cmd->device->lun,
2161+
if (cmd) {
2162+
if (ahc_search_qinfifo(ahc, sdev->id,
2163+
sdev->channel + 'A',
2164+
sdev->lun,
21602165
pending_scb->hscb->tag,
21612166
ROLE_INITIATOR, CAM_REQ_ABORTED,
21622167
SEARCH_COMPLETE) > 0) {
21632168
printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
2164-
ahc_name(ahc), cmd->device->channel,
2165-
cmd->device->id, (u8)cmd->device->lun);
2169+
ahc_name(ahc), sdev->channel,
2170+
sdev->id, (u8)sdev->lun);
21662171
retval = SUCCESS;
21672172
goto done;
21682173
}
2169-
} else if (ahc_search_qinfifo(ahc, cmd->device->id,
2170-
cmd->device->channel + 'A',
2171-
cmd->device->lun,
2174+
} else if (ahc_search_qinfifo(ahc, sdev->id,
2175+
sdev->channel + 'A',
2176+
sdev->lun,
21722177
pending_scb->hscb->tag,
21732178
ROLE_INITIATOR, /*status*/0,
21742179
SEARCH_COUNT) > 0) {
@@ -2181,7 +2186,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
21812186
bus_scb = ahc_lookup_scb(ahc, ahc_inb(ahc, SCB_TAG));
21822187
if (bus_scb == pending_scb)
21832188
disconnected = FALSE;
2184-
else if (flag != SCB_ABORT
2189+
else if (!cmd
21852190
&& ahc_inb(ahc, SAVED_SCSIID) == pending_scb->hscb->scsiid
21862191
&& ahc_inb(ahc, SAVED_LUN) == SCB_GET_LUN(pending_scb))
21872192
disconnected = FALSE;
@@ -2201,18 +2206,18 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
22012206
saved_scsiid = ahc_inb(ahc, SAVED_SCSIID);
22022207
if (last_phase != P_BUSFREE
22032208
&& (pending_scb->hscb->tag == active_scb_index
2204-
|| (flag == SCB_DEVICE_RESET
2205-
&& SCSIID_TARGET(ahc, saved_scsiid) == scmd_id(cmd)))) {
2209+
|| (!cmd && SCSIID_TARGET(ahc, saved_scsiid) == sdev->id))) {
22062210

22072211
/*
22082212
* We're active on the bus, so assert ATN
22092213
* and hope that the target responds.
22102214
*/
22112215
pending_scb = ahc_lookup_scb(ahc, active_scb_index);
2212-
pending_scb->flags |= SCB_RECOVERY_SCB|flag;
2216+
pending_scb->flags |= SCB_RECOVERY_SCB;
2217+
pending_scb->flags |= cmd ? SCB_ABORT : SCB_DEVICE_RESET;
22132218
ahc_outb(ahc, MSG_OUT, HOST_MSG);
22142219
ahc_outb(ahc, SCSISIGO, last_phase|ATNO);
2215-
scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
2220+
sdev_printk(KERN_INFO, sdev, "Device is active, asserting ATN\n");
22162221
wait = TRUE;
22172222
} else if (disconnected) {
22182223

@@ -2233,7 +2238,8 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
22332238
* an unsolicited reselection occurred.
22342239
*/
22352240
pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
2236-
pending_scb->flags |= SCB_RECOVERY_SCB|flag;
2241+
pending_scb->flags |= SCB_RECOVERY_SCB;
2242+
pending_scb->flags |= cmd ? SCB_ABORT : SCB_DEVICE_RESET;
22372243

22382244
/*
22392245
* Remove any cached copy of this SCB in the
@@ -2242,9 +2248,9 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
22422248
* same element in the SCB, SCB_NEXT, for
22432249
* both the qinfifo and the disconnected list.
22442250
*/
2245-
ahc_search_disc_list(ahc, cmd->device->id,
2246-
cmd->device->channel + 'A',
2247-
cmd->device->lun, pending_scb->hscb->tag,
2251+
ahc_search_disc_list(ahc, sdev->id,
2252+
sdev->channel + 'A',
2253+
sdev->lun, pending_scb->hscb->tag,
22482254
/*stop_on_first*/TRUE,
22492255
/*remove*/TRUE,
22502256
/*save_state*/FALSE);
@@ -2267,9 +2273,9 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
22672273
* so we are the next SCB for this target
22682274
* to run.
22692275
*/
2270-
ahc_search_qinfifo(ahc, cmd->device->id,
2271-
cmd->device->channel + 'A',
2272-
cmd->device->lun, SCB_LIST_NULL,
2276+
ahc_search_qinfifo(ahc, sdev->id,
2277+
sdev->channel + 'A',
2278+
(u8)sdev->lun, SCB_LIST_NULL,
22732279
ROLE_INITIATOR, CAM_REQUEUE_REQ,
22742280
SEARCH_COMPLETE);
22752281
ahc_qinfifo_requeue_tail(ahc, pending_scb);
@@ -2278,7 +2284,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
22782284
printk("Device is disconnected, re-queuing SCB\n");
22792285
wait = TRUE;
22802286
} else {
2281-
scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n");
2287+
sdev_printk(KERN_INFO, sdev, "Unable to deliver message\n");
22822288
retval = FAILED;
22832289
goto done;
22842290
}

0 commit comments

Comments
 (0)