2023-02-23 15:28:29

by Po-Wen Kao

[permalink] [raw]
Subject: [PATCH v3 0/6] Several UFS MCQ Code Changes

v2 -> v3
- Remove "scsi: ufs: core: Add hwq print for debug".
send later when error handling is ready.
- Rename patch title to match convention "scsi: ufs: ufs-mediatek:..."
- Add explanation for (nr_hw_queues = MAXQ + 1)
- Remove dummy line

v1 -> v2:
- Add 2 new patches
- Update MTK driver for mcq
- Export symbols for MTK driver
- Fix commit message in "scsi: ufs: core: Fix mcq nr_hw_queues"
- Split name change and fix into two patches

Po-Wen Kao (6):
scsi: ufs: core: Fix mcq tag calcualtion
scsi: ufs: core: Rename symbols
scsi: ufs: core: Fix mcq nr_hw_queues
scsi: ufs: core: Remove redundant check
scsi: ufs: core: Export symbols for MTK driver module
scsi: ufs: ufs-mediatek: Add MCQ support for MTK platform

drivers/ufs/core/ufs-mcq.c | 8 +-
drivers/ufs/core/ufshcd-priv.h | 2 -
drivers/ufs/core/ufshcd.c | 13 ++-
drivers/ufs/host/ufs-mediatek.c | 193 +++++++++++++++++++++++++++++++-
drivers/ufs/host/ufs-mediatek.h | 33 ++++++
include/ufs/ufshcd.h | 7 +-
6 files changed, 243 insertions(+), 13 deletions(-)

--
2.18.0



2023-02-23 15:28:32

by Po-Wen Kao

[permalink] [raw]
Subject: [PATCH v3 1/6] scsi: ufs: core: Fix mcq tag calcualtion

Transfer command descriptor is allocated in ufshcd_memory_alloc()
and referenced by transfer request descriptor with stride size
sizeof_utp_transfer_cmd_desc()
instead of
sizeof(struct utp_transfer_cmd_desc).

Consequently, computing tag by address offset should also refer to the
same stride.

Signed-off-by: Po-Wen Kao <[email protected]>
Reviewed-by: Bart Van Assche <[email protected]>
Reviewed-by: Manivannan Sadhasivam <[email protected]>
Reviewed-by: Stanley Chu <[email protected]>
Reviewed-by: Ziqi Chen <[email protected]>
---
drivers/ufs/core/ufs-mcq.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
index 31df052fbc41..3a27fa4b0024 100644
--- a/drivers/ufs/core/ufs-mcq.c
+++ b/drivers/ufs/core/ufs-mcq.c
@@ -265,7 +265,7 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba,
addr = (le64_to_cpu(cqe->command_desc_base_addr) & CQE_UCD_BA) -
hba->ucdl_dma_addr;

- return div_u64(addr, sizeof(struct utp_transfer_cmd_desc));
+ return div_u64(addr, sizeof_utp_transfer_cmd_desc(hba));
}

static void ufshcd_mcq_process_cqe(struct ufs_hba *hba,
--
2.18.0


2023-02-23 15:28:36

by Po-Wen Kao

[permalink] [raw]
Subject: [PATCH v3 4/6] scsi: ufs: core: Remove redundant check

is_mcq_supported() already check on use_mcq_mode.

Signed-off-by: Po-Wen Kao <[email protected]>
Reviewed-by: Stanley Chu <[email protected]>
Reviewed-by: Ziqi Chen <[email protected]>
---
drivers/ufs/core/ufshcd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 81c9f07ebfc8..3357cfa23616 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -8544,7 +8544,7 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params)
hba->scsi_host_added = true;
}
/* MCQ may be disabled if ufshcd_alloc_mcq() fails */
- if (is_mcq_supported(hba) && use_mcq_mode)
+ if (is_mcq_supported(hba))
ufshcd_config_mcq(hba);
}

--
2.18.0


2023-02-23 15:28:39

by Po-Wen Kao

[permalink] [raw]
Subject: [PATCH v3 3/6] scsi: ufs: core: Fix mcq nr_hw_queues

Since MAXQ is 0 based value, add one to obtain number of hardware queue.

Signed-off-by: Po-Wen Kao <[email protected]>
---
drivers/ufs/core/ufs-mcq.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
index a39746b2a8be..f9af658b4ba2 100644
--- a/drivers/ufs/core/ufs-mcq.c
+++ b/drivers/ufs/core/ufs-mcq.c
@@ -150,7 +150,8 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba)
u32 hba_maxq, rem, tot_queues;
struct Scsi_Host *host = hba->host;

- hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities);
+ /* maxq is 0 based value */
+ hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities) + 1 ;

tot_queues = UFS_MCQ_NUM_DEV_CMD_QUEUES + read_queues + poll_queues +
rw_queues;
--
2.18.0


2023-02-23 15:28:41

by Po-Wen Kao

[permalink] [raw]
Subject: [PATCH v3 2/6] scsi: ufs: core: Rename symbols

To avoid confusion, sizeof_utp_transfer_cmd_desc() is renamed to
ufshcd_get_ucd_size().

Signed-off-by: Po-Wen Kao <[email protected]>
Reviewed-by: Stanley Chu <[email protected]>
Reviewed-by: Ziqi Chen <[email protected]>
---
drivers/ufs/core/ufs-mcq.c | 2 +-
drivers/ufs/core/ufshcd.c | 8 ++++----
include/ufs/ufshcd.h | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
index 3a27fa4b0024..a39746b2a8be 100644
--- a/drivers/ufs/core/ufs-mcq.c
+++ b/drivers/ufs/core/ufs-mcq.c
@@ -265,7 +265,7 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba,
addr = (le64_to_cpu(cqe->command_desc_base_addr) & CQE_UCD_BA) -
hba->ucdl_dma_addr;

- return div_u64(addr, sizeof_utp_transfer_cmd_desc(hba));
+ return div_u64(addr, ufshcd_get_ucd_size(hba));
}

static void ufshcd_mcq_process_cqe(struct ufs_hba *hba,
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 3b3cf78d3b10..81c9f07ebfc8 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -2823,10 +2823,10 @@ static void ufshcd_map_queues(struct Scsi_Host *shost)
static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int i)
{
struct utp_transfer_cmd_desc *cmd_descp = (void *)hba->ucdl_base_addr +
- i * sizeof_utp_transfer_cmd_desc(hba);
+ i * ufshcd_get_ucd_size(hba);
struct utp_transfer_req_desc *utrdlp = hba->utrdl_base_addr;
dma_addr_t cmd_desc_element_addr = hba->ucdl_dma_addr +
- i * sizeof_utp_transfer_cmd_desc(hba);
+ i * ufshcd_get_ucd_size(hba);
u16 response_offset = offsetof(struct utp_transfer_cmd_desc,
response_upiu);
u16 prdt_offset = offsetof(struct utp_transfer_cmd_desc, prd_table);
@@ -3735,7 +3735,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
size_t utmrdl_size, utrdl_size, ucdl_size;

/* Allocate memory for UTP command descriptors */
- ucdl_size = sizeof_utp_transfer_cmd_desc(hba) * hba->nutrs;
+ ucdl_size = ufshcd_get_ucd_size(hba) * hba->nutrs;
hba->ucdl_base_addr = dmam_alloc_coherent(hba->dev,
ucdl_size,
&hba->ucdl_dma_addr,
@@ -3835,7 +3835,7 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)
prdt_offset =
offsetof(struct utp_transfer_cmd_desc, prd_table);

- cmd_desc_size = sizeof_utp_transfer_cmd_desc(hba);
+ cmd_desc_size = ufshcd_get_ucd_size(hba);
cmd_desc_dma_addr = hba->ucdl_dma_addr;

for (i = 0; i < hba->nutrs; i++) {
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index ed9e3d5addb3..8f79cca449e1 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -1136,7 +1136,7 @@ static inline size_t ufshcd_sg_entry_size(const struct ufs_hba *hba)
({ (void)(hba); BUILD_BUG_ON(sg_entry_size != sizeof(struct ufshcd_sg_entry)); })
#endif

-static inline size_t sizeof_utp_transfer_cmd_desc(const struct ufs_hba *hba)
+static inline size_t ufshcd_get_ucd_size(const struct ufs_hba *hba)
{
return sizeof(struct utp_transfer_cmd_desc) + SG_ALL * ufshcd_sg_entry_size(hba);
}
--
2.18.0


2023-02-23 15:28:43

by Po-Wen Kao

[permalink] [raw]
Subject: [PATCH v3 5/6] scsi: ufs: core: Export symbols for MTK driver module

Export
- ufshcd_mcq_config_mac
- ufshcd_mcq_make_queues_operational
- ufshcd_mcq_read_cqis
- ufshcd_disable_intr

Signed-off-by: Po-Wen Kao <[email protected]>
---
drivers/ufs/core/ufs-mcq.c | 3 +++
drivers/ufs/core/ufshcd-priv.h | 2 --
drivers/ufs/core/ufshcd.c | 3 ++-
include/ufs/ufshcd.h | 5 +++++
4 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
index f9af658b4ba2..7f00af766f5c 100644
--- a/drivers/ufs/core/ufs-mcq.c
+++ b/drivers/ufs/core/ufs-mcq.c
@@ -92,6 +92,7 @@ void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds)
val |= FIELD_PREP(MCQ_CFG_MAC_MASK, max_active_cmds);
ufshcd_writel(hba, val, REG_UFS_MCQ_CFG);
}
+EXPORT_SYMBOL_GPL(ufshcd_mcq_config_mac);

