| From 2cfc8d0d51878cedaee8b161dce9791ef1be20c2 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 5 Nov 2020 23:28:47 +0900 |
| Subject: nvme: free sq/cq dbbuf pointers when dbbuf set fails |
| |
| From: Minwoo Im <minwoo.im.dev@gmail.com> |
| |
| [ Upstream commit 0f0d2c876c96d4908a9ef40959a44bec21bdd6cf ] |
| |
| If Doorbell Buffer Config command fails even 'dev->dbbuf_dbs != NULL' |
| which means OACS indicates that NVME_CTRL_OACS_DBBUF_SUPP is set, |
| nvme_dbbuf_update_and_check_event() will check event even it's not been |
| successfully set. |
| |
| This patch fixes mismatch among dbbuf for sq/cqs in case that dbbuf |
| command fails. |
| |
| Signed-off-by: Minwoo Im <minwoo.im.dev@gmail.com> |
| Signed-off-by: Christoph Hellwig <hch@lst.de> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/nvme/host/pci.c | 15 +++++++++++++++ |
| 1 file changed, 15 insertions(+) |
| |
| diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c |
| index a6af96aaa0eb7..3448f7ac209a0 100644 |
| --- a/drivers/nvme/host/pci.c |
| +++ b/drivers/nvme/host/pci.c |
| @@ -292,9 +292,21 @@ static void nvme_dbbuf_init(struct nvme_dev *dev, |
| nvmeq->dbbuf_cq_ei = &dev->dbbuf_eis[cq_idx(qid, dev->db_stride)]; |
| } |
| |
| +static void nvme_dbbuf_free(struct nvme_queue *nvmeq) |
| +{ |
| + if (!nvmeq->qid) |
| + return; |
| + |
| + nvmeq->dbbuf_sq_db = NULL; |
| + nvmeq->dbbuf_cq_db = NULL; |
| + nvmeq->dbbuf_sq_ei = NULL; |
| + nvmeq->dbbuf_cq_ei = NULL; |
| +} |
| + |
| static void nvme_dbbuf_set(struct nvme_dev *dev) |
| { |
| struct nvme_command c; |
| + unsigned int i; |
| |
| if (!dev->dbbuf_dbs) |
| return; |
| @@ -308,6 +320,9 @@ static void nvme_dbbuf_set(struct nvme_dev *dev) |
| dev_warn(dev->ctrl.device, "unable to set dbbuf\n"); |
| /* Free memory and continue on */ |
| nvme_dbbuf_dma_free(dev); |
| + |
| + for (i = 1; i <= dev->online_queues; i++) |
| + nvme_dbbuf_free(&dev->queues[i]); |
| } |
| } |
| |
| -- |
| 2.27.0 |
| |