2019-07-16 00:47:57

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: [PATCH 1/3] nvme: Pass the queue to SQ_SIZE/CQ_SIZE macros

This will make it easier to handle variable queue entry sizes
later. No functional change.

Signed-off-by: Benjamin Herrenschmidt <[email protected]>

# Conflicts:
# drivers/nvme/host/pci.c
---
drivers/nvme/host/pci.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index dd10cf78f2d3..8f006638452b 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -28,8 +28,8 @@
#include "trace.h"
#include "nvme.h"

-#define SQ_SIZE(depth) (depth * sizeof(struct nvme_command))
-#define CQ_SIZE(depth) (depth * sizeof(struct nvme_completion))
+#define SQ_SIZE(q) ((q)->q_depth * sizeof(struct nvme_command))
+#define CQ_SIZE(q) ((q)->q_depth * sizeof(struct nvme_completion))

#define SGES_PER_PAGE (PAGE_SIZE / sizeof(struct nvme_sgl_desc))

@@ -1344,16 +1344,16 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)

static void nvme_free_queue(struct nvme_queue *nvmeq)
{
- dma_free_coherent(nvmeq->dev->dev, CQ_SIZE(nvmeq->q_depth),
+ dma_free_coherent(nvmeq->dev->dev, CQ_SIZE(nvmeq),
(void *)nvmeq->cqes, nvmeq->cq_dma_addr);
if (!nvmeq->sq_cmds)
return;

if (test_and_clear_bit(NVMEQ_SQ_CMB, &nvmeq->flags)) {
pci_free_p2pmem(to_pci_dev(nvmeq->dev->dev),
- nvmeq->sq_cmds, SQ_SIZE(nvmeq->q_depth));
+ nvmeq->sq_cmds, SQ_SIZE(nvmeq));
} else {
- dma_free_coherent(nvmeq->dev->dev, SQ_SIZE(nvmeq->q_depth),
+ dma_free_coherent(nvmeq->dev->dev, SQ_SIZE(nvmeq),
nvmeq->sq_cmds, nvmeq->sq_dma_addr);
}
}
@@ -1433,12 +1433,12 @@ static int nvme_cmb_qdepth(struct nvme_dev *dev, int nr_io_queues,
}

static int nvme_alloc_sq_cmds(struct nvme_dev *dev, struct nvme_queue *nvmeq,
- int qid, int depth)
+ int qid)
{
struct pci_dev *pdev = to_pci_dev(dev->dev);

if (qid && dev->cmb_use_sqes && (dev->cmbsz & NVME_CMBSZ_SQS)) {
- nvmeq->sq_cmds = pci_alloc_p2pmem(pdev, SQ_SIZE(depth));
+ nvmeq->sq_cmds = pci_alloc_p2pmem(pdev, SQ_SIZE(nvmeq));
if (nvmeq->sq_cmds) {
nvmeq->sq_dma_addr = pci_p2pmem_virt_to_bus(pdev,
nvmeq->sq_cmds);
@@ -1447,11 +1447,11 @@ static int nvme_alloc_sq_cmds(struct nvme_dev *dev, struct nvme_queue *nvmeq,
return 0;
}

- pci_free_p2pmem(pdev, nvmeq->sq_cmds, SQ_SIZE(depth));
+ pci_free_p2pmem(pdev, nvmeq->sq_cmds, SQ_SIZE(nvmeq));
}
}

- nvmeq->sq_cmds = dma_alloc_coherent(dev->dev, SQ_SIZE(depth),
+ nvmeq->sq_cmds = dma_alloc_coherent(dev->dev, SQ_SIZE(nvmeq),
&nvmeq->sq_dma_addr, GFP_KERNEL);
if (!nvmeq->sq_cmds)
return -ENOMEM;
@@ -1465,12 +1465,13 @@ static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth)
if (dev->ctrl.queue_count > qid)
return 0;

- nvmeq->cqes = dma_alloc_coherent(dev->dev, CQ_SIZE(depth),
+ nvmeq->q_depth = depth;
+ nvmeq->cqes = dma_alloc_coherent(dev->dev, CQ_SIZE(nvmeq),
&nvmeq->cq_dma_addr, GFP_KERNEL);
if (!nvmeq->cqes)
goto free_nvmeq;

- if (nvme_alloc_sq_cmds(dev, nvmeq, qid, depth))
+ if (nvme_alloc_sq_cmds(dev, nvmeq, qid))
goto free_cqdma;

nvmeq->dev = dev;
@@ -1479,15 +1480,14 @@ static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth)
nvmeq->cq_head = 0;
nvmeq->cq_phase = 1;
nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride];
- nvmeq->q_depth = depth;
nvmeq->qid = qid;
dev->ctrl.queue_count++;

return 0;

free_cqdma:
- dma_free_coherent(dev->dev, CQ_SIZE(depth), (void *)nvmeq->cqes,
- nvmeq->cq_dma_addr);
+ dma_free_coherent(dev->dev, CQ_SIZE(nvmeq), (void *)nvmeq->cqes,
+ nvmeq->cq_dma_addr);
free_nvmeq:
return -ENOMEM;
}
@@ -1515,7 +1515,7 @@ static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
nvmeq->cq_head = 0;
nvmeq->cq_phase = 1;
nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride];
- memset((void *)nvmeq->cqes, 0, CQ_SIZE(nvmeq->q_depth));
+ memset((void *)nvmeq->cqes, 0, CQ_SIZE(nvmeq));
nvme_dbbuf_init(dev, nvmeq, qid);
dev->online_queues++;
wmb(); /* ensure the first interrupt sees the initialization */
--
2.17.1


2019-07-16 00:48:24

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: [PATCH 3/3] nvme: Add support for Apple 2018+ models

Based on reverse engineering and original patch by

Paul Pawlowski <[email protected]>

This adds support for Apple weird implementation of NVME in their
2018 or later machines. It accounts for the twice-as-big SQ entries
for the IO queues, and the fact that only interrupt vector 0 appears
to function properly.

Signed-off-by: Benjamin Herrenschmidt <[email protected]>
---
drivers/nvme/host/core.c | 5 ++++-
drivers/nvme/host/nvme.h | 10 ++++++++++
drivers/nvme/host/pci.c | 6 ++++++
3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 716ebe87a2b8..480ea24d8cf4 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -2701,7 +2701,10 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
ctrl->hmmaxd = le16_to_cpu(id->hmmaxd);

/* Grab required IO queue size */
- ctrl->iosqes = id->sqes & 0xf;
+ if (ctrl->quirks & NVME_QUIRK_128_BYTES_SQES)
+ ctrl->iosqes = 7;
+ else
+ ctrl->iosqes = id->sqes & 0xf;
if (ctrl->iosqes < NVME_NVM_IOSQES) {
dev_err(ctrl->device,
"unsupported required IO queue size %d\n", ctrl->iosqes);
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 34ef35fcd8a5..b2a78d08b984 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -92,6 +92,16 @@ enum nvme_quirks {
* Broken Write Zeroes.
*/
NVME_QUIRK_DISABLE_WRITE_ZEROES = (1 << 9),
+
+ /*
+ * Use only one interrupt vector for all queues
+ */
+ NVME_QUIRK_SINGLE_VECTOR = (1 << 10),
+
+ /*
+ * Use non-standard 128 bytes SQEs.
+ */
+ NVME_QUIRK_128_BYTES_SQES = (1 << 11),
};

/*
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 54b35ea4af88..ab2358137419 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -2080,6 +2080,9 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
dev->io_queues[HCTX_TYPE_DEFAULT] = 1;
dev->io_queues[HCTX_TYPE_READ] = 0;

+ if (dev->ctrl.quirks & NVME_QUIRK_SINGLE_VECTOR)
+ irq_queues = 1;
+
return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues,
PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd);
}
@@ -3037,6 +3040,9 @@ static const struct pci_device_id nvme_id_table[] = {
{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) },
{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) },
+ { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2005),
+ .driver_data = NVME_QUIRK_SINGLE_VECTOR |
+ NVME_QUIRK_128_BYTES_SQES },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, nvme_id_table);
--
2.17.1

2019-07-16 00:49:47

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: [PATCH 2/3] nvme: Retrieve the required IO queue entry size from the controller

On PCIe based NVME devices, this will retrieve the IO queue entry
size from the controller and use the "required" setting.

It should always be 6 (64 bytes) by spec. However some controllers
such as Apple's are not properly implementing the spec and require
the size to be 7 (128 bytes).

This provides the ground work for the subsequent quirks for these
controllers.

Signed-off-by: Benjamin Herrenschmidt <[email protected]>
---
drivers/nvme/host/core.c | 25 +++++++++++++++++++++++++
drivers/nvme/host/nvme.h | 1 +
drivers/nvme/host/pci.c | 9 ++++++---
include/linux/nvme.h | 1 +
4 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index cc09b81fc7f4..716ebe87a2b8 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1986,6 +1986,7 @@ int nvme_enable_ctrl(struct nvme_ctrl *ctrl, u64 cap)
ctrl->ctrl_config = NVME_CC_CSS_NVM;
ctrl->ctrl_config |= (page_shift - 12) << NVME_CC_MPS_SHIFT;
ctrl->ctrl_config |= NVME_CC_AMS_RR | NVME_CC_SHN_NONE;
+ /* Use default IOSQES. We'll update it later if needed */
ctrl->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
ctrl->ctrl_config |= NVME_CC_ENABLE;

@@ -2698,6 +2699,30 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
ctrl->hmmin = le32_to_cpu(id->hmmin);
ctrl->hmminds = le32_to_cpu(id->hmminds);
ctrl->hmmaxd = le16_to_cpu(id->hmmaxd);
+
+ /* Grab required IO queue size */
+ ctrl->iosqes = id->sqes & 0xf;
+ if (ctrl->iosqes < NVME_NVM_IOSQES) {
+ dev_err(ctrl->device,
+ "unsupported required IO queue size %d\n", ctrl->iosqes);
+ ret = -EINVAL;
+ goto out_free;
+ }
+ /*
+ * If our IO queue size isn't the default, update the setting
+ * in CC:IOSQES.
+ */
+ if (ctrl->iosqes != NVME_NVM_IOSQES) {
+ ctrl->ctrl_config &= ~(0xfu << NVME_CC_IOSQES_SHIFT);
+ ctrl->ctrl_config |= ctrl->iosqes << NVME_CC_IOSQES_SHIFT;
+ ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC,
+ ctrl->ctrl_config);
+ if (ret) {
+ dev_err(ctrl->device,
+ "error updating CC register\n");
+ goto out_free;
+ }
+ }
}

ret = nvme_mpath_init(ctrl, id);
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 716a876119c8..34ef35fcd8a5 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -244,6 +244,7 @@ struct nvme_ctrl {
u32 hmmin;
u32 hmminds;
u16 hmmaxd;
+ u8 iosqes;

/* Fabrics only */
u16 sqsize;
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 8f006638452b..54b35ea4af88 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -28,7 +28,7 @@
#include "trace.h"
#include "nvme.h"

-#define SQ_SIZE(q) ((q)->q_depth * sizeof(struct nvme_command))
+#define SQ_SIZE(q) ((q)->q_depth << (q)->sqes)
#define CQ_SIZE(q) ((q)->q_depth * sizeof(struct nvme_completion))

#define SGES_PER_PAGE (PAGE_SIZE / sizeof(struct nvme_sgl_desc))
@@ -162,7 +162,7 @@ static inline struct nvme_dev *to_nvme_dev(struct nvme_ctrl *ctrl)
struct nvme_queue {
struct nvme_dev *dev;
spinlock_t sq_lock;
- struct nvme_command *sq_cmds;
+ void *sq_cmds;
/* only used for poll queues: */
spinlock_t cq_poll_lock ____cacheline_aligned_in_smp;
volatile struct nvme_completion *cqes;
@@ -178,6 +178,7 @@ struct nvme_queue {
u16 last_cq_head;
u16 qid;
u8 cq_phase;
+ u8 sqes;
unsigned long flags;
#define NVMEQ_ENABLED 0
#define NVMEQ_SQ_CMB 1
@@ -488,7 +489,8 @@ static void nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd,
bool write_sq)
{
spin_lock(&nvmeq->sq_lock);
- memcpy(&nvmeq->sq_cmds[nvmeq->sq_tail], cmd, sizeof(*cmd));
+ memcpy(nvmeq->sq_cmds + (nvmeq->sq_tail << nvmeq->sqes),
+ cmd, sizeof(*cmd));
if (++nvmeq->sq_tail == nvmeq->q_depth)
nvmeq->sq_tail = 0;
nvme_write_sq_db(nvmeq, write_sq);
@@ -1465,6 +1467,7 @@ static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth)
if (dev->ctrl.queue_count > qid)
return 0;

+ nvmeq->sqes = qid ? dev->ctrl.iosqes : NVME_NVM_ADMSQES;
nvmeq->q_depth = depth;
nvmeq->cqes = dma_alloc_coherent(dev->dev, CQ_SIZE(nvmeq),
&nvmeq->cq_dma_addr, GFP_KERNEL);
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 01aa6a6c241d..7af18965fb57 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -141,6 +141,7 @@ enum {
* (In bytes and specified as a power of two (2^n)).
*/
#define NVME_NVM_IOSQES 6
+#define NVME_NVM_ADMSQES 6
#define NVME_NVM_IOCQES 4

enum {
--
2.17.1

2019-07-16 00:50:28

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: [PATCH 1/3] nvme: Pass the queue to SQ_SIZE/CQ_SIZE macros

On Tue, 2019-07-16 at 10:46 +1000, Benjamin Herrenschmidt wrote:
> # Conflicts:
> # drivers/nvme/host/pci.c
> ---

Oops :-) You can strip that or should I resend ? I'll wait for
comments/reviews regardless.

Cheers,
Ben.

2019-07-16 05:59:54

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 1/3] nvme: Pass the queue to SQ_SIZE/CQ_SIZE macros

On Tue, Jul 16, 2019 at 10:46:47AM +1000, Benjamin Herrenschmidt wrote:
> This will make it easier to handle variable queue entry sizes
> later. No functional change.

Looks good to me:

Reviewed-by: Christoph Hellwig <[email protected]>

2019-07-16 06:05:49

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 2/3] nvme: Retrieve the required IO queue entry size from the controller

> + /* Use default IOSQES. We'll update it later if needed */
> ctrl->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
> ctrl->ctrl_config |= NVME_CC_ENABLE;
>
> @@ -2698,6 +2699,30 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
> ctrl->hmmin = le32_to_cpu(id->hmmin);
> ctrl->hmminds = le32_to_cpu(id->hmminds);
> ctrl->hmmaxd = le16_to_cpu(id->hmmaxd);
> +
> + /* Grab required IO queue size */
> + ctrl->iosqes = id->sqes & 0xf;
> + if (ctrl->iosqes < NVME_NVM_IOSQES) {
> + dev_err(ctrl->device,
> + "unsupported required IO queue size %d\n", ctrl->iosqes);
> + ret = -EINVAL;
> + goto out_free;
> + }
> + /*
> + * If our IO queue size isn't the default, update the setting
> + * in CC:IOSQES.
> + */
> + if (ctrl->iosqes != NVME_NVM_IOSQES) {
> + ctrl->ctrl_config &= ~(0xfu << NVME_CC_IOSQES_SHIFT);
> + ctrl->ctrl_config |= ctrl->iosqes << NVME_CC_IOSQES_SHIFT;
> + ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC,
> + ctrl->ctrl_config);
> + if (ret) {
> + dev_err(ctrl->device,
> + "error updating CC register\n");
> + goto out_free;
> + }
> + }

Actually, this doesn't work on a "real" nvme controller, to change CC
values the controller needs to be disabled. So back to the version
you circulated to me in private mail that just sets q->sqes and has a
comment that this is magic for The Apple controller. If/when we get
standardized large SQE support we'll need to discover that earlier or
do a disable/enable dance. Sorry for misleading you down this road and
creating the extra work.

2019-07-16 06:07:41

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 3/3] nvme: Add support for Apple 2018+ models

On Tue, Jul 16, 2019 at 10:46:49AM +1000, Benjamin Herrenschmidt wrote:
> Based on reverse engineering and original patch by
>
> Paul Pawlowski <[email protected]>
>
> This adds support for Apple weird implementation of NVME in their
> 2018 or later machines. It accounts for the twice-as-big SQ entries
> for the IO queues, and the fact that only interrupt vector 0 appears
> to function properly.
>
> Signed-off-by: Benjamin Herrenschmidt <[email protected]>
> ---
> drivers/nvme/host/core.c | 5 ++++-
> drivers/nvme/host/nvme.h | 10 ++++++++++
> drivers/nvme/host/pci.c | 6 ++++++
> 3 files changed, 20 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
> index 716ebe87a2b8..480ea24d8cf4 100644
> --- a/drivers/nvme/host/core.c
> +++ b/drivers/nvme/host/core.c
> @@ -2701,7 +2701,10 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
> ctrl->hmmaxd = le16_to_cpu(id->hmmaxd);
>
> /* Grab required IO queue size */
> - ctrl->iosqes = id->sqes & 0xf;
> + if (ctrl->quirks & NVME_QUIRK_128_BYTES_SQES)
> + ctrl->iosqes = 7;
> + else
> + ctrl->iosqes = id->sqes & 0xf;
> if (ctrl->iosqes < NVME_NVM_IOSQES) {
> dev_err(ctrl->device,
> "unsupported required IO queue size %d\n", ctrl->iosqes);
> diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
> index 34ef35fcd8a5..b2a78d08b984 100644
> --- a/drivers/nvme/host/nvme.h
> +++ b/drivers/nvme/host/nvme.h
> @@ -92,6 +92,16 @@ enum nvme_quirks {
> * Broken Write Zeroes.
> */
> NVME_QUIRK_DISABLE_WRITE_ZEROES = (1 << 9),
> +
> + /*
> + * Use only one interrupt vector for all queues
> + */
> + NVME_QUIRK_SINGLE_VECTOR = (1 << 10),
> +
> + /*
> + * Use non-standard 128 bytes SQEs.
> + */
> + NVME_QUIRK_128_BYTES_SQES = (1 << 11),
> };
>
> /*
> diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
> index 54b35ea4af88..ab2358137419 100644
> --- a/drivers/nvme/host/pci.c
> +++ b/drivers/nvme/host/pci.c
> @@ -2080,6 +2080,9 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
> dev->io_queues[HCTX_TYPE_DEFAULT] = 1;
> dev->io_queues[HCTX_TYPE_READ] = 0;
>
> + if (dev->ctrl.quirks & NVME_QUIRK_SINGLE_VECTOR)
> + irq_queues = 1;
> +
> return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues,
> PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd);

Callin pci_alloc_irq_vectors_affinity in this case seems a bit
pointless, but if this works for you I'd rather keep it as-is for now
if this works for you.

2019-07-16 06:22:09

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: [PATCH 2/3] nvme: Retrieve the required IO queue entry size from the controller

On Tue, 2019-07-16 at 08:04 +0200, Christoph Hellwig wrote:
> >
> > + /*
> > + * If our IO queue size isn't the default, update the setting
> > + * in CC:IOSQES.
> > + */
> > + if (ctrl->iosqes != NVME_NVM_IOSQES) {
> > + ctrl->ctrl_config &= ~(0xfu << NVME_CC_IOSQES_SHIFT);
> > + ctrl->ctrl_config |= ctrl->iosqes << NVME_CC_IOSQES_SHIFT;
> > + ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC,
> > + ctrl->ctrl_config);
> > + if (ret) {
> > + dev_err(ctrl->device,
> > + "error updating CC register\n");
> > + goto out_free;
> > + }
> > + }
>
> Actually, this doesn't work on a "real" nvme controller, to change CC
> values the controller needs to be disabled.

Not really. The specs says that MPS, AMD and CSS need to be set before
enabling, but IOCQES and IOSQES can be modified later as long as there
is no IO queue created yet.

This is necessary otherwise there's a chicken and egg problem. You need
the admin queue to do the controller id in order to get the sizes and
for that you need the controller to be enabled.

Note: This is not a huge issue anyway since I only update the register
if the required size isn't 6 which is probably never going to be the
case on non-Apple HW.

> So back to the version
> you circulated to me in private mail that just sets q->sqes and has a
> comment that this is magic for The Apple controller. If/when we get
> standardized large SQE support we'll need to discover that earlier or
> do a disable/enable dance. Sorry for misleading you down this road and
> creating the extra work.

I think it's still ok, let me know...

Ben.

2019-07-16 06:24:39

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: [PATCH 3/3] nvme: Add support for Apple 2018+ models

On Tue, 2019-07-16 at 08:06 +0200, Christoph Hellwig wrote:
>
> > /*
> > diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
> > index 54b35ea4af88..ab2358137419 100644
> > --- a/drivers/nvme/host/pci.c
> > +++ b/drivers/nvme/host/pci.c
> > @@ -2080,6 +2080,9 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
> > dev->io_queues[HCTX_TYPE_DEFAULT] = 1;
> > dev->io_queues[HCTX_TYPE_READ] = 0;
> >
> > + if (dev->ctrl.quirks & NVME_QUIRK_SINGLE_VECTOR)
> > + irq_queues = 1;
> > +
> > return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues,
> > PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd);
>
> Callin pci_alloc_irq_vectors_affinity in this case seems a bit
> pointless, but if this works for you I'd rather keep it as-is for now
> if this works for you.

It seems to work and it's simpler that way. The original patch was
grabbing all the interrupts then hacking the queues to all use vector 0
(well there's only one IO queue). The above is a bit cleaner imho.

Cheers,
Ben.


2019-07-16 09:33:56

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 2/3] nvme: Retrieve the required IO queue entry size from the controller

On Tue, Jul 16, 2019 at 04:21:14PM +1000, Benjamin Herrenschmidt wrote:
> > Actually, this doesn't work on a "real" nvme controller, to change CC
> > values the controller needs to be disabled.
>
> Not really. The specs says that MPS, AMD and CSS need to be set before
> enabling, but IOCQES and IOSQES can be modified later as long as there
> is no IO queue created yet.

I guess that is true based on the spec.

> This is necessary otherwise there's a chicken and egg problem. You need
> the admin queue to do the controller id in order to get the sizes and
> for that you need the controller to be enabled.
>
> Note: This is not a huge issue anyway since I only update the register
> if the required size isn't 6 which is probably never going to be the
> case on non-Apple HW.

Yes, but the whole point of making you go down the route is so that
we can share the code with eventual real nvme controllers that can
support a larger SQE size.

> > So back to the version
> > you circulated to me in private mail that just sets q->sqes and has a
> > comment that this is magic for The Apple controller. If/when we get
> > standardized large SQE support we'll need to discover that earlier or
> > do a disable/enable dance. Sorry for misleading you down this road and
> > creating the extra work.
>
> I think it's still ok, let me know...

Ok, let's go with this series then unless the other maintainers have
objections.

I'm still not sure if we want to queue this up for 5.3 (new hardware
enablement) or wait a bit, though.

2019-07-16 10:59:57

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: [PATCH 2/3] nvme: Retrieve the required IO queue entry size from the controller

On Tue, 2019-07-16 at 11:33 +0200, Christoph Hellwig wrote:
> > > So back to the version
> > > you circulated to me in private mail that just sets q->sqes and has a
> > > comment that this is magic for The Apple controller. If/when we get
> > > standardized large SQE support we'll need to discover that earlier or
> > > do a disable/enable dance. Sorry for misleading you down this road and
> > > creating the extra work.
> >
> > I think it's still ok, let me know...
>
> Ok, let's go with this series then unless the other maintainers have
> objections.
>
> I'm still not sure if we want to queue this up for 5.3 (new hardware
> enablement) or wait a bit, though.

The main risk is if existing controllers return crap in SQES and we try
to then use that crap. The rest should essentially be NOPs.

Maybe I should add some kind of printk to warn in case we use/detect a
non-standard size. That would help diagnosing issues.

Cheers,
Ben.


2019-07-16 12:06:59

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 2/3] nvme: Retrieve the required IO queue entry size from the controller

On Tue, Jul 16, 2019 at 08:58:28PM +1000, Benjamin Herrenschmidt wrote:
> The main risk is if existing controllers return crap in SQES and we try
> to then use that crap. The rest should essentially be NOPs.
>
> Maybe I should add some kind of printk to warn in case we use/detect a
> non-standard size. That would help diagnosing issues.

Given that the spec currently requires bits 0 to 3 of SQES to be 6
we might as well not check SQES and just hardcode it to 6 or 7 depending
on the quirk. That actually was my initial idea, I just suggested using
the SQES naming and indexing.

2019-07-16 12:19:39

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: [PATCH 2/3] nvme: Retrieve the required IO queue entry size from the controller

On Tue, 2019-07-16 at 14:05 +0200, Christoph Hellwig wrote:
> On Tue, Jul 16, 2019 at 08:58:28PM +1000, Benjamin Herrenschmidt wrote:
> > The main risk is if existing controllers return crap in SQES and we try
> > to then use that crap. The rest should essentially be NOPs.
> >
> > Maybe I should add some kind of printk to warn in case we use/detect a
> > non-standard size. That would help diagnosing issues.
>
> Given that the spec currently requires bits 0 to 3 of SQES to be 6
> we might as well not check SQES and just hardcode it to 6 or 7 depending
> on the quirk. That actually was my initial idea, I just suggested using
> the SQES naming and indexing.

If we're going to do that, then I can move it back to pci.c and leave
core.c alone then I suppose. Up to you. I'm just doing that for fun, no
beef in that game :-) let me know how you want it.

Cheers,
Ben.


2019-07-16 12:26:11

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 2/3] nvme: Retrieve the required IO queue entry size from the controller

On Tue, Jul 16, 2019 at 10:17:56PM +1000, Benjamin Herrenschmidt wrote:
> If we're going to do that, then I can move it back to pci.c and leave
> core.c alone then I suppose. Up to you. I'm just doing that for fun, no
> beef in that game :-) let me know how you want it.

Sounds safest to me.