Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 204299
b: refs/heads/master
c: c9de7dc
h: refs/heads/master
i:
  204297: 1057181
  204295: da29119
v: v3
  • Loading branch information
Kashyap, Desai authored and James Bottomley committed Jul 28, 2010
1 parent 222b55c commit b5deb70
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b5833cbbd7c2bc3462e684feadd8e6a0ca8e5387
refs/heads/master: c9de7dc48307395fb71780b567ae8833b080d1c8
2 changes: 2 additions & 0 deletions trunk/drivers/message/fusion/mptbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@ typedef struct _VirtTarget {
u8 raidVolume; /* set, if RAID Volume */
u8 type; /* byte 0 of Inquiry data */
u8 deleted; /* target in process of being removed */
u8 inDMD; /* currently in the device
removal delay timer */
u32 num_luns;
} VirtTarget;

Expand Down
125 changes: 124 additions & 1 deletion trunk/drivers/message/fusion/mptsas.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_sas.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_dbg.h>

#include "mptbase.h"
Expand Down Expand Up @@ -1912,6 +1913,48 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
return mptscsih_qcmd(SCpnt,done);
}

/**
* mptsas_mptsas_eh_timed_out - resets the scsi_cmnd timeout
* if the device under question is currently in the
* device removal delay.
* @sc: scsi command that the midlayer is about to time out
*
**/
static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc)
{
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
VirtDevice *vdevice;
enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;

hd = shost_priv(sc->device->host);
if (hd == NULL) {
printk(KERN_ERR MYNAM ": %s: Can't locate host! (sc=%p)\n",
__func__, sc);
goto done;
}

ioc = hd->ioc;
if (ioc->bus_type != SAS) {
printk(KERN_ERR MYNAM ": %s: Wrong bus type (sc=%p)\n",
__func__, sc);
goto done;
}

vdevice = sc->device->hostdata;
if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD
|| vdevice->vtarget->deleted)) {
dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: target removed "
"or in device removal delay (sc=%p)\n",
ioc->name, __func__, sc));
rc = BLK_EH_RESET_TIMER;
goto done;
}

done:
return rc;
}


static struct scsi_host_template mptsas_driver_template = {
.module = THIS_MODULE,
Expand Down Expand Up @@ -2984,6 +3027,7 @@ static int mptsas_probe_one_phy(struct device *dev,
struct sas_phy *phy;
struct sas_port *port;
int error = 0;
VirtTarget *vtarget;

if (!dev) {
error = -ENODEV;
Expand Down Expand Up @@ -3206,6 +3250,16 @@ static int mptsas_probe_one_phy(struct device *dev,
rphy_to_expander_device(rphy));
}

/* If the device exists,verify it wasn't previously flagged
as a missing device. If so, clear it */
vtarget = mptsas_find_vtarget(ioc,
phy_info->attached.channel,
phy_info->attached.id);
if (vtarget && vtarget->inDMD) {
printk(KERN_INFO "Device returned, unsetting inDMD\n");
vtarget->inDMD = 0;
}

out:
return error;
}
Expand Down Expand Up @@ -3659,9 +3713,42 @@ mptsas_send_link_status_event(struct fw_event_work *fw_event)
MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION)
phy_info->phy->negotiated_linkrate =
SAS_LINK_RATE_FAILED;
else
else {
phy_info->phy->negotiated_linkrate =
SAS_LINK_RATE_UNKNOWN;
if (ioc->device_missing_delay &&
mptsas_is_end_device(&phy_info->attached)) {
struct scsi_device *sdev;
VirtDevice *vdevice;
u8 channel, id;
id = phy_info->attached.id;
channel = phy_info->attached.channel;
devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"Link down for fw_id %d:fw_channel %d\n",
ioc->name, phy_info->attached.id,
phy_info->attached.channel));

shost_for_each_device(sdev, ioc->sh) {
vdevice = sdev->hostdata;
if ((vdevice == NULL) ||
(vdevice->vtarget == NULL))
continue;
if ((vdevice->vtarget->tflags &
MPT_TARGET_FLAGS_RAID_COMPONENT ||
vdevice->vtarget->raidVolume))
continue;
if (vdevice->vtarget->id == id &&
vdevice->vtarget->channel ==
channel)
devtprintk(ioc,
printk(MYIOC_s_DEBUG_FMT
"SDEV OUTSTANDING CMDS"
"%d\n", ioc->name,
sdev->device_busy));
}

}
}
}
out:
mptsas_free_fw_event(ioc, fw_event);
Expand Down Expand Up @@ -4906,12 +4993,47 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
{
EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
(EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data;
u16 ioc_stat;
ioc_stat = le16_to_cpu(reply->IOCStatus);

if (sas_event_data->ReasonCode ==
MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) {
mptsas_target_reset_queue(ioc, sas_event_data);
return 0;
}
if (sas_event_data->ReasonCode ==
MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
ioc->device_missing_delay &&
(ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)) {
VirtTarget *vtarget = NULL;
u8 id, channel;
u32 log_info = le32_to_cpu(reply->IOCLogInfo);

id = sas_event_data->TargetID;
channel = sas_event_data->Bus;

vtarget = mptsas_find_vtarget(ioc, channel, id);
if (vtarget) {
devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"LogInfo (0x%x) available for "
"INTERNAL_DEVICE_RESET"
"fw_id %d fw_channel %d\n", ioc->name,
log_info, id, channel));
if (vtarget->raidVolume) {
devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"Skipping Raid Volume for inDMD\n",
ioc->name));
} else {
devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"Setting device flag inDMD\n",
ioc->name));
vtarget->inDMD = 1;
}

}

}

break;
}
case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
Expand Down Expand Up @@ -5244,6 +5366,7 @@ mptsas_init(void)
sas_attach_transport(&mptsas_transport_functions);
if (!mptsas_transport_template)
return -ENODEV;
mptsas_transport_template->eh_timed_out = mptsas_eh_timed_out;

mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
Expand Down
40 changes: 31 additions & 9 deletions trunk/drivers/message/fusion/mptscsih.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
u32 log_info;

status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;

scsi_state = pScsiReply->SCSIState;
scsi_status = pScsiReply->SCSIStatus;
xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
Expand Down Expand Up @@ -738,15 +739,36 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)

case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
if ( ioc->bus_type == SAS ) {
u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
if ((log_info & SAS_LOGINFO_MASK)
== SAS_LOGINFO_NEXUS_LOSS) {
sc->result =
(DID_TRANSPORT_DISRUPTED
<< 16);
break;
}
u16 ioc_status =
le16_to_cpu(pScsiReply->IOCStatus);
if ((ioc_status &
MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
&&
((log_info & SAS_LOGINFO_MASK) ==
SAS_LOGINFO_NEXUS_LOSS)) {
VirtDevice *vdevice =
sc->device->hostdata;

/* flag the device as being in
* device removal delay so we can
* notify the midlayer to hold off
* on timeout eh */
if (vdevice && vdevice->
vtarget &&
vdevice->vtarget->
raidVolume)
printk(KERN_INFO
"Skipping Raid Volume"
"for inDMD\n");
else if (vdevice &&
vdevice->vtarget)
vdevice->vtarget->
inDMD = 1;

sc->result =
(DID_TRANSPORT_DISRUPTED
<< 16);
break;
}
} else if (ioc->bus_type == FC) {
/*
Expand Down

0 comments on commit b5deb70

Please sign in to comment.