From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753623AbdERGhi (ORCPT ); Thu, 18 May 2017 02:37:38 -0400 Received: from mga14.intel.com ([192.55.52.115]:33805 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751442AbdERGhh (ORCPT ); Thu, 18 May 2017 02:37:37 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.38,357,1491289200"; d="scan'208";a="1170903605" From: Xu Yu To: linux-nvme@lists.infradead.org Cc: linux-kernel@vger.kernel.org, keith.busch@intel.com, axboe@fb.com, hch@lst.de, sagi@grimberg.me, yu.a.xu@intel.com, haozhong.zhang@intel.com Subject: [PATCH] nvme/pci: remap BAR0 to cover admin CQ doorbell for large stride Date: Thu, 18 May 2017 06:35:47 +0800 Message-Id: <1495060547-6180-1-git-send-email-yu.a.xu@intel.com> X-Mailer: git-send-email 2.7.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The existing driver initially maps 8192 bytes of BAR0 which is intended to cover doorbells of admin SQ and CQ. However, if a large stride, e.g. 10, is used, the doorbell of admin CQ will be out of 8192 bytes. Consequently, a page fault will be raised when the admin CQ doorbell is accessed in nvme_configure_admin_queue(). This patch fixes this issue by remapping BAR0 before accessing admin CQ doorbell if the initial mapping is not enough. Signed-off-by: "Xu, Yu A" --- drivers/nvme/host/pci.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 9d4640a..7c991eb 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1322,6 +1322,17 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev) u32 aqa; u64 cap = lo_hi_readq(dev->bar + NVME_REG_CAP); struct nvme_queue *nvmeq; + struct pci_dev *pdev = to_pci_dev(dev->dev); + unsigned long size; + + size = 4096 + 2 * 4 * dev->db_stride; + if (size > 8192) { + iounmap(dev->bar); + dev->bar = ioremap(pci_resource_start(pdev, 0), size); + if (!dev->bar) + return -ENOMEM; + dev->dbs = dev->bar + 4096; + } dev->subsystem = readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 1, 0) ? NVME_CAP_NSSRC(cap) : 0; -- 2.10.1