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>
This commit is contained in:
parent
b1d78f2725
commit
300bb13f5c
|
@ -1173,7 +1173,7 @@ static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
|
||||||
* @cmd_dir: requests data direction
|
* @cmd_dir: requests data direction
|
||||||
*/
|
*/
|
||||||
static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp,
|
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;
|
struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr;
|
||||||
u32 data_direction;
|
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
|
* @hba - per adapter instance
|
||||||
* @lrb - pointer to local reference block
|
* @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;
|
u32 upiu_flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
switch (lrbp->command_type) {
|
if (hba->ufs_version == UFSHCI_VERSION_20)
|
||||||
case UTP_CMD_TYPE_SCSI:
|
lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE;
|
||||||
if (likely(lrbp->cmd)) {
|
else
|
||||||
ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags,
|
lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
|
||||||
lrbp->cmd->sc_data_direction);
|
|
||||||
ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags);
|
ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE);
|
||||||
} else {
|
if (hba->dev_cmd.type == DEV_CMD_TYPE_QUERY)
|
||||||
ret = -EINVAL;
|
ufshcd_prepare_utp_query_req_upiu(hba, lrbp, upiu_flags);
|
||||||
}
|
else if (hba->dev_cmd.type == DEV_CMD_TYPE_NOP)
|
||||||
break;
|
ufshcd_prepare_utp_nop_upiu(lrbp);
|
||||||
case UTP_CMD_TYPE_DEV_MANAGE:
|
else
|
||||||
ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE);
|
ret = -EINVAL;
|
||||||
if (hba->dev_cmd.type == DEV_CMD_TYPE_QUERY)
|
|
||||||
ufshcd_prepare_utp_query_req_upiu(
|
return ret;
|
||||||
hba, lrbp, upiu_flags);
|
}
|
||||||
else if (hba->dev_cmd.type == DEV_CMD_TYPE_NOP)
|
|
||||||
ufshcd_prepare_utp_nop_upiu(lrbp);
|
/**
|
||||||
else
|
* ufshcd_comp_scsi_upiu - UFS Protocol Information Unit(UPIU)
|
||||||
ret = -EINVAL;
|
* for SCSI Purposes
|
||||||
break;
|
* @hba - per adapter instance
|
||||||
case UTP_CMD_TYPE_UFS:
|
* @lrb - pointer to local reference block
|
||||||
/* For UFS native command implementation */
|
*/
|
||||||
ret = -ENOTSUPP;
|
static int ufshcd_comp_scsi_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
|
||||||
dev_err(hba->dev, "%s: UFS native command are not supported\n",
|
{
|
||||||
__func__);
|
u32 upiu_flags;
|
||||||
break;
|
int ret = 0;
|
||||||
default:
|
|
||||||
ret = -ENOTSUPP;
|
if (hba->ufs_version == UFSHCI_VERSION_20)
|
||||||
dev_err(hba->dev, "%s: unknown command type: 0x%x\n",
|
lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE;
|
||||||
__func__, lrbp->command_type);
|
else
|
||||||
break;
|
lrbp->command_type = UTP_CMD_TYPE_SCSI;
|
||||||
} /* end of switch */
|
|
||||||
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1451,10 +1459,9 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
||||||
lrbp->task_tag = tag;
|
lrbp->task_tag = tag;
|
||||||
lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
|
lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
|
||||||
lrbp->intr_cmd = !ufshcd_is_intr_aggr_allowed(hba) ? true : false;
|
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_comp_scsi_upiu(hba, lrbp);
|
||||||
ufshcd_compose_upiu(hba, lrbp);
|
|
||||||
err = ufshcd_map_sg(lrbp);
|
err = ufshcd_map_sg(lrbp);
|
||||||
if (err) {
|
if (err) {
|
||||||
lrbp->cmd = NULL;
|
lrbp->cmd = NULL;
|
||||||
|
@ -1479,11 +1486,10 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba,
|
||||||
lrbp->sense_buffer = NULL;
|
lrbp->sense_buffer = NULL;
|
||||||
lrbp->task_tag = tag;
|
lrbp->task_tag = tag;
|
||||||
lrbp->lun = 0; /* device management cmd is not specific to any LUN */
|
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 */
|
lrbp->intr_cmd = true; /* No interrupt aggregation */
|
||||||
hba->dev_cmd.type = cmd_type;
|
hba->dev_cmd.type = cmd_type;
|
||||||
|
|
||||||
return ufshcd_compose_upiu(hba, lrbp);
|
return ufshcd_comp_devman_upiu(hba, lrbp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -3539,7 +3545,8 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
|
||||||
/* Do not touch lrbp after scsi done */
|
/* Do not touch lrbp after scsi done */
|
||||||
cmd->scsi_done(cmd);
|
cmd->scsi_done(cmd);
|
||||||
__ufshcd_release(hba);
|
__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)
|
if (hba->dev_cmd.complete)
|
||||||
complete(hba->dev_cmd.complete);
|
complete(hba->dev_cmd.complete);
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,6 +279,11 @@ enum {
|
||||||
UTP_CMD_TYPE_DEV_MANAGE = 0x2,
|
UTP_CMD_TYPE_DEV_MANAGE = 0x2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* To accommodate UFS2.0 required Command type */
|
||||||
|
enum {
|
||||||
|
UTP_CMD_TYPE_UFS_STORAGE = 0x1,
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
UTP_SCSI_COMMAND = 0x00000000,
|
UTP_SCSI_COMMAND = 0x00000000,
|
||||||
UTP_NATIVE_UFS_COMMAND = 0x10000000,
|
UTP_NATIVE_UFS_COMMAND = 0x10000000,
|
||||||
|
|
Loading…
Reference in New Issue