aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ufs/ufshcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ufs/ufshcd.c')
-rw-r--r--drivers/scsi/ufs/ufshcd.c67
1 files changed, 34 insertions, 33 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index b103e950db3c..b533ff8afe24 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2231,47 +2231,42 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
2231 u32 tr_doorbell; 2231 u32 tr_doorbell;
2232 int result; 2232 int result;
2233 int index; 2233 int index;
2234 bool int_aggr_reset = false; 2234
2235 /* Resetting interrupt aggregation counters first and reading the
2236 * DOOR_BELL afterward allows us to handle all the completed requests.
2237 * In order to prevent other interrupts starvation the DB is read once
2238 * after reset. The down side of this solution is the possibility of
2239 * false interrupt if device completes another request after resetting
2240 * aggregation and before reading the DB.
2241 */
2242 ufshcd_reset_intr_aggr(hba);
2235 2243
2236 tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); 2244 tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
2237 completed_reqs = tr_doorbell ^ hba->outstanding_reqs; 2245 completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
2238 2246
2239 for (index = 0; index < hba->nutrs; index++) { 2247 for_each_set_bit(index, &completed_reqs, hba->nutrs) {
2240 if (test_bit(index, &completed_reqs)) { 2248 lrbp = &hba->lrb[index];
2241 lrbp = &hba->lrb[index]; 2249 cmd = lrbp->cmd;
2242 cmd = lrbp->cmd; 2250 if (cmd) {
2243 /* 2251 result = ufshcd_transfer_rsp_status(hba, lrbp);
2244 * Don't skip resetting interrupt aggregation counters 2252 scsi_dma_unmap(cmd);
2245 * if a regular command is present. 2253 cmd->result = result;
2246 */ 2254 /* Mark completed command as NULL in LRB */
2247 int_aggr_reset |= !lrbp->intr_cmd; 2255 lrbp->cmd = NULL;
2248 2256 clear_bit_unlock(index, &hba->lrb_in_use);
2249 if (cmd) { 2257 /* Do not touch lrbp after scsi done */
2250 result = ufshcd_transfer_rsp_status(hba, lrbp); 2258 cmd->scsi_done(cmd);
2251 scsi_dma_unmap(cmd); 2259 } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) {
2252 cmd->result = result; 2260 if (hba->dev_cmd.complete)
2253 /* Mark completed command as NULL in LRB */ 2261 complete(hba->dev_cmd.complete);
2254 lrbp->cmd = NULL; 2262 }
2255 clear_bit_unlock(index, &hba->lrb_in_use); 2263 }
2256 /* Do not touch lrbp after scsi done */
2257 cmd->scsi_done(cmd);
2258 } else if (lrbp->command_type ==
2259 UTP_CMD_TYPE_DEV_MANAGE) {
2260 if (hba->dev_cmd.complete)
2261 complete(hba->dev_cmd.complete);
2262 }
2263 } /* end of if */
2264 } /* end of for */
2265 2264
2266 /* clear corresponding bits of completed commands */ 2265 /* clear corresponding bits of completed commands */
2267 hba->outstanding_reqs ^= completed_reqs; 2266 hba->outstanding_reqs ^= completed_reqs;
2268 2267
2269 /* we might have free'd some tags above */ 2268 /* we might have free'd some tags above */
2270 wake_up(&hba->dev_cmd.tag_wq); 2269 wake_up(&hba->dev_cmd.tag_wq);
2271
2272 /* Reset interrupt aggregation counters */
2273 if (int_aggr_reset)
2274 ufshcd_reset_intr_aggr(hba);
2275} 2270}
2276 2271
2277/** 2272/**
@@ -2876,6 +2871,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
2876 int poll_cnt; 2871 int poll_cnt;
2877 u8 resp = 0xF; 2872 u8 resp = 0xF;
2878 struct ufshcd_lrb *lrbp; 2873 struct ufshcd_lrb *lrbp;
2874 u32 reg;
2879 2875
2880 host = cmd->device->host; 2876 host = cmd->device->host;
2881 hba = shost_priv(host); 2877 hba = shost_priv(host);
@@ -2885,6 +2881,13 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
2885 if (!(test_bit(tag, &hba->outstanding_reqs))) 2881 if (!(test_bit(tag, &hba->outstanding_reqs)))
2886 goto out; 2882 goto out;
2887 2883
2884 reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
2885 if (!(reg & (1 << tag))) {
2886 dev_err(hba->dev,
2887 "%s: cmd was completed, but without a notifying intr, tag = %d",
2888 __func__, tag);
2889 }
2890
2888 lrbp = &hba->lrb[tag]; 2891 lrbp = &hba->lrb[tag];
2889 for (poll_cnt = 100; poll_cnt; poll_cnt--) { 2892 for (poll_cnt = 100; poll_cnt; poll_cnt--) {
2890 err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag, 2893 err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
@@ -2893,8 +2896,6 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
2893 /* cmd pending in the device */ 2896 /* cmd pending in the device */
2894 break; 2897 break;
2895 } else if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_COMPL) { 2898 } else if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
2896 u32 reg;
2897
2898 /* 2899 /*
2899 * cmd not pending in the device, check if it is 2900 * cmd not pending in the device, check if it is
2900 * in transition. 2901 * in transition.