RFC: handle queue_depth adjustments because of QUEUE_FULLs in scsi_error.c
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.
RFC PATCH 1/4 scsi-ml: modify change_queue_depth to take in reason why it is being called
From: Mike Christie <[email protected]>
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.
--- drivers/scsi/scsi_sysfs.c | 3 ++- include/scsi/scsi_host.h | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-)
drivers/scsi/scsi_sysfs.c +2 -1
@@ -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;
include/scsi/scsi_host.h +8 -1
@@ -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
Signature · 1 line
1.6.0.6
RFC PATCH 2/4 scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL
From: Mike Christie <[email protected]>
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.
--- drivers/scsi/scsi_error.c | 26 +++++++++++++++++++++++++- 1 files changed, 25 insertions(+), 1 deletions(-)
drivers/scsi/scsi_error.c +25 -1
@@ -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.
Signature · 1 line
1.6.0.6
RFC PATCH 3/4 drivers: convert drivers setting the change_queue_depth callback
From: Mike Christie <[email protected]>
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.
--- 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(-)
drivers/ata/libata-scsi.c +5 -1
@@ -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;
drivers/ata/sata_nv.c +1 -1
@@ -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); }
drivers/message/fusion/mptscsih.c +6 -2
@@ -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",
drivers/message/fusion/mptscsih.h +2 -1
@@ -124,7 +124,8 @@ extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_Fextern 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);
drivers/scsi/3w-9xxx.c +4 -1
@@ -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);
drivers/scsi/3w-xxxx.c +4 -1
@@ -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);
drivers/scsi/53c700.c +4 -1
@@ -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 ;
drivers/scsi/aacraid/linit.c +5 -1
@@ -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;
drivers/scsi/arcmsr/arcmsr_hba.c +4 -1
@@ -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);
drivers/scsi/hptiop.c +4 -1
@@ -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);
drivers/scsi/ibmvscsi/ibmvfc.c +6 -1
@@ -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 ;
drivers/scsi/ibmvscsi/ibmvscsi.c +6 -1
@@ -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 ;
drivers/scsi/ipr.c +6 -1
@@ -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;
drivers/scsi/libsas/sas_scsi_host.c +5 -1
@@ -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);
drivers/scsi/megaraid/megaraid_mbox.c +6 -1
@@ -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);
drivers/scsi/mpt2sas/mpt2sas_scsih.c +7 -3
@@ -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);
include/linux/libata.h +1 -1
@@ -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);
include/scsi/libsas.h +2 -1
@@ -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 *,
Signature · 1 line
1.6.0.6
RFC PATCH 4/4 drivers: convert fc drivers calling scsi_track_queue_full
From: Mike Christie <[email protected]>
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.
--- 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(-)
drivers/scsi/libfc/fc_fcp.c +11 -17
@@ -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);
drivers/scsi/lpfc/lpfc_scsi.c +41 -34
105 lines not on this page · raw message
drivers/scsi/qla2xxx/qla_isr.c +0 -28
@@ -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 )
drivers/scsi/qla2xxx/qla_os.c +27 -2
@@ -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; }
include/scsi/libfc.h +1 -1
@@ -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.
Signature · 1 line
1.6.0.6
Re: [RFC PATCH 4/4] drivers: convert fc drivers calling scsi_track_queue_full
Quoted 8 lines · On Tue, May 19, 2009 at 12:52:47AM -0500, [email protected] wrote:
From: Mike Christie <[email protected]>
This converts the fc drivers that were using
scsi_track_queue_fullto track the queue full from thechange_queue_depthcallback.I have not yet tested the qla2xxx or lpfc parts.
Signed-off-by Mike Christie <[email protected]>
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 <[email protected]>
Now that zfcp implements the scsi_change_queue_depth callback, the reason attribute is also required here.
--- drivers/s390/scsi/zfcp_scsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/s390/scsi/zfcp_scsi.c +2 -1
@@ -28,7 +28,8 @@ char *zfcp_get_fcp_sns_info_ptr(struct freturn 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;
Re: [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL
In reply to [email protected]Quoted 33 lines · On Tue, May 19, 2009 at 12:52:45AM -0500, [email protected] wrote:
From: Mike Christie <[email protected]>
This has scsi-ml call the
change_queue_depthfunctions when we get aQUEUE_FULL. It will only change the queue depth ifchange_queue_depthis 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 <[email protected]>--- drivers/scsi/scsi_error.c | 26 +++++++++++++++++++++++++- 1 files changed, 25 insertions(+), 1 deletions(-)drivers/scsi/scsi_error.c +11
-0@@ -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 ;
drivers/scsi/scsi_error.c static int scsi_check_sense(struct scsi_cmnd *scmd) · line 354
Quoted 10 lines
drivers/scsi/scsi_error.c +10
-0+/* +* 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
Re: [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL
Quoted 40 lines · Christof Schmitt
Quoted 39 lines · On Tue, May 19, 2009 at 12:52:45AM -0500, [email protected] wrote:
From: Mike Christie<[email protected]>
This has scsi-ml call the
change_queue_depthfunctions when we get aQUEUE_FULL. It will only change the queue depth ifchange_queue_depthis 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<[email protected]>--- drivers/scsi/scsi_error.c | 26 +++++++++++++++++++++++++- 1 files changed, 25 insertions(+), 1 deletions(-)drivers/scsi/scsi_error.c +17
-0@@ -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,
Quoted 8 lines
drivers/scsi/scsi_error.c static int scsi_check_sense(struct scsi_cmnd *scmd) · line 354
Quoted 4 lines
drivers/scsi/scsi_error.c +4
-0+ 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.
Re: [RFC PATCH 2/4] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL
Quoted 8 lines · Mike Christie
Quoted 4 lines
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