Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a8e3e0bb authored by Jianchao Wang's avatar Jianchao Wang Committed by Christoph Hellwig
Browse files

nvme-pci: set nvmeq->cq_vector after alloc cq/sq



Set cq_vector after alloc cq/sq, otherwise nvme_suspend_queue will invoke
free_irq for it and cause a 'Trying to free already-free IRQ  xxx'
warning if the create CQ/SQ command times out.

Signed-off-by: default avatarJianchao Wang <jianchao.w.wang@oracle.com>
Reviewed-by: default avatarKeith Busch <keith.busch@intel.com>
[hch: fixed to pass a s16 and clean up the comment]
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent e9a9853c
Loading
Loading
Loading
Loading
+16 −9
Original line number Diff line number Diff line
@@ -1076,7 +1076,7 @@ static int adapter_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id)
}

static int adapter_alloc_cq(struct nvme_dev *dev, u16 qid,
						struct nvme_queue *nvmeq)
		struct nvme_queue *nvmeq, s16 vector)
{
	struct nvme_command c;
	int flags = NVME_QUEUE_PHYS_CONTIG | NVME_CQ_IRQ_ENABLED;
@@ -1091,7 +1091,7 @@ static int adapter_alloc_cq(struct nvme_dev *dev, u16 qid,
	c.create_cq.cqid = cpu_to_le16(qid);
	c.create_cq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
	c.create_cq.cq_flags = cpu_to_le16(flags);
	c.create_cq.irq_vector = cpu_to_le16(nvmeq->cq_vector);
	c.create_cq.irq_vector = cpu_to_le16(vector);

	return nvme_submit_sync_cmd(dev->ctrl.admin_q, &c, NULL, 0);
}
@@ -1466,6 +1466,7 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)
{
	struct nvme_dev *dev = nvmeq->dev;
	int result;
	s16 vector;

	if (dev->cmb && use_cmb_sqes && (dev->cmbsz & NVME_CMBSZ_SQS)) {
		unsigned offset = (qid - 1) * roundup(SQ_SIZE(nvmeq->q_depth),
@@ -1478,15 +1479,21 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)
	 * A queue's vector matches the queue identifier unless the controller
	 * has only one vector available.
	 */
	nvmeq->cq_vector = dev->num_vecs == 1 ? 0 : qid;
	result = adapter_alloc_cq(dev, qid, nvmeq);
	vector = dev->num_vecs == 1 ? 0 : qid;
	result = adapter_alloc_cq(dev, qid, nvmeq, vector);
	if (result < 0)
		goto release_vector;
		goto out;

	result = adapter_alloc_sq(dev, qid, nvmeq);
	if (result < 0)
		goto release_cq;

	/*
	 * Set cq_vector after alloc cq/sq, otherwise nvme_suspend_queue will
	 * invoke free_irq for it and cause a 'Trying to free already-free IRQ
	 * xxx' warning if the create CQ/SQ command times out.
	 */
	nvmeq->cq_vector = vector;
	nvme_init_queue(nvmeq, qid);
	result = queue_request_irq(nvmeq);
	if (result < 0)
@@ -1495,12 +1502,12 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)
	return result;

release_sq:
	nvmeq->cq_vector = -1;
	dev->online_queues--;
	adapter_delete_sq(dev, qid);
release_cq:
	adapter_delete_cq(dev, qid);
 release_vector:
	nvmeq->cq_vector = -1;
out:
	return result;
}