Skip to content

Commit

Permalink
[SCSI] mpt2sas: Expander remove fails when it is processing another e…
Browse files Browse the repository at this point in the history
…xpander add.

This handles the case where driver receives a expander removal event while
it is in the middle of processing an expander add event. The existing
implementation will stop processing futher device adds when a expander
delete arrives on top of add expander add. Due to a sanity check in the
driver, the devices there were not added, were never handshaked to firmware
with the device removal handshake protocal. Since the driver didnt' do the
handshake, the controller never provide further add events.  To fix this
issue, the sanity check was removed so the driver will always do the device
removal handshake protocal.

Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
Signed-off-by: Eric Moore <Eric.moore@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Kashyap, Desai authored and James Bottomley committed Oct 29, 2009
1 parent c5e039b commit a28eb22
Showing 1 changed file with 62 additions and 47 deletions.
109 changes: 62 additions & 47 deletions drivers/scsi/mpt2sas/mpt2sas_scsih.c
Original file line number Diff line number Diff line change
Expand Up @@ -2386,16 +2386,10 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)

spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
if (!sas_device) {
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n",
ioc->name, __func__);
return;
}
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);

/* skip is hidden raid component */
if (sas_device->hidden_raid_component)
if (sas_device && sas_device->hidden_raid_component)
return;

smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
Expand All @@ -2408,27 +2402,38 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
delayed_tr->state = MPT2SAS_REQ_SAS_CNTRL;
list_add_tail(&delayed_tr->list,
&ioc->delayed_tr_list);
if (sas_device->starget)
if (sas_device && sas_device->starget) {
dewtprintk(ioc, starget_printk(KERN_INFO,
sas_device->starget, "DELAYED:tr:handle(0x%04x), "
"(open)\n", sas_device->handle));
"(open)\n", handle));
} else {
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
"DELAYED:tr:handle(0x%04x), (open)\n",
ioc->name, handle));
}
return;
}

if (sas_device->starget && sas_device->starget->hostdata) {
sas_target_priv_data = sas_device->starget->hostdata;
sas_target_priv_data->tm_busy = 1;
dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget,
"tr:handle(0x%04x), (open)\n", sas_device->handle));
if (sas_device) {
sas_device->state |= MPTSAS_STATE_TR_SEND;
sas_device->state |= MPT2SAS_REQ_SAS_CNTRL;
if (sas_device->starget && sas_device->starget->hostdata) {
sas_target_priv_data = sas_device->starget->hostdata;
sas_target_priv_data->tm_busy = 1;
dewtprintk(ioc, starget_printk(KERN_INFO,
sas_device->starget, "tr:handle(0x%04x), (open)\n",
handle));
}
} else {
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
"tr:handle(0x%04x), (open)\n", ioc->name, handle));
}

mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
mpi_request->DevHandle = cpu_to_le16(handle);
mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
sas_device->state |= MPTSAS_STATE_TR_SEND;
sas_device->state |= MPT2SAS_REQ_SAS_CNTRL;
mpt2sas_base_put_smid_hi_priority(ioc, smid);
}

Expand Down Expand Up @@ -2463,21 +2468,25 @@ _scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,

spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
if (!sas_device) {
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n",
ioc->name, __func__);
return 1;
}
sas_device->state |= MPTSAS_STATE_CNTRL_COMPLETE;
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);

if (sas_device->starget)
dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget,
if (sas_device) {
sas_device->state |= MPTSAS_STATE_CNTRL_COMPLETE;
if (sas_device->starget)
dewtprintk(ioc, starget_printk(KERN_INFO,
sas_device->starget,
"sc_complete:handle(0x%04x), "
"ioc_status(0x%04x), loginfo(0x%08x)\n",
handle, le16_to_cpu(mpi_reply->IOCStatus),
le32_to_cpu(mpi_reply->IOCLogInfo)));
} else {
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
"sc_complete:handle(0x%04x), "
"ioc_status(0x%04x), loginfo(0x%08x)\n",
handle, le16_to_cpu(mpi_reply->IOCStatus),
ioc->name, handle, le16_to_cpu(mpi_reply->IOCStatus),
le32_to_cpu(mpi_reply->IOCLogInfo)));
}

return 1;
}

Expand Down Expand Up @@ -2515,28 +2524,33 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
handle = le16_to_cpu(mpi_reply->DevHandle);
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
if (!sas_device) {
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n",
ioc->name, __func__);
return 1;
}
sas_device->state |= MPTSAS_STATE_TR_COMPLETE;
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);

if (sas_device->starget)
dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget,
"tr_complete:handle(0x%04x), (%s) ioc_status(0x%04x), "
"loginfo(0x%08x), completed(%d)\n",
sas_device->handle, (sas_device->state &
MPT2SAS_REQ_SAS_CNTRL) ? "open" : "active",
le16_to_cpu(mpi_reply->IOCStatus),
if (sas_device) {
sas_device->state |= MPTSAS_STATE_TR_COMPLETE;
if (sas_device->starget) {
dewtprintk(ioc, starget_printk(KERN_INFO,
sas_device->starget, "tr_complete:handle(0x%04x), "
"(%s) ioc_status(0x%04x), loginfo(0x%08x), "
"completed(%d)\n", sas_device->handle,
(sas_device->state & MPT2SAS_REQ_SAS_CNTRL) ?
"open" : "active",
le16_to_cpu(mpi_reply->IOCStatus),
le32_to_cpu(mpi_reply->IOCLogInfo),
le32_to_cpu(mpi_reply->TerminationCount)));
if (sas_device->starget->hostdata) {
sas_target_priv_data =
sas_device->starget->hostdata;
sas_target_priv_data->tm_busy = 0;
}
}
} else {
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
"tr_complete:handle(0x%04x), (open) ioc_status(0x%04x), "
"loginfo(0x%08x), completed(%d)\n", ioc->name,
handle, le16_to_cpu(mpi_reply->IOCStatus),
le32_to_cpu(mpi_reply->IOCLogInfo),
le32_to_cpu(mpi_reply->TerminationCount)));

if (sas_device->starget && sas_device->starget->hostdata) {
sas_target_priv_data = sas_device->starget->hostdata;
sas_target_priv_data->tm_busy = 0;
}

if (!list_empty(&ioc->delayed_tr_list)) {
Expand All @@ -2551,8 +2565,7 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
} else
rc = 1;


if (!(sas_device->state & MPT2SAS_REQ_SAS_CNTRL))
if (sas_device && !(sas_device->state & MPT2SAS_REQ_SAS_CNTRL))
return rc;

if (ioc->shost_recovery) {
Expand All @@ -2568,12 +2581,14 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
return rc;
}

if (sas_device)
sas_device->state |= MPTSAS_STATE_CNTRL_SEND;

mpi_request = mpt2sas_base_get_msg_frame(ioc, smid_sas_ctrl);
memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
mpi_request->DevHandle = mpi_reply->DevHandle;
sas_device->state |= MPTSAS_STATE_CNTRL_SEND;
mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl);
return rc;
}
Expand Down

0 comments on commit a28eb22

Please sign in to comment.