forked from Minki/linux
scsi: ufs: add a low-level __ufshcd_issue_tm_cmd helper
Add a helper that takes a utp_task_req_desc and issues it, which will be useful for UFS bsg support. Rewrite ufshcd_issue_tm_cmd0x to use this new helper. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Avri Altman <avri.altman@wdc.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
391e388f85
commit
c6049cd982
@ -633,19 +633,6 @@ static inline int ufshcd_get_tr_ocs(struct ufshcd_lrb *lrbp)
|
||||
return le32_to_cpu(lrbp->utr_descriptor_ptr->header.dword_2) & MASK_OCS;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_get_tmr_ocs - Get the UTMRD Overall Command Status
|
||||
* @task_req_descp: pointer to utp_task_req_desc structure
|
||||
*
|
||||
* This function is used to get the OCS field from UTMRD
|
||||
* Returns the OCS field in the UTMRD
|
||||
*/
|
||||
static inline int
|
||||
ufshcd_get_tmr_ocs(struct utp_task_req_desc *task_req_descp)
|
||||
{
|
||||
return le32_to_cpu(task_req_descp->header.dword_2) & MASK_OCS;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_get_tm_free_slot - get a free slot for task management request
|
||||
* @hba: per adapter instance
|
||||
@ -4616,37 +4603,6 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_task_req_compl - handle task management request completion
|
||||
* @hba: per adapter instance
|
||||
* @index: index of the completed request
|
||||
* @resp: task management service response
|
||||
*
|
||||
* Returns non-zero value on error, zero on success
|
||||
*/
|
||||
static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
|
||||
{
|
||||
struct utp_task_req_desc *treq = hba->utmrdl_base_addr + index;
|
||||
unsigned long flags;
|
||||
int ocs_value;
|
||||
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
|
||||
/* Clear completed tasks from outstanding_tasks */
|
||||
__clear_bit(index, &hba->outstanding_tasks);
|
||||
|
||||
ocs_value = ufshcd_get_tmr_ocs(treq);
|
||||
|
||||
if (ocs_value != OCS_SUCCESS)
|
||||
dev_err(hba->dev, "%s: failed, ocs = 0x%x\n",
|
||||
__func__, ocs_value);
|
||||
else if (resp)
|
||||
*resp = be32_to_cpu(treq->output_param1) & MASK_TM_SERVICE_RESP;
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
|
||||
return ocs_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status
|
||||
* @lrbp: pointer to local reference block of completed command
|
||||
@ -5604,27 +5560,12 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_issue_tm_cmd - issues task management commands to controller
|
||||
* @hba: per adapter instance
|
||||
* @lun_id: LUN ID to which TM command is sent
|
||||
* @task_id: task ID to which the TM command is applicable
|
||||
* @tm_function: task management function opcode
|
||||
* @tm_response: task management service response return value
|
||||
*
|
||||
* Returns non-zero value on error, zero on success.
|
||||
*/
|
||||
static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
|
||||
u8 tm_function, u8 *tm_response)
|
||||
static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
|
||||
struct utp_task_req_desc *treq, u8 tm_function)
|
||||
{
|
||||
struct utp_task_req_desc *treq;
|
||||
struct Scsi_Host *host;
|
||||
struct Scsi_Host *host = hba->host;
|
||||
unsigned long flags;
|
||||
int free_slot;
|
||||
int err;
|
||||
int task_tag;
|
||||
|
||||
host = hba->host;
|
||||
int free_slot, task_tag, err;
|
||||
|
||||
/*
|
||||
* Get free slot, sleep if slots are unavailable.
|
||||
@ -5635,24 +5576,11 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
|
||||
ufshcd_hold(hba, false);
|
||||
|
||||
spin_lock_irqsave(host->host_lock, flags);
|
||||
treq = hba->utmrdl_base_addr + free_slot;
|
||||
|
||||
/* Configure task request descriptor */
|
||||
treq->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
|
||||
treq->header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
|
||||
|
||||
/* Configure task request UPIU */
|
||||
task_tag = hba->nutrs + free_slot;
|
||||
treq->req_header.dword_0 = UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ,
|
||||
0, lun_id, task_tag);
|
||||
treq->req_header.dword_1 = UPIU_HEADER_DWORD(0, tm_function, 0, 0);
|
||||
/*
|
||||
* The host shall provide the same value for LUN field in the basic
|
||||
* header and for Input Parameter.
|
||||
*/
|
||||
treq->input_param1 = cpu_to_be32(lun_id);
|
||||
treq->input_param2 = cpu_to_be32(task_id);
|
||||
|
||||
treq->req_header.dword_0 |= cpu_to_be32(task_tag);
|
||||
|
||||
memcpy(hba->utmrdl_base_addr + free_slot, treq, sizeof(*treq));
|
||||
ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function);
|
||||
|
||||
/* send command to the controller */
|
||||
@ -5682,8 +5610,15 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
|
||||
__func__, free_slot);
|
||||
err = -ETIMEDOUT;
|
||||
} else {
|
||||
err = ufshcd_task_req_compl(hba, free_slot, tm_response);
|
||||
err = 0;
|
||||
memcpy(treq, hba->utmrdl_base_addr + free_slot, sizeof(*treq));
|
||||
|
||||
ufshcd_add_tm_upiu_trace(hba, task_tag, "tm_complete");
|
||||
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
__clear_bit(free_slot, &hba->outstanding_tasks);
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
|
||||
}
|
||||
|
||||
clear_bit(free_slot, &hba->tm_condition);
|
||||
@ -5694,6 +5629,52 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_issue_tm_cmd - issues task management commands to controller
|
||||
* @hba: per adapter instance
|
||||
* @lun_id: LUN ID to which TM command is sent
|
||||
* @task_id: task ID to which the TM command is applicable
|
||||
* @tm_function: task management function opcode
|
||||
* @tm_response: task management service response return value
|
||||
*
|
||||
* Returns non-zero value on error, zero on success.
|
||||
*/
|
||||
static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
|
||||
u8 tm_function, u8 *tm_response)
|
||||
{
|
||||
struct utp_task_req_desc treq = { { 0 }, };
|
||||
int ocs_value, err;
|
||||
|
||||
/* Configure task request descriptor */
|
||||
treq.header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
|
||||
treq.header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
|
||||
|
||||
/* Configure task request UPIU */
|
||||
treq.req_header.dword_0 = cpu_to_be32(lun_id << 8) |
|
||||
cpu_to_be32(UPIU_TRANSACTION_TASK_REQ << 24);
|
||||
treq.req_header.dword_1 = cpu_to_be32(tm_function << 16);
|
||||
|
||||
/*
|
||||
* The host shall provide the same value for LUN field in the basic
|
||||
* header and for Input Parameter.
|
||||
*/
|
||||
treq.input_param1 = cpu_to_be32(lun_id);
|
||||
treq.input_param2 = cpu_to_be32(task_id);
|
||||
|
||||
err = __ufshcd_issue_tm_cmd(hba, &treq, tm_function);
|
||||
if (err == -ETIMEDOUT)
|
||||
return err;
|
||||
|
||||
ocs_value = le32_to_cpu(treq.header.dword_2) & MASK_OCS;
|
||||
if (ocs_value != OCS_SUCCESS)
|
||||
dev_err(hba->dev, "%s: failed, ocs = 0x%x\n",
|
||||
__func__, ocs_value);
|
||||
else if (tm_response)
|
||||
*tm_response = be32_to_cpu(treq.output_param1) &
|
||||
MASK_TM_SERVICE_RESP;
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_eh_device_reset_handler - device reset handler registered to
|
||||
* scsi layer.
|
||||
|
Loading…
Reference in New Issue
Block a user