[PATCH 12/13] nvme-pci: introduce cmb_devmap_align module parameter

Hou Tao posted 13 patches 1 month, 3 weeks ago
[PATCH 12/13] nvme-pci: introduce cmb_devmap_align module parameter
Posted by Hou Tao 1 month, 3 weeks ago
From: Hou Tao <houtao1@huawei.com>

P2PDMA memory has supported compound page. It is best to enable compound
page for p2pdma memory automatically accordingly to the address, the
size and the offset of the CMB, however, for nvme device, the p2pdma
memory may be used in the kernel space (e.g., for SQ entries) and it
will incur a lot of waste when a PUD or PMD-sized page is enabled for
nvme device.

Therefore, introduce a module parameter cmb_devmap_align to control the
alignment of p2pdma memory mapping. Its default value is PAGE_SIZE. When
its value is zero, it will use pci_p2pdma_max_pagemap_align() to find
the maximal possible mapping alignment.

Signed-off-by: Hou Tao <houtao1@huawei.com>
---
 drivers/nvme/host/pci.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index b070095bae5e..ca0126e36834 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -79,6 +79,10 @@ static bool use_cmb_sqes = true;
 module_param(use_cmb_sqes, bool, 0444);
 MODULE_PARM_DESC(use_cmb_sqes, "use controller's memory buffer for I/O SQes");
 
+static unsigned long cmb_devmap_align = PAGE_SIZE;
+module_param(cmb_devmap_align, ulong, 0444);
+MODULE_PARM_DESC(cmb_devmap_align, "the mapping alignment of CMB");
+
 static unsigned int max_host_mem_size_mb = 128;
 module_param(max_host_mem_size_mb, uint, 0444);
 MODULE_PARM_DESC(max_host_mem_size_mb,
@@ -2266,6 +2270,7 @@ static void nvme_map_cmb(struct nvme_dev *dev)
 	u64 size, offset;
 	resource_size_t bar_size;
 	struct pci_dev *pdev = to_pci_dev(dev->dev);
+	size_t align;
 	int bar;
 
 	if (dev->cmb_size)
@@ -2309,7 +2314,10 @@ static void nvme_map_cmb(struct nvme_dev *dev)
 			     dev->bar + NVME_REG_CMBMSC);
 	}
 
