* ufshcd_transfer_req_compl - handle SCSI and query command completion
* @hba: per adapter instance
*/
-static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
+static void ufshcd_transfer_req_compl(struct ufs_hba *hba, int reason)
{
unsigned long completed_reqs;
u32 tr_doorbell;
tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
- __ufshcd_transfer_req_compl(hba, completed_reqs);
+ __ufshcd_transfer_req_compl(hba, reason, completed_reqs);
}
/**
/* Complete requests that have door-bell cleared */
static void ufshcd_complete_requests(struct ufs_hba *hba)
{
- ufshcd_transfer_req_compl(hba);
+ ufshcd_transfer_req_compl(hba, 0);
ufshcd_tmc_handler(hba);
}
* slot forcefully.
*/
if (hba->outstanding_reqs == max_doorbells)
- __ufshcd_transfer_req_compl(hba,
+ __ufshcd_transfer_req_compl(hba, 0,
(1UL << (hba->nutrs - 1)));
spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+ /* Fatal errors need reset */
+ if (err_xfer || err_tm || (hba->saved_err & INT_FATAL_ERRORS) ||
+ ((hba->saved_err & UIC_ERROR) &&
+ ((hba->saved_uic_err & UFSHCD_UIC_DL_PA_INIT_ERROR) ||
+ (hba->saved_uic_err & UFSHCD_UIC_DL_ERROR))))
+ dev_err(hba->dev,
+ "%s: saved_err:0x%x, saved_uic_err:0x%x\n",
+ __func__, hba->saved_err, hba->saved_uic_err);
+
err = ufshcd_reset_and_restore(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
if (err) {
ufshcd_tmc_handler(hba);
if (intr_status & UTP_TRANSFER_REQ_COMPL)
- ufshcd_transfer_req_compl(hba);
+ ufshcd_transfer_req_compl(hba, 0);
}
/**
}
}
spin_lock_irqsave(host->host_lock, flags);
- ufshcd_transfer_req_compl(hba);
+ ufshcd_transfer_req_compl(hba, DID_RESET);
spin_unlock_irqrestore(host->host_lock, flags);
out:
* outstanding requests in s/w here.
*/
spin_lock_irqsave(hba->host->host_lock, flags);
- ufshcd_transfer_req_compl(hba);
+ ufshcd_transfer_req_compl(hba, DID_RESET);
ufshcd_tmc_handler(hba);
spin_unlock_irqrestore(hba->host->host_lock, flags);
}
/* set the state as operational after switching to desired gear */
+ spin_lock_irqsave(hba->host->host_lock, flags);
hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
/*
* If we are in error handling context or in power management callbacks