ufs: add UFS 2.0 capabilities
authorJoao Pinto <Joao.Pinto@synopsys.com>
Wed, 11 May 2016 11:21:27 +0000 (12:21 +0100)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 13 Jul 2016 03:16:31 +0000 (23:16 -0400)
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>
drivers/scsi/ufs/ufshcd.c
drivers/scsi/ufs/ufshci.h

index f8fa72c31a9dd3fad5eda09c4381ee88c17a1381..8e8989a1859bb4f9c0fc69a1874f735c0e767d5e 100644 (file)
@@ -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);
                }
index 4cb1cc63f1a1bd834fb22a972de9803c47891f24..36f58795c601ead2e07f4b59968ecbc256213ced 100644 (file)
@@ -279,6 +279,11 @@ enum {
        UTP_CMD_TYPE_DEV_MANAGE         = 0x2,
 };
 
+/* To accommodate UFS2.0 required Command type */
+enum {
+       UTP_CMD_TYPE_UFS_STORAGE        = 0x1,
+};
+
 enum {
        UTP_SCSI_COMMAND                = 0x00000000,
        UTP_NATIVE_UFS_COMMAND          = 0x10000000,