hw/ufs: fix CQE endianness and UPIU length
Round-trip UTRD fields through cpu_to_le/ le_to_cpu when building MCQ CQEs to keep BE hosts correct. Also avoid double BE conversion of response data_segment_length and document the LE round-trip. Signed-off-by: Jeuk Kim <jeuk20.kim@samsung.com> (cherry picked from commit ed621cc8e2a6dab2663ffb02e875f896f521bee2) Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
This commit is contained in:
parent
cce96e6052
commit
88ef8726ff
3 changed files with 20 additions and 12 deletions
|
|
@ -53,8 +53,7 @@ static void ufs_build_scsi_response_upiu(UfsRequest *req, uint8_t *sense,
|
|||
response = UFS_COMMAND_RESULT_FAIL;
|
||||
}
|
||||
|
||||
data_segment_length =
|
||||
cpu_to_be16(sense_len + sizeof(req->rsp_upiu.sr.sense_data_len));
|
||||
data_segment_length = sense_len + sizeof(req->rsp_upiu.sr.sense_data_len);
|
||||
ufs_build_upiu_header(req, UFS_UPIU_TRANSACTION_RESPONSE, flags, response,
|
||||
status, data_segment_length);
|
||||
}
|
||||
|
|
|
|||
27
hw/ufs/ufs.c
27
hw/ufs/ufs.c
|
|
@ -449,15 +449,24 @@ static void ufs_mcq_process_cq(void *opaque)
|
|||
{
|
||||
ufs_dma_write_rsp_upiu(req);
|
||||
|
||||
req->cqe.utp_addr =
|
||||
((uint64_t)req->utrd.command_desc_base_addr_hi << 32ULL) |
|
||||
req->utrd.command_desc_base_addr_lo;
|
||||
req->cqe.utp_addr |= req->sq->sqid;
|
||||
req->cqe.resp_len = req->utrd.response_upiu_length;
|
||||
req->cqe.resp_off = req->utrd.response_upiu_offset;
|
||||
req->cqe.prdt_len = req->utrd.prd_table_length;
|
||||
req->cqe.prdt_off = req->utrd.prd_table_offset;
|
||||
req->cqe.status = req->utrd.header.dword_2 & 0xf;
|
||||
/* UTRD/CQE are LE; round-trip through host to keep BE correct. */
|
||||
uint64_t ucdba =
|
||||
((uint64_t)le32_to_cpu(req->utrd.command_desc_base_addr_hi)
|
||||
<< 32ULL) |
|
||||
le32_to_cpu(req->utrd.command_desc_base_addr_lo);
|
||||
uint16_t resp_len = le16_to_cpu(req->utrd.response_upiu_length);
|
||||
uint16_t resp_off = le16_to_cpu(req->utrd.response_upiu_offset);
|
||||
uint16_t prdt_len = le16_to_cpu(req->utrd.prd_table_length);
|
||||
uint16_t prdt_off = le16_to_cpu(req->utrd.prd_table_offset);
|
||||
uint8_t status = le32_to_cpu(req->utrd.header.dword_2) & UFS_MASK_OCS;
|
||||
|
||||
ucdba |= req->sq->sqid;
|
||||
req->cqe.utp_addr = cpu_to_le64(ucdba);
|
||||
req->cqe.resp_len = cpu_to_le16(resp_len);
|
||||
req->cqe.resp_off = cpu_to_le16(resp_off);
|
||||
req->cqe.prdt_len = cpu_to_le16(prdt_len);
|
||||
req->cqe.prdt_off = cpu_to_le16(prdt_off);
|
||||
req->cqe.status = status;
|
||||
req->cqe.error = 0;
|
||||
|
||||
ret = ufs_addr_write(u, cq->addr + tail, &req->cqe, sizeof(req->cqe));
|
||||
|
|
|
|||
|
|
@ -645,7 +645,7 @@ enum UtpOcsCodes {
|
|||
};
|
||||
|
||||
enum {
|
||||
UFS_MASK_OCS = 0x0F,
|
||||
UFS_MASK_OCS = 0xFF,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue