Received: by 2002:a25:683:0:0:0:0:0 with SMTP id 125csp55389ybg; Mon, 8 Jun 2020 16:16:40 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx1Nz1FHTLQl/4wNhBOh4Mt02u+2up2tWiS097rYOuufDPJEfkZHd58p6I/VXvEY8RKjPGS X-Received: by 2002:a17:907:685:: with SMTP id wn5mr24202444ejb.283.1591658200621; Mon, 08 Jun 2020 16:16:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1591658200; cv=none; d=google.com; s=arc-20160816; b=0xeq7lBQZ8sjClp8VD3jYKpmsIMuehYrChij/B4fhn3QW5L+DdisVMcxjB05cNeSmm 4O5q7UAoicx0tm4v7I0cL7r4pehT0nbdy13RqmKa8NYeo1AUqyj8q275UP+an21a+3JC nsYiv+0W8yB6nSxfJzi9dNWAmu1Z1bK3wFAPAp7zInww9osilmEhOh2YWbXo5c6MaoKV p5N+30JfF5pf94tpIXr9xPH11t/EJEb9eWbb/az+5dBqZSv8JvDK3pjmF68mifUruKTr q+8jPpl2MOPLfbSho1mxpi9Mji/94T5T9JWec3xdEgusDxdLwV2NRfHeSbBc/wsyGHqB Y1cA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=XwxM5uhXI0ZmxBH9V4Ahl4ClOixy1Cqc/3JCNS2iYjU=; b=WuQ6gBI9R5vYsHVU357eAM3Ot27LpVnqdAkzCosBtoOmWV81F1PjnLh3ShAl9mt/d4 gVDheu3JfgfpUjL+/NHmhYNxwwe6qa9dO0ar4n8A5Ln/3rwoT+tWUcl8r2/DkbwO40Bt YdOzDUsRaTSbpxpiy7Tvz+br0OKHPWII3a9XL9RGGGsXtFwbe05xN4KOlIax+Dvb5aaH EDLLgoSS7FFEj73yHlKQMcpxoB3HpnassHlBhkcyoCKej72trSneNrO19AkANJ7VN5/0 RBIRZDI1SGz+Ghy3VqNbt8CB8LdD953xzbsqTqMn9g/JwZ07rRo2e3/kRd77BkcqyLx8 FFqw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="01kjMDb/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id h91si3775421edd.145.2020.06.08.16.16.13; Mon, 08 Jun 2020 16:16:40 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="01kjMDb/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728944AbgFHXLk (ORCPT + 99 others); Mon, 8 Jun 2020 19:11:40 -0400 Received: from mail.kernel.org ([198.145.29.99]:56110 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728338AbgFHXKG (ORCPT ); Mon, 8 Jun 2020 19:10:06 -0400 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id A86A220C56; Mon, 8 Jun 2020 23:10:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1591657805; bh=m23dLoyLhJjCU66alnaUcLHfXVkJjzbVDLW3x6HWfMs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=01kjMDb/AP1kRQNYo7AAj0DKxqu0R2Lqpq448Jq+DjtXS89myjSmCgM/2754SmGyi 8xpwwezkF73s/u0BE3G8IZ6o+wNMUe77O6ElqdhfOrFWIrWN457nNeJgY1oXNeOMqp 2NILtVs5WEPVSFiw5bqGy9fXruI0DDEPV1VIoPKY= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Weiping Zhang , Keith Busch , Max Gurtovoy , Christoph Hellwig , Jens Axboe , Sasha Levin , linux-nvme@lists.infradead.org Subject: [PATCH AUTOSEL 5.7 182/274] nvme-pci: align io queue count with allocted nvme_queue in nvme_probe Date: Mon, 8 Jun 2020 19:04:35 -0400 Message-Id: <20200608230607.3361041-182-sashal@kernel.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200608230607.3361041-1-sashal@kernel.org> References: <20200608230607.3361041-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Weiping Zhang [ Upstream commit 2a5bcfdd41d68559567cec3c124a75e093506cc1 ] Since commit 147b27e4bd08 ("nvme-pci: allocate device queues storage space at probe"), nvme_alloc_queue does not alloc the nvme queues itself anymore. If the write/poll_queues module parameters are changed at runtime to values larger than the number of allocated queues in nvme_probe, nvme_alloc_queue will access unallocated memory. Add a new nr_allocated_queues member to struct nvme_dev to record how many queues were alloctated in nvme_probe to avoid using more than the allocated queues after a reset following a change to the write/poll_queues module parameters. Also add nr_write_queues and nr_poll_queues members to allow refreshing the number of write and poll queues based on a change to the module parameters when resetting the controller. Fixes: 147b27e4bd08 ("nvme-pci: allocate device queues storage space at probe") Signed-off-by: Weiping Zhang Reviewed-by: Keith Busch Reviewed-by: Max Gurtovoy [hch: add nvme_max_io_queues, update the commit message] Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- drivers/nvme/host/pci.c | 57 ++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index cc46e250fcac..dcf597fbafad 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -128,6 +128,9 @@ struct nvme_dev { dma_addr_t host_mem_descs_dma; struct nvme_host_mem_buf_desc *host_mem_descs; void **host_mem_desc_bufs; + unsigned int nr_allocated_queues; + unsigned int nr_write_queues; + unsigned int nr_poll_queues; }; static int io_queue_depth_set(const char *val, const struct kernel_param *kp) @@ -209,25 +212,14 @@ struct nvme_iod { struct scatterlist *sg; }; -static unsigned int max_io_queues(void) +static inline unsigned int nvme_dbbuf_size(struct nvme_dev *dev) { - return num_possible_cpus() + write_queues + poll_queues; -} - -static unsigned int max_queue_count(void) -{ - /* IO queues + admin queue */ - return 1 + max_io_queues(); -} - -static inline unsigned int nvme_dbbuf_size(u32 stride) -{ - return (max_queue_count() * 8 * stride); + return dev->nr_allocated_queues * 8 * dev->db_stride; } static int nvme_dbbuf_dma_alloc(struct nvme_dev *dev) { - unsigned int mem_size = nvme_dbbuf_size(dev->db_stride); + unsigned int mem_size = nvme_dbbuf_size(dev); if (dev->dbbuf_dbs) return 0; @@ -252,7 +244,7 @@ static int nvme_dbbuf_dma_alloc(struct nvme_dev *dev) static void nvme_dbbuf_dma_free(struct nvme_dev *dev) { - unsigned int mem_size = nvme_dbbuf_size(dev->db_stride); + unsigned int mem_size = nvme_dbbuf_size(dev); if (dev->dbbuf_dbs) { dma_free_coherent(dev->dev, mem_size, @@ -2003,7 +1995,7 @@ static int nvme_setup_host_mem(struct nvme_dev *dev) static void nvme_calc_irq_sets(struct irq_affinity *affd, unsigned int nrirqs) { struct nvme_dev *dev = affd->priv; - unsigned int nr_read_queues; + unsigned int nr_read_queues, nr_write_queues = dev->nr_write_queues; /* * If there is no interupt available for queues, ensure that @@ -2019,12 +2011,12 @@ static void nvme_calc_irq_sets(struct irq_affinity *affd, unsigned int nrirqs) if (!nrirqs) { nrirqs = 1; nr_read_queues = 0; - } else if (nrirqs == 1 || !write_queues) { + } else if (nrirqs == 1 || !nr_write_queues) { nr_read_queues = 0; - } else if (write_queues >= nrirqs) { + } else if (nr_write_queues >= nrirqs) { nr_read_queues = 1; } else { - nr_read_queues = nrirqs - write_queues; + nr_read_queues = nrirqs - nr_write_queues; } dev->io_queues[HCTX_TYPE_DEFAULT] = nrirqs - nr_read_queues; @@ -2048,7 +2040,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues) * Poll queues don't need interrupts, but we need at least one IO * queue left over for non-polled IO. */ - this_p_queues = poll_queues; + this_p_queues = dev->nr_poll_queues; if (this_p_queues >= nr_io_queues) { this_p_queues = nr_io_queues - 1; irq_queues = 1; @@ -2078,14 +2070,25 @@ static void nvme_disable_io_queues(struct nvme_dev *dev) __nvme_disable_io_queues(dev, nvme_admin_delete_cq); } +static unsigned int nvme_max_io_queues(struct nvme_dev *dev) +{ + return num_possible_cpus() + dev->nr_write_queues + dev->nr_poll_queues; +} + static int nvme_setup_io_queues(struct nvme_dev *dev) { struct nvme_queue *adminq = &dev->queues[0]; struct pci_dev *pdev = to_pci_dev(dev->dev); - int result, nr_io_queues; + unsigned int nr_io_queues; unsigned long size; + int result; - nr_io_queues = max_io_queues(); + /* + * Sample the module parameters once at reset time so that we have + * stable values to work with. + */ + dev->nr_write_queues = write_queues; + dev->nr_poll_queues = poll_queues; /* * If tags are shared with admin queue (Apple bug), then @@ -2093,6 +2096,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) */ if (dev->ctrl.quirks & NVME_QUIRK_SHARED_TAGS) nr_io_queues = 1; + else + nr_io_queues = min(nvme_max_io_queues(dev), + dev->nr_allocated_queues - 1); result = nvme_set_queue_count(&dev->ctrl, &nr_io_queues); if (result < 0) @@ -2767,8 +2773,11 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (!dev) return -ENOMEM; - dev->queues = kcalloc_node(max_queue_count(), sizeof(struct nvme_queue), - GFP_KERNEL, node); + dev->nr_write_queues = write_queues; + dev->nr_poll_queues = poll_queues; + dev->nr_allocated_queues = nvme_max_io_queues(dev) + 1; + dev->queues = kcalloc_node(dev->nr_allocated_queues, + sizeof(struct nvme_queue), GFP_KERNEL, node); if (!dev->queues) goto free; -- 2.25.1