aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujit Reddy Thumma <sthumma@codeaurora.org>2014-06-29 02:40:20 -0400
committerChristoph Hellwig <hch@lst.de>2014-07-25 17:17:01 -0400
commit4264fd613a6a4b9c1c91d9291653d0fdaf4fd288 (patch)
tree7dd4f300e45d50dddceba4bcfd541841daee7e40
parent1b3e89563119f1e0422230915dcaf23a262628b7 (diff)
ufs: Fix queue depth handling for best effort cases
Some UFS devices may expose bLUQueueDepth field as zero indicating that the queue depth depends on the number of resources available for LUN at a particular instant to handle the outstanding transfer requests. Currently, when response for SCSI command is TASK_FULL the LLD decrements the queue depth but fails to increment when the resources are available. The scsi mid-layer handles the change in queue depth heuristically and offers simple interface with ->change_queue_depth. Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org> Signed-off-by: Dolev Raviv <draviv@codeaurora.org> Acked-by: Santosh Y <santoshsy@gmail.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--drivers/scsi/ufs/ufshcd.c97
1 files changed, 42 insertions, 55 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index b301ed82ab0a..b103e950db3c 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1991,27 +1991,55 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev)
1991 1991
1992 /* allow SCSI layer to restart the device in case of errors */ 1992 /* allow SCSI layer to restart the device in case of errors */
1993 sdev->allow_restart = 1; 1993 sdev->allow_restart = 1;
1994
1994 lun_qdepth = ufshcd_read_sdev_qdepth(hba, sdev); 1995 lun_qdepth = ufshcd_read_sdev_qdepth(hba, sdev);
1995 if (lun_qdepth == 0 || lun_qdepth > hba->nutrs) { 1996 if (lun_qdepth <= 0)
1996 dev_info(hba->dev, "%s, lun %d queue depth is %d\n", __func__, 1997 /* eventually, we can figure out the real queue depth */
1997 sdev->lun, lun_qdepth);
1998 lun_qdepth = hba->nutrs; 1998 lun_qdepth = hba->nutrs;
1999 } else if (lun_qdepth < 0) { 1999 else
2000 lun_qdepth = 1; 2000 lun_qdepth = min_t(int, lun_qdepth, hba->nutrs);
2001 }
2002 2001
2003 /* 2002 dev_dbg(hba->dev, "%s: activate tcq with queue depth %d\n",
2004 * Inform SCSI Midlayer that the LUN queue depth is same as the 2003 __func__, lun_qdepth);
2005 * controller queue depth. If a LUN queue depth is less than the
2006 * controller queue depth and if the LUN reports
2007 * SAM_STAT_TASK_SET_FULL, the LUN queue depth will be adjusted
2008 * with scsi_adjust_queue_depth.
2009 */
2010 scsi_activate_tcq(sdev, lun_qdepth); 2004 scsi_activate_tcq(sdev, lun_qdepth);
2005
2011 return 0; 2006 return 0;
2012} 2007}
2013 2008
2014/** 2009/**
2010 * ufshcd_change_queue_depth - change queue depth
2011 * @sdev: pointer to SCSI device
2012 * @depth: required depth to set
2013 * @reason: reason for changing the depth
2014 *
2015 * Change queue depth according to the reason and make sure
2016 * the max. limits are not crossed.
2017 */
2018int ufshcd_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
2019{
2020 struct ufs_hba *hba = shost_priv(sdev->host);
2021
2022 if (depth > hba->nutrs)
2023 depth = hba->nutrs;
2024
2025 switch (reason) {
2026 case SCSI_QDEPTH_DEFAULT:
2027 case SCSI_QDEPTH_RAMP_UP:
2028 if (!sdev->tagged_supported)
2029 depth = 1;
2030 scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
2031 break;
2032 case SCSI_QDEPTH_QFULL:
2033 scsi_track_queue_full(sdev, depth);
2034 break;
2035 default:
2036 return -EOPNOTSUPP;
2037 }
2038
2039 return depth;
2040}
2041
2042/**
2015 * ufshcd_slave_destroy - remove SCSI device configurations 2043 * ufshcd_slave_destroy - remove SCSI device configurations
2016 * @sdev: pointer to SCSI device 2044 * @sdev: pointer to SCSI device
2017 */ 2045 */
@@ -2064,42 +2092,6 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
2064} 2092}
2065 2093
2066/** 2094/**
2067 * ufshcd_adjust_lun_qdepth - Update LUN queue depth if device responds with
2068 * SAM_STAT_TASK_SET_FULL SCSI command status.
2069 * @cmd: pointer to SCSI command
2070 */
2071static void ufshcd_adjust_lun_qdepth(struct scsi_cmnd *cmd)
2072{
2073 struct ufs_hba *hba;
2074 int i;
2075 int lun_qdepth = 0;
2076
2077 hba = shost_priv(cmd->device->host);
2078
2079 /*
2080 * LUN queue depth can be obtained by counting outstanding commands
2081 * on the LUN.
2082 */
2083 for (i = 0; i < hba->nutrs; i++) {
2084 if (test_bit(i, &hba->outstanding_reqs)) {
2085
2086 /*
2087 * Check if the outstanding command belongs
2088 * to the LUN which reported SAM_STAT_TASK_SET_FULL.
2089 */
2090 if (cmd->device->lun == hba->lrb[i].lun)
2091 lun_qdepth++;
2092 }
2093 }
2094
2095 /*
2096 * LUN queue depth will be total outstanding commands, except the
2097 * command for which the LUN reported SAM_STAT_TASK_SET_FULL.
2098 */
2099 scsi_adjust_queue_depth(cmd->device, MSG_SIMPLE_TAG, lun_qdepth - 1);
2100}
2101
2102/**
2103 * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status 2095 * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status
2104 * @lrb: pointer to local reference block of completed command 2096 * @lrb: pointer to local reference block of completed command
2105 * @scsi_status: SCSI command status 2097 * @scsi_status: SCSI command status
@@ -2120,12 +2112,6 @@ ufshcd_scsi_cmd_status(struct ufshcd_lrb *lrbp, int scsi_status)
2120 scsi_status; 2112 scsi_status;
2121 break; 2113 break;
2122 case SAM_STAT_TASK_SET_FULL: 2114 case SAM_STAT_TASK_SET_FULL:
2123 /*
2124 * If a LUN reports SAM_STAT_TASK_SET_FULL, then the LUN queue
2125 * depth needs to be adjusted to the exact number of
2126 * outstanding commands the LUN can handle at any given time.
2127 */
2128 ufshcd_adjust_lun_qdepth(lrbp->cmd);
2129 case SAM_STAT_BUSY: 2115 case SAM_STAT_BUSY:
2130 case SAM_STAT_TASK_ABORTED: 2116 case SAM_STAT_TASK_ABORTED:
2131 ufshcd_copy_sense_data(lrbp); 2117 ufshcd_copy_sense_data(lrbp);
@@ -3156,6 +3142,7 @@ static struct scsi_host_template ufshcd_driver_template = {
3156 .queuecommand = ufshcd_queuecommand, 3142 .queuecommand = ufshcd_queuecommand,
3157 .slave_alloc = ufshcd_slave_alloc, 3143 .slave_alloc = ufshcd_slave_alloc,
3158 .slave_destroy = ufshcd_slave_destroy, 3144 .slave_destroy = ufshcd_slave_destroy,
3145 .change_queue_depth = ufshcd_change_queue_depth,
3159 .eh_abort_handler = ufshcd_abort, 3146 .eh_abort_handler = ufshcd_abort,
3160 .eh_device_reset_handler = ufshcd_eh_device_reset_handler, 3147 .eh_device_reset_handler = ufshcd_eh_device_reset_handler,
3161 .eh_host_reset_handler = ufshcd_eh_host_reset_handler, 3148 .eh_host_reset_handler = ufshcd_eh_host_reset_handler,