FAILED: patch "[PATCH] nvme-pci: Remap CMB SQ entries on every controller reset" failed to apply to 4.9-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
815c6704bf9f1c59f3a6be380a4032b9c57b12f1Mon Sep 17 00:00:00 2001
From: Keith Busch <[email protected]>
Date: Tue, 13 Feb 2018 05:44:44 -0700
Subject: [PATCH] nvme-pci: Remap CMB SQ entries on every controller reset
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 +14 -11
@@ -1364,18 +1364,14 @@ 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 && (dev->cmbsz &NVME_CMBSZ_SQS )) { -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 && (dev->cmbsz &NVME_CMBSZ_SQS )) +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 ; }
@@ -1449,6 +1445,13 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)struct nvme_dev *dev = nvmeq->dev;int result; +if (dev->cmb && use_cmb_sqes && (dev->cmbsz &NVME_CMBSZ_SQS )) { +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 )