[PATCH v2 13/18] pci: Map bars with offset and length

Andrew Scull ascull at google.com
Tue Mar 29 18:58:55 CEST 2022


Evolve dm_pci_map_bar() to include an offset and length parameter. These
allow a portion of the memory to be mapped and range checks to be
applied.

Passing both the offset and length as zero results in the previous
behaviour and this is used to migtate the previous callers.

Signed-off-by: Andrew Scull <ascull at google.com>
---
 arch/x86/cpu/baytrail/cpu.c             |  2 +-
 drivers/ata/ahci.c                      |  8 +++----
 drivers/gpio/octeon_gpio.c              |  2 +-
 drivers/i2c/designware_i2c_pci.c        |  2 +-
 drivers/i2c/intel_i2c.c                 |  2 +-
 drivers/i2c/octeon_i2c.c                |  2 +-
 drivers/mmc/octeontx_hsmmc.c            |  2 +-
 drivers/mmc/pci_mmc.c                   |  2 +-
 drivers/mtd/nand/raw/octeontx_bch.c     |  4 ++--
 drivers/mtd/nand/raw/octeontx_nand.c    |  2 +-
 drivers/net/bnxt/bnxt.c                 |  6 +++---
 drivers/net/fsl_enetc.c                 |  2 +-
 drivers/net/fsl_enetc_mdio.c            |  2 +-
 drivers/net/mscc_eswitch/felix_switch.c |  4 ++--
 drivers/net/octeontx/bgx.c              |  2 +-
 drivers/net/octeontx/nic_main.c         |  2 +-
 drivers/net/octeontx/nicvf_main.c       |  2 +-
 drivers/net/octeontx/smi.c              |  2 +-
 drivers/net/octeontx2/cgx.c             |  2 +-
 drivers/net/octeontx2/rvu_af.c          |  2 +-
 drivers/net/octeontx2/rvu_pf.c          |  2 +-
 drivers/net/pch_gbe.c                   |  2 +-
 drivers/nvme/nvme_pci.c                 |  4 ++--
 drivers/pci/pci-uclass.c                | 28 +++++++++++++++++--------
 drivers/spi/octeon_spi.c                |  2 +-
 drivers/usb/host/ohci-pci.c             |  2 +-
 drivers/virtio/virtio_pci_legacy.c      |  2 +-
 include/pci.h                           |  5 ++++-
 test/dm/pci.c                           | 12 +++++------
 29 files changed, 63 insertions(+), 50 deletions(-)

diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c
index 309a50a116..6f1b05175c 100644
--- a/arch/x86/cpu/baytrail/cpu.c
+++ b/arch/x86/cpu/baytrail/cpu.c
@@ -55,7 +55,7 @@ int arch_cpu_init_dm(void)
 	for (i = 0; i < 2; i++) {
 		ret = dm_pci_bus_find_bdf(PCI_BDF(0, 0x1e, 3 + i), &dev);
 		if (!ret) {
-			base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+			base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
 					      PCI_REGION_MEM);
 			hsuart_clock_set(base);
 		}
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 2062197afc..3925807d55 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -416,8 +416,8 @@ static int ahci_init_one(struct ahci_uc_priv *uc_priv, struct udevice *dev)
 	uc_priv->udma_mask = 0x7f;	/*Fixme,assume to support UDMA6 */
 
 #if !defined(CONFIG_DM_SCSI)
