diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c3c933f1f14d..bd6a49910172 100755 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3503,7 +3503,19 @@ static void ufshcd_clk_scaling_update_busy(struct ufs_hba *hba) static inline int ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag) { - int ret = 0; + if (hba->lrb[task_tag].cmd) { + u8 opcode = (u8)(*hba->lrb[task_tag].cmd->cmnd); + + if (opcode == SECURITY_PROTOCOL_OUT && hba->security_in) { + hba->security_in--; + } else if (opcode == SECURITY_PROTOCOL_IN) { + if (hba->security_in) { + WARN_ON(1); + return -EINVAL; + } + hba->security_in++; + } + } hba->lrb[task_tag].issue_time_stamp = ktime_get(); hba->lrb[task_tag].complete_time_stamp = ktime_set(0, 0); @@ -3515,7 +3527,7 @@ int ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag) ufshcd_cond_add_cmd_trace(hba, task_tag, hba->lrb[task_tag].cmd ? "scsi_send" : "dev_cmd_send"); ufshcd_update_tag_stats(hba, task_tag); - return ret; + return 0; } /** @@ -4407,7 +4419,13 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) ufshcd_vops_pm_qos_req_end(hba, cmd->request, true); dev_err(hba->dev, "%s: failed sending command, %d\n", __func__, err); - err = DID_ERROR; + if (err == -EINVAL) { + set_host_byte(cmd, DID_ERROR); + if (has_read_lock) + ufshcd_put_read_lock(hba); + cmd->scsi_done(cmd); + return 0; + } goto out; } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index a7f722210694..88f841c6c99e 100755 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -1112,6 +1112,8 @@ struct ufs_hba { /* Number of requests aborts */ int req_abort_count; + u32 security_in; + /* Number of lanes available (1 or 2) for Rx/Tx */ u32 lanes_per_direction;