scsi: ufs: dump debug info during failures

Inserts driver dumps for UFS Host Controller registers, Transfer Requests
and Task Management Requests.
The dumps will occur on driver initialization failure, ufshcd_abort() and
on error handling path.

Change-Id: Ie8683e22a619cdae20680b15930e546e84f8aa73
Signed-off-by: Dolev Raviv <draviv@codeaurora.org>
[subhashj@codeaurora.org: resolved trivial merge conflicts]
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
Dolev Raviv 2013-10-03 09:39:30 +03:00 committed by David Keitel
parent f5e347b925
commit 24a05915b2
2 changed files with 95 additions and 0 deletions

View file

@ -106,6 +106,9 @@
_ret; \
})
#define ufshcd_hex_dump(prefix_str, buf, len) \
print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, false)
static u32 ufs_query_desc_max_size[] = {
QUERY_DESC_DEVICE_MAX_SIZE,
QUERY_DESC_CONFIGURAION_MAX_SIZE,
@ -237,6 +240,77 @@ static inline void ufshcd_disable_irq(struct ufs_hba *hba)
}
}
static void ufshcd_print_host_regs(struct ufs_hba *hba)
{
/*
* hex_dump reads its data without the readl macro. This might
* cause inconsistency issues on some platform, as the printed
* values may be from cache and not the most recent value.
* To know whether you are looking at an un-cached version verify
* that IORESOURCE_MEM flag is on when xxx_get_resource() is invoked
* during platform/pci probe function.
*/
ufshcd_hex_dump("host regs: ", hba->mmio_base, UFSHCI_REG_SPACE_SIZE);
dev_err(hba->dev, "hba->ufs_version = 0x%x, hba->capabilities = 0x%x",
hba->ufs_version, hba->capabilities);
dev_err(hba->dev,
"hba->outstanding_reqs = 0x%x, hba->outstanding_tasks = 0x%x",
(u32)hba->outstanding_reqs, (u32)hba->outstanding_tasks);
}
static
void ufshcd_print_trs(struct ufs_hba *hba, unsigned long bitmap, bool pr_prdt)
{
struct ufshcd_lrb *lrbp;
int tag;
for_each_set_bit(tag, &bitmap, hba->nutrs) {
lrbp = &hba->lrb[tag];
dev_err(hba->dev, "UPIU[%d] - Transfer Request Descriptor",
tag);
ufshcd_hex_dump("UPIU TRD: ", &lrbp->utr_descriptor_ptr,
sizeof(struct utp_transfer_req_desc));
dev_err(hba->dev, "UPIU[%d] - Request UPIU", tag);
ufshcd_hex_dump("UPIU REQ: ", lrbp->ucd_req_ptr,
sizeof(struct utp_upiu_req));
dev_err(hba->dev, "UPIU[%d] - Response UPIU", tag);
ufshcd_hex_dump("UPIU RSP: ", lrbp->ucd_rsp_ptr,
sizeof(struct utp_upiu_rsp));
if (pr_prdt) {
int prdt_length = le16_to_cpu(
lrbp->utr_descriptor_ptr->prd_table_length);
dev_err(hba->dev, "UPIU[%d] - PRDT - %d entries", tag,
prdt_length);
ufshcd_hex_dump("UPIU PRDT: ", lrbp->ucd_prdt_ptr,
sizeof(struct ufshcd_sg_entry) *
prdt_length);
}
}
}
static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap)
{
struct utp_task_req_desc *tmrdp;
int tag;
for_each_set_bit(tag, &bitmap, hba->nutmrs) {
tmrdp = &hba->utmrdl_base_addr[tag];
dev_err(hba->dev, "TM[%d] - Task Management Header", tag);
ufshcd_hex_dump("TM TRD: ", &tmrdp->header,
sizeof(struct request_desc_header));
dev_err(hba->dev, "TM[%d] - Task Management Request UPIU",
tag);
ufshcd_hex_dump("TM REQ: ", tmrdp->task_req_upiu,
sizeof(struct utp_upiu_req));
dev_err(hba->dev, "TM[%d] - Task Management Response UPIU",
tag);
ufshcd_hex_dump("TM RSP: ", tmrdp->task_rsp_upiu,
sizeof(struct utp_task_req_desc));
}
}
/*
* ufshcd_wait_for_register - wait for register value to change
* @hba - per-adapter interface
@ -3167,6 +3241,8 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
break;
} /* end of switch */
if (host_byte(result) != DID_OK)
ufshcd_print_trs(hba, 1 << lrbp->task_tag, true);
return result;
}
@ -3631,6 +3707,17 @@ static void ufshcd_check_errors(struct ufs_hba *hba)
hba->saved_uic_err |= hba->uic_error;
hba->ufshcd_state = UFSHCD_STATE_ERROR;
/* dump controller state before resetting */
if (hba->saved_err & (INT_FATAL_ERRORS | UIC_ERROR)) {
bool pr_prdt = !!(hba->saved_err &
SYSTEM_BUS_FATAL_ERROR);
ufshcd_print_host_regs(hba);
ufshcd_print_tmrs(hba, hba->outstanding_tasks);
ufshcd_print_trs(hba, hba->outstanding_reqs,
pr_prdt);
}
schedule_work(&hba->eh_work);
}
}
@ -3899,6 +3986,11 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
__func__, tag);
}
/* Print Transfer Request of aborted task */
dev_err(hba->dev, "%s: Device abort task at tag %d", __func__, tag);
ufshcd_print_host_regs(hba);
ufshcd_print_trs(hba, 1 << tag, true);
lrbp = &hba->lrb[tag];
for (poll_cnt = 100; poll_cnt; poll_cnt--) {
err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
@ -5664,6 +5756,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
err = ufshcd_hba_enable(hba);
if (err) {
dev_err(hba->dev, "Host controller enable failed\n");
ufshcd_print_host_regs(hba);
goto out_remove_scsi_host;
}

View file

@ -72,6 +72,8 @@ enum {
REG_UIC_COMMAND_ARG_1 = 0x94,
REG_UIC_COMMAND_ARG_2 = 0x98,
REG_UIC_COMMAND_ARG_3 = 0x9C,
UFSHCI_REG_SPACE_SIZE = 0xA0,
};
/* Controller capability masks */