/**
* ufshcd_mcq_req_to_hwq - find the hardware queue on which the
@@ -242,6 +243,7 @@ u32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i)
{
return readl(mcq_opr_base(hba, OPR_CQIS, i) + REG_CQIS);
}
+EXPORT_SYMBOL_GPL(ufshcd_mcq_read_cqis);

void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i)
{
@@ -372,6 +374,7 @@ void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba)
MCQ_CFG_n(REG_SQATTR, i));
}
}
+EXPORT_SYMBOL_GPL(ufshcd_mcq_make_queues_operational);

void ufshcd_mcq_enable_esi(struct ufs_hba *hba)
{
diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h
index 529f8507a5e4..ffafcac329a8 100644
--- a/drivers/ufs/core/ufshcd-priv.h
+++ b/drivers/ufs/core/ufshcd-priv.h
@@ -66,8 +66,6 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag,
int ufshcd_mcq_init(struct ufs_hba *hba);
int ufshcd_mcq_decide_queue_depth(struct ufs_hba *hba);
int ufshcd_mcq_memory_alloc(struct ufs_hba *hba);
-void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba);
-void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds);
void ufshcd_mcq_select_mcq_mode(struct ufs_hba *hba);
u32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i);
void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i);
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 3357cfa23616..b3966f772063 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -2563,7 +2563,7 @@ static void ufshcd_enable_intr(struct ufs_hba *hba, u32 intrs)
* @hba: per adapter instance
* @intrs: interrupt bits
*/
-static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
+void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
{
u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);

@@ -2579,6 +2579,7 @@ static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)

ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
}
+EXPORT_SYMBOL_GPL(ufshcd_disable_intr);

/**
* ufshcd_prepare_req_desc_hdr - Fill UTP Transfer request descriptor header according to request
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index 8f79cca449e1..c49c9572088a 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -1230,6 +1230,7 @@ static inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg)

int ufshcd_alloc_host(struct device *, struct ufs_hba **);
void ufshcd_dealloc_host(struct ufs_hba *);
+void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs);
int ufshcd_hba_enable(struct ufs_hba *hba);
int ufshcd_init(struct ufs_hba *, void __iomem *, unsigned int);
int ufshcd_link_recovery(struct ufs_hba *hba);
@@ -1242,9 +1243,13 @@ void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk);
void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val);
void ufshcd_hba_stop(struct ufs_hba *hba);
void ufshcd_schedule_eh_work(struct ufs_hba *hba);
+
+void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds);
+u32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i);
void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i);
unsigned long ufshcd_mcq_poll_cqe_nolock(struct ufs_hba *hba,
struct ufs_hw_queue *hwq);
+void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba);
void ufshcd_mcq_enable_esi(struct ufs_hba *hba);
void ufshcd_mcq_config_esi(struct ufs_hba *hba, struct msi_msg *msg);

--
2.18.0


2023-02-23 15:28:53

by Po-Wen Kao

[permalink] [raw]
Subject: [PATCH v3 6/6] scsi: ufs: ufs-mediatek: Add MCQ support for MTK platform

Changes
- Implement vops and setup irq
- Fix pm flow under mcq mode

Signed-off-by: Po-Wen Kao <[email protected]>
---
drivers/ufs/host/ufs-mediatek.c | 193 +++++++++++++++++++++++++++++++-
drivers/ufs/host/ufs-mediatek.h | 33 ++++++
2 files changed, 224 insertions(+), 2 deletions(-)

diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c
index 21d9b047539f..162bbde675aa 100644
--- a/drivers/ufs/host/ufs-mediatek.c
+++ b/drivers/ufs/host/ufs-mediatek.c
@@ -30,6 +30,14 @@
#define CREATE_TRACE_POINTS
#include "ufs-mediatek-trace.h"

+static int ufs_mtk_config_mcq(struct ufs_hba *hba, bool irq);
+static void ufs_mtk_dbg_register_dump(struct ufs_hba *hba);
+
+#define MAX_SUPP_MAC 64
+#define MCQ_QUEUE_OFFSET(c) ((((c) >> 16) & 0xFF) * 0x200)
+
+static unsigned int mtk_mcq_irq[UFSHCD_MAX_Q_NR];
+
static const struct ufs_dev_quirk ufs_mtk_dev_fixups[] = {
{ .wmanufacturerid = UFS_ANY_VENDOR,
.model = UFS_ANY_MODEL,
@@ -843,6 +851,19 @@ static void ufs_mtk_vreg_fix_vccqx(struct ufs_hba *hba)
}
}

+static void ufs_mtk_init_interrupt(struct ufs_hba *hba)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+ int i;
+
+ host->mcq_nr_intr = UFSHCD_MAX_Q_NR;
+
+ for (i = 0; i < host->mcq_nr_intr; i++) {
+ host->mcq_intr_info[i].hba = hba;
+ host->mcq_intr_info[i].intr = mtk_mcq_irq[i];
+ }
+}
+
/**
* ufs_mtk_init - find other essential mmio bases
* @hba: host controller instance
@@ -879,6 +900,8 @@ static int ufs_mtk_init(struct ufs_hba *hba)
/* Initialize host capability */
ufs_mtk_init_host_caps(hba);

