All of lore.kernel.org
 help / color / mirror / Atom feed
* RFC: handle queue_depth adjustments because of QUEUE_FULLs in scsi_error.c
@ 2009-05-19  5:52 michaelc
  2009-05-19  5:52 ` michaelc
  0 siblings, 1 reply; 10+ messages in thread
From: michaelc @ 2009-05-19  5:52 UTC (permalink / raw)
  To: linux-scsi

These patches were made over scsi-rc-fixes. They are only a RFC.

This is the first step to moving the QUEUE_FULL and then the
ramp up code from drivers like qla2xxx and lpfc to scsi-ml.
In the patches I am using the change_queue_depth callback
to allow the drivers to adjust the queue depth, so LLDs do
not have to worry about parsing the sense.

If these patches are ok, then we can move the ramp up code
from qla2xxx and lpfc to scsi-ml. I was planning on using
the change_queue_depth callback for this by calling it
with the SCSI_QDEPTH_RAMP_UP reason.


Note:

I did not convert the non fc drivers that were only calling
scsi_track_queue_full and did not have a change_queue_depth callback.
I think the behavior would be slightly different so I did not want to
mess with them. The patches I am sending will work fine if we
leave these drivers a long and only convert newer drivers.

mpt2sas was an exception where it is a newer driver and had
a change_queue_depth callback but I did not convert it. I wll
work on this one some more if this patchset is ok.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* RFC: handle queue_depth adjustments because of QUEUE_FULLs in scsi_error.c
  2009-05-19  5:52 RFC: handle queue_depth adjustments because of QUEUE_FULLs in scsi_error.c michaelc
@ 2009-05-19  5:52 ` michaelc
  2009-05-19  5:52   ` [RFC PATCH 1/4] scsi-ml: modify change_queue_depth to take in reason why it is being called michaelc
  0 siblings, 1 reply; 10+ messages in thread
From: michaelc @ 2009-05-19  5:52 UTC (permalink / raw)
  To: linux-scsi



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 1/4] scsi-ml: modify change_queue_depth to take in reason why it is being called
  2009-05-19  5:52 ` michaelc
@ 2009-05-19  5:52   ` michaelc
  2009-05-19  5:52     ` [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL michaelc
  0 siblings, 1 reply; 10+ messages in thread
From: michaelc @ 2009-05-19  5:52 UTC (permalink / raw)
  To: linux-scsi; +Cc: Mike Christie

From: Mike Christie <michaelc@cs.wisc.edu>

This patch modifies scsi_host_tematepl->change_queue_depth so that
it takes an argument indicating why it is being called. This will be
used so that if a LLD needs to do some extra processing when
handling queue fulls or later ramp ups, it can do so.

To simplify the review, this patch only modifies scsi-ml. The next
patches will convert each driver.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
---
 drivers/scsi/scsi_sysfs.c |    3 ++-
 include/scsi/scsi_host.h  |    9 ++++++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index fa4711d..2453948 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -783,7 +783,8 @@ sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr,
 	if (depth < 1)
 		return -EINVAL;
 
-	retval = sht->change_queue_depth(sdev, depth);
+	retval = sht->change_queue_depth(sdev, depth,
+					 SCSI_QDEPTH_SYSFS_REQ);
 	if (retval < 0)
 		return retval;
 
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index d123ca8..60495f5 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -43,6 +43,13 @@ struct blk_queue_tags;
 #define DISABLE_CLUSTERING 0
 #define ENABLE_CLUSTERING 1
 
+enum {
+	SCSI_QDEPTH_SYSFS_REQ,	/* user requested change through sysfs */
+	SCSI_QDEPTH_QFULL,	/* scsi-ml requested due to queue full */
+	SCSI_QDEPTH_RAMP_UP,	/* scsi-ml requested due to threshhold event */
+	SCSI_QDEPTH_RAMP_DOWN, 	/* LLD/class requested due to lld/class event */
+};
+
 struct scsi_host_template {
 	struct module *module;
 	const char *name;
@@ -294,7 +301,7 @@ struct scsi_host_template {
 	 *
 	 * Status: OPTIONAL
 	 */
-	int (* change_queue_depth)(struct scsi_device *, int);
+	int (* change_queue_depth)(struct scsi_device *, int, int);
 
 	/*
 	 * Fill in this function to allow the changing of tag types
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL
  2009-05-19  5:52   ` [RFC PATCH 1/4] scsi-ml: modify change_queue_depth to take in reason why it is being called michaelc
@ 2009-05-19  5:52     ` michaelc
  2009-05-19  5:52       ` [RFC PATCH 3/4] drivers: convert drivers setting the change_queue_depth callback michaelc
  2009-06-12 12:48       ` [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL Christof Schmitt
  0 siblings, 2 replies; 10+ messages in thread
From: michaelc @ 2009-05-19  5:52 UTC (permalink / raw)
  To: linux-scsi; +Cc: Mike Christie

From: Mike Christie <michaelc@cs.wisc.edu>

This has scsi-ml call the change_queue_depth functions when
we get a QUEUE_FULL. It will only change the queue depth if
change_queue_depth is set because the LLD may have to
modify some internal resources, so I thought this would
be the safest route.


Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
---
 drivers/scsi/scsi_error.c |   26 +++++++++++++++++++++++++-
 1 files changed, 25 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 0c2c73b..792644e 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -331,6 +331,27 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
 	}
 }
 
+static void scsi_handle_queue_full(struct scsi_device *sdev)
+{
+	struct scsi_host_template *sht = sdev->host->hostt;
+	struct scsi_device *tmp_sdev;
+
+	if (!sht->change_queue_depth)
+		return;
+
+	shost_for_each_device(tmp_sdev, sdev->host) {
+		if (tmp_sdev->id != sdev->id)
+			continue;
+		/*
+		 * We do not know the number of commands that were at
+		 * the device when we got the queue full so we start
+		 * from the highest possible value and work our way down.
+		 */
+		sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth - 1,
+					SCSI_QDEPTH_QFULL);
+	}
+}
+
 /**
  * scsi_eh_completed_normally - Disposition a eh cmd on return from LLD.
  * @scmd:	SCSI cmd to examine.
@@ -382,8 +403,10 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd)
 		 * who knows?  FIXME(eric)
 		 */
 		return SUCCESS;