-	if (pci_p2pdma_add_resource(pdev, bar, size, PAGE_SIZE, offset)) {
+	align = cmb_devmap_align;
+	if (!align)
+		align = pci_p2pdma_max_pagemap_align(pdev, bar, size, offset);
+	if (pci_p2pdma_add_resource(pdev, bar, size, align, offset)) {
 		dev_warn(dev->ctrl.device,
 			 "failed to register the CMB\n");
 		hi_lo_writeq(0, dev->bar + NVME_REG_CMBMSC);
-- 
2.29.2
Re: [PATCH 12/13] nvme-pci: introduce cmb_devmap_align module parameter
Posted by kernel test robot 1 month, 3 weeks ago
Hi Hou,

kernel test robot noticed the following build errors:

[auto build test ERROR on driver-core/driver-core-testing]
[also build test ERROR on driver-core/driver-core-next driver-core/driver-core-linus akpm-mm/mm-everything linus/master v6.19-rc1 next-20251219]
[cannot apply to pci/next pci/for-linus]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Hou-Tao/PCI-P2PDMA-Release-the-per-cpu-ref-of-pgmap-when-vm_insert_page-fails/20251220-121804
base:   driver-core/driver-core-testing
patch link:    https://lore.kernel.org/r/20251220040446.274991-13-houtao%40huaweicloud.com
patch subject: [PATCH 12/13] nvme-pci: introduce cmb_devmap_align module parameter
config: alpha-allyesconfig (https://download.01.org/0day-ci/archive/20251221/202512210635.b7EdhXBT-lkp@intel.com/config)
compiler: alpha-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251221/202512210635.b7EdhXBT-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512210635.b7EdhXBT-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/nvme/host/pci.c: In function 'nvme_map_cmb':
>> drivers/nvme/host/pci.c:2319:54: error: passing argument 1 of 'pci_p2pdma_max_pagemap_align' makes integer from pointer without a cast [-Wint-conversion]
    2319 |                 align = pci_p2pdma_max_pagemap_align(pdev, bar, size, offset);
         |                                                      ^~~~
         |                                                      |
         |                                                      struct pci_dev *
   In file included from include/linux/blk-mq-dma.h:6,
                    from drivers/nvme/host/pci.c:10:
   include/linux/pci-p2pdma.h:232:67: note: expected 'resource_size_t' {aka 'long long unsigned int'} but argument is of type 'struct pci_dev *'
     232 | static inline size_t pci_p2pdma_max_pagemap_align(resource_size_t start,
         |                                                   ~~~~~~~~~~~~~~~~^~~~~
>> drivers/nvme/host/pci.c:2319:25: error: too many arguments to function 'pci_p2pdma_max_pagemap_align'; expected 3, have 4
    2319 |                 align = pci_p2pdma_max_pagemap_align(pdev, bar, size, offset);
         |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~                  ~~~~~~
   include/linux/pci-p2pdma.h:232:22: note: declared here
     232 | static inline size_t pci_p2pdma_max_pagemap_align(resource_size_t start,
         |                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~


vim +/pci_p2pdma_max_pagemap_align +2319 drivers/nvme/host/pci.c

  2267	
  2268	static void nvme_map_cmb(struct nvme_dev *dev)
  2269	{
  2270		u64 size, offset;
  2271		resource_size_t bar_size;
  2272		struct pci_dev *pdev = to_pci_dev(dev->dev);
  2273		size_t align;
  2274		int bar;
  2275	
  2276		if (dev->cmb_size)
  2277			return;
  2278	
  2279		if (NVME_CAP_CMBS(dev->ctrl.cap))
  2280			writel(NVME_CMBMSC_CRE, dev->bar + NVME_REG_CMBMSC);
  2281	
  2282		dev->cmbsz = readl(dev->bar + NVME_REG_CMBSZ);
  2283		if (!dev->cmbsz)
  2284			return;
  2285		dev->cmbloc = readl(dev->bar + NVME_REG_CMBLOC);
  2286	
  2287		size = nvme_cmb_size_unit(dev) * nvme_cmb_size(dev);
  2288		offset = nvme_cmb_size_unit(dev) * NVME_CMB_OFST(dev->cmbloc);
  2289		bar = NVME_CMB_BIR(dev->cmbloc);
  2290		bar_size = pci_resource_len(pdev, bar);
  2291	
  2292		if (offset > bar_size)
  2293			return;
  2294	
  2295		/*
  2296		 * Controllers may support a CMB size larger than their BAR, for
  2297		 * example, due to being behind a bridge. Reduce the CMB to the
  2298		 * reported size of the BAR
  2299		 */
  2300		size = min(size, bar_size - offset);
  2301	
  2302		if (!IS_ALIGNED(size, memremap_compat_align()) ||
  2303		    !IS_ALIGNED(pci_resource_start(pdev, bar),
  2304				memremap_compat_align()))
  2305			return;
  2306	
  2307		/*
  2308		 * Tell the controller about the host side address mapping the CMB,
  2309		 * and enable CMB decoding for the NVMe 1.4+ scheme:
  2310		 */
  2311		if (NVME_CAP_CMBS(dev->ctrl.cap)) {
  2312			hi_lo_writeq(NVME_CMBMSC_CRE | NVME_CMBMSC_CMSE |
  2313				     (pci_bus_address(pdev, bar) + offset),
  2314				     dev->bar + NVME_REG_CMBMSC);
  2315		}
  2316	
  2317		align = cmb_devmap_align;
  2318		if (!align)
> 2319			align = pci_p2pdma_max_pagemap_align(pdev, bar, size, offset);
  2320		if (pci_p2pdma_add_resource(pdev, bar, size, align, offset)) {
  2321			dev_warn(dev->ctrl.device,
  2322				 "failed to register the CMB\n");
  2323			hi_lo_writeq(0, dev->bar + NVME_REG_CMBMSC);
  2324			return;
  2325		}
  2326	
  2327		dev->cmb_size = size;
  2328		dev->cmb_use_sqes = use_cmb_sqes && (dev->cmbsz & NVME_CMBSZ_SQS);
  2329	
  2330		if ((dev->cmbsz & (NVME_CMBSZ_WDS | NVME_CMBSZ_RDS)) ==
  2331				(NVME_CMBSZ_WDS | NVME_CMBSZ_RDS))
  2332			pci_p2pmem_publish(pdev, true);
  2333	}
  2334	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki