summaryrefslogtreecommitdiff
path: root/drivers/scsi/ufs/ufshcd.c
diff options
context:
space:
mode:
authorJoao Pinto <Joao.Pinto@synopsys.com>2016-05-11 12:21:27 +0100
committerMartin K. Petersen <martin.petersen@oracle.com>2016-07-12 23:16:31 -0400
commit300bb13f5c7b1d6b970d32232d0462ae36d50b9d (patch)
tree279c91f9afa836fe8576781ffb56dd507963b5f5 /drivers/scsi/ufs/ufshcd.c
parentb1d78f27255203f74fcfa0a8329c1b73015de132 (diff)
ufs: add UFS 2.0 capabilities
Add UFS 2.0 support to the UFS core driver. Signed-off-by: Joao Pinto <jpinto@synopsys.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Tomas Winkler <tomas.winkler@intel.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/ufs/ufshcd.c')
-rw-r--r--drivers/scsi/ufs/ufshcd.c89
1 files changed, 48 insertions, 41 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f8fa72c31a9d..8e8989a1859b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1173,7 +1173,7 @@ static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
* @cmd_dir: requests data direction
*/
static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp,
- u32 *upiu_flags, enum dma_data_direction cmd_dir)
+ u32 *upiu_flags, enum dma_data_direction cmd_dir)
{
struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr;
u32 data_direction;
@@ -1299,47 +1299,55 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
}
/**
- * ufshcd_compose_upiu - form UFS Protocol Information Unit(UPIU)
+ * ufshcd_comp_devman_upiu - UFS Protocol Information Unit(UPIU)
+ * for Device Management Purposes
* @hba - per adapter instance
* @lrb - pointer to local reference block
*/
-static int ufshcd_compose_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+static int ufshcd_comp_devman_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
{
u32 upiu_flags;
int ret = 0;
- switch (lrbp->command_type) {
- case UTP_CMD_TYPE_SCSI:
- if (likely(lrbp->cmd)) {
- ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags,
- lrbp->cmd->sc_data_direction);
- ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags);
- } else {
- ret = -EINVAL;
- }
- break;
- case UTP_CMD_TYPE_DEV_MANAGE:
- ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE);
- if (hba->dev_cmd.type == DEV_CMD_TYPE_QUERY)
- ufshcd_prepare_utp_query_req_upiu(
- hba, lrbp, upiu_flags);
- else if (hba->dev_cmd.type == DEV_CMD_TYPE_NOP)
- ufshcd_prepare_utp_nop_upiu(lrbp);
- else
- ret = -EINVAL;
- break;
- case UTP_CMD_TYPE_UFS:
- /* For UFS native command implementation */
- ret = -ENOTSUPP;
- dev_err(hba->dev, "%s: UFS native command are not supported\n",
- __func__);
- break;
- default:
- ret = -ENOTSUPP;
- dev_err(hba->dev, "%s: unknown command type: 0x%x\n",
- __func__, lrbp->command_type);
- break;
- } /* end of switch */
+ if (hba->ufs_version == UFSHCI_VERSION_20)
+ lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE;
+ else
+ lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
+
+ ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE);
+ if (hba->dev_cmd.type == DEV_CMD_TYPE_QUERY)
+ ufshcd_prepare_utp_query_req_upiu(hba, lrbp, upiu_flags);
+ else if (hba->dev_cmd.type == DEV_CMD_TYPE_NOP)
+ ufshcd_prepare_utp_nop_upiu(lrbp);
+ else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+/**
+ * ufshcd_comp_scsi_upiu - UFS Protocol Information Unit(UPIU)
+ * for SCSI Purposes
+ * @hba - per adapter instance
+ * @lrb - pointer to local reference block
+ */
+static int ufshcd_comp_scsi_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+{
+ u32 upiu_flags;
+ int ret = 0;
+
+ if (hba->ufs_version == UFSHCI_VERSION_20)
+ lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE;
+ else
+ lrbp->command_type = UTP_CMD_TYPE_SCSI;
+
+ if (likely(lrbp->cmd)) {
+ ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags,
+ lrbp->cmd->sc_data_direction);
+ ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags);
+ } else {
+ ret = -EINVAL;
+ }
return ret;
}
@@ -1451,10 +1459,9 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
lrbp->task_tag = tag;
lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
lrbp->intr_cmd = !ufshcd_is_intr_aggr_allowed(hba) ? true : false;
- lrbp->command_type = UTP_CMD_TYPE_SCSI;
- /* form UPIU before issuing the command */
- ufshcd_compose_upiu(hba, lrbp);
+ ufshcd_comp_scsi_upiu(hba, lrbp);
+
err = ufshcd_map_sg(lrbp);
if (err) {
lrbp->cmd = NULL;
@@ -1479,11 +1486,10 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba,
lrbp->sense_buffer = NULL;
lrbp->task_tag = tag;
lrbp->lun = 0; /* device management cmd is not specific to any LUN */
- lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
lrbp->intr_cmd = true; /* No interrupt aggregation */
hba->dev_cmd.type = cmd_type;
- return ufshcd_compose_upiu(hba, lrbp);
+ return ufshcd_comp_devman_upiu(hba, lrbp);
}
static int
@@ -3539,7 +3545,8 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
/* Do not touch lrbp after scsi done */
cmd->scsi_done(cmd);
__ufshcd_release(hba);
- } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) {
+ } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE ||
+ lrbp->command_type == UTP_CMD_TYPE_UFS_STORAGE) {
if (hba->dev_cmd.complete)
complete(hba->dev_cmd.complete);
}