+ ufs_mtk_init_interrupt(hba);
+
err = ufs_mtk_bind_mphy(hba);
if (err)
goto out_variant_clear;
@@ -1174,7 +1197,16 @@ static int ufs_mtk_link_set_hpm(struct ufs_hba *hba)
else
return err;

- err = ufshcd_make_hba_operational(hba);
+ if (!hba->mcq_enabled)
+ err = ufshcd_make_hba_operational(hba);
+ else {
+ ufs_mtk_config_mcq(hba, false);
+ ufshcd_mcq_make_queues_operational(hba);
+ ufshcd_mcq_config_mac(hba, hba->nutrs);
+ ufshcd_writel(hba, ufshcd_readl(hba, REG_UFS_MEM_CFG) | 0x1,
+ REG_UFS_MEM_CFG);
+ }
+
if (err)
return err;

@@ -1361,6 +1393,12 @@ static int ufs_mtk_apply_dev_quirks(struct ufs_hba *hba)
ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME), 10);
}

+ /*
+ * Disable MCQ_CQ_EVENT interrupt.
+ * Use CQ Tail Entry Push Status instead.
+ */
+ ufshcd_disable_intr(hba, MCQ_CQ_EVENT_STATUS);
+
/*
* Decide waiting time before gating reference clock and
* after ungating reference clock according to vendors'
@@ -1498,6 +1536,116 @@ static int ufs_mtk_clk_scale_notify(struct ufs_hba *hba, bool scale_up,
return 0;
}

+static int ufs_mtk_get_hba_mac(struct ufs_hba *hba)
+{
+ return MAX_SUPP_MAC;
+}
+
+static int ufs_mtk_op_runtime_config(struct ufs_hba *hba)
+{
+ struct ufshcd_mcq_opr_info_t *opr;
+ int i;
+
+ for (i = 0; i < OPR_MAX; i++) {
+ opr = &hba->mcq_opr[i];
+ opr->stride = REG_UFS_MCQ_STRIDE;
+ }
+
+ hba->mcq_opr[OPR_SQD].offset = REG_UFS_MTK_SQD;
+ hba->mcq_opr[OPR_SQIS].offset = REG_UFS_MTK_SQIS;
+ hba->mcq_opr[OPR_CQD].offset = REG_UFS_MTK_CQD;
+ hba->mcq_opr[OPR_CQIS].offset = REG_UFS_MTK_CQIS;
+
+ hba->mcq_opr[OPR_SQD].base = hba->mmio_base + REG_UFS_MTK_SQD;
+ hba->mcq_opr[OPR_SQIS].base = hba->mmio_base + REG_UFS_MTK_SQIS;
+ hba->mcq_opr[OPR_CQD].base = hba->mmio_base + REG_UFS_MTK_CQD;
+ hba->mcq_opr[OPR_CQIS].base = hba->mmio_base + REG_UFS_MTK_CQIS;
+
+ return 0;
+}
+
+static int ufs_mtk_mcq_config_resource(struct ufs_hba *hba)
+{
+ hba->mcq_base = hba->mmio_base + MCQ_QUEUE_OFFSET(hba->mcq_capabilities);
+ return 0;
+}
+
+static irqreturn_t ufs_mtk_mcq_intr(int irq, void *__intr_info)
+{
+ struct ufs_mtk_mcq_intr_info *mcq_intr_info = __intr_info;
+ struct ufs_hba *hba = mcq_intr_info->hba;
+ struct ufs_hw_queue *hwq;
+ u32 events;
+ int i = mcq_intr_info->qid;
+
+ hwq = &hba->uhq[i];
+
+ events = ufshcd_mcq_read_cqis(hba, i);
+ if (events)
+ ufshcd_mcq_write_cqis(hba, events, i);
+
+ if (events & UFSHCD_MCQ_CQIS_TAIL_ENT_PUSH_STS)
+ ufshcd_mcq_poll_cqe_nolock(hba, hwq);
+
+ return IRQ_HANDLED;
+}
+
+static int ufs_mtk_config_mcq_irq(struct ufs_hba *hba)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+ u32 irq, i;
+ int ret;
+
+ for (i = 0; i < host->mcq_nr_intr; i++) {
+ irq = host->mcq_intr_info[i].intr;
+ if (irq == MTK_MCQ_INVALID_IRQ) {
+ dev_err(hba->dev, "invalid irq. %d\n", i);
+ return -ENOPARAM;
+ }
+
+ host->mcq_intr_info[i].qid = i;
+ ret = devm_request_irq(hba->dev, irq, ufs_mtk_mcq_intr, 0, UFSHCD,
+ &host->mcq_intr_info[i]);
+
+ dev_info(hba->dev, "request irq %d intr %s\n", irq, ret ? "failed": "");
+
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ufs_mtk_config_mcq(struct ufs_hba *hba, bool irq)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+ int ret = 0;
+
+ if (!host->mcq_set_intr) {
+
+ /* Disable irq option register */
+ ufshcd_rmwl(hba, MCQ_INTR_EN_MSK, 0, REG_UFS_MMIO_OPT_CTRL_0);
+
+ if (irq)
+ ret = ufs_mtk_config_mcq_irq(hba);
+
+ if (ret)
+ return ret;
+
+ host->mcq_set_intr = true;
+ }
+
+ ufshcd_rmwl(hba, MCQ_AH8, MCQ_AH8, REG_UFS_MMIO_OPT_CTRL_0);
+ ufshcd_rmwl(hba, MCQ_INTR_EN_MSK, MCQ_MULTI_INTR_EN, REG_UFS_MMIO_OPT_CTRL_0);
+
+ return 0;
+}
+
+static int ufs_mtk_config_esi(struct ufs_hba *hba)
+{
+ return ufs_mtk_config_mcq(hba, true);
+}
+
/*
* struct ufs_hba_mtk_vops - UFS MTK specific variant operations
*
@@ -1521,8 +1669,43 @@ static const struct ufs_hba_variant_ops ufs_hba_mtk_vops = {
.event_notify = ufs_mtk_event_notify,
.config_scaling_param = ufs_mtk_config_scaling_param,
.clk_scale_notify = ufs_mtk_clk_scale_notify,
+ /* mcq vops */
+ .get_hba_mac = ufs_mtk_get_hba_mac,
+ .op_runtime_config = ufs_mtk_op_runtime_config,
+ .mcq_config_resource = ufs_mtk_mcq_config_resource,
+ .config_esi = ufs_mtk_config_esi,
};