-	case BUSY:
 	case QUEUE_FULL:
+		scsi_handle_queue_full(scmd->device);
+		/* fall through */
+	case BUSY:
 	case RESERVATION_CONFLICT:
 	default:
 		return FAILED;
@@ -1380,6 +1403,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
 	 */
 	switch (status_byte(scmd->result)) {
 	case QUEUE_FULL:
+		scsi_handle_queue_full(scmd->device);
 		/*
 		 * the case of trying to send too many commands to a
 		 * tagged queueing device.
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 3/4] drivers: convert drivers setting the change_queue_depth callback
  2009-05-19  5:52     ` [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL michaelc
@ 2009-05-19  5:52       ` michaelc
  2009-05-19  5:52         ` [RFC PATCH 4/4] drivers: convert fc drivers calling scsi_track_queue_full michaelc
  2009-06-12 12:48       ` [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL Christof Schmitt
  1 sibling, 1 reply; 10+ messages in thread
From: michaelc @ 2009-05-19  5:52 UTC (permalink / raw)
  To: linux-scsi; +Cc: Mike Christie

From: Mike Christie <michaelc@cs.wisc.edu>

This is a simple port of the drivers setting a change_queue_depth
callback but were not tracking queue fulls. In the patch I just have
these LLDs adjust the queue depth if the user was requesting it.

Patch is only compile tested.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
---
 drivers/ata/libata-scsi.c             |    6 +++++-
 drivers/ata/sata_nv.c                 |    2 +-
 drivers/message/fusion/mptscsih.c     |    8 ++++++--
 drivers/message/fusion/mptscsih.h     |    3 ++-
 drivers/scsi/3w-9xxx.c                |    5 ++++-
 drivers/scsi/3w-xxxx.c                |    5 ++++-
 drivers/scsi/53c700.c                 |    5 ++++-
 drivers/scsi/aacraid/linit.c          |    6 +++++-
 drivers/scsi/arcmsr/arcmsr_hba.c      |    5 ++++-
 drivers/scsi/hptiop.c                 |    5 ++++-
 drivers/scsi/ibmvscsi/ibmvfc.c        |    7 ++++++-
 drivers/scsi/ibmvscsi/ibmvscsi.c      |    7 ++++++-
 drivers/scsi/ipr.c                    |    7 ++++++-
 drivers/scsi/libsas/sas_scsi_host.c   |    6 +++++-
 drivers/scsi/megaraid/megaraid_mbox.c |    7 ++++++-
 drivers/scsi/mpt2sas/mpt2sas_scsih.c  |   10 +++++++---
 include/linux/libata.h                |    2 +-
 include/scsi/libsas.h                 |    3 ++-
 18 files changed, 78 insertions(+), 21 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 68d9132..45eecb9 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1223,12 +1223,16 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
  *	RETURNS:
  *	Newly configured queue depth.
  */
-int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
+int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
+				int reason)
 {
 	struct ata_port *ap = ata_shost_to_port(sdev->host);
 	struct ata_device *dev;
 	unsigned long flags;
 
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
+
 	if (queue_depth < 1 || queue_depth == sdev->queue_depth)
 		return sdev->queue_depth;
 
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 6cda12b..a1c09d9 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -1931,7 +1931,7 @@ static int nv_swncq_slave_config(struct scsi_device *sdev)
 	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
 	if (strncmp(model_num, "Maxtor", 6) == 0) {
-		ata_scsi_change_queue_depth(sdev, 1);
+		ata_scsi_change_queue_depth(sdev, 1, SCSI_QDEPTH_SYSFS_REQ);
 		ata_dev_printk(dev, KERN_NOTICE,
 			"Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth);
 	}
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index e62c6bc..f201846 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -2393,7 +2393,7 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
  *	Adding support for new 'change_queue_depth' api.
 */
 int
-mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
 {
 	MPT_SCSI_HOST		*hd = shost_priv(sdev->host);
 	VirtTarget 		*vtarget;
@@ -2405,6 +2405,9 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 	starget = scsi_target(sdev);
 	vtarget = starget->hostdata;
 
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
+
 	if (ioc->bus_type == SPI) {
 		if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
 			max_depth = 1;
@@ -2457,7 +2460,8 @@ mptscsih_slave_configure(struct scsi_device *sdev)
 		    sdev->ppr, sdev->inquiry_len));
 
 	vdevice->configured_lun = 1;
-	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
+	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH,
+				    SCSI_QDEPTH_SYSFS_REQ);
 
 	dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 		"Queue depth=%d, tflags=%x\n",
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 319aa30..6404c10 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -124,7 +124,8 @@ extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_F
 extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
-extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
+extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth,
+				       int reason);
 extern void mptscsih_timer_expired(unsigned long data);
 extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
 extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 36c21b1..c3d49b3 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -186,8 +186,11 @@ static ssize_t twa_show_stats(struct device *dev,
 } /* End twa_show_stats() */
 
 /* This function will set a devices queue depth */
