Merge "fix(ufs): retry commands on unit attention" into integration
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 754d173..d8c0a14 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -477,6 +477,7 @@
{
utrd_header_t *hd;
resp_upiu_t *resp;
+ sense_data_t *sense;
unsigned int data;
int slot;
@@ -499,6 +500,15 @@
inv_dcache_range((uintptr_t)hd, UFS_DESC_SIZE);
assert(hd->ocs == OCS_SUCCESS);
assert((resp->trans_type & TRANS_TYPE_CODE_MASK) == trans_type);
+
+ sense = &resp->sd.sense;
+ if (sense->resp_code == SENSE_DATA_VALID &&
+ sense->sense_key == SENSE_KEY_UNIT_ATTENTION && sense->asc == 0x29 &&
+ sense->ascq == 0) {
+ WARN("Unit Attention Condition\n");
+ return -EAGAIN;
+ }
+
(void)resp;
(void)slot;
return 0;
@@ -507,14 +517,18 @@
static void ufs_send_cmd(utp_utrd_t *utrd, uint8_t cmd_op, uint8_t lun, int lba, uintptr_t buf,
size_t length)
{
- int result;
-
- get_utrd(utrd);
+ int result, i;
- result = ufs_prepare_cmd(utrd, cmd_op, lun, lba, buf, length);
- assert(result == 0);
- ufs_send_request(utrd->task_tag);
- result = ufs_check_resp(utrd, RESPONSE_UPIU);
+ for (i = 0; i < UFS_CMD_RETRIES; ++i) {
+ get_utrd(utrd);
+ result = ufs_prepare_cmd(utrd, cmd_op, lun, lba, buf, length);
+ assert(result == 0);
+ ufs_send_request(utrd->task_tag);
+ result = ufs_check_resp(utrd, RESPONSE_UPIU);
+ if (result == 0 || result == -EIO) {
+ break;
+ }
+ }
assert(result == 0);
(void)result;
}
diff --git a/include/drivers/ufs.h b/include/drivers/ufs.h
index 09b8b72..1cd1bee 100644
--- a/include/drivers/ufs.h
+++ b/include/drivers/ufs.h
@@ -259,6 +259,9 @@
/* maximum number of retries for a general UIC command */
#define UFS_UIC_COMMAND_RETRIES 3
+/* maximum number of retries for a transfer command */
+#define UFS_CMD_RETRIES 3
+
/* maximum number of retries for reading UFS capacity */
#define UFS_READ_CAPACITY_RETRIES 10