diff options
author | Bart Van Assche <bvanassche@acm.org> | 2024-07-08 14:16:05 -0700 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2024-07-10 22:19:05 -0400 |
commit | af568c7e8292bd96f5a4f3d81dcc099bcfe7cb73 (patch) | |
tree | 409c79460aa7478beccd97d989c1fab31a4c228d /drivers/ufs | |
parent | 5e2053a41984f6086460a6b377a53af46ebe2b0f (diff) |
scsi: ufs: mcq: Make .get_hba_mac() optional
UFSHCI controllers that are compliant with the UFSHCI 4.0 standard report
the maximum number of supported commands in the controller capabilities
register. Use that value if .get_hba_mac == NULL.
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20240708211716.2827751-11-bvanassche@acm.org
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/ufs')
-rw-r--r-- | drivers/ufs/core/ufs-mcq.c | 26 | ||||
-rw-r--r-- | drivers/ufs/core/ufshcd-priv.h | 1 | ||||
-rw-r--r-- | drivers/ufs/core/ufshcd.c | 3 |
3 files changed, 23 insertions, 7 deletions
diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c index ef98c9797d07..70951829192f 100644 --- a/drivers/ufs/core/ufs-mcq.c +++ b/drivers/ufs/core/ufs-mcq.c @@ -138,18 +138,26 @@ EXPORT_SYMBOL_GPL(ufshcd_mcq_queue_cfg_addr); * * MAC - Max. Active Command of the Host Controller (HC) * HC wouldn't send more than this commands to the device. - * It is mandatory to implement get_hba_mac() to enable MCQ mode. * Calculates and adjusts the queue depth based on the depth * supported by the HC and ufs device. */ int ufshcd_mcq_decide_queue_depth(struct ufs_hba *hba) { - int mac = -EOPNOTSUPP; + int mac; - if (!hba->vops || !hba->vops->get_hba_mac) - goto err; - - mac = hba->vops->get_hba_mac(hba); + if (!hba->vops || !hba->vops->get_hba_mac) { + /* + * Extract the maximum number of active transfer tasks value + * from the host controller capabilities register. This value is + * 0-based. + */ + hba->capabilities = + ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES); + mac = hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS_MCQ; + mac++; + } else { + mac = hba->vops->get_hba_mac(hba); + } if (mac < 0) goto err; @@ -424,6 +432,12 @@ void ufshcd_mcq_enable(struct ufs_hba *hba) } EXPORT_SYMBOL_GPL(ufshcd_mcq_enable); +void ufshcd_mcq_disable(struct ufs_hba *hba) +{ + ufshcd_rmwl(hba, MCQ_MODE_SELECT, 0, REG_UFS_MEM_CFG); + hba->mcq_enabled = false; +} + void ufshcd_mcq_config_esi(struct ufs_hba *hba, struct msi_msg *msg) { ufshcd_writel(hba, msg->address_lo, REG_UFS_ESILBA); diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h index 88ce93748305..ce36154ce963 100644 --- a/drivers/ufs/core/ufshcd-priv.h +++ b/drivers/ufs/core/ufshcd-priv.h @@ -64,6 +64,7 @@ void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit); void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag, struct cq_entry *cqe); int ufshcd_mcq_init(struct ufs_hba *hba); +void ufshcd_mcq_disable(struct ufs_hba *hba); int ufshcd_mcq_decide_queue_depth(struct ufs_hba *hba); int ufshcd_mcq_memory_alloc(struct ufs_hba *hba); struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba, diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 3fff49953f04..64f72937c0a2 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -8753,12 +8753,13 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params) if (ret) return ret; if (is_mcq_supported(hba) && !hba->scsi_host_added) { + ufshcd_mcq_enable(hba); ret = ufshcd_alloc_mcq(hba); if (!ret) { ufshcd_config_mcq(hba); - ufshcd_mcq_enable(hba); } else { /* Continue with SDB mode */ + ufshcd_mcq_disable(hba); use_mcq_mode = false; dev_err(hba->dev, "MCQ mode is disabled, err=%d\n", ret); |