-static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth)
+static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth,
+				  int reason)
 {
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
 	if (queue_depth > TW_Q_LENGTH-2)
 		queue_depth = TW_Q_LENGTH-2;
 	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index faa0fcf..5bc1251 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -521,8 +521,11 @@ static ssize_t tw_show_stats(struct device *dev, struct device_attribute *attr,
 } /* End tw_show_stats() */
 
 /* This function will set a devices queue depth */
-static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth)
+static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth,
+				 int reason)
 {
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
 	if (queue_depth > TW_Q_LENGTH-2)
 		queue_depth = TW_Q_LENGTH-2;
 	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index f5a9add..8fea91a 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -2082,8 +2082,11 @@ NCR_700_slave_destroy(struct scsi_device *SDp)
 }
 
 static int
-NCR_700_change_queue_depth(struct scsi_device *SDp, int depth)
+NCR_700_change_queue_depth(struct scsi_device *SDp, int depth, int reason)
 {
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
+
 	if (depth > NCR_700_MAX_TAGS)
 		depth = NCR_700_MAX_TAGS;
 
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 9b97c3e..0b4605a 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -472,8 +472,12 @@ static int aac_slave_configure(struct scsi_device *sdev)
  *	total capacity and the queue depth supported by the target device.
  */
 
-static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
+static int aac_change_queue_depth(struct scsi_device *sdev, int depth,
+				  int reason)
 {
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
+
 	if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
 	    (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
 		struct scsi_device * dev;
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 80aac01..a3d0ded 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -98,8 +98,11 @@ static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb);
 static const char *arcmsr_info(struct Scsi_Host *);
 static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
 static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev,
-								int queue_depth)
+					  int queue_depth, int reason)
 {
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
+
 	if (queue_depth > ARCMSR_MAX_CMD_PERLUN)
 		queue_depth = ARCMSR_MAX_CMD_PERLUN;
 	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index c596ab5..a2f3c41 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -847,10 +847,13 @@ static int hptiop_reset(struct scsi_cmnd *scp)
 }
 
 static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
-						int queue_depth)
+					  int queue_depth, int reason)
 {
 	struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata;
 
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
+
 	if (queue_depth > hba->max_requests)
 		queue_depth = hba->max_requests;
 	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index ea4abee..4e39afa 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -2388,12 +2388,17 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev)
  * ibmvfc_change_queue_depth - Change the device's queue depth
  * @sdev:	scsi device struct
  * @qdepth:	depth to set
+ * @reason:	calling context
  *
  * Return value:
  * 	actual depth set
  **/
-static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth)
+static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth,
+				     int reason)
 {
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
+
 	if (qdepth > IBMVFC_MAX_CMDS_PER_LUN)
 		qdepth = IBMVFC_MAX_CMDS_PER_LUN;
 
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index c9aa761..6ac1698 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -1455,12 +1455,17 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev)
  * ibmvscsi_change_queue_depth - Change the device's queue depth
  * @sdev:	scsi device struct
  * @qdepth:	depth to set
+ * @reason:	calling context
  *
  * Return value:
  * 	actual depth set
  **/
-static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
+static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth,
+				       int reason)
 {
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
+
 	if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN)
 		qdepth = IBMVSCSI_MAX_CMDS_PER_LUN;
 
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index dd689de..aa04fb5 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -3367,16 +3367,21 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; };
  * ipr_change_queue_depth - Change the device's queue depth
  * @sdev:	scsi device struct
  * @qdepth:	depth to set
+ * @reason:	calling context
  *
  * Return value:
  * 	actual depth set
  **/
-static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth)
+static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth,
+				  int reason)
 {
 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
 	struct ipr_resource_entry *res;
 	unsigned long lock_flags = 0;
 
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
+
 	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
 	res = (struct ipr_resource_entry *)sdev->hostdata;
 
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 1c558d3..84230ae 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -820,10 +820,14 @@ void sas_slave_destroy(struct scsi_device *scsi_dev)
 		ata_port_disable(dev->sata_dev.ap);
 }
 
-int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth)
+int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth,
+			   int reason)
 {
 	int res = min(new_depth, SAS_MAX_QD);
 
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
+
 	if (scsi_dev->tagged_supported)
 		scsi_adjust_queue_depth(scsi_dev, scsi_get_tag_type(scsi_dev),
 					res);
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 234f0b7..dc17d75 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -335,12 +335,17 @@ static struct device_attribute *megaraid_sdev_attrs[] = {
  * megaraid_change_queue_depth - Change the device's queue depth
  * @sdev:	scsi device struct
  * @qdepth:	depth to set
+ * @reason:	calling context
  *
  * Return value:
  * 	actual depth set
  */
-static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth)
+static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth,
+				       int reason)
 {
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
+
 	if (qdepth > MBOX_MAX_SCSI_CMDS)
 		qdepth = MBOX_MAX_SCSI_CMDS;
 	scsi_adjust_queue_depth(sdev, 0, qdepth);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index e3a7967..d5e1a3d 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -1050,16 +1050,20 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
  * scsih_change_queue_depth - setting device queue depth
  * @sdev: scsi device struct
  * @qdepth: requested queue depth
+ * @reason: calling context
  *
  * Returns queue depth.
  */
 static int
-scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
 {
 	struct Scsi_Host *shost = sdev->host;
 	int max_depth;
 	int tag_type;
 
+	if (reason != SCSI_QDEPTH_SYSFS_REQ)
+		return -EOPNOTSUPP;
+
 	max_depth = shost->can_queue;
 	if (!sdev->tagged_supported)
 		max_depth = 1;
@@ -1489,7 +1493,7 @@ scsih_slave_configure(struct scsi_device *sdev)
 		    r_level, raid_device->handle,
 		    (unsigned long long)raid_device->wwid,
 		    raid_device->num_pds, ds);
-		scsih_change_queue_depth(sdev, qdepth);
+		scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_SYSFS_REQ);
 		return 0;
 	}
 
@@ -1535,7 +1539,7 @@ scsih_slave_configure(struct scsi_device *sdev)
 			scsih_display_sata_capabilities(ioc, sas_device, sdev);
 	}
 
-	scsih_change_queue_depth(sdev, qdepth);
+	scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_SYSFS_REQ);
 
 	if (ssp_target)
 		sas_read_port_mode_page(sdev);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 3d501db..026cf2e 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -1008,7 +1008,7 @@ extern int ata_std_bios_param(struct scsi_device *sdev,
 extern int ata_scsi_slave_config(struct scsi_device *sdev);
 extern void ata_scsi_slave_destroy(struct scsi_device *sdev);
 extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
-				       int queue_depth);
+				       int queue_depth, int reason);
 extern struct ata_device *ata_dev_pair(struct ata_device *adev);
 extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
 
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index e78d3b6..9eaa3f0 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -634,7 +634,8 @@ extern int sas_target_alloc(struct scsi_target *);
 extern int sas_slave_alloc(struct scsi_device *);
 extern int sas_slave_configure(struct scsi_device *);
 extern void sas_slave_destroy(struct scsi_device *);
-extern int sas_change_queue_depth(struct scsi_device *, int new_depth);
+extern int sas_change_queue_depth(struct scsi_device *, int new_depth,
+				  int reason);
 extern int sas_change_queue_type(struct scsi_device *, int qt);
 extern int sas_bios_param(struct scsi_device *,
 			  struct block_device *,
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 4/4] drivers: convert fc drivers calling scsi_track_queue_full
  2009-05-19  5:52       ` [RFC PATCH 3/4] drivers: convert drivers setting the change_queue_depth callback michaelc
@ 2009-05-19  5:52         ` michaelc
  2009-06-12 12:57           ` Christof Schmitt
  0 siblings, 1 reply; 10+ messages in thread
From: michaelc @ 2009-05-19  5:52 UTC (permalink / raw)
  To: linux-scsi; +Cc: Mike Christie

From: Mike Christie <michaelc@cs.wisc.edu>

This converts the fc drivers that were using scsi_track_queue_full
to track the queue full from the change_queue_depth callback.

I have not yet tested the qla2xxx or lpfc parts.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
---
 drivers/scsi/libfc/fc_fcp.c    |   28 ++++++---------
 drivers/scsi/lpfc/lpfc_scsi.c  |   75 ++++++++++++++++++++++------------------
 drivers/scsi/qla2xxx/qla_isr.c |   28 ---------------
 drivers/scsi/qla2xxx/qla_os.c  |   29 ++++++++++++++-
 include/scsi/libfc.h           |    2 +-
 5 files changed, 80 insertions(+), 82 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 521f996..5b10f37 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1848,21 +1848,6 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
 			sc_cmd->result = DID_OK << 16;
 			if (fsp->scsi_resid)
 				CMD_RESID_LEN(sc_cmd) = fsp->scsi_resid;
-		} else if (fsp->cdb_status == QUEUE_FULL) {
-			struct scsi_device *tmp_sdev;
-			struct scsi_device *sdev = sc_cmd->device;
-
-			shost_for_each_device(tmp_sdev, sdev->host) {
-				if (tmp_sdev->id != sdev->id)
-					continue;
-
-				if (tmp_sdev->queue_depth > 1) {
-					scsi_track_queue_full(tmp_sdev,
-							      tmp_sdev->
-							      queue_depth - 1);
-				}
-			}
-			sc_cmd->result = (DID_OK << 16) | fsp->cdb_status;
 		} else {
 			/*
 			 * transport level I/O was ok but scsi
@@ -2090,9 +2075,18 @@ int fc_slave_alloc(struct scsi_device *sdev)
 }
 EXPORT_SYMBOL(fc_slave_alloc);
 
-int fc_change_queue_depth(struct scsi_device *sdev, int qdepth)
+int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
 {
-	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+	switch (reason) {
+	case SCSI_QDEPTH_SYSFS_REQ:
+		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+		break;
+	case SCSI_QDEPTH_QFULL:
+		scsi_track_queue_full(sdev, qdepth);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
 	return sdev->queue_depth;
 }
 EXPORT_SYMBOL(fc_change_queue_depth);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 167b66d..f0c9904 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -1694,7 +1694,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
 	struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
 	int result;
 	struct scsi_device *tmp_sdev;
-	int depth = 0;
 	unsigned long flags;
 	struct lpfc_fast_path_event *fast_path_evt;
 	struct Scsi_Host *shost = cmd->device->host;
@@ -1893,39 +1892,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
 	}
 
 	/*
-	 * 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) {
-			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);
-		}
-	}
-
-	/*
 	 * If there is a thread waiting for command completion
 	 * wake up the thread.
 	 */
@@ -2922,6 +2888,45 @@ lpfc_slave_configure(struct scsi_device *sdev)
 	return 0;
 }
 
+static int lpfc_change_queue_depth(struct scsi_device *sdev, int queue_depth,
+				   int reason)
+{
+	struct Scsi_Host *shost = sdev->host;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba *phba = vport->phba;
+	struct lpfc_rport_data *rdata = sdev->hostdata;
+	struct lpfc_nodelist *pnode = rdata->pnode;
+	int depth;
+
+	if (reason != SCSI_QDEPTH_QFULL)
+		return -EOPNOTSUPP;
+
+	if (!pnode || !NLP_CHK_NODE_ACT(pnode))
+		return -EINVAL;
+
+	pnode->last_q_full_time = jiffies;
+
+	depth = scsi_track_queue_full(sdev, queue_depth);
+	/*
+	 * 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) {
+		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);
+	}
+	return sdev->queue_depth;
+}
+
 /**
  * lpfc_slave_destroy - slave_destroy entry point of SHT data structure
  * @sdev: Pointer to scsi_device.
@@ -2944,6 +2949,7 @@ struct scsi_host_template lpfc_template = {
 	.eh_abort_handler	= lpfc_abort_handler,
 	.eh_device_reset_handler= lpfc_device_reset_handler,
 	.eh_bus_reset_handler	= lpfc_bus_reset_handler,
+	.change_queue_depth	= lpfc_change_queue_depth,
 	.slave_alloc		= lpfc_slave_alloc,
 	.slave_configure	= lpfc_slave_configure,
 	.slave_destroy		= lpfc_slave_destroy,
@@ -2964,6 +2970,7 @@ struct scsi_host_template lpfc_vport_template = {
 	.eh_abort_handler	= lpfc_abort_handler,
 	.eh_device_reset_handler= lpfc_device_reset_handler,
 	.eh_bus_reset_handler	= lpfc_bus_reset_handler,
+	.change_queue_depth	= lpfc_change_queue_depth,
 	.slave_alloc		= lpfc_slave_alloc,
 	.slave_configure	= lpfc_slave_configure,
 	.slave_destroy		= lpfc_slave_destroy,
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index d049818..fd359b3 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -787,20 +787,6 @@ qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, void *data)
 	    sdev->queue_depth));
 }
 
-static void
-qla2x00_adjust_sdev_qdepth_down(struct scsi_device *sdev, void *data)
-{
-	fc_port_t *fcport = data;
-
-	if (!scsi_track_queue_full(sdev, sdev->queue_depth - 1))
-		return;
-
-	DEBUG2(qla_printk(KERN_INFO, fcport->vha->hw,
-	    "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n",
-	    fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
-	    sdev->queue_depth));
-}
-
 static inline void
 qla2x00_ramp_up_queue_depth(scsi_qla_host_t *vha, struct req_que *req,
 								srb_t *sp)
@@ -1119,11 +1105,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 			    "scsi(%ld): QUEUE FULL status detected "
 			    "0x%x-0x%x.\n", vha->host_no, comp_status,
 			    scsi_status));
-
-			/* Adjust queue depth for all luns on the port. */
-			fcport->last_queue_full = jiffies;
-			starget_for_each_device(cp->device->sdev_target,
-			    fcport, qla2x00_adjust_sdev_qdepth_down);
 			break;
 		}
 		if (lscsi_status != SS_CHECK_CONDITION)
@@ -1174,15 +1155,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 				    "scsi(%ld): QUEUE FULL status detected "
 				    "0x%x-0x%x.\n", vha->host_no, comp_status,
 				    scsi_status));
-
-				/*
-				 * Adjust queue depth for all luns on the
-				 * port.
-				 */
-				fcport->last_queue_full = jiffies;
-				starget_for_each_device(
-				    cp->device->sdev_target, fcport,
-				    qla2x00_adjust_sdev_qdepth_down);
 				break;
 			}
 			if (lscsi_status != SS_CHECK_CONDITION)
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index e4fdcda..e9af1bc 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1141,10 +1141,35 @@ qla2xxx_slave_destroy(struct scsi_device *sdev)
 	sdev->hostdata = NULL;
 }
 
+static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth)
+{
+	fc_port_t *fcport = (struct fc_port *) sdev->device->hostdata;
+
+	fcport->last_queue_full = jiffies;
+
+	if (!scsi_track_queue_full(sdev, qdepth))
+		return;
+
+	DEBUG2(qla_printk(KERN_INFO, fcport->vha->hw,
+		"scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n",
+		fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
+		sdev->queue_depth));
+}
+
 static int
-qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth)
+qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
 {
-	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+	switch (reason) {
+	case SCSI_QDEPTH_SYSFS_REQ:
+		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+		break;
+	case SCSI_QDEPTH_QFULL:
+		qla2x00_handle_queue_full(sdev, qdepth);
+		break;
+	default:
+		return EOPNOTSUPP;
+	}
+
 	return sdev->queue_depth;
 }
 
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 45f9cc6..ae1a07f 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -868,7 +868,7 @@ int fc_slave_alloc(struct scsi_device *sdev);
 /*
  * Adjust the queue depth.
  */
-int fc_change_queue_depth(struct scsi_device *sdev, int qdepth);
+int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason);
 
 /*
  * Change the tag type.
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL
  2009-05-19  5:52     ` [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL michaelc
  2009-05-19  5:52       ` [RFC PATCH 3/4] drivers: convert drivers setting the change_queue_depth callback michaelc
@ 2009-06-12 12:48       ` Christof Schmitt
  2009-06-15 17:34         ` Mike Christie
  1 sibling, 1 reply; 10+ messages in thread
From: Christof Schmitt @ 2009-06-12 12:48 UTC (permalink / raw)
  To: michaelc; +Cc: linux-scsi

On Tue, May 19, 2009 at 12:52:45AM -0500, michaelc@cs.wisc.edu wrote:
> From: Mike Christie <michaelc@cs.wisc.edu>
> 
> This has scsi-ml call the change_queue_depth functions when
> we get a QUEUE_FULL. It will only change the queue depth if
> change_queue_depth is set because the LLD may have to
> modify some internal resources, so I thought this would
> be the safest route.
> 
> 
> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
> ---
>  drivers/scsi/scsi_error.c |   26 +++++++++++++++++++++++++-
>  1 files changed, 25 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
> index 0c2c73b..792644e 100644
> --- a/drivers/scsi/scsi_error.c
> +++ b/drivers/scsi/scsi_error.c
> @@ -331,6 +331,27 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
>  	}
>  }
> 
> +static void scsi_handle_queue_full(struct scsi_device *sdev)
> +{
> +	struct scsi_host_template *sht = sdev->host->hostt;
> +	struct scsi_device *tmp_sdev;
> +
> +	if (!sht->change_queue_depth)
> +		return;
> +
> +	shost_for_each_device(tmp_sdev, sdev->host) {
> +		if (tmp_sdev->id != sdev->id)
> +			continue;
> +		/*
> +		 * We do not know the number of commands that were at
> +		 * the device when we got the queue full so we start
> +		 * from the highest possible value and work our way down.
> +		 */
> +		sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth - 1,
> +					SCSI_QDEPTH_QFULL);
> +	}
> +}
> +

This was called because of a "queue full" for one SCSI device. Why do
you decrement the queue depth for all SCSI devices on the same host
and not only for one device?

I think the overall approach looks good.

Thanks for working on this,

Christof

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH 4/4] drivers: convert fc drivers calling scsi_track_queue_full
  2009-05-19  5:52         ` [RFC PATCH 4/4] drivers: convert fc drivers calling scsi_track_queue_full michaelc
@ 2009-06-12 12:57           ` Christof Schmitt
  0 siblings, 0 replies; 10+ messages in thread
From: Christof Schmitt @ 2009-06-12 12:57 UTC (permalink / raw)
  To: michaelc; +Cc: linux-scsi

On Tue, May 19, 2009 at 12:52:47AM -0500, michaelc@cs.wisc.edu wrote:
> From: Mike Christie <michaelc@cs.wisc.edu>
> 
> This converts the fc drivers that were using scsi_track_queue_full
> to track the queue full from the change_queue_depth callback.
> 
> I have not yet tested the qla2xxx or lpfc parts.
> 
> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>

In scsi-misc zfcp also implements the change_queue_depth callback, so
this has to be adjusted, too:
--
zfcp: Add reason attribute to scsi_change_queue_depth callback

From: Christof Schmitt <christof.schmitt@de.ibm.com>

Now that zfcp implements the scsi_change_queue_depth callback, the
reason attribute is also required here.

Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
---
 drivers/s390/scsi/zfcp_scsi.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

--- a/drivers/s390/scsi/zfcp_scsi.c	2009-06-12 14:16:55.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_scsi.c	2009-06-12 14:33:20.000000000 +0200
@@ -28,7 +28,8 @@ char *zfcp_get_fcp_sns_info_ptr(struct f
 	return fcp_sns_info_ptr;
 }
 
-static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth)
+static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth,
+					int reason)
 {
 	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
 	return sdev->queue_depth;

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL
  2009-06-12 12:48       ` [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL Christof Schmitt
@ 2009-06-15 17:34         ` Mike Christie
  2009-06-16 13:16           ` James Smart
  0 siblings, 1 reply; 10+ messages in thread
From: Mike Christie @ 2009-06-15 17:34 UTC (permalink / raw)
  To: Christof Schmitt; +Cc: linux-scsi, James Smart, Andrew Vasquez

On 06/12/2009 07:48 AM, Christof Schmitt wrote:
> On Tue, May 19, 2009 at 12:52:45AM -0500, michaelc@cs.wisc.edu wrote:
>> From: Mike Christie<michaelc@cs.wisc.edu>
>>
>> This has scsi-ml call the change_queue_depth functions when
>> we get a QUEUE_FULL. It will only change the queue depth if
>> change_queue_depth is set because the LLD may have to
>> modify some internal resources, so I thought this would
>> be the safest route.
>>
>>
>> Signed-off-by: Mike Christie<michaelc@cs.wisc.edu>
>> ---
>>   drivers/scsi/scsi_error.c |   26 +++++++++++++++++++++++++-
>>   1 files changed, 25 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
>> index 0c2c73b..792644e 100644
>> --- a/drivers/scsi/scsi_error.c
>> +++ b/drivers/scsi/scsi_error.c
>> @@ -331,6 +331,27 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
>>   	}
>>   }
>>
>> +static void scsi_handle_queue_full(struct scsi_device *sdev)
>> +{
>> +	struct scsi_host_template *sht = sdev->host->hostt;
>> +	struct scsi_device *tmp_sdev;
>> +
>> +	if (!sht->change_queue_depth)
>> +		return;
>> +
>> +	shost_for_each_device(tmp_sdev, sdev->host) {
>> +		if (tmp_sdev->id != sdev->id)
>> +			continue;
>> +		/*
>> +		 * We do not know the number of commands that were at
>> +		 * the device when we got the queue full so we start
>> +		 * from the highest possible value and work our way down.
>> +		 */
>> +		sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth - 1,
>> +					SCSI_QDEPTH_QFULL);
>> +	}
>> +}
>> +
>
> This was called because of a "queue full" for one SCSI device. Why do
> you decrement the queue depth for all SCSI devices on the same host
> and not only for one device?

It should actually do it for only the devices on the same target where 
the problem occurred. I copied the code from lpfc and qla2xxx and cannot 
remember the reason why this is done now.  I am ccing AndrewV and JamesS.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL
  2009-06-15 17:34         ` Mike Christie
@ 2009-06-16 13:16           ` James Smart
  0 siblings, 0 replies; 10+ messages in thread
From: James Smart @ 2009-06-16 13:16 UTC (permalink / raw)
  To: Mike Christie; +Cc: Christof Schmitt, linux-scsi, Andrew Vasquez



Mike Christie wrote:
>> This was called because of a "queue full" for one SCSI device. Why do
>> you decrement the queue depth for all SCSI devices on the same host
>> and not only for one device?
>>     
>
> It should actually do it for only the devices on the same target where 
> the problem occurred. I copied the code from lpfc and qla2xxx and cannot 
> remember the reason why this is done now.  I am ccing AndrewV and JamesS.
>
>   

Agree that it should be localized to the target and not propagated to 
all targets.   Our design issue was choosing how to apply the backoff - 
did a queue full on a single lun imply the entire target is full ?  
Thus, should we reduce all luns at that point, or only the lun that saw 
the queue full.   All depends on how fast you want to ramp down the 
overall situation and how biased things get on multiple luns..  And the 
same decision on the ramp up - to we raise everyone, or let the luns 
function independently.  Raising everyone too quickly recauses the 
issue, and why would one hot lun steal capacity/queuing depth for a slow 
lun ?  There's a lot of assumptions being made in this choice on what is 
the gating resource (the io capacity of the target being equally shared 
by all luns).

-- james s



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2009-06-16 13:16 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-19  5:52 RFC: handle queue_depth adjustments because of QUEUE_FULLs in scsi_error.c michaelc
2009-05-19  5:52 ` michaelc
2009-05-19  5:52   ` [RFC PATCH 1/4] scsi-ml: modify change_queue_depth to take in reason why it is being called michaelc
2009-05-19  5:52     ` [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL michaelc
2009-05-19  5:52       ` [RFC PATCH 3/4] drivers: convert drivers setting the change_queue_depth callback michaelc
2009-05-19  5:52         ` [RFC PATCH 4/4] drivers: convert fc drivers calling scsi_track_queue_full michaelc
2009-06-12 12:57           ` Christof Schmitt
2009-06-12 12:48       ` [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL Christof Schmitt
2009-06-15 17:34         ` Mike Christie
2009-06-16 13:16           ` James Smart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.