Skip to content

Commit 5074f48

Browse files
Merge patch series "ufs: pci: Add support UFSHCI 4.0 MCQ"
Minwoo Im <[email protected]> says: This patchset introduces add support for MCQ introduced in UFSHCI 4.0. The first patch adds a simple helper to get the address of MCQ queue config registers. The second one enables MCQ feature by adding mandatory vops callback functions required at MCQ initialization phase. The last one is to prevent a case where number of MCQ is given 1 since driver allocates poll_queues first rather than I/O queues to handle device commands. Instead of causing exception handlers due to no I/O queue, failfast during the initialization time. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin K. Petersen <[email protected]>
2 parents e8a1d87 + a420a8e commit 5074f48

File tree

3 files changed

+71
-1
lines changed

3 files changed

+71
-1
lines changed

drivers/ufs/core/ufs-mcq.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/iopoll.h>
1919

2020
#define MAX_QUEUE_SUP GENMASK(7, 0)
21+
#define QCFGPTR GENMASK(23, 16)
2122
#define UFS_MCQ_MIN_RW_QUEUES 2
2223
#define UFS_MCQ_MIN_READ_QUEUES 0
2324
#define UFS_MCQ_MIN_POLL_QUEUES 0
@@ -116,6 +117,19 @@ struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba,
116117
return &hba->uhq[hwq];
117118
}
118119

120+
/**
121+
* ufshcd_mcq_queue_cfg_addr - get an start address of the MCQ Queue Config
122+
* Registers.
123+
* @hba: per adapter instance
124+
*
125+
* Return: Start address of MCQ Queue Config Registers in HCI
126+
*/
127+
unsigned int ufshcd_mcq_queue_cfg_addr(struct ufs_hba *hba)
128+
{
129+
return FIELD_GET(QCFGPTR, hba->mcq_capabilities) * 0x200;
130+
}
131+
EXPORT_SYMBOL_GPL(ufshcd_mcq_queue_cfg_addr);
132+
119133
/**
120134
* ufshcd_mcq_decide_queue_depth - decide the queue depth
121135
* @hba: per adapter instance
@@ -165,6 +179,15 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba)
165179
return -EOPNOTSUPP;
166180
}
167181

182+
/*
183+
* Device should support at least one I/O queue to handle device
184+
* commands via hba->dev_cmd_queue.
185+
*/
186+
if (hba_maxq == poll_queues) {
187+
dev_err(hba->dev, "At least one non-poll queue required\n");
188+
return -EOPNOTSUPP;
189+
}
190+
168191
rem = hba_maxq;
169192

170193
if (rw_queues) {

drivers/ufs/host/ufshcd-pci.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include <linux/acpi.h>
2121
#include <linux/gpio/consumer.h>
2222

23+
#define MAX_SUPP_MAC 64
24+
2325
struct ufs_host {
2426
void (*late_init)(struct ufs_hba *hba);
2527
};
@@ -446,6 +448,49 @@ static int ufs_intel_mtl_init(struct ufs_hba *hba)
446448
return ufs_intel_common_init(hba);
447449
}
448450

451+
static int ufs_qemu_get_hba_mac(struct ufs_hba *hba)
452+
{
453+
return MAX_SUPP_MAC;
454+
}
455+
456+
static int ufs_qemu_mcq_config_resource(struct ufs_hba *hba)
457+
{
458+
hba->mcq_base = hba->mmio_base + ufshcd_mcq_queue_cfg_addr(hba);
459+
460+
return 0;
461+
}
462+
463+
static int ufs_qemu_op_runtime_config(struct ufs_hba *hba)
464+
{
465+
struct ufshcd_mcq_opr_info_t *opr;
466+
int i;
467+
468+
u32 sqdao = ufsmcq_readl(hba, ufshcd_mcq_cfg_offset(REG_SQDAO, 0));
469+
u32 sqisao = ufsmcq_readl(hba, ufshcd_mcq_cfg_offset(REG_SQISAO, 0));
470+
u32 cqdao = ufsmcq_readl(hba, ufshcd_mcq_cfg_offset(REG_CQDAO, 0));
471+
u32 cqisao = ufsmcq_readl(hba, ufshcd_mcq_cfg_offset(REG_CQISAO, 0));
472+
473+
hba->mcq_opr[OPR_SQD].offset = sqdao;
474+
hba->mcq_opr[OPR_SQIS].offset = sqisao;
475+
hba->mcq_opr[OPR_CQD].offset = cqdao;
476+
hba->mcq_opr[OPR_CQIS].offset = cqisao;
477+
478+
for (i = 0; i < OPR_MAX; i++) {
479+
opr = &hba->mcq_opr[i];
480+
opr->stride = 48;
481+
opr->base = hba->mmio_base + opr->offset;
482+
}
483+
484+
return 0;
485+
}
486+
487+
static struct ufs_hba_variant_ops ufs_qemu_hba_vops = {
488+
.name = "qemu-pci",
489+
.get_hba_mac = ufs_qemu_get_hba_mac,
490+
.mcq_config_resource = ufs_qemu_mcq_config_resource,
491+
.op_runtime_config = ufs_qemu_op_runtime_config,
492+
};
493+
449494
static struct ufs_hba_variant_ops ufs_intel_cnl_hba_vops = {
450495
.name = "intel-pci",
451496
.init = ufs_intel_common_init,
@@ -591,7 +636,8 @@ static const struct dev_pm_ops ufshcd_pci_pm_ops = {
591636
};
592637

593638
static const struct pci_device_id ufshcd_pci_tbl[] = {
594-
{ PCI_VENDOR_ID_REDHAT, 0x0013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
639+
{ PCI_VENDOR_ID_REDHAT, 0x0013, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
640+
(kernel_ulong_t)&ufs_qemu_hba_vops },
595641
{ PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
596642
{ PCI_VDEVICE(INTEL, 0x9DFA), (kernel_ulong_t)&ufs_intel_cnl_hba_vops },
597643
{ PCI_VDEVICE(INTEL, 0x4B41), (kernel_ulong_t)&ufs_intel_ehl_hba_vops },

include/ufs/ufshcd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,6 +1278,7 @@ void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val);
12781278
void ufshcd_hba_stop(struct ufs_hba *hba);
12791279
void ufshcd_schedule_eh_work(struct ufs_hba *hba);
12801280
void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds);
1281+
unsigned int ufshcd_mcq_queue_cfg_addr(struct ufs_hba *hba);
12811282
u32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i);
12821283
void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i);
12831284
unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba,

0 commit comments

Comments
 (0)