-	uc_priv->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5,
-					      PCI_REGION_MEM);
+	uc_priv->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5, 0, 0,
+					    PCI_REGION_MEM);
 
 	/* Take from kernel:
 	 * JMicron-specific fixup:
@@ -1148,7 +1148,7 @@ int ahci_probe_scsi_pci(struct udevice *ahci_dev)
 	ulong base;
 	u16 vendor, device;
 
-	base = (ulong)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_5,
+	base = (ulong)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_5, 0, 0,
 				     PCI_REGION_MEM);
 
 	/*
@@ -1163,7 +1163,7 @@ int ahci_probe_scsi_pci(struct udevice *ahci_dev)
 
 	if (vendor == PCI_VENDOR_ID_CAVIUM &&
 	    device == PCI_DEVICE_ID_CAVIUM_SATA)
-		base = (uintptr_t)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_0,
+		base = (uintptr_t)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_0, 0, 0,
 						 PCI_REGION_MEM);
 	return ahci_probe_scsi(ahci_dev, base);
 }
diff --git a/drivers/gpio/octeon_gpio.c b/drivers/gpio/octeon_gpio.c
index 42eae79d8c..e6a8e1a521 100644
--- a/drivers/gpio/octeon_gpio.c
+++ b/drivers/gpio/octeon_gpio.c
@@ -183,7 +183,7 @@ static int octeon_gpio_probe(struct udevice *dev)
 	priv->data = (const struct octeon_gpio_data *)dev_get_driver_data(dev);
 
 	if (priv->data->probe == PROBE_PCI) {
-		priv->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+		priv->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
 					    PCI_REGION_MEM);
 		uc_priv->gpio_count = readq(priv->base +
 					    priv->data->reg_offs + GPIO_CONST) &
diff --git a/drivers/i2c/designware_i2c_pci.c b/drivers/i2c/designware_i2c_pci.c
index 9e387737b6..51f1357d10 100644
--- a/drivers/i2c/designware_i2c_pci.c
+++ b/drivers/i2c/designware_i2c_pci.c
@@ -59,7 +59,7 @@ static int designware_i2c_pci_of_to_plat(struct udevice *dev)
 		priv->regs = (struct i2c_regs *)dm_pci_read_bar32(dev, 0);
 	} else {
 		priv->regs = (struct i2c_regs *)
-			dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+			dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_MEM);
 	}
 	if (!priv->regs)
 		return -EINVAL;
diff --git a/drivers/i2c/intel_i2c.c b/drivers/i2c/intel_i2c.c
index 52f7a528ef..7b5b62e3eb 100644
--- a/drivers/i2c/intel_i2c.c
+++ b/drivers/i2c/intel_i2c.c
@@ -251,7 +251,7 @@ static int intel_i2c_probe(struct udevice *dev)
 	ulong base;
 
 	/* Save base address from PCI BAR */
-	priv->base = (ulong)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4,
+	priv->base = (ulong)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4, 0, 0,
 					   PCI_REGION_IO);
 	base = priv->base;
 
diff --git a/drivers/i2c/octeon_i2c.c b/drivers/i2c/octeon_i2c.c
index 50199ff46e..74fd5c3d2e 100644
--- a/drivers/i2c/octeon_i2c.c
+++ b/drivers/i2c/octeon_i2c.c
@@ -792,7 +792,7 @@ static int octeon_i2c_probe(struct udevice *dev)
 
 		debug("TWSI PCI device: %x\n", bdf);
 
