[PATCH v2] PCI: Update Resizable BAR Capability Register fields

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



PCI Express Base Spec r6.0 defines BAR size up to 8 EB (2^63 bytes),
but supporting anything bigger than 128TB requires changes to pci_rebar_get_possible_sizes()
to read the additional Capability bits from the Control register.

Signed-off-by: Zhiyuan Dai <daizhiyuan@xxxxxxxxxxxxxx>
---
 drivers/pci/pci.c             | 14 ++++++++++----
 include/uapi/linux/pci_regs.h |  3 ++-
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 661f98c6c63a..8903deb2d891 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3752,12 +3752,13 @@ static int pci_rebar_find_pos(struct pci_dev *pdev, int bar)
  * @bar: BAR to query
  *
  * Get the possible sizes of a resizable BAR as bitmask defined in the spec
- * (bit 0=1MB, bit 19=512GB). Returns 0 if BAR isn't resizable.
+ * (bit 0=1MB, bit 43=8EB). Returns 0 if BAR isn't resizable.
  */
-u32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar)
+u64 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar)
 {
 	int pos;
-	u32 cap;
+	u64 cap;
+	u32 cap2;
 
 	pos = pci_rebar_find_pos(pdev, bar);
 	if (pos < 0)
@@ -3766,6 +3767,11 @@ u32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar)
 	pci_read_config_dword(pdev, pos + PCI_REBAR_CAP, &cap);
 	cap = FIELD_GET(PCI_REBAR_CAP_SIZES, cap);
 
+	pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &cap2);
+	cap2 = FIELD_GET(PCI_REBAR_CTRL_CAP_SIZES, cap2);
+
+	cap |= (cap2 << 32);
+
 	/* Sapphire RX 5600 XT Pulse has an invalid cap dword for BAR 0 */
 	if (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x731f &&
 	    bar == 0 && cap == 0x700)
@@ -3800,7 +3806,7 @@ int pci_rebar_get_current_size(struct pci_dev *pdev, int bar)
  * pci_rebar_set_size - set a new size for a BAR
  * @pdev: PCI device
  * @bar: BAR to set size to
- * @size: new size as defined in the spec (0=1MB, 19=512GB)
+ * @size: new size as defined in the spec (0=1MB, 43=8EB)
  *
  * Set the new size of a BAR as defined in the spec.
  * Returns zero if resizing was successful, error code otherwise.
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 1601c7ed5fab..345f45264567 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -1013,13 +1013,14 @@
 
 /* Resizable BARs */
 #define PCI_REBAR_CAP		4	/* capability register */
-#define  PCI_REBAR_CAP_SIZES		0x00FFFFF0  /* supported BAR sizes */
+#define  PCI_REBAR_CAP_SIZES		0xFFFFFFF0  /* supported BAR sizes */
 #define PCI_REBAR_CTRL		8	/* control register */
 #define  PCI_REBAR_CTRL_BAR_IDX		0x00000007  /* BAR index */
 #define  PCI_REBAR_CTRL_NBAR_MASK	0x000000E0  /* # of resizable BARs */
 #define  PCI_REBAR_CTRL_NBAR_SHIFT	5	    /* shift for # of BARs */
 #define  PCI_REBAR_CTRL_BAR_SIZE	0x00001F00  /* BAR size */
 #define  PCI_REBAR_CTRL_BAR_SHIFT	8	    /* shift for BAR size */
+#define  PCI_REBAR_CTRL_CAP_SIZES	0xFFFF0000  /* supported BAR sizes */
 
 /* Dynamic Power Allocation */
 #define PCI_DPA_CAP		4	/* capability register */
-- 
2.43.0





[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux