summaryrefslogtreecommitdiff
path: root/drivers/ufs/core/ufshcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ufs/core/ufshcd.c')
-rw-r--r--drivers/ufs/core/ufshcd.c176
1 files changed, 96 insertions, 80 deletions
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 05eac965ee27..17d7bb875fee 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -422,7 +422,9 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag,
{
u64 lba = 0;
u8 opcode = 0, group_id = 0;
- u32 intr, doorbell;
+ u32 doorbell = 0;
+ u32 intr;
+ int hwq_id = -1;
struct ufshcd_lrb *lrbp = &hba->lrb[tag];
struct scsi_cmnd *cmd = lrbp->cmd;
struct request *rq = scsi_cmd_to_rq(cmd);
@@ -456,9 +458,16 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag,
}
intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
- doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+
+ if (is_mcq_enabled(hba)) {
+ struct ufs_hw_queue *hwq = ufshcd_mcq_req_to_hwq(hba, rq);
+
+ hwq_id = hwq->id;
+ } else {
+ doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+ }
trace_ufshcd_command(dev_name(hba->dev), str_t, tag,
- doorbell, transfer_len, intr, lba, opcode, group_id);
+ doorbell, hwq_id, transfer_len, intr, lba, opcode, group_id);
}
static void ufshcd_print_clk_freqs(struct ufs_hba *hba)
@@ -533,48 +542,66 @@ static void ufshcd_print_evt_hist(struct ufs_hba *hba)
}
static
-void ufshcd_print_trs(struct ufs_hba *hba, unsigned long bitmap, bool pr_prdt)
+void ufshcd_print_tr(struct ufs_hba *hba, int tag, bool pr_prdt)
{
const struct ufshcd_lrb *lrbp;
int prdt_length;
- int tag;
- for_each_set_bit(tag, &bitmap, hba->nutrs) {
- lrbp = &hba->lrb[tag];
+ lrbp = &hba->lrb[tag];
- dev_err(hba->dev, "UPIU[%d] - issue time %lld us\n",
- tag, div_u64(lrbp->issue_time_stamp_local_clock, 1000));
- dev_err(hba->dev, "UPIU[%d] - complete time %lld us\n",
- tag, div_u64(lrbp->compl_time_stamp_local_clock, 1000));
- dev_err(hba->dev,
- "UPIU[%d] - Transfer Request Descriptor phys@0x%llx\n",
- tag, (u64)lrbp->utrd_dma_addr);
-
- ufshcd_hex_dump("UPIU TRD: ", lrbp->utr_descriptor_ptr,
- sizeof(struct utp_transfer_req_desc));
- dev_err(hba->dev, "UPIU[%d] - Request UPIU phys@0x%llx\n", tag,
- (u64)lrbp->ucd_req_dma_addr);
- ufshcd_hex_dump("UPIU REQ: ", lrbp->ucd_req_ptr,
- sizeof(struct utp_upiu_req));
- dev_err(hba->dev, "UPIU[%d] - Response UPIU phys@0x%llx\n", tag,
- (u64)lrbp->ucd_rsp_dma_addr);
- ufshcd_hex_dump("UPIU RSP: ", lrbp->ucd_rsp_ptr,
- sizeof(struct utp_upiu_rsp));
-
- prdt_length = le16_to_cpu(
- lrbp->utr_descriptor_ptr->prd_table_length);
- if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN)
- prdt_length /= ufshcd_sg_entry_size(hba);
+ dev_err(hba->dev, "UPIU[%d] - issue time %lld us\n",
+ tag, div_u64(lrbp->issue_time_stamp_local_clock, 1000));
+ dev_err(hba->dev, "UPIU[%d] - complete time %lld us\n",
+ tag, div_u64(lrbp->compl_time_stamp_local_clock, 1000));
+ dev_err(hba->dev,
+ "UPIU[%d] - Transfer Request Descriptor phys@0x%llx\n",
+ tag, (u64)lrbp->utrd_dma_addr);
+
+ ufshcd_hex_dump("UPIU TRD: ", lrbp->utr_descriptor_ptr,
+ sizeof(struct utp_transfer_req_desc));
+ dev_err(hba->dev, "UPIU[%d] - Request UPIU phys@0x%llx\n", tag,
+ (u64)lrbp->ucd_req_dma_addr);
+ ufshcd_hex_dump("UPIU REQ: ", lrbp->ucd_req_ptr,
+ sizeof(struct utp_upiu_req));
+ dev_err(hba->dev, "UPIU[%d] - Response UPIU phys@0x%llx\n", tag,
+ (u64)lrbp->ucd_rsp_dma_addr);
+ ufshcd_hex_dump("UPIU RSP: ", lrbp->ucd_rsp_ptr,
+ sizeof(struct utp_upiu_rsp));
+
+ prdt_length = le16_to_cpu(
+ lrbp->utr_descriptor_ptr->prd_table_length);
+ if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN)
+ prdt_length /= ufshcd_sg_entry_size(hba);
- dev_err(hba->dev,
- "UPIU[%d] - PRDT - %d entries phys@0x%llx\n",
- tag, prdt_length,
- (u64)lrbp->ucd_prdt_dma_addr);
+ dev_err(hba->dev,
+ "UPIU[%d] - PRDT - %d entries phys@0x%llx\n",
+ tag, prdt_length,
+ (u64)lrbp->ucd_prdt_dma_addr);
- if (pr_prdt)
- ufshcd_hex_dump("UPIU PRDT: ", lrbp->ucd_prdt_ptr,
- ufshcd_sg_entry_size(hba) * prdt_length);
- }
+ if (pr_prdt)
+ ufshcd_hex_dump("UPIU PRDT: ", lrbp->ucd_prdt_ptr,
+ ufshcd_sg_entry_size(hba) * prdt_length);
+}
+
+static bool ufshcd_print_tr_iter(struct request *req, void *priv)
+{
+ struct scsi_device *sdev = req->q->queuedata;
+ struct Scsi_Host *shost = sdev->host;
+ struct ufs_hba *hba = shost_priv(shost);
+
+ ufshcd_print_tr(hba, req->tag, *(bool *)priv);
+
+ return true;
+}
+
+/**
+ * ufshcd_print_trs_all - print trs for all started requests.
+ * @hba: per-adapter instance.
+ * @pr_prdt: need to print prdt or not.
+ */
+static void ufshcd_print_trs_all(struct ufs_hba *hba, bool pr_prdt)
+{
+ blk_mq_tagset_busy_iter(&hba->host->tag_set, ufshcd_print_tr_iter, &pr_prdt);
}
static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap)
@@ -1242,7 +1269,7 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up)
struct ufs_pa_layer_attr new_pwr_info;
if (scale_up) {
- memcpy(&new_pwr_info, &hba->clk_scaling.saved_pwr_info.info,
+ memcpy(&new_pwr_info, &hba->clk_scaling.saved_pwr_info,
sizeof(struct ufs_pa_layer_attr));
} else {
memcpy(&new_pwr_info, &hba->pwr_info,
@@ -1251,7 +1278,7 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up)
if (hba->pwr_info.gear_tx > hba->clk_scaling.min_gear ||
hba->pwr_info.gear_rx > hba->clk_scaling.min_gear) {
/* save the current power mode */
- memcpy(&hba->clk_scaling.saved_pwr_info.info,
+ memcpy(&hba->clk_scaling.saved_pwr_info,
&hba->pwr_info,
sizeof(struct ufs_pa_layer_attr));
@@ -1409,13 +1436,6 @@ static int ufshcd_devfreq_target(struct device *dev,
struct ufs_clk_info *clki;
unsigned long irq_flags;
- /*
- * Skip devfreq if UFS initialization is not finished.
- * Otherwise ufs could be in a inconsistent state.
- */
- if (!smp_load_acquire(&hba->logical_unit_scan_finished))
- return 0;
-
if (!ufshcd_is_clkscaling_supported(hba))
return -EINVAL;
@@ -1500,7 +1520,7 @@ start_window:
scaling->window_start_t = curr_t;
scaling->tot_busy_t = 0;
- if (hba->outstanding_reqs) {
+ if (scaling->active_reqs) {
scaling->busy_start_t = curr_t;
scaling->is_busy_started = true;
} else {
@@ -2118,7 +2138,7 @@ static void ufshcd_clk_scaling_update_busy(struct ufs_hba *hba)
spin_lock_irqsave(hba->host->host_lock, flags);
hba->clk_scaling.active_reqs--;
- if (!hba->outstanding_reqs && scaling->is_busy_started) {
+ if (!scaling->active_reqs && scaling->is_busy_started) {
scaling->tot_busy_t += ktime_to_us(ktime_sub(ktime_get(),
scaling->busy_start_t));
scaling->busy_start_t = 0;
@@ -2215,10 +2235,11 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag,
if (is_mcq_enabled(hba)) {
int utrd_size = sizeof(struct utp_transfer_req_desc);
+ struct utp_transfer_req_desc *src = lrbp->utr_descriptor_ptr;
+ struct utp_transfer_req_desc *dest = hwq->sqe_base_addr + hwq->sq_tail_slot;
spin_lock(&hwq->sq_lock);
- memcpy(hwq->sqe_base_addr + (hwq->sq_tail_slot * utrd_size),
- lrbp->utr_descriptor_ptr, utrd_size);
+ memcpy(dest, src, utrd_size);
ufshcd_inc_sq_tail(hwq);
spin_unlock(&hwq->sq_lock);
} else {
@@ -5238,6 +5259,9 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp,
int scsi_status;
enum utp_ocs ocs;
+ scsi_set_resid(lrbp->cmd,
+ be32_to_cpu(lrbp->ucd_rsp_ptr->sr.residual_transfer_count));
+
/* overall command status of utrd */
ocs = ufshcd_get_tr_ocs(lrbp, cqe);
@@ -5328,7 +5352,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp,
if ((host_byte(result) != DID_OK) &&
(host_byte(result) != DID_REQUEUE) && !hba->silence_err_logs)
- ufshcd_print_trs(hba, 1 << lrbp->task_tag, true);
+ ufshcd_print_tr(hba, lrbp->task_tag, true);
return result;
}
@@ -6412,7 +6436,7 @@ again:
ufshcd_print_pwr_info(hba);
ufshcd_print_evt_hist(hba);
ufshcd_print_tmrs(hba, hba->outstanding_tasks);
- ufshcd_print_trs(hba, hba->outstanding_reqs, pr_prdt);
+ ufshcd_print_trs_all(hba, pr_prdt);
spin_lock_irqsave(hba->host->host_lock, flags);
}
@@ -7441,9 +7465,9 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
ufshcd_print_evt_hist(hba);
ufshcd_print_host_state(hba);
ufshcd_print_pwr_info(hba);
- ufshcd_print_trs(hba, 1 << tag, true);
+ ufshcd_print_tr(hba, tag, true);
} else {
- ufshcd_print_trs(hba, 1 << tag, false);
+ ufshcd_print_tr(hba, tag, false);
}
hba->req_abort_count++;
@@ -8399,6 +8423,21 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
if (ret)
goto out;
+ /* Initialize devfreq after UFS device is detected */
+ if (ufshcd_is_clkscaling_supported(hba)) {
+ memcpy(&hba->clk_scaling.saved_pwr_info,
+ &hba->pwr_info,
+ sizeof(struct ufs_pa_layer_attr));
+ hba->clk_scaling.is_allowed = true;
+
+ ret = ufshcd_devfreq_init(hba);
+ if (ret)
+ goto out;
+
+ hba->clk_scaling.is_enabled = true;
+ ufshcd_init_clk_scaling_sysfs(hba);
+ }
+
ufs_bsg_probe(hba);
ufshpb_init(hba);
scsi_scan_host(hba->host);
@@ -8670,12 +8709,6 @@ out:
if (ret) {
pm_runtime_put_sync(hba->dev);
ufshcd_hba_exit(hba);
- } else {
- /*
- * Make sure that when reader code sees UFS initialization has finished,
- * all initialization steps have really been executed.
- */
- smp_store_release(&hba->logical_unit_scan_finished, true);
}
}
@@ -8721,7 +8754,7 @@ static struct ufs_hba_variant_params ufs_hba_vps = {
.ondemand_data.downdifferential = 5,
};
-static struct scsi_host_template ufshcd_driver_template = {
+static const struct scsi_host_template ufshcd_driver_template = {
.module = THIS_MODULE,
.name = UFSHCD,
.proc_name = UFSHCD,
@@ -8744,6 +8777,7 @@ static struct scsi_host_template ufshcd_driver_template = {
.max_sectors = (1 << 20) / SECTOR_SIZE, /* 1 MiB */
.max_host_blocked = 1,
.track_queue_depth = 1,
+ .skip_settle_delay = 1,
.sdev_groups = ufshcd_driver_groups,
.rpm_autosuspend_delay = RPM_AUTOSUSPEND_DELAY_MS,
};
@@ -10316,30 +10350,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
*/
ufshcd_set_ufs_dev_active(hba);
- /* Initialize devfreq */
- if (ufshcd_is_clkscaling_supported(hba)) {
- memcpy(&hba->clk_scaling.saved_pwr_info.info,
- &hba->pwr_info,
- sizeof(struct ufs_pa_layer_attr));
- hba->clk_scaling.saved_pwr_info.is_valid = true;
- hba->clk_scaling.is_allowed = true;
-
- err = ufshcd_devfreq_init(hba);
- if (err)
- goto rpm_put_sync;
-
- hba->clk_scaling.is_enabled = true;
- ufshcd_init_clk_scaling_sysfs(hba);
- }
-
async_schedule(ufshcd_async_scan, hba);
ufs_sysfs_add_nodes(hba->dev);
device_enable_async_suspend(dev);
return 0;
-rpm_put_sync:
- pm_runtime_put_sync(dev);
free_tmf_queue:
blk_mq_destroy_queue(hba->tmf_queue);
blk_put_queue(hba->tmf_queue);