PCI changes for the v3.17 merge window:
Resource management - Support BAR sizes up to 128GB (Yinghai Lu) - Keep original resource if we fail to expand it (Guo Chao) - Return conventional error values from pci_revert_fw_address() (Bjorn Helgaas) - Tidy resource assignment messages (Bjorn Helgaas) - Don't exclude low BIOS area for non-PCI cards (Christoph Schulz) PCI device hotplug - Prevent NULL dereference during pciehp probe (Andreas Noever) - Make pciehp pcie_wait_cmd() self-contained (Bjorn Helgaas) - Wait for pciehp hotplug command completion lazily (Bjorn Helgaas) - Compute pciehp timeout from hotplug command start time (Bjorn Helgaas) - Remove pciehp assumptions about which commands cause completion events (Bjorn Helgaas) - Clear pciehp Data Link Layer State Changed during init (Myron Stowe) - Remove pciehp struct controller.no_cmd_complete (Rajat Jain) - Remove cpqphp unnecessary null test (Fabian Frederick) - Remove "invalid IRQ" warning for hot-added PCIe ports (Jiang Liu) IOMMU - Add DMA alias quirk for Intel 82801 bridge (Alex Williamson) MSI - Add internal msix_clear_and_set_ctrl() (Yijing Wang) - Remove unused msi_enabled_mask() (Yijing Wang) - Cache Multiple Message Capable in struct msi_desc (Yijing Wang) - Add msi_setup_entry() to clean up initialization (Yijing Wang) - Remove unused msi_remove_pci_irq_vectors() (Yijing Wang) - Retrieve first MSI IRQ from msi_desc rather than pci_dev (Yijing Wang) - Remove unused list access in __pci_restore_msix_state() (Yijing Wang) - Use irq_get_msi_desc() to simplify code (Yijing Wang) Generic host bridge driver - Fix GPL v2 license string typo (Bjorn Helgaas) Marvell MVEBU - Fix GPL v2 license string typo (Thierry Reding) NVIDIA Tegra - Use correct initial HW settings (Phil Edworthy) - Remove rcar_pcie_setup_window() resource argument (Phil Edworthy) - Fix GPL v2 license string typo (Thierry Reding) Renesas R-Car - Remove redundant config accessor register checks (Sergei Shtylyov) - Fix GPL v2 license string typo (Bjorn Helgaas) Virtualization - Factor secondary bus reset logic (Gavin Shan) - Remove duplicate powerpc reset logic (Gavin Shan) Miscellaneous - Rework default VGA detection for EFI (Bruno Prémont) - Fix sysfs "acpi_index" and "label" errors for NIC renaming (Simone Gotti) - Configure ASPM at pci_enable_device()-time (Vidya Sagar) - Add include/linux/pci_ids.h include guard (Rasmus Villemoes) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJTzppBAAoJEFmIoMA60/r8mtQP/jgVWCSU+0ulHjoxVSRLu4Lc UGKQFjS03oWWflHdvW6wZFqN82Ynva9fYCLMtiKdPg7cgTosSRT3I4DjAIm80ZI/ kZvHxSmi6DBYmchZBsWzj60zxNiYZeEgd7CevzcJRHuwbKNMr2y12s6hjJbyl5lF ygaXWpDveKjsEDjyk9vKjUGwul/NJKynar253Yh178XaoypdGuiEIw3D1lQFMZZp ADcRijIi+CD2BENtDr6fbldbj+yQ93yyUSloEnaKtWZD+Ao5IsHngN0IyRu+l1Wl LFob0AsopeYVFKdw22Gn1KAq9Jj01acsSBRXjgrauU+tLY512Vkbp1lFYl85B/38 /Z0VNHncmIh29rq9Tl2xQwEeI3Ja27FfnMjC70dLM5YjWf8vsYnDEQZHyxAAe15D p3H3YuuDjmvHkoSrHY/68DLfDl9ubw3/BFUlCMqijL7444ZWLXathrnCV8ZJimmr PlF/m7GtXYF4wIw19m9KQqNBUPJJEsVHExKzICOY4v5/nMlvx4ZkBDR3tPNEH1sk 3AYKjLDw21Nle7yKcAlxDI/TYWZqxuph23UpevzlQd16tutq2i2FqpauiqI3DFm4 VfYVbOVQwfeUJt11VOCgxvE7RsTxCk5QefB+YKVAdVK6vMZHeZxsetYvrCDptnea cId/NfiEFnmr+u3mAyPM =U5Ip -----END PGP SIGNATURE----- Merge tag 'pci-v3.17-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci Pull PCI updates from Bjorn Helgaas: "I'll be on vacation until Aug 11, and I suspect the merge window will open before then, so I'm sending this to you early. There are more things I'd like to get into v3.17, so I hope to send another pull request soon after I return. The most notable pieces here are: - Support BARs up to 128GB (up from 8GB) - Fix SR-IOV resource assignment when we fail to expand a resource - Rework pciehp to handle a common hardware erratum - Cleanup MSI - Fix NIC renaming issue - Fix VGA default device issue on EFI systems - Fix ASPM configuration (previously we didn't enable it as expected) Alex Williamson has graciously agreed to take care of any major issues with this if you take it before I return. Details: Resource management - Support BAR sizes up to 128GB (Yinghai Lu) - Keep original resource if we fail to expand it (Guo Chao) - Return conventional error values from pci_revert_fw_address() (Bjorn Helgaas) - Tidy resource assignment messages (Bjorn Helgaas) - Don't exclude low BIOS area for non-PCI cards (Christoph Schulz) PCI device hotplug - Prevent NULL dereference during pciehp probe (Andreas Noever) - Make pciehp pcie_wait_cmd() self-contained (Bjorn Helgaas) - Wait for pciehp hotplug command completion lazily (Bjorn Helgaas) - Compute pciehp timeout from hotplug command start time (Bjorn Helgaas) - Remove pciehp assumptions about which commands cause completion events (Bjorn Helgaas) - Clear pciehp Data Link Layer State Changed during init (Myron Stowe) - Remove pciehp struct controller.no_cmd_complete (Rajat Jain) - Remove cpqphp unnecessary null test (Fabian Frederick) - Remove "invalid IRQ" warning for hot-added PCIe ports (Jiang Liu) IOMMU - Add DMA alias quirk for Intel 82801 bridge (Alex Williamson) MSI - Add internal msix_clear_and_set_ctrl() (Yijing Wang) - Remove unused msi_enabled_mask() (Yijing Wang) - Cache Multiple Message Capable in struct msi_desc (Yijing Wang) - Add msi_setup_entry() to clean up initialization (Yijing Wang) - Remove unused msi_remove_pci_irq_vectors() (Yijing Wang) - Retrieve first MSI IRQ from msi_desc rather than pci_dev (Yijing Wang) - Remove unused list access in __pci_restore_msix_state() (Yijing Wang) - Use irq_get_msi_desc() to simplify code (Yijing Wang) Generic host bridge driver - Fix GPL v2 license string typo (Bjorn Helgaas) Marvell MVEBU - Fix GPL v2 license string typo (Thierry Reding) NVIDIA Tegra - Use correct initial HW settings (Phil Edworthy) - Remove rcar_pcie_setup_window() resource argument (Phil Edworthy) - Fix GPL v2 license string typo (Thierry Reding) Renesas R-Car - Remove redundant config accessor register checks (Sergei Shtylyov) - Fix GPL v2 license string typo (Bjorn Helgaas) Virtualization - Factor secondary bus reset logic (Gavin Shan) - Remove duplicate powerpc reset logic (Gavin Shan) Miscellaneous - Rework default VGA detection for EFI (Bruno Prémont) - Fix sysfs "acpi_index" and "label" errors for NIC renaming (Simone Gotti) - Configure ASPM at pci_enable_device()-time (Vidya Sagar) - Add include/linux/pci_ids.h include guard (Rasmus Villemoes)" * tag 'pci-v3.17-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (38 commits) PCI/MSI: Use irq_get_msi_desc() to simplify code PCI/MSI: Remove unused list access in __pci_restore_msix_state() PCI/MSI: Retrieve first MSI IRQ from msi_desc rather than pci_dev PCI/MSI: Remove unused function msi_remove_pci_irq_vectors() PCI/MSI: Add msi_setup_entry() to clean up MSI initialization PCI: Configure ASPM when enabling device x86: don't exclude low BIOS area when allocating address space for non-PCI cards PCI: generic: Fix GPL v2 license string typo PCI: rcar: Fix GPL v2 license string typo PCI: tegra: Fix GPL v2 license string typo PCI: mvebu: Fix GPL v2 license string typo PCI: Add include guard to include/linux/pci_ids.h x86, ia64: Move EFI_FB vga_default_device() initialization to pci_vga_fixup() PCI: Tidy resource assignment messages PCI: Return conventional error values from pci_revert_fw_address() PCI: Cleanup control flow PCI: Support BAR sizes up to 128GB PCI: cpqphp: Remove unnecessary null test before debugfs_remove() PCI: pciehp: Clear Data Link Layer State Changed during init PCI: Add bridge DMA alias quirk for Intel 82801 bridge ...
This commit is contained in:
Коммит
f74ad8df4e
|
@ -6,6 +6,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/vgaarb.h>
|
||||
#include <linux/screen_info.h>
|
||||
|
||||
#include <asm/machvec.h>
|
||||
|
||||
|
@ -37,6 +38,27 @@ static void pci_fixup_video(struct pci_dev *pdev)
|
|||
return;
|
||||
/* Maybe, this machine supports legacy memory map. */
|
||||
|
||||
if (!vga_default_device()) {
|
||||
resource_size_t start, end;
|
||||
int i;
|
||||
|
||||
/* Does firmware framebuffer belong to us? */
|
||||
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
|
||||
if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
|
||||
continue;
|
||||
|
||||
start = pci_resource_start(pdev, i);
|
||||
end = pci_resource_end(pdev, i);
|
||||
|
||||
if (!start || !end)
|
||||
continue;
|
||||
|
||||
if (screen_info.lfb_base >= start &&
|
||||
(screen_info.lfb_base + screen_info.lfb_size) < end)
|
||||
vga_set_default_device(pdev);
|
||||
}
|
||||
}
|
||||
|
||||
/* Is VGA routed to us? */
|
||||
bus = pdev->bus;
|
||||
while (bus) {
|
||||
|
|
|
@ -123,21 +123,12 @@ resource_size_t pcibios_window_alignment(struct pci_bus *bus,
|
|||
|
||||
void pcibios_reset_secondary_bus(struct pci_dev *dev)
|
||||
{
|
||||
u16 ctrl;
|
||||
|
||||
if (ppc_md.pcibios_reset_secondary_bus) {
|
||||
ppc_md.pcibios_reset_secondary_bus(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl);
|
||||
ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
|
||||
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
|
||||
msleep(2);
|
||||
|
||||
ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
|
||||
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
|
||||
ssleep(1);
|
||||
pci_reset_secondary_bus(dev);
|
||||
}
|
||||
|
||||
static resource_size_t pcibios_io_size(const struct pci_controller *hose)
|
||||
|
|
|
@ -17,10 +17,4 @@
|
|||
#define vga_readb(x) (*(x))
|
||||
#define vga_writeb(x, y) (*(y) = (x))
|
||||
|
||||
#ifdef CONFIG_FB_EFI
|
||||
#define __ARCH_HAS_VGA_DEFAULT_DEVICE
|
||||
extern struct pci_dev *vga_default_device(void);
|
||||
extern void vga_set_default_device(struct pci_dev *pdev);
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_X86_VGA_H */
|
||||
|
|
|
@ -37,10 +37,12 @@ static void remove_e820_regions(struct resource *avail)
|
|||
|
||||
void arch_remove_reservations(struct resource *avail)
|
||||
{
|
||||
/* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */
|
||||
/*
|
||||
* Trim out BIOS area (high 2MB) and E820 regions. We do not remove
|
||||
* the low 1MB unconditionally, as this area is needed for some ISA
|
||||
* cards requiring a memory range, e.g. the i82365 PCMCIA controller.
|
||||
*/
|
||||
if (avail->flags & IORESOURCE_MEM) {
|
||||
if (avail->start < BIOS_END)
|
||||
avail->start = BIOS_END;
|
||||
resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END);
|
||||
|
||||
remove_e820_regions(avail);
|
||||
|
|
|
@ -326,6 +326,27 @@ static void pci_fixup_video(struct pci_dev *pdev)
|
|||
struct pci_bus *bus;
|
||||
u16 config;
|
||||
|
||||
if (!vga_default_device()) {
|
||||
resource_size_t start, end;
|
||||
int i;
|
||||
|
||||
/* Does firmware framebuffer belong to us? */
|
||||
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
|
||||
if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
|
||||
continue;
|
||||
|
||||
start = pci_resource_start(pdev, i);
|
||||
end = pci_resource_end(pdev, i);
|
||||
|
||||
if (!start || !end)
|
||||
continue;
|
||||
|
||||
if (screen_info.lfb_base >= start &&
|
||||
(screen_info.lfb_base + screen_info.lfb_size) < end)
|
||||
vga_set_default_device(pdev);
|
||||
}
|
||||
}
|
||||
|
||||
/* Is VGA routed to us? */
|
||||
bus = pdev->bus;
|
||||
while (bus) {
|
||||
|
|
|
@ -162,6 +162,10 @@ pcibios_align_resource(void *data, const struct resource *res,
|
|||
return start;
|
||||
if (start & 0x300)
|
||||
start = (start + 0x3ff) & ~0x3ff;
|
||||
} else if (res->flags & IORESOURCE_MEM) {
|
||||
/* The low 1MB range is reserved for ISA cards */
|
||||
if (start < BIOS_END)
|
||||
start = BIOS_END;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
|
|
@ -385,4 +385,4 @@ module_platform_driver(gen_pci_driver);
|
|||
|
||||
MODULE_DESCRIPTION("Generic PCI host driver");
|
||||
MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
|
||||
MODULE_LICENSE("GPLv2");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -1094,4 +1094,4 @@ module_platform_driver(mvebu_pcie_driver);
|
|||
|
||||
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
|
||||
MODULE_DESCRIPTION("Marvell EBU PCIe driver");
|
||||
MODULE_LICENSE("GPLv2");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -1716,4 +1716,4 @@ module_platform_driver(tegra_pcie_driver);
|
|||
|
||||
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
|
||||
MODULE_DESCRIPTION("NVIDIA Tegra PCIe driver");
|
||||
MODULE_LICENSE("GPLv2");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 19)
|
||||
#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 16)
|
||||
|
||||
#define PCI_MAX_RESOURCES 4
|
||||
#define RCAR_PCI_MAX_RESOURCES 4
|
||||
#define MAX_NR_INBOUND_MAPS 6
|
||||
|
||||
struct rcar_msi {
|
||||
|
@ -127,7 +127,7 @@ static inline struct rcar_msi *to_rcar_msi(struct msi_chip *chip)
|
|||
struct rcar_pcie {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct resource res[PCI_MAX_RESOURCES];
|
||||
struct resource res[RCAR_PCI_MAX_RESOURCES];
|
||||
struct resource busn;
|
||||
int root_bus_nr;
|
||||
struct clk *clk;
|
||||
|
@ -140,36 +140,37 @@ static inline struct rcar_pcie *sys_to_pcie(struct pci_sys_data *sys)
|
|||
return sys->private_data;
|
||||
}
|
||||
|
||||
static void pci_write_reg(struct rcar_pcie *pcie, unsigned long val,
|
||||
unsigned long reg)
|
||||
static void rcar_pci_write_reg(struct rcar_pcie *pcie, unsigned long val,
|
||||
unsigned long reg)
|
||||
{
|
||||
writel(val, pcie->base + reg);
|
||||
}
|
||||
|
||||
static unsigned long pci_read_reg(struct rcar_pcie *pcie, unsigned long reg)
|
||||
static unsigned long rcar_pci_read_reg(struct rcar_pcie *pcie,
|
||||
unsigned long reg)
|
||||
{
|
||||
return readl(pcie->base + reg);
|
||||
}
|
||||
|
||||
enum {
|
||||
PCI_ACCESS_READ,
|
||||
PCI_ACCESS_WRITE,
|
||||
RCAR_PCI_ACCESS_READ,
|
||||
RCAR_PCI_ACCESS_WRITE,
|
||||
};
|
||||
|
||||
static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)
|
||||
{
|
||||
int shift = 8 * (where & 3);
|
||||
u32 val = pci_read_reg(pcie, where & ~3);
|
||||
u32 val = rcar_pci_read_reg(pcie, where & ~3);
|
||||
|
||||
val &= ~(mask << shift);
|
||||
val |= data << shift;
|
||||
pci_write_reg(pcie, val, where & ~3);
|
||||
rcar_pci_write_reg(pcie, val, where & ~3);
|
||||
}
|
||||
|
||||
static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)
|
||||
{
|
||||
int shift = 8 * (where & 3);
|
||||
u32 val = pci_read_reg(pcie, where & ~3);
|
||||
u32 val = rcar_pci_read_reg(pcie, where & ~3);
|
||||
|
||||
return val >> shift;
|
||||
}
|
||||
|
@ -205,14 +206,14 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
|
|||
if (dev != 0)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
if (access_type == PCI_ACCESS_READ) {
|
||||
*data = pci_read_reg(pcie, PCICONF(index));
|
||||
if (access_type == RCAR_PCI_ACCESS_READ) {
|
||||
*data = rcar_pci_read_reg(pcie, PCICONF(index));
|
||||
} else {
|
||||
/* Keep an eye out for changes to the root bus number */
|
||||
if (pci_is_root_bus(bus) && (reg == PCI_PRIMARY_BUS))
|
||||
pcie->root_bus_nr = *data & 0xff;
|
||||
|
||||
pci_write_reg(pcie, *data, PCICONF(index));
|
||||
rcar_pci_write_reg(pcie, *data, PCICONF(index));
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
|
@ -222,20 +223,20 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
|
|||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
/* Clear errors */
|
||||
pci_write_reg(pcie, pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
|
||||
rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
|
||||
|
||||
/* Set the PIO address */
|
||||
pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) | PCIE_CONF_DEV(dev) |
|
||||
PCIE_CONF_FUNC(func) | reg, PCIECAR);
|
||||
rcar_pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) |
|
||||
PCIE_CONF_DEV(dev) | PCIE_CONF_FUNC(func) | reg, PCIECAR);
|
||||
|
||||
/* Enable the configuration access */
|
||||
if (bus->parent->number == pcie->root_bus_nr)
|
||||
pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
|
||||
rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
|
||||
else
|
||||
pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
|
||||
rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
|
||||
|
||||
/* Check for errors */
|
||||
if (pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
|
||||
if (rcar_pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
/* Check for master and target aborts */
|
||||
|
@ -243,13 +244,13 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
|
|||
(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
if (access_type == PCI_ACCESS_READ)
|
||||
*data = pci_read_reg(pcie, PCIECDR);
|
||||
if (access_type == RCAR_PCI_ACCESS_READ)
|
||||
*data = rcar_pci_read_reg(pcie, PCIECDR);
|
||||
else
|
||||
pci_write_reg(pcie, *data, PCIECDR);
|
||||
rcar_pci_write_reg(pcie, *data, PCIECDR);
|
||||
|
||||
/* Disable the configuration access */
|
||||
pci_write_reg(pcie, 0, PCIECCTLR);
|
||||
rcar_pci_write_reg(pcie, 0, PCIECCTLR);
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
@ -260,12 +261,7 @@ static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
|
|||
struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
|
||||
int ret;
|
||||
|
||||
if ((size == 2) && (where & 1))
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
else if ((size == 4) && (where & 3))
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
|
||||
ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
|
||||
ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_READ,
|
||||
bus, devfn, where, val);
|
||||
if (ret != PCIBIOS_SUCCESSFUL) {
|
||||
*val = 0xffffffff;
|
||||
|
@ -291,12 +287,7 @@ static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
|
|||
int shift, ret;
|
||||
u32 data;
|
||||
|
||||
if ((size == 2) && (where & 1))
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
else if ((size == 4) && (where & 3))
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
|
||||
ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
|
||||
ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_READ,
|
||||
bus, devfn, where, &data);
|
||||
if (ret != PCIBIOS_SUCCESSFUL)
|
||||
return ret;
|
||||
|
@ -315,7 +306,7 @@ static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
|
|||
} else
|
||||
data = val;
|
||||
|
||||
ret = rcar_pcie_config_access(pcie, PCI_ACCESS_WRITE,
|
||||
ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_WRITE,
|
||||
bus, devfn, where, &data);
|
||||
|
||||
return ret;
|
||||
|
@ -326,14 +317,15 @@ static struct pci_ops rcar_pcie_ops = {
|
|||
.write = rcar_pcie_write_conf,
|
||||
};
|
||||
|
||||
static void rcar_pcie_setup_window(int win, struct resource *res,
|
||||
struct rcar_pcie *pcie)
|
||||
static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
|
||||
{
|
||||
struct resource *res = &pcie->res[win];
|
||||
|
||||
/* Setup PCIe address space mappings for each resource */
|
||||
resource_size_t size;
|
||||
u32 mask;
|
||||
|
||||
pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
|
||||
rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
|
||||
|
||||
/*
|
||||
* The PAMR mask is calculated in units of 128Bytes, which
|
||||
|
@ -341,17 +333,17 @@ static void rcar_pcie_setup_window(int win, struct resource *res,
|
|||
*/
|
||||
size = resource_size(res);
|
||||
mask = (roundup_pow_of_two(size) / SZ_128) - 1;
|
||||
pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
|
||||
rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
|
||||
|
||||
pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
|
||||
pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
|
||||
rcar_pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
|
||||
rcar_pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
|
||||
|
||||
/* First resource is for IO */
|
||||
mask = PAR_ENABLE;
|
||||
if (res->flags & IORESOURCE_IO)
|
||||
mask |= IO_SPACE;
|
||||
|
||||
pci_write_reg(pcie, mask, PCIEPTCTLR(win));
|
||||
rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win));
|
||||
}
|
||||
|
||||
static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
|
||||
|
@ -363,13 +355,13 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
|
|||
pcie->root_bus_nr = -1;
|
||||
|
||||
/* Setup PCI resources */
|
||||
for (i = 0; i < PCI_MAX_RESOURCES; i++) {
|
||||
for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) {
|
||||
|
||||
res = &pcie->res[i];
|
||||
if (!res->flags)
|
||||
continue;
|
||||
|
||||
rcar_pcie_setup_window(i, res, pcie);
|
||||
rcar_pcie_setup_window(i, pcie);
|
||||
|
||||
if (res->flags & IORESOURCE_IO)
|
||||
pci_ioremap_io(nr * SZ_64K, res->start);
|
||||
|
@ -415,7 +407,7 @@ static int phy_wait_for_ack(struct rcar_pcie *pcie)
|
|||
unsigned int timeout = 100;
|
||||
|
||||
while (timeout--) {
|
||||
if (pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
|
||||
if (rcar_pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
|
||||
return 0;
|
||||
|
||||
udelay(100);
|
||||
|
@ -438,15 +430,15 @@ static void phy_write_reg(struct rcar_pcie *pcie,
|
|||
((addr & 0xff) << ADR_POS);
|
||||
|
||||
/* Set write data */
|
||||
pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
|
||||
pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
|
||||
rcar_pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
|
||||
rcar_pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
|
||||
|
||||
/* Ignore errors as they will be dealt with if the data link is down */
|
||||
phy_wait_for_ack(pcie);
|
||||
|
||||
/* Clear command */
|
||||
pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
|
||||
pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
|
||||
rcar_pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
|
||||
rcar_pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
|
||||
|
||||
/* Ignore errors as they will be dealt with if the data link is down */
|
||||
phy_wait_for_ack(pcie);
|
||||
|
@ -457,7 +449,7 @@ static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
|
|||
unsigned int timeout = 10;
|
||||
|
||||
while (timeout--) {
|
||||
if ((pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
|
||||
if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
|
||||
return 0;
|
||||
|
||||
msleep(5);
|
||||
|
@ -471,17 +463,17 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
|
|||
int err;
|
||||
|
||||
/* Begin initialization */
|
||||
pci_write_reg(pcie, 0, PCIETCTLR);
|
||||
rcar_pci_write_reg(pcie, 0, PCIETCTLR);
|
||||
|
||||
/* Set mode */
|
||||
pci_write_reg(pcie, 1, PCIEMSR);
|
||||
rcar_pci_write_reg(pcie, 1, PCIEMSR);
|
||||
|
||||
/*
|
||||
* Initial header for port config space is type 1, set the device
|
||||
* class to match. Hardware takes care of propagating the IDSETR
|
||||
* settings, so there is no need to bother with a quirk.
|
||||
*/
|
||||
pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
|
||||
rcar_pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
|
||||
|
||||
/*
|
||||
* Setup Secondary Bus Number & Subordinate Bus Number, even though
|
||||
|
@ -491,33 +483,31 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
|
|||
rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
|
||||
|
||||
/* Initialize default capabilities. */
|
||||
rcar_rmw32(pcie, REXPCAP(0), 0, PCI_CAP_ID_EXP);
|
||||
rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
|
||||
rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
|
||||
PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
|
||||
rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
|
||||
PCI_HEADER_TYPE_BRIDGE);
|
||||
|
||||
/* Enable data link layer active state reporting */
|
||||
rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), 0, PCI_EXP_LNKCAP_DLLLARC);
|
||||
rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), PCI_EXP_LNKCAP_DLLLARC,
|
||||
PCI_EXP_LNKCAP_DLLLARC);
|
||||
|
||||
/* Write out the physical slot number = 0 */
|
||||
rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
|
||||
|
||||
/* Set the completion timer timeout to the maximum 50ms. */
|
||||
rcar_rmw32(pcie, TLCTLR+1, 0x3f, 50);
|
||||
rcar_rmw32(pcie, TLCTLR + 1, 0x3f, 50);
|
||||
|
||||
/* Terminate list of capabilities (Next Capability Offset=0) */
|
||||
rcar_rmw32(pcie, RVCCAP(0), 0xfff0, 0);
|
||||
|
||||
/* Enable MAC data scrambling. */
|
||||
rcar_rmw32(pcie, MACCTLR, SCRAMBLE_DISABLE, 0);
|
||||
rcar_rmw32(pcie, RVCCAP(0), 0xfff00000, 0);
|
||||
|
||||
/* Enable MSI */
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI))
|
||||
pci_write_reg(pcie, 0x101f0000, PCIEMSITXR);
|
||||
rcar_pci_write_reg(pcie, 0x101f0000, PCIEMSITXR);
|
||||
|
||||
/* Finish initialization - establish a PCI Express link */
|
||||
pci_write_reg(pcie, CFINIT, PCIETCTLR);
|
||||
rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
|
||||
|
||||
/* This will timeout if we don't have a link. */
|
||||
err = rcar_pcie_wait_for_dl(pcie);
|
||||
|
@ -527,11 +517,6 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
|
|||
/* Enable INTx interrupts */
|
||||
rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8);
|
||||
|
||||
/* Enable slave Bus Mastering */
|
||||
rcar_rmw32(pcie, RCONF(PCI_STATUS), PCI_STATUS_DEVSEL_MASK,
|
||||
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
|
||||
PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_FAST);
|
||||
|
||||
wmb();
|
||||
|
||||
return 0;
|
||||
|
@ -560,7 +545,7 @@ static int rcar_pcie_hw_init_h1(struct rcar_pcie *pcie)
|
|||
phy_write_reg(pcie, 0, 0x66, 0x1, 0x00008000);
|
||||
|
||||
while (timeout--) {
|
||||
if (pci_read_reg(pcie, H1_PCIEPHYSR))
|
||||
if (rcar_pci_read_reg(pcie, H1_PCIEPHYSR))
|
||||
return rcar_pcie_hw_init(pcie);
|
||||
|
||||
msleep(5);
|
||||
|
@ -599,7 +584,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
|
|||
struct rcar_msi *msi = &pcie->msi;
|
||||
unsigned long reg;
|
||||
|
||||
reg = pci_read_reg(pcie, PCIEMSIFR);
|
||||
reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
|
||||
|
||||
/* MSI & INTx share an interrupt - we only handle MSI here */
|
||||
if (!reg)
|
||||
|
@ -610,7 +595,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
|
|||
unsigned int irq;
|
||||
|
||||
/* clear the interrupt */
|
||||
pci_write_reg(pcie, 1 << index, PCIEMSIFR);
|
||||
rcar_pci_write_reg(pcie, 1 << index, PCIEMSIFR);
|
||||
|
||||
irq = irq_find_mapping(msi->domain, index);
|
||||
if (irq) {
|
||||
|
@ -624,7 +609,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
|
|||
}
|
||||
|
||||
/* see if there's any more pending in this vector */
|
||||
reg = pci_read_reg(pcie, PCIEMSIFR);
|
||||
reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -651,8 +636,8 @@ static int rcar_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
|
|||
|
||||
irq_set_msi_desc(irq, desc);
|
||||
|
||||
msg.address_lo = pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
|
||||
msg.address_hi = pci_read_reg(pcie, PCIEMSIAUR);
|
||||
msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
|
||||
msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR);
|
||||
msg.data = hwirq;
|
||||
|
||||
write_msi_msg(irq, &msg);
|
||||
|
@ -729,11 +714,11 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
|
|||
msi->pages = __get_free_pages(GFP_KERNEL, 0);
|
||||
base = virt_to_phys((void *)msi->pages);
|
||||
|
||||
pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
|
||||
pci_write_reg(pcie, 0, PCIEMSIAUR);
|
||||
rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
|
||||
rcar_pci_write_reg(pcie, 0, PCIEMSIAUR);
|
||||
|
||||
/* enable all MSI interrupts */
|
||||
pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
|
||||
rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -826,6 +811,7 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
|
|||
if (cpu_addr > 0) {
|
||||
unsigned long nr_zeros = __ffs64(cpu_addr);
|
||||
u64 alignment = 1ULL << nr_zeros;
|
||||
|
||||
size = min(range->size, alignment);
|
||||
} else {
|
||||
size = range->size;
|
||||
|
@ -841,13 +827,13 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
|
|||
* Set up 64-bit inbound regions as the range parser doesn't
|
||||
* distinguish between 32 and 64-bit types.
|
||||
*/
|
||||
pci_write_reg(pcie, lower_32_bits(pci_addr), PCIEPRAR(idx));
|
||||
pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx));
|
||||
pci_write_reg(pcie, lower_32_bits(mask) | flags, PCIELAMR(idx));
|
||||
rcar_pci_write_reg(pcie, lower_32_bits(pci_addr), PCIEPRAR(idx));
|
||||
rcar_pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx));
|
||||
rcar_pci_write_reg(pcie, lower_32_bits(mask) | flags, PCIELAMR(idx));
|
||||
|
||||
pci_write_reg(pcie, upper_32_bits(pci_addr), PCIEPRAR(idx+1));
|
||||
pci_write_reg(pcie, upper_32_bits(cpu_addr), PCIELAR(idx+1));
|
||||
pci_write_reg(pcie, 0, PCIELAMR(idx+1));
|
||||
rcar_pci_write_reg(pcie, upper_32_bits(pci_addr), PCIEPRAR(idx+1));
|
||||
rcar_pci_write_reg(pcie, upper_32_bits(cpu_addr), PCIELAR(idx+1));
|
||||
rcar_pci_write_reg(pcie, 0, PCIELAMR(idx + 1));
|
||||
|
||||
pci_addr += size;
|
||||
cpu_addr += size;
|
||||
|
@ -952,7 +938,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
|
|||
of_pci_range_to_resource(&range, pdev->dev.of_node,
|
||||
&pcie->res[win++]);
|
||||
|
||||
if (win > PCI_MAX_RESOURCES)
|
||||
if (win > RCAR_PCI_MAX_RESOURCES)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -982,7 +968,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
data = pci_read_reg(pcie, MACSR);
|
||||
data = rcar_pci_read_reg(pcie, MACSR);
|
||||
dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
|
||||
|
||||
rcar_pcie_enable(pcie);
|
||||
|
@ -1003,4 +989,4 @@ module_platform_driver(rcar_pcie_driver);
|
|||
|
||||
MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
|
||||
MODULE_DESCRIPTION("Renesas R-Car PCIe driver");
|
||||
MODULE_LICENSE("GPLv2");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -216,8 +216,7 @@ void cpqhp_create_debugfs_files(struct controller *ctrl)
|
|||
|
||||
void cpqhp_remove_debugfs_files(struct controller *ctrl)
|
||||
{
|
||||
if (ctrl->dentry)
|
||||
debugfs_remove(ctrl->dentry);
|
||||
debugfs_remove(ctrl->dentry);
|
||||
ctrl->dentry = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,9 +92,10 @@ struct controller {
|
|||
struct slot *slot;
|
||||
wait_queue_head_t queue; /* sleep & wake process */
|
||||
u32 slot_cap;
|
||||
u32 slot_ctrl;
|
||||
struct timer_list poll_timer;
|
||||
unsigned long cmd_started; /* jiffies */
|
||||
unsigned int cmd_busy:1;
|
||||
unsigned int no_cmd_complete:1;
|
||||
unsigned int link_active_reporting:1;
|
||||
unsigned int notification_enabled:1;
|
||||
unsigned int power_fault_detected;
|
||||
|
|
|
@ -255,6 +255,13 @@ static int pciehp_probe(struct pcie_device *dev)
|
|||
else if (pciehp_acpi_slot_detection_check(dev->port))
|
||||
goto err_out_none;
|
||||
|
||||
if (!dev->port->subordinate) {
|
||||
/* Can happen if we run out of bus numbers during probe */
|
||||
dev_err(&dev->device,
|
||||
"Hotplug bridge without secondary bus, ignoring\n");
|
||||
goto err_out_none;
|
||||
}
|
||||
|
||||
ctrl = pcie_init(dev);
|
||||
if (!ctrl) {
|
||||
dev_err(&dev->device, "Controller initialization failed\n");
|
||||
|
|
|
@ -104,11 +104,10 @@ static inline void pciehp_free_irq(struct controller *ctrl)
|
|||
free_irq(ctrl->pcie->irq, ctrl);
|
||||
}
|
||||
|
||||
static int pcie_poll_cmd(struct controller *ctrl)
|
||||
static int pcie_poll_cmd(struct controller *ctrl, int timeout)
|
||||
{
|
||||
struct pci_dev *pdev = ctrl_dev(ctrl);
|
||||
u16 slot_status;
|
||||
int timeout = 1000;
|
||||
|
||||
pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
|
||||
if (slot_status & PCI_EXP_SLTSTA_CC) {
|
||||
|
@ -129,18 +128,52 @@ static int pcie_poll_cmd(struct controller *ctrl)
|
|||
return 0; /* timeout */
|
||||
}
|
||||
|
||||
static void pcie_wait_cmd(struct controller *ctrl, int poll)
|
||||
static void pcie_wait_cmd(struct controller *ctrl)
|
||||
{
|
||||
unsigned int msecs = pciehp_poll_mode ? 2500 : 1000;
|
||||
unsigned long timeout = msecs_to_jiffies(msecs);
|
||||
unsigned long duration = msecs_to_jiffies(msecs);
|
||||
unsigned long cmd_timeout = ctrl->cmd_started + duration;
|
||||
unsigned long now, timeout;
|
||||
int rc;
|
||||
|
||||
if (poll)
|
||||
rc = pcie_poll_cmd(ctrl);
|
||||
/*
|
||||
* If the controller does not generate notifications for command
|
||||
* completions, we never need to wait between writes.
|
||||
*/
|
||||
if (NO_CMD_CMPL(ctrl))
|
||||
return;
|
||||
|
||||
if (!ctrl->cmd_busy)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Even if the command has already timed out, we want to call
|
||||
* pcie_poll_cmd() so it can clear PCI_EXP_SLTSTA_CC.
|
||||
*/
|
||||
now = jiffies;
|
||||
if (time_before_eq(cmd_timeout, now))
|
||||
timeout = 1;
|
||||
else
|
||||
timeout = cmd_timeout - now;
|
||||
|
||||
if (ctrl->slot_ctrl & PCI_EXP_SLTCTL_HPIE &&
|
||||
ctrl->slot_ctrl & PCI_EXP_SLTCTL_CCIE)
|
||||
rc = wait_event_timeout(ctrl->queue, !ctrl->cmd_busy, timeout);
|
||||
else
|
||||
rc = pcie_poll_cmd(ctrl, timeout);
|
||||
|
||||
/*
|
||||
* Controllers with errata like Intel CF118 don't generate
|
||||
* completion notifications unless the power/indicator/interlock
|
||||
* control bits are changed. On such controllers, we'll emit this
|
||||
* timeout message when we wait for completion of commands that
|
||||
* don't change those bits, e.g., commands that merely enable
|
||||
* interrupts.
|
||||
*/
|
||||
if (!rc)
|
||||
ctrl_dbg(ctrl, "Command not completed in 1000 msec\n");
|
||||
ctrl_info(ctrl, "Timeout on hotplug command %#010x (issued %u msec ago)\n",
|
||||
ctrl->slot_ctrl,
|
||||
jiffies_to_msecs(now - ctrl->cmd_started));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,34 +185,12 @@ static void pcie_wait_cmd(struct controller *ctrl, int poll)
|
|||
static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
|
||||
{
|
||||
struct pci_dev *pdev = ctrl_dev(ctrl);
|
||||
u16 slot_status;
|
||||
u16 slot_ctrl;
|
||||
|
||||
mutex_lock(&ctrl->ctrl_lock);
|
||||
|
||||
pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
|
||||
if (slot_status & PCI_EXP_SLTSTA_CC) {
|
||||
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
|
||||
PCI_EXP_SLTSTA_CC);
|
||||
if (!ctrl->no_cmd_complete) {
|
||||
/*
|
||||
* After 1 sec and CMD_COMPLETED still not set, just
|
||||
* proceed forward to issue the next command according
|
||||
* to spec. Just print out the error message.
|
||||
*/
|
||||
ctrl_dbg(ctrl, "CMD_COMPLETED not clear after 1 sec\n");
|
||||
} else if (!NO_CMD_CMPL(ctrl)) {
|
||||
/*
|
||||
* This controller seems to notify of command completed
|
||||
* event even though it supports none of power
|
||||
* controller, attention led, power led and EMI.
|
||||
*/
|
||||
ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Need to wait for command completed event\n");
|
||||
ctrl->no_cmd_complete = 0;
|
||||
} else {
|
||||
ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Maybe the controller is broken\n");
|
||||
}
|
||||
}
|
||||
/* Wait for any previous command that might still be in progress */
|
||||
pcie_wait_cmd(ctrl);
|
||||
|
||||
pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);
|
||||
slot_ctrl &= ~mask;
|
||||
|
@ -187,22 +198,9 @@ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
|
|||
ctrl->cmd_busy = 1;
|
||||
smp_mb();
|
||||
pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl);
|
||||
ctrl->cmd_started = jiffies;
|
||||
ctrl->slot_ctrl = slot_ctrl;
|
||||
|
||||
/*
|
||||
* Wait for command completion.
|
||||
*/
|
||||
if (!ctrl->no_cmd_complete) {
|
||||
int poll = 0;
|
||||
/*
|
||||
* if hotplug interrupt is not enabled or command
|
||||
* completed interrupt is not enabled, we need to poll
|
||||
* command completed event.
|
||||
*/
|
||||
if (!(slot_ctrl & PCI_EXP_SLTCTL_HPIE) ||
|
||||
!(slot_ctrl & PCI_EXP_SLTCTL_CCIE))
|
||||
poll = 1;
|
||||
pcie_wait_cmd(ctrl, poll);
|
||||
}
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
}
|
||||
|
||||
|
@ -773,15 +771,6 @@ struct controller *pcie_init(struct pcie_device *dev)
|
|||
mutex_init(&ctrl->ctrl_lock);
|
||||
init_waitqueue_head(&ctrl->queue);
|
||||
dbg_ctrl(ctrl);
|
||||
/*
|
||||
* Controller doesn't notify of command completion if the "No
|
||||
* Command Completed Support" bit is set in Slot Capability
|
||||
* register or the controller supports none of power
|
||||
* controller, attention led, power led and EMI.
|
||||
*/
|
||||
if (NO_CMD_CMPL(ctrl) ||
|
||||
!(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl)))
|
||||
ctrl->no_cmd_complete = 1;
|
||||
|
||||
/* Check if Data Link Layer Link Active Reporting is implemented */
|
||||
pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap);
|
||||
|
@ -794,7 +783,7 @@ struct controller *pcie_init(struct pcie_device *dev)
|
|||
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
|
||||
PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
|
||||
PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
|
||||
PCI_EXP_SLTSTA_CC);
|
||||
PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC);
|
||||
|
||||
/* Disable software notification */
|
||||
pcie_disable_notification(ctrl);
|
||||
|
|
|
@ -149,15 +149,14 @@ static void msi_set_enable(struct pci_dev *dev, int enable)
|
|||
pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
|
||||
}
|
||||
|
||||
static void msix_set_enable(struct pci_dev *dev, int enable)
|
||||
static void msix_clear_and_set_ctrl(struct pci_dev *dev, u16 clear, u16 set)
|
||||
{
|
||||
u16 control;
|
||||
u16 ctrl;
|
||||
|
||||
pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
|
||||
control &= ~PCI_MSIX_FLAGS_ENABLE;
|
||||
if (enable)
|
||||
control |= PCI_MSIX_FLAGS_ENABLE;
|
||||
pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
|
||||
pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &ctrl);
|
||||
ctrl &= ~clear;
|
||||
ctrl |= set;
|
||||
pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, ctrl);
|
||||
}
|
||||
|
||||
static inline __attribute_const__ u32 msi_mask(unsigned x)
|
||||
|
@ -168,16 +167,6 @@ static inline __attribute_const__ u32 msi_mask(unsigned x)
|
|||
return (1 << (1 << x)) - 1;
|
||||
}
|
||||
|
||||
static inline __attribute_const__ u32 msi_capable_mask(u16 control)
|
||||
{
|
||||
return msi_mask((control >> 1) & 7);
|
||||
}
|
||||
|
||||
static inline __attribute_const__ u32 msi_enabled_mask(u16 control)
|
||||
{
|
||||
return msi_mask((control >> 4) & 7);
|
||||
}
|
||||
|
||||
/*
|
||||
* PCI 2.3 does not specify mask bits for each MSI interrupt. Attempting to
|
||||
* mask all MSI interrupts by clearing the MSI enable bit does not work
|
||||
|
@ -246,7 +235,7 @@ static void msi_set_mask_bit(struct irq_data *data, u32 flag)
|
|||
msix_mask_irq(desc, flag);
|
||||
readl(desc->mask_base); /* Flush write to device */
|
||||
} else {
|
||||
unsigned offset = data->irq - desc->dev->irq;
|
||||
unsigned offset = data->irq - desc->irq;
|
||||
msi_mask_irq(desc, 1 << offset, flag << offset);
|
||||
}
|
||||
}
|
||||
|
@ -460,7 +449,8 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
|
|||
arch_restore_msi_irqs(dev);
|
||||
|
||||
pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
|
||||
msi_mask_irq(entry, msi_capable_mask(control), entry->masked);
|
||||
msi_mask_irq(entry, msi_mask(entry->msi_attrib.multi_cap),
|
||||
entry->masked);
|
||||
control &= ~PCI_MSI_FLAGS_QSIZE;
|
||||
control |= (entry->msi_attrib.multiple << 4) | PCI_MSI_FLAGS_ENABLE;
|
||||
pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
|
||||
|
@ -469,26 +459,22 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
|
|||
static void __pci_restore_msix_state(struct pci_dev *dev)
|
||||
{
|
||||
struct msi_desc *entry;
|
||||
u16 control;
|
||||
|
||||
if (!dev->msix_enabled)
|
||||
return;
|
||||
BUG_ON(list_empty(&dev->msi_list));
|
||||
entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
|
||||
pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
|
||||
|
||||
/* route the table */
|
||||
pci_intx_for_msi(dev, 0);
|
||||
control |= PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL;
|
||||
pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
|
||||
msix_clear_and_set_ctrl(dev, 0,
|
||||
PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL);
|
||||
|
||||
arch_restore_msi_irqs(dev);
|
||||
list_for_each_entry(entry, &dev->msi_list, list) {
|
||||
msix_mask_irq(entry, entry->masked);
|
||||
}
|
||||
|
||||
control &= ~PCI_MSIX_FLAGS_MASKALL;
|
||||
pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
|
||||
msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
|
||||
}
|
||||
|
||||
void pci_restore_msi_state(struct pci_dev *dev)
|
||||
|
@ -501,7 +487,6 @@ EXPORT_SYMBOL_GPL(pci_restore_msi_state);
|
|||
static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct msi_desc *entry;
|
||||
unsigned long irq;
|
||||
int retval;
|
||||
|
@ -510,12 +495,11 @@ static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
|
|||
if (retval)
|
||||
return retval;
|
||||
|
||||
list_for_each_entry(entry, &pdev->msi_list, list) {
|
||||
if (entry->irq == irq) {
|
||||
return sprintf(buf, "%s\n",
|
||||
entry->msi_attrib.is_msix ? "msix" : "msi");
|
||||
}
|
||||
}
|
||||
entry = irq_get_msi_desc(irq);
|
||||
if (entry)
|
||||
return sprintf(buf, "%s\n",
|
||||
entry->msi_attrib.is_msix ? "msix" : "msi");
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -594,6 +578,38 @@ error_attrs:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct msi_desc *msi_setup_entry(struct pci_dev *dev)
|
||||
{
|
||||
u16 control;
|
||||
struct msi_desc *entry;
|
||||
|
||||
/* MSI Entry Initialization */
|
||||
entry = alloc_msi_entry(dev);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
|
||||
|
||||
entry->msi_attrib.is_msix = 0;
|
||||
entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT);
|
||||
entry->msi_attrib.entry_nr = 0;
|
||||
entry->msi_attrib.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT);
|
||||
entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
|
||||
entry->msi_attrib.pos = dev->msi_cap;
|
||||
entry->msi_attrib.multi_cap = (control & PCI_MSI_FLAGS_QMASK) >> 1;
|
||||
|
||||
if (control & PCI_MSI_FLAGS_64BIT)
|
||||
entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_64;
|
||||
else
|
||||
entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_32;
|
||||
|
||||
/* Save the initial mask status */
|
||||
if (entry->msi_attrib.maskbit)
|
||||
pci_read_config_dword(dev, entry->mask_pos, &entry->masked);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* msi_capability_init - configure device's MSI capability structure
|
||||
* @dev: pointer to the pci_dev data structure of MSI device function
|
||||
|
@ -609,32 +625,16 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
|
|||
{
|
||||
struct msi_desc *entry;
|
||||
int ret;
|
||||
u16 control;
|
||||
unsigned mask;
|
||||
|
||||
msi_set_enable(dev, 0); /* Disable MSI during set up */
|
||||
|
||||
pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
|
||||
/* MSI Entry Initialization */
|
||||
entry = alloc_msi_entry(dev);
|
||||
entry = msi_setup_entry(dev);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
entry->msi_attrib.is_msix = 0;
|
||||
entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT);
|
||||
entry->msi_attrib.entry_nr = 0;
|
||||
entry->msi_attrib.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT);
|
||||
entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
|
||||
entry->msi_attrib.pos = dev->msi_cap;
|
||||
|
||||
if (control & PCI_MSI_FLAGS_64BIT)
|
||||
entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_64;
|
||||
else
|
||||
entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_32;
|
||||
/* All MSIs are unmasked by default, Mask them all */
|
||||
if (entry->msi_attrib.maskbit)
|
||||
pci_read_config_dword(dev, entry->mask_pos, &entry->masked);
|
||||
mask = msi_capable_mask(control);
|
||||
mask = msi_mask(entry->msi_attrib.multi_cap);
|
||||
msi_mask_irq(entry, mask, mask);
|
||||
|
||||
list_add_tail(&entry->list, &dev->msi_list);
|
||||
|
@ -743,12 +743,10 @@ static int msix_capability_init(struct pci_dev *dev,
|
|||
u16 control;
|
||||
void __iomem *base;
|
||||
|
||||
pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
|
||||
|
||||
/* Ensure MSI-X is disabled while it is set up */
|
||||
control &= ~PCI_MSIX_FLAGS_ENABLE;
|
||||
pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
|
||||
msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
|
||||
|
||||
pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
|
||||
/* Request & Map MSI-X table region */
|
||||
base = msix_map_region(dev, msix_table_size(control));
|
||||
if (!base)
|
||||
|
@ -767,8 +765,8 @@ static int msix_capability_init(struct pci_dev *dev,
|
|||
* MSI-X registers. We need to mask all the vectors to prevent
|
||||
* interrupts coming in before they're fully set up.
|
||||
*/
|
||||
control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE;
|
||||
pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
|
||||
msix_clear_and_set_ctrl(dev, 0,
|
||||
PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE);
|
||||
|
||||
msix_program_entries(dev, entries);
|
||||
|
||||
|
@ -780,8 +778,7 @@ static int msix_capability_init(struct pci_dev *dev,
|
|||
pci_intx_for_msi(dev, 0);
|
||||
dev->msix_enabled = 1;
|
||||
|
||||
control &= ~PCI_MSIX_FLAGS_MASKALL;
|
||||
pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
|
||||
msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -882,7 +879,6 @@ void pci_msi_shutdown(struct pci_dev *dev)
|
|||
{
|
||||
struct msi_desc *desc;
|
||||
u32 mask;
|
||||
u16 ctrl;
|
||||
|
||||
if (!pci_msi_enable || !dev || !dev->msi_enabled)
|
||||
return;
|
||||
|
@ -895,8 +891,7 @@ void pci_msi_shutdown(struct pci_dev *dev)
|
|||
dev->msi_enabled = 0;
|
||||
|
||||
/* Return the device with MSI unmasked as initial states */
|
||||
pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &ctrl);
|
||||
mask = msi_capable_mask(ctrl);
|
||||
mask = msi_mask(desc->msi_attrib.multi_cap);
|
||||
/* Keep cached state to be restored */
|
||||
arch_msi_mask_irq(desc, mask, ~mask);
|
||||
|
||||
|
@ -1001,7 +996,7 @@ void pci_msix_shutdown(struct pci_dev *dev)
|
|||
arch_msix_mask_irq(entry, 1);
|
||||
}
|
||||
|
||||
msix_set_enable(dev, 0);
|
||||
msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
|
||||
pci_intx_for_msi(dev, 1);
|
||||
dev->msix_enabled = 0;
|
||||
}
|
||||
|
@ -1016,24 +1011,6 @@ void pci_disable_msix(struct pci_dev *dev)
|
|||
}
|
||||
EXPORT_SYMBOL(pci_disable_msix);
|
||||
|
||||
/**
|
||||
* msi_remove_pci_irq_vectors - reclaim MSI(X) irqs to unused state
|
||||
* @dev: pointer to the pci_dev data structure of MSI(X) device function
|
||||
*
|
||||
* Being called during hotplug remove, from which the device function
|
||||
* is hot-removed. All previous assigned MSI/MSI-X irqs, if
|
||||
* allocated for this device function, are reclaimed to unused state,
|
||||
* which may be used later on.
|
||||
**/
|
||||
void msi_remove_pci_irq_vectors(struct pci_dev *dev)
|
||||
{
|
||||
if (!pci_msi_enable || !dev)
|
||||
return;
|
||||
|
||||
if (dev->msi_enabled || dev->msix_enabled)
|
||||
free_msi_irqs(dev);
|
||||
}
|
||||
|
||||
void pci_no_msi(void)
|
||||
{
|
||||
pci_msi_enable = 0;
|
||||
|
@ -1065,7 +1042,7 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
|
|||
|
||||
dev->msix_cap = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
if (dev->msix_cap)
|
||||
msix_set_enable(dev, 0);
|
||||
msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -161,8 +161,8 @@ enum acpi_attr_enum {
|
|||
static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf)
|
||||
{
|
||||
int len;
|
||||
len = utf16s_to_utf8s((const wchar_t *)obj->string.pointer,
|
||||
obj->string.length,
|
||||
len = utf16s_to_utf8s((const wchar_t *)obj->buffer.pointer,
|
||||
obj->buffer.length,
|
||||
UTF16_LITTLE_ENDIAN,
|
||||
buf, PAGE_SIZE);
|
||||
buf[len] = '\n';
|
||||
|
@ -187,16 +187,22 @@ static int dsm_get_label(struct device *dev, char *buf,
|
|||
tmp = obj->package.elements;
|
||||
if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 &&
|
||||
tmp[0].type == ACPI_TYPE_INTEGER &&
|
||||
tmp[1].type == ACPI_TYPE_STRING) {
|
||||
(tmp[1].type == ACPI_TYPE_STRING ||
|
||||
tmp[1].type == ACPI_TYPE_BUFFER)) {
|
||||
/*
|
||||
* The second string element is optional even when
|
||||
* this _DSM is implemented; when not implemented,
|
||||
* this entry must return a null string.
|
||||
*/
|
||||
if (attr == ACPI_ATTR_INDEX_SHOW)
|
||||
if (attr == ACPI_ATTR_INDEX_SHOW) {
|
||||
scnprintf(buf, PAGE_SIZE, "%llu\n", tmp->integer.value);
|
||||
else if (attr == ACPI_ATTR_LABEL_SHOW)
|
||||
dsm_label_utf16s_to_utf8s(tmp + 1, buf);
|
||||
} else if (attr == ACPI_ATTR_LABEL_SHOW) {
|
||||
if (tmp[1].type == ACPI_TYPE_STRING)
|
||||
scnprintf(buf, PAGE_SIZE, "%s\n",
|
||||
tmp[1].string.pointer);
|
||||
else if (tmp[1].type == ACPI_TYPE_BUFFER)
|
||||
dsm_label_utf16s_to_utf8s(tmp + 1, buf);
|
||||
}
|
||||
len = strlen(buf) > 0 ? strlen(buf) : -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -839,12 +839,6 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
|||
|
||||
if (!__pci_complete_power_transition(dev, state))
|
||||
error = 0;
|
||||
/*
|
||||
* When aspm_policy is "powersave" this call ensures
|
||||
* that ASPM is configured.
|
||||
*/
|
||||
if (!error && dev->bus->self)
|
||||
pcie_aspm_powersave_config_link(dev->bus->self);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -1195,12 +1189,18 @@ int __weak pcibios_enable_device(struct pci_dev *dev, int bars)
|
|||
static int do_pci_enable_device(struct pci_dev *dev, int bars)
|
||||
{
|
||||
int err;
|
||||
struct pci_dev *bridge;
|
||||
u16 cmd;
|
||||
u8 pin;
|
||||
|
||||
err = pci_set_power_state(dev, PCI_D0);
|
||||
if (err < 0 && err != -EIO)
|
||||
return err;
|
||||
|
||||
bridge = pci_upstream_bridge(dev);
|
||||
if (bridge)
|
||||
pcie_aspm_powersave_config_link(bridge);
|
||||
|
||||
err = pcibios_enable_device(dev, bars);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -3198,7 +3198,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
|
||||
void pci_reset_secondary_bus(struct pci_dev *dev)
|
||||
{
|
||||
u16 ctrl;
|
||||
|
||||
|
@ -3224,6 +3224,11 @@ void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
|
|||
ssleep(1);
|
||||
}
|
||||
|
||||
void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
|
||||
{
|
||||
pci_reset_secondary_bus(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_reset_bridge_secondary_bus - Reset the secondary bus on a PCI bridge.
|
||||
* @dev: Bridge device
|
||||
|
|
|
@ -203,10 +203,6 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
|
|||
(pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)))
|
||||
return -ENODEV;
|
||||
|
||||
if (!dev->irq && dev->pin) {
|
||||
dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; check vendor BIOS\n",
|
||||
dev->vendor, dev->device);
|
||||
}
|
||||
status = pcie_port_device_register(dev);
|
||||
if (status)
|
||||
return status;
|
||||
|
|
|
@ -3405,6 +3405,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ASMEDIA, 0x1080,
|
|||
DECLARE_PCI_FIXUP_HEADER(0x10e3, 0x8113, quirk_use_pcie_bridge_dma_alias);
|
||||
/* ITE 8892, https://bugzilla.kernel.org/show_bug.cgi?id=73551 */
|
||||
DECLARE_PCI_FIXUP_HEADER(0x1283, 0x8892, quirk_use_pcie_bridge_dma_alias);
|
||||
/* Intel 82801, https://bugzilla.kernel.org/show_bug.cgi?id=44881#c49 */
|
||||
DECLARE_PCI_FIXUP_HEADER(0x8086, 0x244e, quirk_use_pcie_bridge_dma_alias);
|
||||
|
||||
static struct pci_dev *pci_func_0_dma_source(struct pci_dev *dev)
|
||||
{
|
||||
|
|
|
@ -925,7 +925,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
|||
{
|
||||
struct pci_dev *dev;
|
||||
resource_size_t min_align, align, size, size0, size1;
|
||||
resource_size_t aligns[14]; /* Alignments from 1Mb to 8Gb */
|
||||
resource_size_t aligns[18]; /* Alignments from 1Mb to 128Gb */
|
||||
int order, max_order;
|
||||
struct resource *b_res = find_free_bus_resource(bus,
|
||||
mask | IORESOURCE_PREFETCH, type);
|
||||
|
|
|
@ -166,11 +166,10 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
|
|||
{
|
||||
struct resource *root, *conflict;
|
||||
resource_size_t fw_addr, start, end;
|
||||
int ret = 0;
|
||||
|
||||
fw_addr = pcibios_retrieve_fw_addr(dev, resno);
|
||||
if (!fw_addr)
|
||||
return 1;
|
||||
return -ENOMEM;
|
||||
|
||||
start = res->start;
|
||||
end = res->end;
|
||||
|
@ -189,14 +188,13 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
|
|||
resno, res);
|
||||
conflict = request_resource_conflict(root, res);
|
||||
if (conflict) {
|
||||
dev_info(&dev->dev,
|
||||
"BAR %d: %pR conflicts with %s %pR\n", resno,
|
||||
res, conflict->name, conflict);
|
||||
dev_info(&dev->dev, "BAR %d: %pR conflicts with %s %pR\n",
|
||||
resno, res, conflict->name, conflict);
|
||||
res->start = start;
|
||||
res->end = end;
|
||||
ret = 1;
|
||||
return -EBUSY;
|
||||
}
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
|
||||
|
@ -250,10 +248,8 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
|
|||
static int _pci_assign_resource(struct pci_dev *dev, int resno,
|
||||
resource_size_t size, resource_size_t min_align)
|
||||
{
|
||||
struct resource *res = dev->resource + resno;
|
||||
struct pci_bus *bus;
|
||||
int ret;
|
||||
char *type;
|
||||
|
||||
bus = dev->bus;
|
||||
while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
|
||||
|
@ -262,21 +258,6 @@ static int _pci_assign_resource(struct pci_dev *dev, int resno,
|
|||
bus = bus->parent;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
if (res->flags & IORESOURCE_MEM)
|
||||
if (res->flags & IORESOURCE_PREFETCH)
|
||||
type = "mem pref";
|
||||
else
|
||||
type = "mem";
|
||||
else if (res->flags & IORESOURCE_IO)
|
||||
type = "io";
|
||||
else
|
||||
type = "unknown";
|
||||
dev_info(&dev->dev,
|
||||
"BAR %d: can't assign %s (size %#llx)\n",
|
||||
resno, type, (unsigned long long) resource_size(res));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -302,17 +283,24 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
|
|||
* where firmware left it. That at least has a chance of
|
||||
* working, which is better than just leaving it disabled.
|
||||
*/
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_info(&dev->dev, "BAR %d: no space for %pR\n", resno, res);
|
||||
ret = pci_revert_fw_address(res, dev, resno, size);
|
||||
|
||||
if (!ret) {
|
||||
res->flags &= ~IORESOURCE_UNSET;
|
||||
res->flags &= ~IORESOURCE_STARTALIGN;
|
||||
dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
|
||||
if (resno < PCI_BRIDGE_RESOURCES)
|
||||
pci_update_resource(dev, resno);
|
||||
}
|
||||
return ret;
|
||||
|
||||
if (ret < 0) {
|
||||
dev_info(&dev->dev, "BAR %d: failed to assign %pR\n", resno,
|
||||
res);
|
||||
return ret;
|
||||
}
|
||||
|
||||
res->flags &= ~IORESOURCE_UNSET;
|
||||
res->flags &= ~IORESOURCE_STARTALIGN;
|
||||
dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
|
||||
if (resno < PCI_BRIDGE_RESOURCES)
|
||||
pci_update_resource(dev, resno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_assign_resource);
|
||||
|
||||
|
@ -320,9 +308,11 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
|
|||
resource_size_t min_align)
|
||||
{
|
||||
struct resource *res = dev->resource + resno;
|
||||
unsigned long flags;
|
||||
resource_size_t new_size;
|
||||
int ret;
|
||||
|
||||
flags = res->flags;
|
||||
res->flags |= IORESOURCE_UNSET;
|
||||
if (!res->parent) {
|
||||
dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR\n",
|
||||
|
@ -333,14 +323,21 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
|
|||
/* already aligned with min_align */
|
||||
new_size = resource_size(res) + addsize;
|
||||
ret = _pci_assign_resource(dev, resno, new_size, min_align);
|
||||
if (!ret) {
|
||||
res->flags &= ~IORESOURCE_UNSET;
|
||||
res->flags &= ~IORESOURCE_STARTALIGN;
|
||||
dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
|
||||
if (resno < PCI_BRIDGE_RESOURCES)
|
||||
pci_update_resource(dev, resno);
|
||||
if (ret) {
|
||||
res->flags = flags;
|
||||
dev_info(&dev->dev, "BAR %d: %pR (failed to expand by %#llx)\n",
|
||||
resno, res, (unsigned long long) addsize);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
|
||||
res->flags &= ~IORESOURCE_UNSET;
|
||||
res->flags &= ~IORESOURCE_STARTALIGN;
|
||||
dev_info(&dev->dev, "BAR %d: reassigned %pR (expanded by %#llx)\n",
|
||||
resno, res, (unsigned long long) addsize);
|
||||
if (resno < PCI_BRIDGE_RESOURCES)
|
||||
pci_update_resource(dev, resno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pci_enable_resources(struct pci_dev *dev, int mask)
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
static bool request_mem_succeeded = false;
|
||||
|
||||
static struct pci_dev *default_vga;
|
||||
|
||||
static struct fb_var_screeninfo efifb_defined = {
|
||||
.activate = FB_ACTIVATE_NOW,
|
||||
.height = -1,
|
||||
|
@ -84,23 +82,10 @@ static struct fb_ops efifb_ops = {
|
|||
.fb_imageblit = cfb_imageblit,
|
||||
};
|
||||
|
||||
struct pci_dev *vga_default_device(void)
|
||||
{
|
||||
return default_vga;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(vga_default_device);
|
||||
|
||||
void vga_set_default_device(struct pci_dev *pdev)
|
||||
{
|
||||
default_vga = pdev;
|
||||
}
|
||||
|
||||
static int efifb_setup(char *options)
|
||||
{
|
||||
char *this_opt;
|
||||
int i;
|
||||
struct pci_dev *dev = NULL;
|
||||
|
||||
if (options && *options) {
|
||||
while ((this_opt = strsep(&options, ",")) != NULL) {
|
||||
|
@ -126,30 +111,6 @@ static int efifb_setup(char *options)
|
|||
}
|
||||
}
|
||||
|
||||
for_each_pci_dev(dev) {
|
||||
int i;
|
||||
|
||||
if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
|
||||
continue;
|
||||
|
||||
for (i=0; i < DEVICE_COUNT_RESOURCE; i++) {
|
||||
resource_size_t start, end;
|
||||
|
||||
if (!(pci_resource_flags(dev, i) & IORESOURCE_MEM))
|
||||
continue;
|
||||
|
||||
start = pci_resource_start(dev, i);
|
||||
end = pci_resource_end(dev, i);
|
||||
|
||||
if (!start || !end)
|
||||
continue;
|
||||
|
||||
if (screen_info.lfb_base >= start &&
|
||||
(screen_info.lfb_base + screen_info.lfb_size) < end)
|
||||
default_vga = dev;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg);
|
|||
struct msi_desc {
|
||||
struct {
|
||||
__u8 is_msix : 1;
|
||||
__u8 multiple: 3; /* log2 number of messages */
|
||||
__u8 multiple: 3; /* log2 num of messages allocated */
|
||||
__u8 multi_cap : 3; /* log2 num of messages supported */
|
||||
__u8 maskbit : 1; /* mask-pending bit supported ? */
|
||||
__u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
|
||||
__u8 pos; /* Location of the msi capability */
|
||||
|
|
|
@ -978,6 +978,8 @@ int pci_try_reset_slot(struct pci_slot *slot);
|
|||
int pci_probe_reset_bus(struct pci_bus *bus);
|
||||
int pci_reset_bus(struct pci_bus *bus);
|
||||
int pci_try_reset_bus(struct pci_bus *bus);
|
||||
void pci_reset_secondary_bus(struct pci_dev *dev);
|
||||
void pcibios_reset_secondary_bus(struct pci_dev *dev);
|
||||
void pci_reset_bridge_secondary_bus(struct pci_dev *dev);
|
||||
void pci_update_resource(struct pci_dev *dev, int resno);
|
||||
int __must_check pci_assign_resource(struct pci_dev *dev, int i);
|
||||
|
@ -1186,7 +1188,6 @@ int pci_msix_vec_count(struct pci_dev *dev);
|
|||
int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec);
|
||||
void pci_msix_shutdown(struct pci_dev *dev);
|
||||
void pci_disable_msix(struct pci_dev *dev);
|
||||
void msi_remove_pci_irq_vectors(struct pci_dev *dev);
|
||||
void pci_restore_msi_state(struct pci_dev *dev);
|
||||
int pci_msi_enabled(void);
|
||||
int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec);
|
||||
|
@ -1217,7 +1218,6 @@ static inline int pci_enable_msix(struct pci_dev *dev,
|
|||
{ return -ENOSYS; }
|
||||
static inline void pci_msix_shutdown(struct pci_dev *dev) { }
|
||||
static inline void pci_disable_msix(struct pci_dev *dev) { }
|
||||
static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) { }
|
||||
static inline void pci_restore_msi_state(struct pci_dev *dev) { }
|
||||
static inline int pci_msi_enabled(void) { return 0; }
|
||||
static inline int pci_enable_msi_range(struct pci_dev *dev, int minvec,
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
* Do not add new entries to this file unless the definitions
|
||||
* are shared between multiple drivers.
|
||||
*/
|
||||
#ifndef _LINUX_PCI_IDS_H
|
||||
#define _LINUX_PCI_IDS_H
|
||||
|
||||
/* Device classes and subclasses */
|
||||
|
||||
|
@ -2968,3 +2970,5 @@
|
|||
#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001
|
||||
|
||||
#define PCI_VENDOR_ID_OCZ 0x1b85
|
||||
|
||||
#endif /* _LINUX_PCI_IDS_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче