Re: [PATCH V2 6/6] nvme-pci: remove .init_request callback

2017-12-24 Thread Sagi Grimberg



Please prepare a formal one(at least tested in normal case), either I
or Zhang Yi may test/verify it.


OK.


@@ -1387,10 +1385,7 @@ static int nvme_alloc_sq_cmds(struct nvme_dev *dev,
struct nvme_queue *nvmeq,
  static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
 int depth, int node)
  {
-   struct nvme_queue *nvmeq = kzalloc_node(sizeof(*nvmeq), GFP_KERNEL,
-   node);
-   if (!nvmeq)
-   return NULL;
+   struct nvme_queue *nvmeq = >queues[qid];


Maybe you need to zero *nvmeq again since it is done in current code.


Relying on this is not a good idea, so I think we better off without
it because I want to know about it and fix it.


@@ -2470,8 +2465,9 @@ static int nvme_probe(struct pci_dev *pdev, const
struct pci_device_id *id)
 dev = kzalloc_node(sizeof(*dev), GFP_KERNEL, node);
 if (!dev)
 return -ENOMEM;
-   dev->queues = kzalloc_node((num_possible_cpus() + 1) * sizeof(void
*),
-   GFP_KERNEL, node);
+
+   alloc_size = (num_possible_cpus() + 1) * sizeof(struct nvme_queue
*);


The element size should be 'sizeof(struct nvme_queue)'.


Right.


Re: [PATCH V2 6/6] nvme-pci: remove .init_request callback

2017-12-21 Thread Ming Lei
Hi Sagi,

On Thu, Dec 21, 2017 at 10:20:45AM +0200, Sagi Grimberg wrote:
> Ming,
> 
> I'd prefer that we make the pci driver match
> the rest of the drivers in nvme.

OK, this way looks better.

> 
> IMO it would be better to allocate a queues array at probe time
> and simply reuse it at reset sequence.
> 
> Can this (untested) patch also fix the issue your seeing:

Please prepare a formal one(at least tested in normal case), either I
or Zhang Yi may test/verify it.

> --
> diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
> index f26aaa393016..a8edb29dac16 100644
> --- a/drivers/nvme/host/pci.c
> +++ b/drivers/nvme/host/pci.c
> @@ -75,7 +75,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool
> shutdown);
>   * Represents an NVM Express device.  Each nvme_dev is a PCI function.
>   */
>  struct nvme_dev {
> -   struct nvme_queue **queues;
> +   struct nvme_queue *queues;
> struct blk_mq_tag_set tagset;
> struct blk_mq_tag_set admin_tagset;
> u32 __iomem *dbs;
> @@ -365,7 +365,7 @@ static int nvme_admin_init_hctx(struct blk_mq_hw_ctx
> *hctx, void *data,
> unsigned int hctx_idx)
>  {
> struct nvme_dev *dev = data;
> -   struct nvme_queue *nvmeq = dev->queues[0];
> +   struct nvme_queue *nvmeq = >queues[0];
> 
> WARN_ON(hctx_idx != 0);
> WARN_ON(dev->admin_tagset.tags[0] != hctx->tags);
> @@ -387,7 +387,7 @@ static int nvme_init_hctx(struct blk_mq_hw_ctx *hctx,
> void *data,
>   unsigned int hctx_idx)
>  {
> struct nvme_dev *dev = data;
> -   struct nvme_queue *nvmeq = dev->queues[hctx_idx + 1];
> +   struct nvme_queue *nvmeq = >queues[hctx_idx + 1];
> 
> if (!nvmeq->tags)
> nvmeq->tags = >tagset.tags[hctx_idx];
> @@ -403,7 +403,7 @@ static int nvme_init_request(struct blk_mq_tag_set *set,
> struct request *req,
> struct nvme_dev *dev = set->driver_data;
> struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
> int queue_idx = (set == >tagset) ? hctx_idx + 1 : 0;
> -   struct nvme_queue *nvmeq = dev->queues[queue_idx];
> +   struct nvme_queue *nvmeq = >queues[queue_idx];
> 
> BUG_ON(!nvmeq);
> iod->nvmeq = nvmeq;
> @@ -1046,7 +1046,7 @@ static int nvme_poll(struct blk_mq_hw_ctx *hctx,
> unsigned int tag)
>  static void nvme_pci_submit_async_event(struct nvme_ctrl *ctrl)
>  {
> struct nvme_dev *dev = to_nvme_dev(ctrl);
> -   struct nvme_queue *nvmeq = dev->queues[0];
> +   struct nvme_queue *nvmeq = >queues[0];
> struct nvme_command c;
> 
> memset(, 0, sizeof(c));
> @@ -1290,10 +1290,8 @@ static void nvme_free_queues(struct nvme_dev *dev,
> int lowest)
> int i;
> 
> for (i = dev->ctrl.queue_count - 1; i >= lowest; i--) {
> -   struct nvme_queue *nvmeq = dev->queues[i];
> dev->ctrl.queue_count--;
> -   dev->queues[i] = NULL;
> -   nvme_free_queue(nvmeq);
> +   nvme_free_queue(>queues[i]);
> }
>  }
> 
> @@ -1325,7 +1323,7 @@ static int nvme_suspend_queue(struct nvme_queue
> *nvmeq)
> 
>  static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown)
>  {
> -   struct nvme_queue *nvmeq = dev->queues[0];
> +   struct nvme_queue *nvmeq = >queues[0];
> 
> if (!nvmeq)
> return;
> @@ -1387,10 +1385,7 @@ static int nvme_alloc_sq_cmds(struct nvme_dev *dev,
> struct nvme_queue *nvmeq,
>  static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
> int depth, int node)
>  {
> -   struct nvme_queue *nvmeq = kzalloc_node(sizeof(*nvmeq), GFP_KERNEL,
> -   node);
> -   if (!nvmeq)
> -   return NULL;
> +   struct nvme_queue *nvmeq = >queues[qid];

Maybe you need to zero *nvmeq again since it is done in current code.

> 
> nvmeq->cqes = dma_zalloc_coherent(dev->dev, CQ_SIZE(depth),
>   >cq_dma_addr, GFP_KERNEL);
> @@ -1409,7 +1404,6 @@ static struct nvme_queue *nvme_alloc_queue(struct
> nvme_dev *dev, int qid,
> nvmeq->q_depth = depth;
> nvmeq->qid = qid;
> nvmeq->cq_vector = -1;
> -   dev->queues[qid] = nvmeq;
> dev->ctrl.queue_count++;
> 
> return nvmeq;
> @@ -1592,7 +1586,7 @@ static int nvme_pci_configure_admin_queue(struct
> nvme_dev *dev)
> if (result < 0)
> return result;
> 
> -   nvmeq = dev->queues[0];
> +   nvmeq = >queues[0];
> if (!nvmeq) {
> nvmeq = nvme_alloc_queue(dev, 0, NVME_AQ_DEPTH,
> dev_to_node(dev->dev));
> @@ -1638,7 +1632,7 @@ static int nvme_create_io_queues(struct nvme_dev *dev)
> 
> max = min(dev->max_qid, dev->ctrl.queue_count - 1);
> for (i = dev->online_queues; i <= max; 

Re: [PATCH V2 6/6] nvme-pci: remove .init_request callback

2017-12-21 Thread Johannes Thumshirn
On Thu, Dec 21, 2017 at 10:20:45AM +0200, Sagi Grimberg wrote:
> @@ -2470,8 +2465,9 @@ static int nvme_probe(struct pci_dev *pdev, const
> struct pci_device_id *id)
> dev = kzalloc_node(sizeof(*dev), GFP_KERNEL, node);
> if (!dev)
> return -ENOMEM;
> -   dev->queues = kzalloc_node((num_possible_cpus() + 1) * sizeof(void
> *),
> -   GFP_KERNEL, node);
> +
> +   alloc_size = (num_possible_cpus() + 1) * sizeof(struct nvme_queue
> *);
> +   dev->queues = kzalloc_node(alloc_size, GFP_KERNEL, node);

Nit:
  dev->queues = kcalloc_node(num_possible_cpus() + 1,
 sizeof(struct nvme_queue *),
 node);
-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850


Re: [PATCH V2 6/6] nvme-pci: remove .init_request callback

2017-12-21 Thread Sagi Grimberg

Ming,

I'd prefer that we make the pci driver match
the rest of the drivers in nvme.

IMO it would be better to allocate a queues array at probe time
and simply reuse it at reset sequence.

Can this (untested) patch also fix the issue your seeing:
--
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index f26aaa393016..a8edb29dac16 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -75,7 +75,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, 
bool shutdown);

  * Represents an NVM Express device.  Each nvme_dev is a PCI function.
  */
 struct nvme_dev {
-   struct nvme_queue **queues;
+   struct nvme_queue *queues;
struct blk_mq_tag_set tagset;
struct blk_mq_tag_set admin_tagset;
u32 __iomem *dbs;
@@ -365,7 +365,7 @@ static int nvme_admin_init_hctx(struct blk_mq_hw_ctx 
*hctx, void *data,

unsigned int hctx_idx)
 {
struct nvme_dev *dev = data;
-   struct nvme_queue *nvmeq = dev->queues[0];
+   struct nvme_queue *nvmeq = >queues[0];

WARN_ON(hctx_idx != 0);
WARN_ON(dev->admin_tagset.tags[0] != hctx->tags);
@@ -387,7 +387,7 @@ static int nvme_init_hctx(struct blk_mq_hw_ctx 
*hctx, void *data,

  unsigned int hctx_idx)
 {
struct nvme_dev *dev = data;
-   struct nvme_queue *nvmeq = dev->queues[hctx_idx + 1];
+   struct nvme_queue *nvmeq = >queues[hctx_idx + 1];

if (!nvmeq->tags)
nvmeq->tags = >tagset.tags[hctx_idx];
@@ -403,7 +403,7 @@ static int nvme_init_request(struct blk_mq_tag_set 
*set, struct request *req,

struct nvme_dev *dev = set->driver_data;
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
int queue_idx = (set == >tagset) ? hctx_idx + 1 : 0;
-   struct nvme_queue *nvmeq = dev->queues[queue_idx];
+   struct nvme_queue *nvmeq = >queues[queue_idx];

BUG_ON(!nvmeq);
iod->nvmeq = nvmeq;
@@ -1046,7 +1046,7 @@ static int nvme_poll(struct blk_mq_hw_ctx *hctx, 
unsigned int tag)

 static void nvme_pci_submit_async_event(struct nvme_ctrl *ctrl)
 {
struct nvme_dev *dev = to_nvme_dev(ctrl);
-   struct nvme_queue *nvmeq = dev->queues[0];
+   struct nvme_queue *nvmeq = >queues[0];
struct nvme_command c;

memset(, 0, sizeof(c));
@@ -1290,10 +1290,8 @@ static void nvme_free_queues(struct nvme_dev 
*dev, int lowest)

int i;

for (i = dev->ctrl.queue_count - 1; i >= lowest; i--) {
-   struct nvme_queue *nvmeq = dev->queues[i];
dev->ctrl.queue_count--;
-   dev->queues[i] = NULL;
-   nvme_free_queue(nvmeq);
+   nvme_free_queue(>queues[i]);
}
 }

@@ -1325,7 +1323,7 @@ static int nvme_suspend_queue(struct nvme_queue 
*nvmeq)


 static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown)
 {
-   struct nvme_queue *nvmeq = dev->queues[0];
+   struct nvme_queue *nvmeq = >queues[0];

if (!nvmeq)
return;
@@ -1387,10 +1385,7 @@ static int nvme_alloc_sq_cmds(struct nvme_dev 
*dev, struct nvme_queue *nvmeq,

 static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
int depth, int 
node)

 {
-   struct nvme_queue *nvmeq = kzalloc_node(sizeof(*nvmeq), GFP_KERNEL,
-   node);
-   if (!nvmeq)
-   return NULL;
+   struct nvme_queue *nvmeq = >queues[qid];

nvmeq->cqes = dma_zalloc_coherent(dev->dev, CQ_SIZE(depth),
  >cq_dma_addr, GFP_KERNEL);
@@ -1409,7 +1404,6 @@ static struct nvme_queue *nvme_alloc_queue(struct 
nvme_dev *dev, int qid,

nvmeq->q_depth = depth;
nvmeq->qid = qid;
nvmeq->cq_vector = -1;
-   dev->queues[qid] = nvmeq;
dev->ctrl.queue_count++;

return nvmeq;
@@ -1592,7 +1586,7 @@ static int nvme_pci_configure_admin_queue(struct 
nvme_dev *dev)

if (result < 0)
return result;

-   nvmeq = dev->queues[0];
+   nvmeq = >queues[0];
if (!nvmeq) {
nvmeq = nvme_alloc_queue(dev, 0, NVME_AQ_DEPTH,
dev_to_node(dev->dev));
@@ -1638,7 +1632,7 @@ static int nvme_create_io_queues(struct nvme_dev *dev)

max = min(dev->max_qid, dev->ctrl.queue_count - 1);
for (i = dev->online_queues; i <= max; i++) {
-   ret = nvme_create_queue(dev->queues[i], i);
+   ret = nvme_create_queue(>queues[i], i);
if (ret)
break;
}
@@ -1894,7 +1888,7 @@ static int nvme_setup_host_mem(struct nvme_dev *dev)

 static int nvme_setup_io_queues(struct nvme_dev *dev)
 {
-   struct nvme_queue *adminq = dev->queues[0];
+   struct nvme_queue *adminq = >queues[0];
struct pci_dev *pdev = to_pci_dev(dev->dev);
int result,