[PATCH v8 2/3] PCI: Make sure the driver could get correct BAR size from pci_resource_len()

Yongji Xie xyjxie at linux.vnet.ibm.com
Fri Jan 20 18:41:52 AEDT 2017


When using resource_alignment kernel parameter, the current implement
reassigns the alignment by expanding resources' size. So there exists two
kinds of *size* for one PCI BAR. One is the hardware size, the other is
the allocated size. Currently pci_resource_len() used by drivers return
the allocated size rather than the hardware size. This may potentially
break some drivers when they use the size to locate some registers whose
length is related to the hardware size. Some examples as below:

- misc\Hpilo.c:
off = pci_resource_len(pdev, bar) - 0x2000;

- net\ethernet\chelsio\cxgb4\cxgb4_uld.h:
(pci_resource_len((pdev), 2) - roundup_pow_of_two((vres)->ocq.size))

- infiniband\hw\nes\Nes_hw.c:
num_pds = pci_resource_len(nesdev->pcidev, BAR_1) >> PAGE_SHIFT;

This modifies pci_resource_len() to be aware of the increased size.
So it could return the hardware size instead. And if we need the allocated
size, resource_size()(or we can introuce a new helper function) can be used
to get it.

Signed-off-by: Yongji Xie <xyjxie at linux.vnet.ibm.com>
---
 drivers/pci/pci.c   |    1 +
 include/linux/pci.h |    6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 220c31e..04f2100 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -5096,6 +5096,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
 
 		size = resource_size(r);
 		if (size < align) {
+			dev->res_addsize[i] = align - size;
 			size = align;
 			dev_info(&dev->dev,
 				"Rounding up size of resource #%d to %#llx.\n",
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e2d1a12..e4099fb 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -334,6 +334,7 @@ struct pci_dev {
 	 */
 	unsigned int	irq;
 	struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
+	resource_size_t res_addsize[PCI_ROM_RESOURCE + 1];
 
 	bool match_driver;		/* Skip attaching driver */
 	/* These fields are used by common fixups */
@@ -1644,7 +1645,10 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
 /* these helpers provide future and backwards compatibility
  * for accessing popular PCI BAR info */
 #define pci_resource_start(dev, bar)	((dev)->resource[(bar)].start)
-#define pci_resource_end(dev, bar)	((dev)->resource[(bar)].end)
+#define pci_resource_end(dev, bar)	(((bar) > PCI_ROM_RESOURCE) ?	\
+					(dev)->resource[(bar)].end :	\
+					((dev)->resource[(bar)].end -	\
+					(dev)->res_addsize[(bar)]))
 #define pci_resource_flags(dev, bar)	((dev)->resource[(bar)].flags)
 #define pci_resource_len(dev,bar) \
 	((pci_resource_start((dev), (bar)) == 0 &&	\
-- 
1.7.9.5



More information about the Linuxppc-dev mailing list