|
@@ -121,6 +121,7 @@ static void mptsas_expander_delete(MPT_ADAPTER *ioc,
|
|
|
static void mptsas_send_expander_event(struct fw_event_work *fw_event);
|
|
|
static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
|
|
|
static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
|
|
|
+static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event);
|
|
|
static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id);
|
|
|
|
|
|
static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
|
|
@@ -680,6 +681,18 @@ mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc,
|
|
|
mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus,
|
|
|
phys_disk.PhysDiskID);
|
|
|
|
|
|
+ mutex_lock(&ioc->sas_device_info_mutex);
|
|
|
+ list_for_each_entry(sas_info, &ioc->sas_device_info_list,
|
|
|
+ list) {
|
|
|
+ if (!sas_info->is_logical_volume &&
|
|
|
+ (sas_info->fw.channel == phys_disk.PhysDiskBus &&
|
|
|
+ sas_info->fw.id == phys_disk.PhysDiskID)) {
|
|
|
+ sas_info->is_hidden_raid_component = 1;
|
|
|
+ sas_info->volume_id = starget->id;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ mutex_unlock(&ioc->sas_device_info_mutex);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -746,6 +759,29 @@ mptsas_add_device_component_starget(MPT_ADAPTER *ioc,
|
|
|
phy_info->attached.slot, enclosure_info.enclosure_logical_id);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * mptsas_del_device_component_by_os - Once a device has been removed, we
|
|
|
+ * mark the entry in the list as being cached
|
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
|
+ * @channel: os mapped id's
|
|
|
+ * @id:
|
|
|
+ *
|
|
|
+ **/
|
|
|
+static void
|
|
|
+mptsas_del_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
|
|
|
+{
|
|
|
+ struct mptsas_device_info *sas_info, *next;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Set is_cached flag
|
|
|
+ */
|
|
|
+ list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
|
|
|
+ list) {
|
|
|
+ if (sas_info->os.channel == channel && sas_info->os.id == id)
|
|
|
+ sas_info->is_cached = 1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* mptsas_del_device_components - Cleaning the list
|
|
|
* @ioc: Pointer to MPT_ADAPTER structure
|
|
@@ -1576,6 +1612,9 @@ mptsas_firmware_event_work(struct work_struct *work)
|
|
|
case MPI_EVENT_SAS_PHY_LINK_STATUS:
|
|
|
mptsas_send_link_status_event(fw_event);
|
|
|
break;
|
|
|
+ case MPI_EVENT_QUEUE_FULL:
|
|
|
+ mptsas_handle_queue_full_event(fw_event);
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1705,6 +1744,9 @@ mptsas_target_destroy(struct scsi_target *starget)
|
|
|
|
|
|
vtarget = starget->hostdata;
|
|
|
|
|
|
+ mptsas_del_device_component_by_os(ioc, starget->channel,
|
|
|
+ starget->id);
|
|
|
+
|
|
|
|
|
|
if (starget->channel == MPTSAS_RAID_CHANNEL)
|
|
|
goto out;
|
|
@@ -3398,6 +3440,8 @@ mptsas_not_responding_devices(MPT_ADAPTER *ioc)
|
|
|
mutex_lock(&ioc->sas_device_info_mutex);
|
|
|
redo_device_scan:
|
|
|
list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
|
|
|
+ if (sas_info->is_cached)
|
|
|
+ continue;
|
|
|
if (!sas_info->is_logical_volume) {
|
|
|
sas_device.handle = 0;
|
|
|
retry_count = 0;
|
|
@@ -3612,6 +3656,95 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+static void
|
|
|
+mptsas_handle_queue_full_event(struct fw_event_work *fw_event)
|
|
|
+{
|
|
|
+ MPT_ADAPTER *ioc;
|
|
|
+ EventDataQueueFull_t *qfull_data;
|
|
|
+ struct mptsas_device_info *sas_info;
|
|
|
+ struct scsi_device *sdev;
|
|
|
+ int depth;
|
|
|
+ int id = -1;
|
|
|
+ int channel = -1;
|
|
|
+ int fw_id, fw_channel;
|
|
|
+ u16 current_depth;
|
|
|
+
|
|
|
+
|
|
|
+ ioc = fw_event->ioc;
|
|
|
+ qfull_data = (EventDataQueueFull_t *)fw_event->event_data;
|
|
|
+ fw_id = qfull_data->TargetID;
|
|
|
+ fw_channel = qfull_data->Bus;
|
|
|
+ current_depth = le16_to_cpu(qfull_data->CurrentDepth);
|
|
|
+
|
|
|
+ /* if hidden raid component, look for the volume id */
|
|
|
+ mutex_lock(&ioc->sas_device_info_mutex);
|
|
|
+ if (mptscsih_is_phys_disk(ioc, fw_channel, fw_id)) {
|
|
|
+ list_for_each_entry(sas_info, &ioc->sas_device_info_list,
|
|
|
+ list) {
|
|
|
+ if (sas_info->is_cached ||
|
|
|
+ sas_info->is_logical_volume)
|
|
|
+ continue;
|
|
|
+ if (sas_info->is_hidden_raid_component &&
|
|
|
+ (sas_info->fw.channel == fw_channel &&
|
|
|
+ sas_info->fw.id == fw_id)) {
|
|
|
+ id = sas_info->volume_id;
|
|
|
+ channel = MPTSAS_RAID_CHANNEL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ list_for_each_entry(sas_info, &ioc->sas_device_info_list,
|
|
|
+ list) {
|
|
|
+ if (sas_info->is_cached ||
|
|
|
+ sas_info->is_hidden_raid_component ||
|
|
|
+ sas_info->is_logical_volume)
|
|
|
+ continue;
|
|
|
+ if (sas_info->fw.channel == fw_channel &&
|
|
|
+ sas_info->fw.id == fw_id) {
|
|
|
+ id = sas_info->os.id;
|
|
|
+ channel = sas_info->os.channel;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ out:
|
|
|
+ mutex_unlock(&ioc->sas_device_info_mutex);
|
|
|
+
|
|
|
+ if (id != -1) {
|
|
|
+ shost_for_each_device(sdev, ioc->sh) {
|
|
|
+ if (sdev->id == id && sdev->channel == channel) {
|
|
|
+ if (current_depth > sdev->queue_depth) {
|
|
|
+ sdev_printk(KERN_INFO, sdev,
|
|
|
+ "strange observation, the queue "
|
|
|
+ "depth is (%d) meanwhile fw queue "
|
|
|
+ "depth (%d)\n", sdev->queue_depth,
|
|
|
+ current_depth);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ depth = scsi_track_queue_full(sdev,
|
|
|
+ current_depth - 1);
|
|
|
+ if (depth > 0)
|
|
|
+ sdev_printk(KERN_INFO, sdev,
|
|
|
+ "Queue depth reduced to (%d)\n",
|
|
|
+ depth);
|
|
|
+ else if (depth < 0)
|
|
|
+ sdev_printk(KERN_INFO, sdev,
|
|
|
+ "Tagged Command Queueing is being "
|
|
|
+ "disabled\n");
|
|
|
+ else if (depth == 0)
|
|
|
+ sdev_printk(KERN_INFO, sdev,
|
|
|
+ "Queue depth not changed yet\n");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ mptsas_free_fw_event(ioc, fw_event);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static struct mptsas_phyinfo *
|
|
|
mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
|
|
|
{
|