aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas/mpt2sas_scsih.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_scsih.c')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c597
1 files changed, 329 insertions, 268 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index d953a57e779d..76973e8ca4ba 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -579,14 +579,12 @@ _scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc,
return;
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- if (mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
- sas_device->sas_address)) {
- list_del(&sas_device->list);
- kfree(sas_device);
- }
+ list_del(&sas_device->list);
+ kfree(sas_device);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
}
+
/**
* _scsih_sas_device_add - insert sas_device to the list.
* @ioc: per adapter object
@@ -645,8 +643,8 @@ _scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc,
spin_lock_irqsave(&ioc->sas_device_lock, flags);
list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
_scsih_determine_boot_device(ioc, sas_device, 0);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
}
/**
@@ -755,7 +753,6 @@ _scsih_raid_device_add(struct MPT2SAS_ADAPTER *ioc,
* @ioc: per adapter object
* @raid_device: raid_device object
*
- * This is removed from the raid_device_list link list.
*/
static void
_scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc,
@@ -765,7 +762,6 @@ _scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc,
spin_lock_irqsave(&ioc->raid_device_lock, flags);
list_del(&raid_device->list);
- memset(raid_device, 0, sizeof(struct _raid_device));
kfree(raid_device);
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
}
@@ -1199,10 +1195,10 @@ _scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
sas_device_priv_data->sas_target->sas_address);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (sas_device && sas_device->device_info &
MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
max_depth = MPT2SAS_SATA_QUEUE_DEPTH;
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
not_sata:
@@ -1299,7 +1295,8 @@ _scsih_target_alloc(struct scsi_target *starget)
sas_target_priv_data->handle = raid_device->handle;
sas_target_priv_data->sas_address = raid_device->wwid;
sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
- sas_target_priv_data->raid_device = raid_device;
+ if (ioc->is_warpdrive)
+ sas_target_priv_data->raid_device = raid_device;
raid_device->starget = starget;
}
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
@@ -1465,12 +1462,12 @@ _scsih_slave_destroy(struct scsi_device *sdev)
/**
* _scsih_display_sata_capabilities - sata capabilities
* @ioc: per adapter object
- * @sas_device: the sas_device object
+ * @handle: device handle
* @sdev: scsi device struct
*/
static void
_scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_device *sas_device, struct scsi_device *sdev)
+ u16 handle, struct scsi_device *sdev)
{
Mpi2ConfigReply_t mpi_reply;
Mpi2SasDevicePage0_t sas_device_pg0;
@@ -1479,7 +1476,7 @@ _scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc,
u32 device_info;
if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
- MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, sas_device->handle))) {
+ MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
return;
@@ -1537,27 +1534,40 @@ _scsih_get_resync(struct device *dev)
Mpi2RaidVolPage0_t vol_pg0;
Mpi2ConfigReply_t mpi_reply;
u32 volume_status_flags;
- u8 percent_complete = 0;
+ u8 percent_complete;
+ u16 handle;
+
+ percent_complete = 0;
+ handle = 0;
+ if (ioc->is_warpdrive)
+ goto out;
spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
sdev->channel);
+ if (raid_device) {
+ handle = raid_device->handle;
+ percent_complete = raid_device->percent_complete;
+ }
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- if (!raid_device || ioc->is_warpdrive)
+ if (!handle)
goto out;
if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
- MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle,
+ MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
sizeof(Mpi2RaidVolPage0_t))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
+ percent_complete = 0;
goto out;
}
volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags);
- if (volume_status_flags & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS)
- percent_complete = raid_device->percent_complete;
+ if (!(volume_status_flags &
+ MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS))
+ percent_complete = 0;
+
out:
raid_set_resync(mpt2sas_raid_template, dev, percent_complete);
}
@@ -1577,17 +1587,20 @@ _scsih_get_state(struct device *dev)
Mpi2ConfigReply_t mpi_reply;
u32 volstate;
enum raid_state state = RAID_STATE_UNKNOWN;
+ u16 handle = 0;
spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
sdev->channel);
+ if (raid_device)
+ handle = raid_device->handle;
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
if (!raid_device)
goto out;
if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
- MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle,
+ MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
sizeof(Mpi2RaidVolPage0_t))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
@@ -1620,14 +1633,14 @@ _scsih_get_state(struct device *dev)
/**
* _scsih_set_level - set raid level
* @sdev: scsi device struct
- * @raid_device: raid_device object
+ * @volume_type: volume type
*/
static void
-_scsih_set_level(struct scsi_device *sdev, struct _raid_device *raid_device)
+_scsih_set_level(struct scsi_device *sdev, u8 volume_type)
{
enum raid_level level = RAID_LEVEL_UNKNOWN;
- switch (raid_device->volume_type) {
+ switch (volume_type) {
case MPI2_RAID_VOL_TYPE_RAID0:
level = RAID_LEVEL_0;
break;
@@ -1722,6 +1735,7 @@ _scsih_disable_ddio(struct MPT2SAS_ADAPTER *ioc)
struct _raid_device *raid_device;
u16 handle;
u16 ioc_status;
+ unsigned long flags;
handle = 0xFFFF;
while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
@@ -1731,9 +1745,11 @@ _scsih_disable_ddio(struct MPT2SAS_ADAPTER *ioc)
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
handle = le16_to_cpu(vol_pg1.DevHandle);
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
if (raid_device)
raid_device->direct_io_enabled = 0;
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
}
return;
}
@@ -1838,7 +1854,8 @@ _scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc,
if (mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
&pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
vol_pg0->PhysDisk[count].PhysDiskNum) ||
- pd_pg0.DevHandle == MPT2SAS_INVALID_DEVICE_HANDLE) {
+ le16_to_cpu(pd_pg0.DevHandle) ==
+ MPT2SAS_INVALID_DEVICE_HANDLE) {
printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is "
"disabled for the drive with handle(0x%04x) member"
"handle retrieval failed for member number=%d\n",
@@ -1968,19 +1985,21 @@ _scsih_slave_configure(struct scsi_device *sdev)
u8 ssp_target = 0;
char *ds = "";
char *r_level = "";
+ u16 handle, volume_handle = 0;
+ u64 volume_wwid = 0;
qdepth = 1;
sas_device_priv_data = sdev->hostdata;
sas_device_priv_data->configured_lun = 1;
sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
sas_target_priv_data = sas_device_priv_data->sas_target;
+ handle = sas_target_priv_data->handle;
/* raid volume handling */
if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_handle(ioc,
- sas_target_priv_data->handle);
+ raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
if (!raid_device) {
dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
@@ -1989,8 +2008,6 @@ _scsih_slave_configure(struct scsi_device *sdev)
return 1;
}
- _scsih_get_volume_capabilities(ioc, raid_device);
-
if (_scsih_get_volume_capabilities(ioc, raid_device)) {
dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
"failure at %s:%d/%s()!\n", ioc->name, __FILE__,
@@ -2058,68 +2075,67 @@ _scsih_slave_configure(struct scsi_device *sdev)
_scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
/* raid transport support */
if (!ioc->is_warpdrive)
- _scsih_set_level(sdev, raid_device);
+ _scsih_set_level(sdev, raid_device->volume_type);
return 0;
}
/* non-raid handling */
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
- sas_device_priv_data->sas_target->sas_address);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (sas_device) {
- if (sas_target_priv_data->flags &
- MPT_TARGET_FLAGS_RAID_COMPONENT) {
- if (mpt2sas_config_get_volume_handle(ioc,
- sas_device->handle, &sas_device->volume_handle)) {
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__));
- return 1;
- }
- if (sas_device->volume_handle &&
- mpt2sas_config_get_volume_wwid(ioc,
- sas_device->volume_handle,
- &sas_device->volume_wwid)) {
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__));
- return 1;
- }
+ if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
+ if (mpt2sas_config_get_volume_handle(ioc, handle,
+ &volume_handle)) {
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+ "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__));
+ return 1;
}
- if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
- qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
- ssp_target = 1;
- ds = "SSP";
- } else {
- qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
- if (sas_device->device_info &
- MPI2_SAS_DEVICE_INFO_STP_TARGET)
- ds = "STP";
- else if (sas_device->device_info &
- MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
- ds = "SATA";
+ if (volume_handle && mpt2sas_config_get_volume_wwid(ioc,
+ volume_handle, &volume_wwid)) {
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+ "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__));
+ return 1;
}
+ }
- sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
- "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
- ds, sas_device->handle,
- (unsigned long long)sas_device->sas_address,
- sas_device->phy,
- (unsigned long long)sas_device->device_name);
- sdev_printk(KERN_INFO, sdev, "%s: "
- "enclosure_logical_id(0x%016llx), slot(%d)\n", ds,
- (unsigned long long) sas_device->enclosure_logical_id,
- sas_device->slot);
-
- if (!ssp_target)
- _scsih_display_sata_capabilities(ioc, sas_device, sdev);
- } else {
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device_priv_data->sas_target->sas_address);
+ if (!sas_device) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
- __func__));
+ "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
+ __LINE__, __func__));
return 1;
}
+ sas_device->volume_handle = volume_handle;
+ sas_device->volume_wwid = volume_wwid;
+ if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
+ qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
+ ssp_target = 1;
+ ds = "SSP";
+ } else {
+ qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
+ if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
+ ds = "STP";
+ else if (sas_device->device_info &
+ MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
+ ds = "SATA";
+ }
+ sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
+ "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
+ ds, sas_device->handle,
+ (unsigned long long)sas_device->sas_address,
+ sas_device->phy,
+ (unsigned long long)sas_device->device_name);
+ sdev_printk(KERN_INFO, sdev, "%s: "
+ "enclosure_logical_id(0x%016llx), slot(%d)\n", ds,
+ (unsigned long long) sas_device->enclosure_logical_id,
+ sas_device->slot);
+
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (!ssp_target)
+ _scsih_display_sata_capabilities(ioc, handle, sdev);
+
_scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
@@ -2899,7 +2915,7 @@ _scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
* During device pull we need to appropiately set the sdev state.
*/
static void
-_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
{
struct MPT2SAS_DEVICE *sas_device_priv_data;
struct scsi_device *sdev;
@@ -2910,10 +2926,12 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
continue;
if (!sas_device_priv_data->block)
continue;
- if (sas_device_priv_data->sas_target->handle == handle) {
+ if (sas_device_priv_data->sas_target->sas_address ==
+ sas_address) {
dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
MPT2SAS_INFO_FMT "SDEV_RUNNING: "
- "handle(0x%04x)\n", ioc->name, handle));
+ "sas address(0x%016llx)\n", ioc->name,
+ (unsigned long long)sas_address));
sas_device_priv_data->block = 0;
scsi_internal_device_unblock(sdev);
}
@@ -3006,10 +3024,10 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc,
sas_device =
mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
mpt2sas_port->remote_identify.sas_address);
+ if (sas_device)
+ set_bit(sas_device->handle,
+ ioc->blocking_handles);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (!sas_device)
- continue;
- _scsih_block_io_device(ioc, sas_device->handle);
}
}
@@ -3020,12 +3038,9 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc,
SAS_EDGE_EXPANDER_DEVICE ||
mpt2sas_port->remote_identify.device_type ==
SAS_FANOUT_EXPANDER_DEVICE) {
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
expander_sibling =
mpt2sas_scsih_expander_find_by_sas_address(
ioc, mpt2sas_port->remote_identify.sas_address);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
_scsih_block_io_to_children_attached_to_ex(ioc,
expander_sibling);
}
@@ -3124,7 +3139,7 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: "
"handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle,
(unsigned long long)sas_address));
- _scsih_ublock_io_device(ioc, handle);
+ _scsih_ublock_io_device(ioc, sas_address);
sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
}
@@ -3174,16 +3189,19 @@ static u8
_scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
u8 msix_index, u32 reply)
{
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
Mpi2SasIoUnitControlReply_t *mpi_reply =
mpt2sas_base_get_reply_virt_addr(ioc, reply);
-#endif
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "sc_complete:handle(0x%04x), (open) "
- "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
- ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
- le16_to_cpu(mpi_reply->IOCStatus),
- le32_to_cpu(mpi_reply->IOCLogInfo)));
+ if (likely(mpi_reply)) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
+ "sc_complete:handle(0x%04x), (open) "
+ "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
+ le16_to_cpu(mpi_reply->IOCStatus),
+ le32_to_cpu(mpi_reply->IOCLogInfo)));
+ } else {
+ printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ }
return 1;
}
@@ -3262,7 +3280,11 @@ _scsih_tm_volume_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
"progress!\n", __func__, ioc->name));
return 1;
}
-
+ if (unlikely(!mpi_reply)) {
+ printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return 1;
+ }
mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid);
handle = le16_to_cpu(mpi_request_tm->DevHandle);
if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
@@ -3325,7 +3347,11 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
"operational\n", __func__, ioc->name));
return 1;
}
-
+ if (unlikely(!mpi_reply)) {
+ printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return 1;
+ }
mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid);
handle = le16_to_cpu(mpi_request_tm->DevHandle);
if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
@@ -3441,14 +3467,20 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
_scsih_block_io_to_children_attached_directly(ioc, event_data);
return;
}
-
- if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING
- || event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) {
+ if (event_data->ExpStatus ==
+ MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) {
+ /* put expander attached devices into blocking state */
spin_lock_irqsave(&ioc->sas_node_lock, flags);
sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
expander_handle);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
_scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+ do {
+ handle = find_first_bit(ioc->blocking_handles,
+ ioc->facts.MaxDevHandle);
+ if (handle < ioc->facts.MaxDevHandle)
+ _scsih_block_io_device(ioc, handle);
+ } while (test_and_clear_bit(handle, ioc->blocking_handles));
} else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
_scsih_block_io_to_children_attached_directly(ioc, event_data);
@@ -4446,8 +4478,8 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
!= MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) {
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
ioc->scsi_lookup[smid - 1].scmd = scmd;
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
_scsih_scsi_direct_io_set(ioc, smid, 0);
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
mpi_request->DevHandle =
cpu_to_le16(sas_device_priv_data->sas_target->handle);
@@ -5020,13 +5052,11 @@ mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
spin_lock_irqsave(&ioc->sas_node_lock, flags);
sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
sas_address);
- if (!sas_expander) {
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- return;
- }
- list_del(&sas_expander->list);
+ if (sas_expander)
+ list_del(&sas_expander->list);
spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- _scsih_expander_node_remove(ioc, sas_expander);
+ if (sas_expander)
+ _scsih_expander_node_remove(ioc, sas_expander);
}
/**
@@ -5106,6 +5136,7 @@ _scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
struct MPT2SAS_TARGET *sas_target_priv_data;
u32 device_info;
+
if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
return;
@@ -5139,21 +5170,24 @@ _scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
sas_target_priv_data->handle = handle;
sas_device->handle = handle;
}
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
/* check if device is present */
if (!(le16_to_cpu(sas_device_pg0.Flags) &
MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
printk(MPT2SAS_ERR_FMT "device is not present "
"handle(0x%04x), flags!!!\n", ioc->name, handle);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
return;
}
/* check if there were any issues with discovery */
if (_scsih_check_access_status(ioc, sas_address, handle,
- sas_device_pg0.AccessStatus))
+ sas_device_pg0.AccessStatus)) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
return;
- _scsih_ublock_io_device(ioc, handle);
+ }
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ _scsih_ublock_io_device(ioc, sas_address);
}
@@ -5280,54 +5314,71 @@ static void
_scsih_remove_device(struct MPT2SAS_ADAPTER *ioc,
struct _sas_device *sas_device)
{
- struct _sas_device sas_device_backup;
struct MPT2SAS_TARGET *sas_target_priv_data;
- if (!sas_device)
- return;
-
- memcpy(&sas_device_backup, sas_device, sizeof(struct _sas_device));
- _scsih_sas_device_remove(ioc, sas_device);
-
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: "
"handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
- sas_device_backup.handle, (unsigned long long)
- sas_device_backup.sas_address));
+ sas_device->handle, (unsigned long long)
+ sas_device->sas_address));
- if (sas_device_backup.starget && sas_device_backup.starget->hostdata) {
- sas_target_priv_data = sas_device_backup.starget->hostdata;
+ if (sas_device->starget && sas_device->starget->hostdata) {
+ sas_target_priv_data = sas_device->starget->hostdata;
sas_target_priv_data->deleted = 1;
- _scsih_ublock_io_device(ioc, sas_device_backup.handle);
+ _scsih_ublock_io_device(ioc, sas_device->sas_address);
sas_target_priv_data->handle =
MPT2SAS_INVALID_DEVICE_HANDLE;
}
- _scsih_ublock_io_device(ioc, sas_device_backup.handle);
-
if (!ioc->hide_drives)
mpt2sas_transport_port_remove(ioc,
- sas_device_backup.sas_address,
- sas_device_backup.sas_address_parent);
+ sas_device->sas_address,
+ sas_device->sas_address_parent);
printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr"
- "(0x%016llx)\n", ioc->name, sas_device_backup.handle,
- (unsigned long long) sas_device_backup.sas_address);
+ "(0x%016llx)\n", ioc->name, sas_device->handle,
+ (unsigned long long) sas_device->sas_address);
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit: "
"handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
- sas_device_backup.handle, (unsigned long long)
- sas_device_backup.sas_address));
+ sas_device->handle, (unsigned long long)
+ sas_device->sas_address));
+ kfree(sas_device);
+}
+/**
+ * _scsih_device_remove_by_handle - removing device object by handle
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * Return nothing.
+ */
+static void
+_scsih_device_remove_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ struct _sas_device *sas_device;
+ unsigned long flags;
+
+ if (ioc->shost_recovery)
+ return;
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ if (sas_device)
+ list_del(&sas_device->list);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (sas_device)
+ _scsih_remove_device(ioc, sas_device);
}
/**
- * mpt2sas_device_remove - removing device object
+ * mpt2sas_device_remove_by_sas_address - removing device object by sas address
* @ioc: per adapter object
- * @sas_address: expander sas_address
+ * @sas_address: device sas_address
*
* Return nothing.
*/
void
-mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
+mpt2sas_device_remove_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
+ u64 sas_address)
{
struct _sas_device *sas_device;
unsigned long flags;
@@ -5338,14 +5389,12 @@ mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
sas_address);
- if (!sas_device) {
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return;
- }
+ if (sas_device)
+ list_del(&sas_device->list);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- _scsih_remove_device(ioc, sas_device);
+ if (sas_device)
+ _scsih_remove_device(ioc, sas_device);
}
-
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
/**
* _scsih_sas_topology_change_event_debug - debug for topology event
@@ -5442,7 +5491,6 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
u16 reason_code;
u8 phy_number, max_phys;
struct _sas_node *sas_expander;
- struct _sas_device *sas_device;
u64 sas_address;
unsigned long flags;
u8 link_rate, prev_link_rate;
@@ -5477,15 +5525,17 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
spin_lock_irqsave(&ioc->sas_node_lock, flags);
sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
parent_handle);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
if (sas_expander) {
sas_address = sas_expander->sas_address;
max_phys = sas_expander->num_phys;
} else if (parent_handle < ioc->sas_hba.num_phys) {
sas_address = ioc->sas_hba.sas_address;
max_phys = ioc->sas_hba.num_phys;
- } else
+ } else {
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
return;
+ }
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
/* handle siblings events */
for (i = 0; i < event_data->NumEntries; i++) {
@@ -5540,16 +5590,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
break;
case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
- 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);
- break;
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- _scsih_remove_device(ioc, sas_device);
+ _scsih_device_remove_by_handle(ioc, handle);
break;
}
}
@@ -5672,20 +5713,24 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
sas_address = le64_to_cpu(event_data->SASAddress);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
sas_address);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (!sas_device || !sas_device->starget)
+ if (!sas_device || !sas_device->starget) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
return;
+ }
target_priv_data = sas_device->starget->hostdata;
- if (!target_priv_data)
+ if (!target_priv_data) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
return;
+ }
if (event_data->ReasonCode ==
MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
target_priv_data->tm_busy = 1;
else
target_priv_data->tm_busy = 0;
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
}
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
@@ -5950,30 +5995,6 @@ _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
}
/**
- * _scsih_reprobe_target - reprobing target
- * @starget: scsi target struct
- * @no_uld_attach: sdev->no_uld_attach flag setting
- *
- * Note: no_uld_attach flag determines whether the disk device is attached
- * to block layer. A value of `1` means to not attach.
- **/
-static void
-_scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach)
-{
- struct MPT2SAS_TARGET *sas_target_priv_data;
-
- if (starget == NULL)
- return;
- sas_target_priv_data = starget->hostdata;
- if (no_uld_attach)
- sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
- else
- sas_target_priv_data->flags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
-
- starget_for_each_device(starget, no_uld_attach ? (void *)1 : NULL,
- _scsih_reprobe_lun);
-}
-/**
* _scsih_sas_volume_add - add new volume
* @ioc: per adapter object
* @element: IR config element data
@@ -6024,8 +6045,11 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
raid_device->id, 0);
if (rc)
_scsih_raid_device_remove(ioc, raid_device);
- } else
+ } else {
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
_scsih_determine_boot_device(ioc, raid_device, 1);
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+ }
}
/**
@@ -6042,21 +6066,25 @@ _scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, u16 handle)
struct _raid_device *raid_device;
unsigned long flags;
struct MPT2SAS_TARGET *sas_target_priv_data;
+ struct scsi_target *starget = NULL;
spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- if (!raid_device)
- return;
- if (raid_device->starget) {
- sas_target_priv_data = raid_device->starget->hostdata;
- sas_target_priv_data->deleted = 1;
- scsi_remove_target(&raid_device->starget->dev);
+ if (raid_device) {
+ if (raid_device->starget) {
+ starget = raid_device->starget;
+ sas_target_priv_data = starget->hostdata;
+ sas_target_priv_data->deleted = 1;
+ }
+ printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
+ "(0x%016llx)\n", ioc->name, raid_device->handle,
+ (unsigned long long) raid_device->wwid);
+ list_del(&raid_device->list);
+ kfree(raid_device);
}
- printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
- "(0x%016llx)\n", ioc->name, raid_device->handle,
- (unsigned long long) raid_device->wwid);
- _scsih_raid_device_remove(ioc, raid_device);
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+ if (starget)
+ scsi_remove_target(&starget->dev);
}
/**
@@ -6072,20 +6100,31 @@ _scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc,
Mpi2EventIrConfigElement_t *element)
{
struct _sas_device *sas_device;
+ struct scsi_target *starget = NULL;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
unsigned long flags;
u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ if (sas_device) {
+ sas_device->volume_handle = 0;
+ sas_device->volume_wwid = 0;
+ clear_bit(handle, ioc->pd_handles);
+ if (sas_device->starget && sas_device->starget->hostdata) {
+ starget = sas_device->starget;
+ sas_target_priv_data = starget->hostdata;
+ sas_target_priv_data->flags &=
+ ~MPT_TARGET_FLAGS_RAID_COMPONENT;
+ }
+ }
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (!sas_device)
return;
/* exposing raid component */
- sas_device->volume_handle = 0;
- sas_device->volume_wwid = 0;
- clear_bit(handle, ioc->pd_handles);
- _scsih_reprobe_target(sas_device->starget, 0);
+ if (starget)
+ starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
}
/**
@@ -6101,23 +6140,38 @@ _scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc,
Mpi2EventIrConfigElement_t *element)
{
struct _sas_device *sas_device;
+ struct scsi_target *starget = NULL;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
unsigned long flags;
u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+ u16 volume_handle = 0;
+ u64 volume_wwid = 0;
+
+ mpt2sas_config_get_volume_handle(ioc, handle, &volume_handle);
+ if (volume_handle)
+ mpt2sas_config_get_volume_wwid(ioc, volume_handle,
+ &volume_wwid);
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ if (sas_device) {
+ set_bit(handle, ioc->pd_handles);
+ if (sas_device->starget && sas_device->starget->hostdata) {
+ starget = sas_device->starget;
+ sas_target_priv_data = starget->hostdata;
+ sas_target_priv_data->flags |=
+ MPT_TARGET_FLAGS_RAID_COMPONENT;
+ sas_device->volume_handle = volume_handle;
+ sas_device->volume_wwid = volume_wwid;
+ }
+ }
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (!sas_device)
return;
/* hiding raid component */
- mpt2sas_config_get_volume_handle(ioc, handle,
- &sas_device->volume_handle);
- mpt2sas_config_get_volume_wwid(ioc, sas_device->volume_handle,
- &sas_device->volume_wwid);
- set_bit(handle, ioc->pd_handles);
- _scsih_reprobe_target(sas_device->starget, 1);
-
+ if (starget)
+ starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
}
/**
@@ -6132,16 +6186,9 @@ static void
_scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc,
Mpi2EventIrConfigElement_t *element)
{
- struct _sas_device *sas_device;
- unsigned long flags;
u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (!sas_device)
- return;
- _scsih_remove_device(ioc, sas_device);
+ _scsih_device_remove_by_handle(ioc, handle);
}
/**
@@ -6583,18 +6630,13 @@ _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc,
/* code added for raid transport support */
if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
- handle = le16_to_cpu(event_data->VolDevHandle);
-
spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ handle = le16_to_cpu(event_data->VolDevHandle);
raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-
- if (!raid_device)
- return;
-
- if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC)
+ if (raid_device)
raid_device->percent_complete =
event_data->PercentComplete;
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
}
}
@@ -6761,13 +6803,18 @@ _scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid,
* required data for Direct IO
*/
_scsih_init_warpdrive_properties(ioc, raid_device);
- if (raid_device->handle == handle)
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ if (raid_device->handle == handle) {
+ spin_unlock_irqrestore(&ioc->raid_device_lock,
+ flags);
return;
+ }
printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
raid_device->handle);
raid_device->handle = handle;
if (sas_target_priv_data)
sas_target_priv_data->handle = handle;
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
return;
}
}
@@ -6939,58 +6986,56 @@ static void
_scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
{
struct _sas_device *sas_device, *sas_device_next;
- struct _sas_node *sas_expander;
+ struct _sas_node *sas_expander, *sas_expander_next;
struct _raid_device *raid_device, *raid_device_next;
+ struct list_head tmp_list;
+ unsigned long flags;
printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n",
ioc->name);
+ /* removing unresponding end devices */
+ printk(MPT2SAS_INFO_FMT "removing unresponding devices: end-devices\n",
+ ioc->name);
list_for_each_entry_safe(sas_device, sas_device_next,
&ioc->sas_device_list, list) {
- if (sas_device->responding) {
+ if (!sas_device->responding)
+ mpt2sas_device_remove_by_sas_address(ioc,
+ sas_device->sas_address);
+ else
sas_device->responding = 0;
- continue;
- }
- if (sas_device->starget)
- starget_printk(KERN_INFO, sas_device->starget,
- "removing: handle(0x%04x), sas_addr(0x%016llx), "
- "enclosure logical id(0x%016llx), slot(%d)\n",
- sas_device->handle,
- (unsigned long long)sas_device->sas_address,
- (unsigned long long)
- sas_device->enclosure_logical_id,
- sas_device->slot);
- _scsih_remove_device(ioc, sas_device);
}
- if (!ioc->ir_firmware)
- goto retry_expander_search;
-
- list_for_each_entry_safe(raid_device, raid_device_next,
- &ioc->raid_device_list, list) {
- if (raid_device->responding) {
- raid_device->responding = 0;
- continue;
- }
- if (raid_device->starget) {
- starget_printk(KERN_INFO, raid_device->starget,
- "removing: handle(0x%04x), wwid(0x%016llx)\n",
- raid_device->handle,
- (unsigned long long)raid_device->wwid);
- scsi_remove_target(&raid_device->starget->dev);
+ /* removing unresponding volumes */
+ if (ioc->ir_firmware) {
+ printk(MPT2SAS_INFO_FMT "removing unresponding devices: "
+ "volumes\n", ioc->name);
+ list_for_each_entry_safe(raid_device, raid_device_next,
+ &ioc->raid_device_list, list) {
+ if (!raid_device->responding)
+ _scsih_sas_volume_delete(ioc,
+ raid_device->handle);
+ else
+ raid_device->responding = 0;
}
- _scsih_raid_device_remove(ioc, raid_device);
}
-
- retry_expander_search:
- sas_expander = NULL;
- list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
- if (sas_expander->responding) {
+ /* removing unresponding expanders */
+ printk(MPT2SAS_INFO_FMT "removing unresponding devices: expanders\n",
+ ioc->name);
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ INIT_LIST_HEAD(&tmp_list);
+ list_for_each_entry_safe(sas_expander, sas_expander_next,
+ &ioc->sas_expander_list, list) {
+ if (!sas_expander->responding)
+ list_move_tail(&sas_expander->list, &tmp_list);
+ else
sas_expander->responding = 0;
- continue;
- }
- mpt2sas_expander_remove(ioc, sas_expander->sas_address);
- goto retry_expander_search;
+ }
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+ list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list,
+ list) {
+ list_del(&sas_expander->list);
+ _scsih_expander_node_remove(ioc, sas_expander);
}
printk(MPT2SAS_INFO_FMT "removing unresponding devices: complete\n",
ioc->name);
@@ -7043,6 +7088,7 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
struct _sas_device *sas_device;
struct _sas_node *expander_device;
static struct _raid_device *raid_device;
+ unsigned long flags;
printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name);
@@ -7057,8 +7103,10 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
handle = le16_to_cpu(expander_pg0.DevHandle);
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
expander_device = mpt2sas_scsih_expander_find_by_sas_address(
ioc, le64_to_cpu(expander_pg0.SASAddress));
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
if (expander_device)
_scsih_refresh_expander_links(ioc, expander_device,
handle);
@@ -7080,7 +7128,9 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
break;
phys_disk_num = pd_pg0.PhysDiskNum;
handle = le16_to_cpu(pd_pg0.DevHandle);
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (sas_device)
continue;
if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
@@ -7107,8 +7157,10 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
handle = le16_to_cpu(volume_pg1.DevHandle);
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_wwid(ioc,
le64_to_cpu(volume_pg1.WWID));
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
if (raid_device)
continue;
if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
@@ -7140,8 +7192,10 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
if (!(_scsih_is_end_device(
le32_to_cpu(sas_device_pg0.DeviceInfo))))
continue;
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
le64_to_cpu(sas_device_pg0.SASAddress));
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (sas_device)
continue;
parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
@@ -7235,7 +7289,7 @@ _firmware_event_work(struct work_struct *work)
switch (fw_event->event) {
case MPT2SAS_REMOVE_UNRESPONDING_DEVICES:
- while (scsi_host_in_recovery(ioc->shost))
+ while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery)
ssleep(1);
_scsih_remove_unresponding_sas_devices(ioc);
_scsih_scan_for_devices_after_reset(ioc);
@@ -7313,6 +7367,13 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
return 1;
mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+
+ if (unlikely(!mpi_reply)) {
+ printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return 1;
+ }
+
event = le16_to_cpu(mpi_reply->Event);
switch (event) {
@@ -7353,14 +7414,14 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
case MPI2_EVENT_LOG_ENTRY_ADDED:
{
Mpi2EventDataLogEntryAdded_t *log_entry;
- u32 *log_code;
+ __le32 *log_code;
if (!ioc->is_warpdrive)
break;
log_entry = (Mpi2EventDataLogEntryAdded_t *)
mpi_reply->EventData;
- log_code = (u32 *)log_entry->LogData;
+ log_code = (__le32 *)log_entry->LogData;
if (le16_to_cpu(log_entry->LogEntryQualifier)
!= MPT2_WARPDRIVE_LOGENTRY)
@@ -7487,7 +7548,7 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
return;
if (mpt2sas_port->remote_identify.device_type ==
SAS_END_DEVICE)
- mpt2sas_device_remove(ioc,
+ mpt2sas_device_remove_by_sas_address(ioc,
mpt2sas_port->remote_identify.sas_address);
else if (mpt2sas_port->remote_identify.device_type ==
SAS_EDGE_EXPANDER_DEVICE ||
@@ -7661,7 +7722,7 @@ _scsih_remove(struct pci_dev *pdev)
&ioc->sas_hba.sas_port_list, port_list) {
if (mpt2sas_port->remote_identify.device_type ==
SAS_END_DEVICE)
- mpt2sas_device_remove(ioc,
+ mpt2sas_device_remove_by_sas_address(ioc,
mpt2sas_port->remote_identify.sas_address);
else if (mpt2sas_port->remote_identify.device_type ==
SAS_EDGE_EXPANDER_DEVICE ||
@@ -7733,11 +7794,11 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
if (rc)
_scsih_raid_device_remove(ioc, raid_device);
} else {
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = device;
handle = sas_device->handle;
sas_address_parent = sas_device->sas_address_parent;
sas_address = sas_device->sas_address;
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
list_move_tail(&sas_device->list, &ioc->sas_device_list);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
@@ -8061,8 +8122,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
out_thread_fail:
list_del(&ioc->list);
scsi_remove_host(shost);
- scsi_host_put(shost);
out_add_shost_fail:
+ scsi_host_put(shost);
return -ENODEV;
}