-		twsi->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+		twsi->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
 					    PCI_REGION_MEM);
 	} else {
 		twsi->base = dev_remap_addr(dev);
diff --git a/drivers/mmc/octeontx_hsmmc.c b/drivers/mmc/octeontx_hsmmc.c
index f0519f0cf8..0bf38945a1 100644
--- a/drivers/mmc/octeontx_hsmmc.c
+++ b/drivers/mmc/octeontx_hsmmc.c
@@ -3822,7 +3822,7 @@ static int octeontx_mmc_host_probe(struct udevice *dev)
 
 	/* Octeon TX & TX2 use PCI based probing */
 	if (device_is_compatible(dev, "cavium,thunder-8890-mmc")) {
-		host->base_addr = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+		host->base_addr = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
 						 PCI_REGION_MEM);
 		if (!host->base_addr) {
 			pr_err("%s: Error: MMC base address not found\n",
diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c
index b9ab064b60..1bc2fbcfdf 100644
--- a/drivers/mmc/pci_mmc.c
+++ b/drivers/mmc/pci_mmc.c
@@ -50,7 +50,7 @@ static int pci_mmc_probe(struct udevice *dev)
 	desc = mmc_get_blk_desc(&plat->mmc);
 	desc->removable = !(plat->cfg.host_caps & MMC_CAP_NONREMOVABLE);
 
-	host->ioaddr = (void *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+	host->ioaddr = (void *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
 					      PCI_REGION_MEM);
 	host->name = dev->name;
 	host->cd_gpio = priv->cd_gpio;
diff --git a/drivers/mtd/nand/raw/octeontx_bch.c b/drivers/mtd/nand/raw/octeontx_bch.c
index 24ffa5105f..c1cc5fa187 100644
--- a/drivers/mtd/nand/raw/octeontx_bch.c
+++ b/drivers/mtd/nand/raw/octeontx_bch.c
@@ -176,7 +176,7 @@ static int octeontx_pci_bchpf_probe(struct udevice *dev)
 	if (!bch)
 		return -ENOMEM;
 
-	bch->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+	bch->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_MEM);
 	bch->dev = dev;
 
 	debug("%s: base address: %p\n", __func__, bch->reg_base);
@@ -361,7 +361,7 @@ static int octeontx_pci_bchvf_probe(struct udevice *dev)
 	vf->dev = dev;
 
 	/* Map PF's configuration registers */
-	vf->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+	vf->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_MEM);
 	debug("%s: reg base: %p\n", __func__, vf->reg_base);
 
 	err = octeontx_cmd_queue_initialize(dev, QID_BCH, QDEPTH - 1, 0,
diff --git a/drivers/mtd/nand/raw/octeontx_nand.c b/drivers/mtd/nand/raw/octeontx_nand.c
index ff363a56b5..3e84bb2fc0 100644
--- a/drivers/mtd/nand/raw/octeontx_nand.c
+++ b/drivers/mtd/nand/raw/octeontx_nand.c
@@ -2098,7 +2098,7 @@ static int octeontx_pci_nand_probe(struct udevice *dev)
 	tn->dev = dev;
 	INIT_LIST_HEAD(&tn->chips);
 
-	tn->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+	tn->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_MEM);
 	if (!tn->base) {
 		ret = -EINVAL;
 		goto release;
diff --git a/drivers/net/bnxt/bnxt.c b/drivers/net/bnxt/bnxt.c
index 9844e96072..a24f965ec1 100644
--- a/drivers/net/bnxt/bnxt.c
+++ b/drivers/net/bnxt/bnxt.c
@@ -28,9 +28,9 @@ static void bnxt_bring_pci(struct bnxt *bp)
 	dm_pci_read_config16(bp->pdev, PCI_SUBSYSTEM_ID, &bp->subsystem_device);
 	dm_pci_read_config16(bp->pdev, PCI_COMMAND, &bp->cmd_reg);
 	dm_pci_read_config8(bp->pdev, PCI_INTERRUPT_LINE, &bp->irq);
-	bp->bar0 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
-	bp->bar1 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_2, PCI_REGION_MEM);
-	bp->bar2 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_4, PCI_REGION_MEM);
+	bp->bar0 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_MEM);
+	bp->bar1 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_2, 0, 0, PCI_REGION_MEM);
+	bp->bar2 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_4, 0, 0, PCI_REGION_MEM);
 	cmd_reg = bp->cmd_reg | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
 	cmd_reg |= PCI_COMMAND_INTX_DISABLE; /* disable intr */
 	dm_pci_write_config16(bp->pdev, PCI_COMMAND, cmd_reg);
diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c
index 915c7c8025..60a7b27c81 100644
--- a/drivers/net/fsl_enetc.c
+++ b/drivers/net/fsl_enetc.c
@@ -344,7 +344,7 @@ static int enetc_probe(struct udevice *dev)
 	}
 
 	/* initialize register */
-	priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0);
+	priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, 0);
 	if (!priv->regs_base) {
 		enetc_dbg(dev, "failed to map BAR0\n");
 		return -EINVAL;
diff --git a/drivers/net/fsl_enetc_mdio.c b/drivers/net/fsl_enetc_mdio.c
index 3eb6ac9fc8..f025c2255c 100644
--- a/drivers/net/fsl_enetc_mdio.c
+++ b/drivers/net/fsl_enetc_mdio.c
@@ -125,7 +125,7 @@ static int enetc_mdio_probe(struct udevice *dev)
 {
 	struct enetc_mdio_priv *priv = dev_get_priv(dev);
 
-	priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0);
+	priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, 0);
 	if (!priv->regs_base) {
 		enetc_dbg(dev, "failed to map BAR0\n");
 		return -EINVAL;
diff --git a/drivers/net/mscc_eswitch/felix_switch.c b/drivers/net/mscc_eswitch/felix_switch.c
index 60b2e8f32d..0badb23828 100644
--- a/drivers/net/mscc_eswitch/felix_switch.c
+++ b/drivers/net/mscc_eswitch/felix_switch.c
@@ -292,13 +292,13 @@ static int felix_probe(struct udevice *dev)
 		return -ENODEV;
 	}
 
-	priv->imdio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0);
+	priv->imdio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, 0);
 	if (!priv->imdio_base) {
 		dev_err(dev, "failed to map BAR0\n");
 		return -EINVAL;
 	}
 
