|
|
@@ -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
|
|
|
@@ -5949,30 +5994,6 @@ _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
|
|
|
rc = scsi_device_reprobe(sdev);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * _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
|
|
|
@@ -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;
|
|
|
}
|
|
|
|