+static int ufs_mtk_mcq_get_irq(struct platform_device *pdev)
+{
+ int i, irq, cnt;
+
+ for (i = 0; i < UFSHCD_MAX_Q_NR; i++)
+ mtk_mcq_irq[i] = MTK_MCQ_INVALID_IRQ;
+
+ cnt = platform_irq_count(pdev);
+
+ if (cnt < 0)
+ return cnt;
+
+ /* no irq for mcq */
+ if (cnt == 1)
+ return 0;
+
+ for (i = 0; i < UFSHCD_MAX_Q_NR; i++) {
+ /* irq index 0 is ufshcd system irq, sq, cq irq start from index 1 */
+ irq = platform_get_irq(pdev, i + 1);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "get platform mcq irq fail: %d\n", i);
+ return irq;
+ }
+ mtk_mcq_irq[i] = irq;
+ dev_info(&pdev->dev, "get platform mcq irq: %d, %d\n", i, irq);
+ }
+
+ return 0;
+}
+
/**
* ufs_mtk_probe - probe routine of the driver
* @pdev: pointer to Platform device handle
@@ -1562,12 +1745,18 @@ static int ufs_mtk_probe(struct platform_device *pdev)
}

skip_reset:
+ err = ufs_mtk_mcq_get_irq(pdev);
+ if (err) {
+ dev_err(dev, "get irq failed %d\n", err);
+ goto out;
+ }
+
/* perform generic probe */
err = ufshcd_pltfrm_init(pdev, &ufs_hba_mtk_vops);

out:
if (err)
- dev_info(dev, "probe failed %d\n", err);
+ dev_err(dev, "probe failed %d\n", err);

of_node_put(reset_node);
return err;
diff --git a/drivers/ufs/host/ufs-mediatek.h b/drivers/ufs/host/ufs-mediatek.h
index 2fc6d7b87694..542b4c3a763c 100644
--- a/drivers/ufs/host/ufs-mediatek.h
+++ b/drivers/ufs/host/ufs-mediatek.h
@@ -10,11 +10,27 @@
#include <linux/pm_qos.h>
#include <linux/soc/mediatek/mtk_sip_svc.h>

+/*
+ * MCQ define and struct
+ */
+#define UFSHCD_MAX_Q_NR 8
+#define MTK_MCQ_INVALID_IRQ 0xFFFF
+
+/* REG_UFS_MMIO_OPT_CTRL_0 160h */
+#define EHS_EN 0x1
+#define PFM_IMPV 0x2
+#define MCQ_MULTI_INTR_EN 0x4
+#define MCQ_CMB_INTR_EN 0x8
+#define MCQ_AH8 0x10
+
+#define MCQ_INTR_EN_MSK (MCQ_MULTI_INTR_EN | MCQ_CMB_INTR_EN)
+
/*
* Vendor specific UFSHCI Registers
*/
#define REG_UFS_XOUFS_CTRL 0x140
#define REG_UFS_REFCLK_CTRL 0x144
+#define REG_UFS_MMIO_OPT_CTRL_0 0x160
#define REG_UFS_EXTREG 0x2100
#define REG_UFS_MPHYCTRL 0x2200
#define REG_UFS_MTK_IP_VER 0x2240
@@ -26,6 +42,13 @@
#define REG_UFS_DEBUG_SEL_B2 0x22D8
#define REG_UFS_DEBUG_SEL_B3 0x22DC

+#define REG_UFS_MTK_SQD 0x2800
+#define REG_UFS_MTK_SQIS 0x2814
+#define REG_UFS_MTK_CQD 0x281C
+#define REG_UFS_MTK_CQIS 0x2824
+
+#define REG_UFS_MCQ_STRIDE 0x30
+
/*
* Ref-clk control
*
@@ -136,6 +159,12 @@ struct ufs_mtk_hw_ver {
u8 major;
};

+struct ufs_mtk_mcq_intr_info {
+ struct ufs_hba *hba;
+ u32 intr;
+ u8 qid;
+};
+
struct ufs_mtk_host {
struct phy *mphy;
struct pm_qos_request pm_qos_req;
@@ -155,6 +184,10 @@ struct ufs_mtk_host {
u16 ref_clk_ungating_wait_us;
u16 ref_clk_gating_wait_us;
u32 ip_ver;
+
+ bool mcq_set_intr;
+ int mcq_nr_intr;
+ struct ufs_mtk_mcq_intr_info mcq_intr_info[UFSHCD_MAX_Q_NR];
};

/*
--
2.18.0


2023-02-26 16:10:46

by Bean Huo

[permalink] [raw]
Subject: Re: [PATCH v3 3/6] scsi: ufs: core: Fix mcq nr_hw_queues

On 23.02.23 4:27 PM, Po-Wen Kao wrote:
> Since MAXQ is 0 based value, add one to obtain number of hardware queue.

MAXQ in Multi-Circular Queue Capability Register is 0 based, hence ..

>
> Signed-off-by: Po-Wen Kao<[email protected]>
> ---
> drivers/ufs/core/ufs-mcq.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
> index a39746b2a8be..f9af658b4ba2 100644
> --- a/drivers/ufs/core/ufs-mcq.c
> +++ b/drivers/ufs/core/ufs-mcq.c
> @@ -150,7 +150,8 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba)
> u32 hba_maxq, rem, tot_queues;
> struct Scsi_Host *host = hba->host;
>
> - hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities);
> + /* maxq is 0 based value */
> + hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities) + 1 ;

Reviewed-by: Bean Huo <[email protected]>


2023-02-26 16:23:27

by Bean Huo

[permalink] [raw]
Subject: Re: [PATCH v3 4/6] scsi: ufs: core: Remove redundant check

On 23.02.23 4:27 PM, Po-Wen Kao wrote:
> is_mcq_supported() already check on use_mcq_mode.
>
> Signed-off-by: Po-Wen Kao <[email protected]>
> Reviewed-by: Stanley Chu <[email protected]>
> Reviewed-by: Ziqi Chen <[email protected]>
> ---
> drivers/ufs/core/ufshcd.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
> index 81c9f07ebfc8..3357cfa23616 100644
> --- a/drivers/ufs/core/ufshcd.c
> +++ b/drivers/ufs/core/ufshcd.c
> @@ -8544,7 +8544,7 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params)
> hba->scsi_host_added = true;
> }
> /* MCQ may be disabled if ufshcd_alloc_mcq() fails */
> - if (is_mcq_supported(hba) && use_mcq_mode)

This has been removed/optimized  by commit:

https://patches.linaro.org/project/linux-scsi/patch/8840cea4a57b46dabce18acc39afc50ab826330f.1676567593.git.quic_asutoshd@quicinc.com/

so this patch is not necessary anymore???


> + if (is_mcq_supported(hba))
> ufshcd_config_mcq(hba);
> }
>

2023-03-01 03:39:13

by Po-Wen Kao

[permalink] [raw]
Subject: Re: [PATCH v3 4/6] scsi: ufs: core: Remove redundant check

Hi Bean,

Yes, looks like it's fixed by that patch.

Please drop this one then.

On Sun, 2023-02-26 at 17:23 +0100, Bean Huo wrote:
> On 23.02.23 4:27 PM, Po-Wen Kao wrote:
> > is_mcq_supported() already check on use_mcq_mode.
> >
> > Signed-off-by: Po-Wen Kao <[email protected]>
> > Reviewed-by: Stanley Chu <[email protected]>
> > Reviewed-by: Ziqi Chen <[email protected]>
> > ---
> > drivers/ufs/core/ufshcd.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
> > index 81c9f07ebfc8..3357cfa23616 100644
> > --- a/drivers/ufs/core/ufshcd.c
> > +++ b/drivers/ufs/core/ufshcd.c
> > @@ -8544,7 +8544,7 @@ static int ufshcd_device_init(struct ufs_hba
> > *hba, bool init_dev_params)
> > hba->scsi_host_added = true;
> > }
> > /* MCQ may be disabled if ufshcd_alloc_mcq() fails */
> > - if (is_mcq_supported(hba) && use_mcq_mode)
>
> This has been removed/optimized by commit:
>
>
https://urldefense.com/v3/__https://patches.linaro.org/project/linux-scsi/patch/8840cea4a57b46dabce18acc39afc50ab826330f.1676567593.git.quic_asutoshd@quicinc.com/__;!!CTRNKA9wMg0ARbw!legN0lOmB4vG3dFE4M0Wm1kLquVrJo9db7WDDHm6YMc2VM2QAhGFKYo9qZmrGnkLM-UNpgMOni5aor9swQ$ 
>
>
> so this patch is not necessary anymore???
>
>
> > + if (is_mcq_supported(hba))
> > ufshcd_config_mcq(hba);
> > }
> >

2023-03-01 07:12:57

by Manivannan Sadhasivam

[permalink] [raw]
Subject: Re: [PATCH v3 2/6] scsi: ufs: core: Rename symbols

Subject could mention the actual function that is being renamed:
sizeof_utp_transfer_cmd_desc

On Thu, Feb 23, 2023 at 11:27:52PM +0800, Po-Wen Kao wrote:
> To avoid confusion, sizeof_utp_transfer_cmd_desc() is renamed to
> ufshcd_get_ucd_size().
>

How about:

"Naming the functions after standard operators like sizeof may cause
confusion. So let's rename it to ufshcd_get_ucd_size()."

Suggested-by: Manivannan Sadhasivam <[email protected]>

Thanks,
Mani

> Signed-off-by: Po-Wen Kao <[email protected]>
> Reviewed-by: Stanley Chu <[email protected]>
> Reviewed-by: Ziqi Chen <[email protected]>
> ---
> drivers/ufs/core/ufs-mcq.c | 2 +-
> drivers/ufs/core/ufshcd.c | 8 ++++----
> include/ufs/ufshcd.h | 2 +-
> 3 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
> index 3a27fa4b0024..a39746b2a8be 100644
> --- a/drivers/ufs/core/ufs-mcq.c
> +++ b/drivers/ufs/core/ufs-mcq.c
> @@ -265,7 +265,7 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba,
> addr = (le64_to_cpu(cqe->command_desc_base_addr) & CQE_UCD_BA) -
> hba->ucdl_dma_addr;
>
> - return div_u64(addr, sizeof_utp_transfer_cmd_desc(hba));
> + return div_u64(addr, ufshcd_get_ucd_size(hba));
> }
>
> static void ufshcd_mcq_process_cqe(struct ufs_hba *hba,
> diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
> index 3b3cf78d3b10..81c9f07ebfc8 100644
> --- a/drivers/ufs/core/ufshcd.c
> +++ b/drivers/ufs/core/ufshcd.c
> @@ -2823,10 +2823,10 @@ static void ufshcd_map_queues(struct Scsi_Host *shost)
> static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int i)
> {
> struct utp_transfer_cmd_desc *cmd_descp = (void *)hba->ucdl_base_addr +
> - i * sizeof_utp_transfer_cmd_desc(hba);
> + i * ufshcd_get_ucd_size(hba);
> struct utp_transfer_req_desc *utrdlp = hba->utrdl_base_addr;
> dma_addr_t cmd_desc_element_addr = hba->ucdl_dma_addr +
> - i * sizeof_utp_transfer_cmd_desc(hba);
> + i * ufshcd_get_ucd_size(hba);
> u16 response_offset = offsetof(struct utp_transfer_cmd_desc,
> response_upiu);
> u16 prdt_offset = offsetof(struct utp_transfer_cmd_desc, prd_table);
> @@ -3735,7 +3735,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
> size_t utmrdl_size, utrdl_size, ucdl_size;
>
> /* Allocate memory for UTP command descriptors */
> - ucdl_size = sizeof_utp_transfer_cmd_desc(hba) * hba->nutrs;
> + ucdl_size = ufshcd_get_ucd_size(hba) * hba->nutrs;
> hba->ucdl_base_addr = dmam_alloc_coherent(hba->dev,
> ucdl_size,
> &hba->ucdl_dma_addr,
> @@ -3835,7 +3835,7 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)
> prdt_offset =
> offsetof(struct utp_transfer_cmd_desc, prd_table);
>
> - cmd_desc_size = sizeof_utp_transfer_cmd_desc(hba);
> + cmd_desc_size = ufshcd_get_ucd_size(hba);
> cmd_desc_dma_addr = hba->ucdl_dma_addr;
>
> for (i = 0; i < hba->nutrs; i++) {
> diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
> index ed9e3d5addb3..8f79cca449e1 100644
> --- a/include/ufs/ufshcd.h
> +++ b/include/ufs/ufshcd.h
> @@ -1136,7 +1136,7 @@ static inline size_t ufshcd_sg_entry_size(const struct ufs_hba *hba)
> ({ (void)(hba); BUILD_BUG_ON(sg_entry_size != sizeof(struct ufshcd_sg_entry)); })
> #endif
>
> -static inline size_t sizeof_utp_transfer_cmd_desc(const struct ufs_hba *hba)
> +static inline size_t ufshcd_get_ucd_size(const struct ufs_hba *hba)
> {
> return sizeof(struct utp_transfer_cmd_desc) + SG_ALL * ufshcd_sg_entry_size(hba);
> }
> --
> 2.18.0
>

--
மணிவண்ணன் சதாசிவம்

2023-03-01 07:13:59

by Manivannan Sadhasivam

[permalink] [raw]
Subject: Re: [PATCH v3 3/6] scsi: ufs: core: Fix mcq nr_hw_queues

On Thu, Feb 23, 2023 at 11:27:53PM +0800, Po-Wen Kao wrote:
> Since MAXQ is 0 based value, add one to obtain number of hardware queue.
>
> Signed-off-by: Po-Wen Kao <[email protected]>

Reviewed-by: Manivannan Sadhasivam <[email protected]>

Thanks,
Mani

> ---
> drivers/ufs/core/ufs-mcq.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
> index a39746b2a8be..f9af658b4ba2 100644
> --- a/drivers/ufs/core/ufs-mcq.c
> +++ b/drivers/ufs/core/ufs-mcq.c
> @@ -150,7 +150,8 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba)
> u32 hba_maxq, rem, tot_queues;
> struct Scsi_Host *host = hba->host;
>
> - hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities);
> + /* maxq is 0 based value */
> + hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities) + 1 ;
>
> tot_queues = UFS_MCQ_NUM_DEV_CMD_QUEUES + read_queues + poll_queues +
> rw_queues;
> --
> 2.18.0
>

--
மணிவண்ணன் சதாசிவம்