-	priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4, 0);
+	priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4, 0, 0, 0);
 	if (!priv->regs_base) {
 		dev_err(dev, "failed to map BAR4\n");
 		return -EINVAL;
diff --git a/drivers/net/octeontx/bgx.c b/drivers/net/octeontx/bgx.c
index a5c0c9fe2b..cc8ef099c2 100644
--- a/drivers/net/octeontx/bgx.c
+++ b/drivers/net/octeontx/bgx.c
@@ -1458,7 +1458,7 @@ int octeontx_bgx_probe(struct udevice *dev)
 	int bgx_idx, node;
 	int inc = 1;
 
-	bgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+	bgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
 				       PCI_REGION_MEM);
 	if (!bgx->reg_base) {
 		debug("No PCI region found\n");
diff --git a/drivers/net/octeontx/nic_main.c b/drivers/net/octeontx/nic_main.c
index 0f36f2586e..4754c042f1 100644
--- a/drivers/net/octeontx/nic_main.c
+++ b/drivers/net/octeontx/nic_main.c
@@ -713,7 +713,7 @@ int nic_initialize(struct udevice *dev)
 		return -ENOMEM;
 
 	/* MAP PF's configuration registers */
-	nic->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+	nic->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
 				       PCI_REGION_MEM);
 	if (!nic->reg_base) {
 		printf("Cannot map config register space, aborting\n");
diff --git a/drivers/net/octeontx/nicvf_main.c b/drivers/net/octeontx/nicvf_main.c
index c30ba49c27..097df6df1e 100644
--- a/drivers/net/octeontx/nicvf_main.c
+++ b/drivers/net/octeontx/nicvf_main.c
@@ -509,7 +509,7 @@ int nicvf_initialize(struct udevice *dev)
 	/* Enable TSO support */
 	nicvf->hw_tso = true;
 
-	nicvf->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+	nicvf->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
 					 PCI_REGION_MEM);
 
 	debug("nicvf->reg_base: %p\n", nicvf->reg_base);
diff --git a/drivers/net/octeontx/smi.c b/drivers/net/octeontx/smi.c
index d70fa820c7..2d521bd3ca 100644
--- a/drivers/net/octeontx/smi.c
+++ b/drivers/net/octeontx/smi.c
@@ -322,7 +322,7 @@ int octeontx_smi_probe(struct udevice *dev)
 	u64 baseaddr;
 
 	debug("SMI PCI device: %x\n", bdf);
-	if (!dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM)) {
+	if (!dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_MEM)) {
 		printf("Failed to map PCI region for bdf %x\n", bdf);
 		return -1;
 	}
diff --git a/drivers/net/octeontx2/cgx.c b/drivers/net/octeontx2/cgx.c
index d139029f4e..eed31a9579 100644
--- a/drivers/net/octeontx2/cgx.c
+++ b/drivers/net/octeontx2/cgx.c
@@ -253,7 +253,7 @@ int cgx_probe(struct udevice *dev)
 	struct cgx *cgx = dev_get_priv(dev);
 	int err;
 
-	cgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+	cgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
 				       PCI_REGION_MEM);
 	cgx->dev = dev;
 	cgx->cgx_id = ((u64)(cgx->reg_base) >> 24) & 0x7;
diff --git a/drivers/net/octeontx2/rvu_af.c b/drivers/net/octeontx2/rvu_af.c
index d2f9654861..47c1502ef8 100644
--- a/drivers/net/octeontx2/rvu_af.c
+++ b/drivers/net/octeontx2/rvu_af.c
@@ -127,7 +127,7 @@ int rvu_af_probe(struct udevice *dev)
 {
 	struct rvu_af *af_ptr = dev_get_priv(dev);
 
-	af_ptr->af_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+	af_ptr->af_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
 					 PCI_REGION_MEM);
 	debug("%s RVU AF BAR %p\n", __func__, af_ptr->af_base);
 	af_ptr->dev = dev;
diff --git a/drivers/net/octeontx2/rvu_pf.c b/drivers/net/octeontx2/rvu_pf.c
index 4b00178989..024e17e748 100644
--- a/drivers/net/octeontx2/rvu_pf.c
+++ b/drivers/net/octeontx2/rvu_pf.c
@@ -58,7 +58,7 @@ int rvu_pf_probe(struct udevice *dev)
 
 	debug("%s: name: %s\n", __func__, dev->name);
 
-	rvu->pf_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_2, PCI_REGION_MEM);
+	rvu->pf_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_2, 0, 0, PCI_REGION_MEM);
 	rvu->pfid = dev_seq(dev) + 1; // RVU PF's start from 1;
 	rvu->dev = dev;
 	if (!rvu_af_dev) {
diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c
index fabcf85c0d..c93cc2ead2 100644
--- a/drivers/net/pch_gbe.c
+++ b/drivers/net/pch_gbe.c
@@ -449,7 +449,7 @@ static int pch_gbe_probe(struct udevice *dev)
 
 	priv->dev = dev;
 
-	iobase = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, PCI_REGION_MEM);
+	iobase = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, 0, 0, PCI_REGION_MEM);
 
 	plat->iobase = (ulong)iobase;
 	priv->mac_regs = (struct pch_gbe_regs *)iobase;
diff --git a/drivers/nvme/nvme_pci.c b/drivers/nvme/nvme_pci.c
index 5f60fb884f..3499a7b6e7 100644
--- a/drivers/nvme/nvme_pci.c
+++ b/drivers/nvme/nvme_pci.c
@@ -28,8 +28,8 @@ static int nvme_probe(struct udevice *udev)
 	sprintf(ndev->vendor, "0x%.4x", pplat->vendor);
 
 	ndev->instance = trailing_strtol(udev->name);
-	ndev->bar = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0,
-			PCI_REGION_MEM);
+	ndev->bar = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, 0, 0,
+				   PCI_REGION_MEM);
 	return nvme_init(udev);
 }
 
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index ba210bc91f..033c52bb4e 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -1565,7 +1565,8 @@ static phys_addr_t dm_pci_map_ea_virt(struct udevice *dev, int ea_off,
 	return addr;
 }
 
-static void *dm_pci_map_ea_bar(struct udevice *dev, int bar, int ea_off,
+static void *dm_pci_map_ea_bar(struct udevice *dev, int bar, size_t offset,
+			       size_t len, int ea_off,
 			       struct pci_child_plat *pdata)
 {
 	int ea_cnt, i, entry_size;
@@ -1608,14 +1609,18 @@ static void *dm_pci_map_ea_bar(struct udevice *dev, int bar, int ea_off,
 		if (IS_ENABLED(CONFIG_PCI_SRIOV))
 			addr += dm_pci_map_ea_virt(dev, ea_off, pdata);
 
+		if (~((phys_addr_t)0) - addr < offset)
+			return NULL;
+
 		/* size ignored for now */
-		return map_physmem(addr, 0, MAP_NOCACHE);
+		return map_physmem(addr + offset, len, MAP_NOCACHE);
 	}
 
 	return 0;
 }
 
-void *dm_pci_map_bar(struct udevice *dev, int bar, unsigned long flags)
+void *dm_pci_map_bar(struct udevice *dev, int bar, size_t offset, size_t len,
+		     unsigned long flags)
 {
 	struct pci_child_plat *pdata = dev_get_parent_plat(dev);
 	struct udevice *udev = dev;
@@ -1640,20 +1645,25 @@ void *dm_pci_map_bar(struct udevice *dev, int bar, unsigned long flags)
 		 */
 		ea_off = dm_pci_find_capability(udev, PCI_CAP_ID_EA);
 		if (ea_off)
-			return dm_pci_map_ea_bar(udev, bar, ea_off, pdata);
+			return dm_pci_map_ea_bar(udev, bar, offset, len, ea_off,
+						 pdata);
 	}
 
 	/* read BAR address */
 	dm_pci_read_config32(udev, bar, &bar_response);
 	pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
 
+	if (~((pci_addr_t)0) - pci_bus_addr < offset)
+		return NULL;
+
 	/*
-	 * Pass "0" as the length argument to pci_bus_to_virt.  The arg
-	 * isn't actually used on any platform because U-Boot assumes a static
-	 * linear mapping.  In the future, this could read the BAR size
-	 * and pass that as the size if needed.
+	 * Forward the length argument to dm_pci_bus_to_virt. The length will
+	 * be used to check that the entire address range has been declared as
+	 * a PCI range, but a better check would be to probe for the size of
+	 * the bar and prevent overflow more locally.
 	 */
-	return dm_pci_bus_to_virt(udev, pci_bus_addr, flags, 0, MAP_NOCACHE);
+	return dm_pci_bus_to_virt(udev, pci_bus_addr + offset, flags, len,
+				  MAP_NOCACHE);
 }
 
 static int _dm_pci_find_next_capability(struct udevice *dev, u8 pos, int cap)
