nvme-pci: Remap CMB SQ entries on every controller reset
Subsystems (2)
PATCH 1/1 nvme-pci: Remap CMB SQ entries on every controller reset
Commit 815c6704bf9f1c59f3a6be380a4032b9c57b12f1 upstream.
The controller memory buffer is remapped into a kernel address on each reset, but the driver was setting the submission queue base address only on the very first queue creation. The remapped address is likely to change after a reset, so accessing the old address will hit a kernel bug.
This patch fixes that by setting the queue's CMB base address each time the queue is created.
--- drivers/nvme/host/pci.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-)
drivers/nvme/host/pci.c +16 -11
@@ -1233,17 +1233,15 @@ 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) { -if (qid && dev->cmb && use_cmb_sqes &&NVME_CMB_SQS (dev->cmbsz)) { -unsigned offset = (qid -1 ) *roundup (SQ_SIZE (depth), - dev->ctrl.page_size); - nvmeq->sq_dma_addr = dev->cmb_bus_addr + offset; - nvmeq->sq_cmds_io = dev->cmb + offset; - }else { - nvmeq->sq_cmds =dma_alloc_coherent (dev->dev,SQ_SIZE (depth), - &nvmeq->sq_dma_addr,GFP_KERNEL ); -if (!nvmeq->sq_cmds) -return -ENOMEM ; - } + +/* CMB SQEs will be mapped before creation */ +if (qid && dev->cmb && use_cmb_sqes &&NVME_CMB_SQS (dev->cmbsz)) +return 0 ; + + nvmeq->sq_cmds =dma_alloc_coherent (dev->dev,SQ_SIZE (depth), + &nvmeq->sq_dma_addr,GFP_KERNEL ); +if (!nvmeq->sq_cmds) +return -ENOMEM ;return 0 ; }
@@ -1320,6 +1318,13 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)struct nvme_dev *dev = nvmeq->dev;int result; +if (qid && dev->cmb && use_cmb_sqes &&NVME_CMB_SQS (dev->cmbsz)) { +unsigned offset = (qid -1 ) *roundup (SQ_SIZE (nvmeq->q_depth), + dev->ctrl.page_size); + nvmeq->sq_dma_addr = dev->cmb_bus_addr + offset; + nvmeq->sq_cmds_io = dev->cmb + offset; + } + nvmeq->cq_vector = qid -1 ; result =adapter_alloc_cq (dev, qid, nvmeq);if (result <0 )
Signature · 1 line
2.17.1
Thank you, Scott
Quoted 84 lines · Scott Bauer
Commit
815c6704bf9f1c59f3a6be380a4032b9c57b12f1upstream.The controller memory buffer is remapped into a kernel address on each
reset, but the driver was setting the submission queue base address only on the very first queue creation. The remapped address is likely to
change after a reset, so accessing the old address will hit a kernel bug.This patch fixes that by setting the queue's CMB base address each time
the queue is created.Fixes f63572dff1421 ("nvme: unmap CMB and remove sysfs file in resetpath")
Reported-by Christian Black <[email protected]>Cc Jon Derrick <[email protected]>Signed-off-by Keith Busch <[email protected]>Reviewed-by Christoph Hellwig <[email protected]>Signed-off-by Scott Bauer <[email protected]>--- drivers/nvme/host/pci.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-)drivers/nvme/host/pci.c +0
-8@@ -1233,17 +1233,15 @@ static int nvme_cmb_qdepth(struct nvme_dev *dev, int nr_io_queues, static int nvme_alloc_sq_cmds(struct nvme_dev *dev, structnvme_queue *nvmeq,int qid,int depth) { -if (qid && dev->cmb && use_cmb_sqes &&NVME_CMB_SQS (dev- >cmbsz)) { -unsigned offset = (qid -1 ) * roundup(SQ_SIZE(depth), - dev- >ctrl.page_size); - nvmeq->sq_dma_addr = dev->cmb_bus_addr + offset; - nvmeq->sq_cmds_io = dev->cmb + offset; - }else { - nvmeq->sq_cmds = dma_alloc_coherent(dev->dev, SQ_SIZE(depth), - &nvmeq->sq_dma_addr,
GFP_KERNEL);drivers/nvme/host/pci.c +3
-3-if (!nvmeq->sq_cmds) -return -ENOMEM ; - } + +/* CMB SQEs will be mapped before creation */ + if (qid && dev->cmb && use_cmb_sqes && NVME_CMB_SQS(dev-Quoted 1 line
cmbsz))
drivers/nvme/host/pci.c +3
-0+return 0 ; + + nvmeq->sq_cmds = dma_alloc_coherent(dev->dev,
SQ_SIZE(depth),drivers/nvme/host/pci.c +1
-0+ &nvmeq->sq_dma_addr,
GFP_KERNEL);drivers/nvme/host/pci.c +5
-0+if (!nvmeq->sq_cmds) +return -ENOMEM ;return 0 ; }@@ -1320,6 +1318,13 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)struct nvme_dev *dev = nvmeq->dev;int result; +if (qid && dev->cmb && use_cmb_sqes &&NVME_CMB_SQS (dev- >cmbsz)) { + unsigned offset = (qid - 1) * roundup(SQ_SIZE(nvmeq- >q_depth), + dev-Quoted 1 line
ctrl.page_size);
drivers/nvme/host/pci.c +4
-0+ nvmeq->sq_dma_addr = dev->cmb_bus_addr + offset; + nvmeq->sq_cmds_io = dev->cmb + offset; + } + nvmeq->cq_vector = qid -1 ; result =adapter_alloc_cq (dev, qid, nvmeq);if (result <0 )
Greg KH
maintainerQuoted 17 lines · Scott Bauer
Commit
815c6704bf9f1c59f3a6be380a4032b9c57b12f1upstream.The controller memory buffer is remapped into a kernel address on each reset, but the driver was setting the submission queue base address only on the very first queue creation. The remapped address is likely to change after a reset, so accessing the old address will hit a kernel bug.
This patch fixes that by setting the queue's CMB base address each time the queue is created.
Fixes f63572dff1421 ("nvme: unmap CMB and remove sysfs file in reset path")Reported-by Christian Black <[email protected]>Cc Jon Derrick <[email protected]>Signed-off-by Keith Busch <[email protected]>Reviewed-by Christoph Hellwig <[email protected]>Signed-off-by Scott Bauer <[email protected]>Reviewed-by Jon Derrick <[email protected]>
Quoted 3 lines
--- drivers/nvme/host/pci.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-)
"backport" to where? What kernel tree(s) do you want this applied to?
I need a hint please...
thanks,
greg k-h
Quoted 22 lines · Greg KH
Quoted 17 lines · Scott Bauer
Commit
815c6704bf9f1c59f3a6be380a4032b9c57b12f1upstream.The controller memory buffer is remapped into a kernel address on each reset, but the driver was setting the submission queue base address only on the very first queue creation. The remapped address is likely to change after a reset, so accessing the old address will hit a kernel bug.
This patch fixes that by setting the queue's CMB base address each time the queue is created.
Fixes f63572dff1421 ("nvme: unmap CMB and remove sysfs file in reset path")Reported-by Christian Black <[email protected]>Cc Jon Derrick <[email protected]>Signed-off-by Keith Busch <[email protected]>Reviewed-by Christoph Hellwig <[email protected]>Signed-off-by Scott Bauer <[email protected]>Reviewed-by Jon Derrick <[email protected]>Quoted 3 lines
--- drivers/nvme/host/pci.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-)
Quoted 3 lines
"backport" to where? What kernel tree(s) do you want this applied to?
I need a hint please...
Sorry about that. 4.9 and 4.14 are the applicable targets.
Quoted 17 lines · Scott Bauer
Commit
815c6704bf9f1c59f3a6be380a4032b9c57b12f1upstream.The controller memory buffer is remapped into a kernel address on each reset, but the driver was setting the submission queue base address only on the very first queue creation. The remapped address is likely to change after a reset, so accessing the old address will hit a kernel bug.
This patch fixes that by setting the queue's CMB base address each time the queue is created.
Fixes f63572dff1421 ("nvme: unmap CMB and remove sysfs file in reset path")Reported-by Christian Black <[email protected]>Cc Jon Derrick <[email protected]>Signed-off-by Keith Busch <[email protected]>Reviewed-by Christoph Hellwig <[email protected]>Signed-off-by Scott Bauer <[email protected]>Reviewed-by Jon Derrick <[email protected]>
Quoted 3 lines
--- drivers/nvme/host/pci.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-)
Now queued up, thanks.
greg k-h