From 93ef12d92f65facf8e02ad6578a898a190aa6cf4 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 8 Jul 2024 14:15:57 -0700 Subject: scsi: ufs: core: Initialize struct uic_command once Instead of first zero-initializing struct uic_command and next initializing it memberwise, initialize all members at once. Reviewed-by: Daejun Park Reviewed-by: Avri Altman Reviewed-by: Manivannan Sadhasivam Reviewed-by: Peter Wang Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20240708211716.2827751-3-bvanassche@acm.org Signed-off-by: Martin K. Petersen --- include/ufs/ufshcd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/ufs') diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 9e0581115b34..d4d63507d090 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -73,8 +73,8 @@ enum ufs_event_type { * @done: UIC command completion */ struct uic_command { - u32 command; - u32 argument1; + const u32 command; + const u32 argument1; u32 argument2; u32 argument3; int cmd_active; -- cgit v1.2.3 From b53eb9a050d76fc695258e04384e71b3fbb1e7d5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 8 Jul 2024 14:15:59 -0700 Subject: scsi: ufs: core: Rename the MASK_TRANSFER_REQUESTS_SLOTS constant Rename this constant to prepare for the introduction of the MASK_TRANSFER_REQUESTS_SLOTS_MCQ constant. The acronym "SDB" stands for "single doorbell" (mode). Reviewed-by: Peter Wang Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20240708211716.2827751-5-bvanassche@acm.org Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshcd.c | 2 +- include/ufs/ufshci.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include/ufs') diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 7957c570a12a..bfcfbfb648d1 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -2401,7 +2401,7 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba) hba->capabilities &= ~MASK_64_ADDRESSING_SUPPORT; /* nutrs and nutmrs are 0 based values */ - hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1; + hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS_SDB) + 1; hba->nutmrs = ((hba->capabilities & MASK_TASK_MANAGEMENT_REQUEST_SLOTS) >> 16) + 1; hba->reserved_slot = hba->nutrs - 1; diff --git a/include/ufs/ufshci.h b/include/ufs/ufshci.h index c50f92bf2e1d..8d0cc73537c6 100644 --- a/include/ufs/ufshci.h +++ b/include/ufs/ufshci.h @@ -67,7 +67,7 @@ enum { /* Controller capability masks */ enum { - MASK_TRANSFER_REQUESTS_SLOTS = 0x0000001F, + MASK_TRANSFER_REQUESTS_SLOTS_SDB = 0x0000001F, MASK_NUMBER_OUTSTANDING_RTT = 0x0000FF00, MASK_TASK_MANAGEMENT_REQUEST_SLOTS = 0x00070000, MASK_EHSLUTRD_SUPPORTED = 0x00400000, -- cgit v1.2.3 From 0fca3318e550d48e9a6c844763bf9eab91c30f07 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 8 Jul 2024 14:16:01 -0700 Subject: scsi: ufs: core: Inline is_mcq_enabled() Improve code readability by inlining is_mcq_enabled(). Cc: Peter Wang Cc: Manivannan Sadhasivam Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20240708211716.2827751-7-bvanassche@acm.org Reviewed-by: Manivannan Sadhasivam Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshcd.c | 28 ++++++++++++++-------------- drivers/ufs/host/ufs-mediatek.c | 6 +++--- include/ufs/ufshcd.h | 5 ----- 3 files changed, 17 insertions(+), 22 deletions(-) (limited to 'include/ufs') diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index aed6b7acfcc9..a40b0bf2922e 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -453,7 +453,7 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag, intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS); - if (is_mcq_enabled(hba)) { + if (hba->mcq_enabled) { struct ufs_hw_queue *hwq = ufshcd_mcq_req_to_hwq(hba, rq); hwq_id = hwq->id; @@ -2301,7 +2301,7 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag, if (unlikely(ufshcd_should_inform_monitor(hba, lrbp))) ufshcd_start_monitor(hba, lrbp); - if (is_mcq_enabled(hba)) { + if (hba->mcq_enabled) { 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; @@ -3000,7 +3000,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) goto out; } - if (is_mcq_enabled(hba)) + if (hba->mcq_enabled) hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd)); ufshcd_send_command(hba, tag, hwq); @@ -3059,7 +3059,7 @@ static int ufshcd_clear_cmd(struct ufs_hba *hba, u32 task_tag) unsigned long flags; int err; - if (is_mcq_enabled(hba)) { + if (hba->mcq_enabled) { /* * MCQ mode. Clean up the MCQ resources similar to * what the ufshcd_utrl_clear() does for SDB mode. @@ -3169,7 +3169,7 @@ retry: __func__, lrbp->task_tag); /* MCQ mode */ - if (is_mcq_enabled(hba)) { + if (hba->mcq_enabled) { /* successfully cleared the command, retry if needed */ if (ufshcd_clear_cmd(hba, lrbp->task_tag) == 0) err = -EAGAIN; @@ -5560,7 +5560,7 @@ static int ufshcd_poll(struct Scsi_Host *shost, unsigned int queue_num) u32 tr_doorbell; struct ufs_hw_queue *hwq; - if (is_mcq_enabled(hba)) { + if (hba->mcq_enabled) { hwq = &hba->uhq[queue_num]; return ufshcd_mcq_poll_cqe_lock(hba, hwq); @@ -6201,7 +6201,7 @@ out: /* Complete requests that have door-bell cleared */ static void ufshcd_complete_requests(struct ufs_hba *hba, bool force_compl) { - if (is_mcq_enabled(hba)) + if (hba->mcq_enabled) ufshcd_mcq_compl_pending_transfer(hba, force_compl); else ufshcd_transfer_req_compl(hba); @@ -6458,7 +6458,7 @@ static bool ufshcd_abort_one(struct request *rq, void *priv) *ret ? "failed" : "succeeded"); /* Release cmd in MCQ mode if abort succeeds */ - if (is_mcq_enabled(hba) && (*ret == 0)) { + if (hba->mcq_enabled && (*ret == 0)) { hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(lrbp->cmd)); spin_lock_irqsave(&hwq->cq_lock, flags); if (ufshcd_cmd_inflight(lrbp->cmd)) @@ -7389,7 +7389,7 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) goto out; } - if (is_mcq_enabled(hba)) { + if (hba->mcq_enabled) { for (pos = 0; pos < hba->nutrs; pos++) { lrbp = &hba->lrb[pos]; if (ufshcd_cmd_inflight(lrbp->cmd) && @@ -7485,7 +7485,7 @@ int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag) */ dev_err(hba->dev, "%s: cmd at tag %d not pending in the device.\n", __func__, tag); - if (is_mcq_enabled(hba)) { + if (hba->mcq_enabled) { /* MCQ mode */ if (ufshcd_cmd_inflight(lrbp->cmd)) { /* sleep for max. 200us same delay as in SDB mode */ @@ -7563,7 +7563,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) ufshcd_hold(hba); - if (!is_mcq_enabled(hba)) { + if (!hba->mcq_enabled) { reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); if (!test_bit(tag, &hba->outstanding_reqs)) { /* If command is already aborted/completed, return FAILED. */ @@ -7596,7 +7596,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) } hba->req_abort_count++; - if (!is_mcq_enabled(hba) && !(reg & (1 << tag))) { + if (!hba->mcq_enabled && !(reg & (1 << tag))) { /* only execute this code in single doorbell mode */ dev_err(hba->dev, "%s: cmd was completed, but without a notifying intr, tag = %d", @@ -7623,7 +7623,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) goto release; } - if (is_mcq_enabled(hba)) { + if (hba->mcq_enabled) { /* MCQ mode. Branch off to handle abort for mcq mode */ err = ufshcd_mcq_abort(cmd); goto release; @@ -8732,7 +8732,7 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params) ufshcd_set_link_active(hba); /* Reconfigure MCQ upon reset */ - if (is_mcq_enabled(hba) && !init_dev_params) + if (hba->mcq_enabled && !init_dev_params) ufshcd_config_mcq(hba); /* Verify device initialization by sending NOP OUT UPIU */ diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index c7a0ab9b1f59..02c9064284e1 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -693,7 +693,7 @@ static void ufs_mtk_mcq_disable_irq(struct ufs_hba *hba) struct ufs_mtk_host *host = ufshcd_get_variant(hba); u32 irq, i; - if (!is_mcq_enabled(hba)) + if (!hba->mcq_enabled) return; if (host->mcq_nr_intr == 0) @@ -711,7 +711,7 @@ static void ufs_mtk_mcq_enable_irq(struct ufs_hba *hba) struct ufs_mtk_host *host = ufshcd_get_variant(hba); u32 irq, i; - if (!is_mcq_enabled(hba)) + if (!hba->mcq_enabled) return; if (host->mcq_nr_intr == 0) @@ -1308,7 +1308,7 @@ static int ufs_mtk_link_set_hpm(struct ufs_hba *hba) if (err) return err; - if (is_mcq_enabled(hba)) { + if (hba->mcq_enabled) { ufs_mtk_config_mcq(hba, false); ufshcd_mcq_make_queues_operational(hba); ufshcd_mcq_config_mac(hba, hba->nutrs); diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index d4d63507d090..c0e28a512b3c 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -1132,11 +1132,6 @@ struct ufs_hw_queue { #define MCQ_QCFG_SIZE 0x40 -static inline bool is_mcq_enabled(struct ufs_hba *hba) -{ - return hba->mcq_enabled; -} - static inline unsigned int ufshcd_mcq_opr_offset(struct ufs_hba *hba, enum ufshcd_mcq_opr opr, int idx) { -- cgit v1.2.3 From af568c7e8292bd96f5a4f3d81dcc099bcfe7cb73 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 8 Jul 2024 14:16:05 -0700 Subject: 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 Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20240708211716.2827751-11-bvanassche@acm.org Reviewed-by: Manivannan Sadhasivam Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufs-mcq.c | 26 ++++++++++++++++++++------ drivers/ufs/core/ufshcd-priv.h | 1 + drivers/ufs/core/ufshcd.c | 3 ++- include/ufs/ufshcd.h | 4 +++- include/ufs/ufshci.h | 1 + 5 files changed, 27 insertions(+), 8 deletions(-) (limited to 'include/ufs') 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); diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index c0e28a512b3c..6518997930f3 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -325,7 +325,9 @@ struct ufs_pwr_mode_info { * @event_notify: called to notify important events * @reinit_notify: called to notify reinit of UFSHCD during max gear switch * @mcq_config_resource: called to configure MCQ platform resources - * @get_hba_mac: called to get vendor specific mac value, mandatory for mcq mode + * @get_hba_mac: reports maximum number of outstanding commands supported by + * the controller. Should be implemented for UFSHCI 4.0 or later + * controllers that are not compliant with the UFSHCI 4.0 specification. * @op_runtime_config: called to config Operation and runtime regs Pointers * @get_outstanding_cqs: called to get outstanding completion queues * @config_esi: called to config Event Specific Interrupt diff --git a/include/ufs/ufshci.h b/include/ufs/ufshci.h index 8d0cc73537c6..38fe97971a65 100644 --- a/include/ufs/ufshci.h +++ b/include/ufs/ufshci.h @@ -68,6 +68,7 @@ enum { /* Controller capability masks */ enum { MASK_TRANSFER_REQUESTS_SLOTS_SDB = 0x0000001F, + MASK_TRANSFER_REQUESTS_SLOTS_MCQ = 0x000000FF, MASK_NUMBER_OUTSTANDING_RTT = 0x0000FF00, MASK_TASK_MANAGEMENT_REQUEST_SLOTS = 0x00070000, MASK_EHSLUTRD_SUPPORTED = 0x00400000, -- cgit v1.2.3