diff --git a/drivers/spi/octeon_spi.c b/drivers/spi/octeon_spi.c
index fcabc112d2..2f8a8a8649 100644
--- a/drivers/spi/octeon_spi.c
+++ b/drivers/spi/octeon_spi.c
@@ -568,7 +568,7 @@ static int octeon_spi_probe(struct udevice *dev)
 		pci_dev_t bdf = dm_pci_get_bdf(dev);
 
 		debug("SPI PCI device: %x\n", bdf);
-		priv->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+		priv->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
 					    PCI_REGION_MEM);
 		/* Add base offset */
 		priv->base += 0x1000;
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 6ddc9da704..eab0d96637 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -18,7 +18,7 @@ static int ohci_pci_probe(struct udevice *dev)
 {
 	struct ohci_regs *regs;
 
-	regs = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+	regs = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_MEM);
 	return ohci_register(dev, regs);
 }
 
diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c
index 03fa5cb608..504a7ff7b9 100644
--- a/drivers/virtio/virtio_pci_legacy.c
+++ b/drivers/virtio/virtio_pci_legacy.c
@@ -319,7 +319,7 @@ static int virtio_pci_probe(struct udevice *udev)
 	uc_priv->device = subdevice;
 	uc_priv->vendor = subvendor;
 
-	priv->ioaddr = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, PCI_REGION_IO);
+	priv->ioaddr = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_IO);
 	if (!priv->ioaddr)
 		return -ENXIO;
 	debug("(%s): virtio legacy device reg base %04lx\n",
diff --git a/include/pci.h b/include/pci.h
index e5fbe03cb9..d137debb68 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -1471,10 +1471,13 @@ pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t addr, size_t len,
  *
  * @dev:	Device to check
  * @bar:	Bar register offset (PCI_BASE_ADDRESS_...)
+ * @offset:     Offset from the base to map
+ * @len:        Length to map
  * @flags:	Flags for the region type (PCI_REGION_...)
  * @return: pointer to the virtual address to use or 0 on error
  */
-void *dm_pci_map_bar(struct udevice *dev, int bar, unsigned long flags);
+void *dm_pci_map_bar(struct udevice *dev, int bar, size_t offset, size_t len,
+		     unsigned long flags);
 
 /**
  * dm_pci_find_next_capability() - find a capability starting from an offset
diff --git a/test/dm/pci.c b/test/dm/pci.c
index 9789103c7d..c8598e4c17 100644
--- a/test/dm/pci.c
+++ b/test/dm/pci.c
@@ -268,27 +268,27 @@ static int dm_test_pci_ea(struct unit_test_state *uts)
 	ut_asserteq(PCI_CAP_ID_EA_OFFSET, cap);
 
 	/* test swap case in BAR 1 */
-	bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_0, 0);
+	bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_0, 0, 0, 0);
 	ut_assertnonnull(bar);
 	*(int *)bar = 2; /* swap upper/lower */
 
-	bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_1, 0);
+	bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_1, 0, 0, 0);
 	ut_assertnonnull(bar);
 	strcpy(bar, "ea TEST");
 	unmap_sysmem(bar);
-	bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_1, 0);
+	bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_1, 0, 0, 0);
 	ut_assertnonnull(bar);
 	ut_asserteq_str("EA test", bar);
 
 	/* test magic values in BARs2, 4;  BAR 3 is n/a */
-	bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_2, 0);
+	bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_2, 0, 0, 0);
 	ut_assertnonnull(bar);
 	ut_asserteq(PCI_EA_BAR2_MAGIC, *(u32 *)bar);
 
-	bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_3, 0);
+	bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_3, 0, 0, 0);
 	ut_assertnull(bar);
 
-	bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_4, 0);
+	bar = dm_pci_map_bar(swap, PCI_BASE_ADDRESS_4, 0, 0, 0);
 	ut_assertnonnull(bar);
 	ut_asserteq(PCI_EA_BAR4_MAGIC, *(u32 *)bar);
 
-- 
2.35.1.1021.g381101b075-goog



More information about the U-Boot mailing list