[SCSI] lpfc 8.3.6 : FC Protocol Fixes
FC protocol fixes.
- Fix send sequence logic to handle multi SGL IOCBs.
- Fix FDISC completion always setting VPORT state to failed.
- Ported the fix on reporting of max_vpi to uppper layer.
- Fix incorrect number of Vports allowed to be created.
- Fixed Dead FCoE port after creating vports.
- Added handling of ELS request for Reinstate Recovery Qualifier (RRQ)
- Handle unsolicited CT exchange initiator receiving CT exchange ABTS
- Migrate LUN queue depth ramp up code to scsi mid-layer.
- Made ABTS WQE go to the same WQ as the WQE to be aborted.
- Fix Vport does not rediscover after FCF goes away.
- Fixed lpfc_unreg_vfi failure after devloss timeout.
- Fixed RPI bit leak.
- Fix hbq pointer corruption during target discovery.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index f5ab5dd..bf80cde 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -246,6 +246,36 @@
}
/**
+ * lpfc_change_queue_depth - Alter scsi device queue depth
+ * @sdev: Pointer the scsi device on which to change the queue depth.
+ * @qdepth: New queue depth to set the sdev to.
+ * @reason: The reason for the queue depth change.
+ *
+ * This function is called by the midlayer and the LLD to alter the queue
+ * depth for a scsi device. This function sets the queue depth to the new
+ * value and sends an event out to log the queue depth change.
+ **/
+int
+lpfc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+{
+ struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ struct lpfc_rport_data *rdata;
+ unsigned long new_queue_depth, old_queue_depth;
+
+ old_queue_depth = sdev->queue_depth;
+ scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+ new_queue_depth = sdev->queue_depth;
+ rdata = sdev->hostdata;
+ if (rdata)
+ lpfc_send_sdev_queuedepth_change_event(phba, vport,
+ rdata->pnode, sdev->lun,
+ old_queue_depth,
+ new_queue_depth);
+ return sdev->queue_depth;
+}
+
+/**
* lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread
* @phba: The Hba for which this call is being executed.
*
@@ -309,8 +339,10 @@
if (vport->cfg_lun_queue_depth <= queue_depth)
return;
spin_lock_irqsave(&phba->hbalock, flags);
- if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) ||
- ((phba->last_rsrc_error_time + QUEUE_RAMP_UP_INTERVAL ) > jiffies)) {
+ if (time_before(jiffies,
+ phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) ||
+ time_before(jiffies,
+ phba->last_rsrc_error_time + QUEUE_RAMP_UP_INTERVAL)) {
spin_unlock_irqrestore(&phba->hbalock, flags);
return;
}
@@ -342,10 +374,9 @@
struct lpfc_vport **vports;
struct Scsi_Host *shost;
struct scsi_device *sdev;
- unsigned long new_queue_depth, old_queue_depth;
+ unsigned long new_queue_depth;
unsigned long num_rsrc_err, num_cmd_success;
int i;
- struct lpfc_rport_data *rdata;
num_rsrc_err = atomic_read(&phba->num_rsrc_err);
num_cmd_success = atomic_read(&phba->num_cmd_success);
@@ -363,22 +394,8 @@
else
new_queue_depth = sdev->queue_depth -
new_queue_depth;
- old_queue_depth = sdev->queue_depth;
- if (sdev->ordered_tags)
- scsi_adjust_queue_depth(sdev,
- MSG_ORDERED_TAG,
- new_queue_depth);
- else
- scsi_adjust_queue_depth(sdev,
- MSG_SIMPLE_TAG,
- new_queue_depth);
- rdata = sdev->hostdata;
- if (rdata)
- lpfc_send_sdev_queuedepth_change_event(
- phba, vports[i],
- rdata->pnode,
- sdev->lun, old_queue_depth,
- new_queue_depth);
+ lpfc_change_queue_depth(sdev, new_queue_depth,
+ SCSI_QDEPTH_DEFAULT);
}
}
lpfc_destroy_vport_work_array(phba, vports);
@@ -402,7 +419,6 @@
struct Scsi_Host *shost;
struct scsi_device *sdev;
int i;
- struct lpfc_rport_data *rdata;
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
@@ -412,22 +428,9 @@
if (vports[i]->cfg_lun_queue_depth <=
sdev->queue_depth)
continue;
- if (sdev->ordered_tags)
- scsi_adjust_queue_depth(sdev,
- MSG_ORDERED_TAG,
- sdev->queue_depth+1);
- else
- scsi_adjust_queue_depth(sdev,
- MSG_SIMPLE_TAG,
- sdev->queue_depth+1);
- rdata = sdev->hostdata;
- if (rdata)
- lpfc_send_sdev_queuedepth_change_event(
- phba, vports[i],
- rdata->pnode,
- sdev->lun,
- sdev->queue_depth - 1,
- sdev->queue_depth);
+ lpfc_change_queue_depth(sdev,
+ sdev->queue_depth+1,
+ SCSI_QDEPTH_RAMP_UP);
}
}
lpfc_destroy_vport_work_array(phba, vports);
@@ -2208,7 +2211,7 @@
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
int result;
struct scsi_device *tmp_sdev;
- int depth = 0;
+ int depth;
unsigned long flags;
struct lpfc_fast_path_event *fast_path_evt;
struct Scsi_Host *shost = cmd->device->host;
@@ -2375,67 +2378,29 @@
return;
}
-
if (!result)
lpfc_rampup_queue_depth(vport, queue_depth);
- if (!result && pnode && NLP_CHK_NODE_ACT(pnode) &&
- ((jiffies - pnode->last_ramp_up_time) >
- LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
- ((jiffies - pnode->last_q_full_time) >
- LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
- (vport->cfg_lun_queue_depth > queue_depth)) {
- shost_for_each_device(tmp_sdev, shost) {
- if (vport->cfg_lun_queue_depth > tmp_sdev->queue_depth){
- if (tmp_sdev->id != scsi_id)
- continue;
- if (tmp_sdev->ordered_tags)
- scsi_adjust_queue_depth(tmp_sdev,
- MSG_ORDERED_TAG,
- tmp_sdev->queue_depth+1);
- else
- scsi_adjust_queue_depth(tmp_sdev,
- MSG_SIMPLE_TAG,
- tmp_sdev->queue_depth+1);
-
- pnode->last_ramp_up_time = jiffies;
- }
- }
- lpfc_send_sdev_queuedepth_change_event(phba, vport, pnode,
- 0xFFFFFFFF,
- queue_depth , queue_depth + 1);
- }
-
/*
* Check for queue full. If the lun is reporting queue full, then
* back off the lun queue depth to prevent target overloads.
*/
if (result == SAM_STAT_TASK_SET_FULL && pnode &&
NLP_CHK_NODE_ACT(pnode)) {
- pnode->last_q_full_time = jiffies;
-
shost_for_each_device(tmp_sdev, shost) {
if (tmp_sdev->id != scsi_id)
continue;
depth = scsi_track_queue_full(tmp_sdev,
- tmp_sdev->queue_depth - 1);
- }
- /*
- * The queue depth cannot be lowered any more.
- * Modify the returned error code to store
- * the final depth value set by
- * scsi_track_queue_full.
- */
- if (depth == -1)
- depth = shost->cmd_per_lun;
-
- if (depth) {
+ tmp_sdev->queue_depth-1);
+ if (depth <= 0)
+ continue;
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
"0711 detected queue full - lun queue "
"depth adjusted to %d.\n", depth);
lpfc_send_sdev_queuedepth_change_event(phba, vport,
- pnode, 0xFFFFFFFF,
- depth+1, depth);
+ pnode,
+ tmp_sdev->lun,
+ depth+1, depth);
}
}
@@ -3019,6 +2984,10 @@
icmd->ulpLe = 1;
icmd->ulpClass = cmd->ulpClass;
+
+ /* ABTS WQE must go to the same WQ as the WQE to be aborted */
+ abtsiocb->fcp_wqidx = iocb->fcp_wqidx;
+
if (lpfc_is_link_up(phba))
icmd->ulpCommand = CMD_ABORT_XRI_CN;
else
@@ -3596,6 +3565,7 @@
.shost_attrs = lpfc_hba_attrs,
.max_sectors = 0xFFFF,
.vendor_id = LPFC_NL_VENDOR_ID,
+ .change_queue_depth = lpfc_change_queue_depth,
};
struct scsi_host_template lpfc_vport_template = {
@@ -3617,4 +3587,5 @@
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = lpfc_vport_attrs,
.max_sectors = 0xFFFF,
+ .change_queue_depth = lpfc_change_queue_depth,
};