PCI: Add pci_bus_addr_t
David Ahern reported thatd63e2e1f3d
("sparc/PCI: Clip bridge windows to fit in upstream windows") fails to boot on sparc/T5-8: pci 0000:06:00.0: reg 0x184: can't handle BAR above 4GB (bus address 0x110204000) The problem is that sparc64 assumed that dma_addr_t only needed to hold DMA addresses, i.e., bus addresses returned via the DMA API (dma_map_single(), etc.), while the PCI core assumed dma_addr_t could hold *any* bus address, including raw BAR values. On sparc64, all DMA addresses fit in 32 bits, so dma_addr_t is a 32-bit type. However, BAR values can be 64 bits wide, so they don't fit in a dma_addr_t.d63e2e1f3d
added new checking that tripped over this mismatch. Add pci_bus_addr_t, which is wide enough to hold any PCI bus address, including both raw BAR values and DMA addresses. This will be 64 bits on 64-bit platforms and on platforms with a 64-bit dma_addr_t. Then dma_addr_t only needs to be wide enough to hold addresses from the DMA API. [bhelgaas: changelog, bugzilla, Kconfig to ensure pci_bus_addr_t is at least as wide as dma_addr_t, documentation] Fixes:d63e2e1f3d
("sparc/PCI: Clip bridge windows to fit in upstream windows") Fixes:23b13bc76f
("PCI: Fail safely if we can't handle BARs larger than 4GB") Link: http://lkml.kernel.org/r/CAE9FiQU1gJY1LYrxs+ma5LCTEEe4xmtjRG0aXJ9K_Tsu+m9Wuw@mail.gmail.com Link: http://lkml.kernel.org/r/1427857069-6789-1-git-send-email-yinghai@kernel.org Link: https://bugzilla.kernel.org/show_bug.cgi?id=96231 Reported-by: David Ahern <david.ahern@oracle.com> Tested-by: David Ahern <david.ahern@oracle.com> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: David S. Miller <davem@davemloft.net> CC: stable@vger.kernel.org # v3.19+
This commit is contained in:
parent
5ebe6afaf0
commit
3a9ad0b4fd
7 changed files with 66 additions and 43 deletions
|
@ -577,9 +577,15 @@ int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
|
|||
int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
|
||||
int reg, int len, u32 val);
|
||||
|
||||
#ifdef CONFIG_PCI_BUS_ADDR_T_64BIT
|
||||
typedef u64 pci_bus_addr_t;
|
||||
#else
|
||||
typedef u32 pci_bus_addr_t;
|
||||
#endif
|
||||
|
||||
struct pci_bus_region {
|
||||
dma_addr_t start;
|
||||
dma_addr_t end;
|
||||
pci_bus_addr_t start;
|
||||
pci_bus_addr_t end;
|
||||
};
|
||||
|
||||
struct pci_dynids {
|
||||
|
@ -1128,7 +1134,7 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
|
|||
|
||||
int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
|
||||
|
||||
static inline dma_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
|
||||
static inline pci_bus_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
|
||||
{
|
||||
struct pci_bus_region region;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue