Commit a0bfb673 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6

* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (41 commits)
  PCI: fix pci_ioremap_bar() on s390
  PCI: fix AER capability check
  PCI: use pci_find_ext_capability everywhere
  PCI: remove #ifdef DEBUG around dev_dbg call
  PCI hotplug: fix get_##name return value problem
  PCI: document the pcie_aspm kernel parameter
  PCI: introduce an pci_ioremap(pdev, barnr) function
  powerpc/PCI: Add legacy PCI access via sysfs
  PCI: Add ability to mmap legacy_io on some platforms
  PCI: probing debug message uniformization
  PCI: support PCIe ARI capability
  PCI: centralize the capabilities code in probe.c
  PCI: centralize the capabilities code in pci-sysfs.c
  PCI: fix 64-vbit prefetchable memory resource BARs
  PCI: replace cfg space size (256/4096) by macros.
  PCI: use resource_size() everywhere.
  PCI: use same arg names in PCI_VDEVICE comment
  PCI hotplug: rpaphp: make debug var unique
  PCI: use %pF instead of print_fn_descriptor_symbol() in quirks.c
  PCI: fix hotplug get_##name return value problem
  ...
parents 92b29b86 96499871
...@@ -236,10 +236,8 @@ software system can set different pages for controlling accesses to the ...@@ -236,10 +236,8 @@ software system can set different pages for controlling accesses to the
MSI-X structure. The implementation of MSI support requires the PCI MSI-X structure. The implementation of MSI support requires the PCI
subsystem, not a device driver, to maintain full control of the MSI-X subsystem, not a device driver, to maintain full control of the MSI-X
table/MSI-X PBA (Pending Bit Array) and MMIO address space of the MSI-X table/MSI-X PBA (Pending Bit Array) and MMIO address space of the MSI-X
table/MSI-X PBA. A device driver is prohibited from requesting the MMIO table/MSI-X PBA. A device driver should not access the MMIO address
address space of the MSI-X table/MSI-X PBA. Otherwise, the PCI subsystem space of the MSI-X table/MSI-X PBA.
will fail enabling MSI-X on its hardware device when it calls the function
pci_enable_msix().
5.3.2 API pci_enable_msix 5.3.2 API pci_enable_msix
......
...@@ -163,6 +163,10 @@ need pass only as many optional fields as necessary: ...@@ -163,6 +163,10 @@ need pass only as many optional fields as necessary:
o class and classmask fields default to 0 o class and classmask fields default to 0
o driver_data defaults to 0UL. o driver_data defaults to 0UL.
Note that driver_data must match the value used by any of the pci_device_id
entries defined in the driver. This makes the driver_data field mandatory
if all the pci_device_id entries have a non-zero driver_data value.
Once added, the driver probe routine will be invoked for any unclaimed Once added, the driver probe routine will be invoked for any unclaimed
PCI devices listed in its (newly updated) pci_ids list. PCI devices listed in its (newly updated) pci_ids list.
......
...@@ -203,22 +203,17 @@ to mmio_enabled. ...@@ -203,22 +203,17 @@ to mmio_enabled.
3.3 helper functions 3.3 helper functions
3.3.1 int pci_find_aer_capability(struct pci_dev *dev); 3.3.1 int pci_enable_pcie_error_reporting(struct pci_dev *dev);
pci_find_aer_capability locates the PCI Express AER capability
in the device configuration space. If the device doesn't support
PCI-Express AER, the function returns 0.
3.3.2 int pci_enable_pcie_error_reporting(struct pci_dev *dev);
pci_enable_pcie_error_reporting enables the device to send error pci_enable_pcie_error_reporting enables the device to send error
messages to root port when an error is detected. Note that devices messages to root port when an error is detected. Note that devices
don't enable the error reporting by default, so device drivers need don't enable the error reporting by default, so device drivers need
call this function to enable it. call this function to enable it.
3.3.3 int pci_disable_pcie_error_reporting(struct pci_dev *dev); 3.3.2 int pci_disable_pcie_error_reporting(struct pci_dev *dev);
pci_disable_pcie_error_reporting disables the device to send error pci_disable_pcie_error_reporting disables the device to send error
messages to root port when an error is detected. messages to root port when an error is detected.
3.3.4 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev); 3.3.3 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable
error status register. error status register.
......
...@@ -101,6 +101,7 @@ parameter is applicable: ...@@ -101,6 +101,7 @@ parameter is applicable:
X86-64 X86-64 architecture is enabled. X86-64 X86-64 architecture is enabled.
More X86-64 boot options can be found in More X86-64 boot options can be found in
Documentation/x86_64/boot-options.txt . Documentation/x86_64/boot-options.txt .
X86 Either 32bit or 64bit x86 (same as X86-32+X86-64)
In addition, the following text indicates that the option: In addition, the following text indicates that the option:
...@@ -1588,7 +1589,7 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1588,7 +1589,7 @@ and is between 256 and 4096 characters. It is defined in the file
See also Documentation/paride.txt. See also Documentation/paride.txt.
pci=option[,option...] [PCI] various PCI subsystem options: pci=option[,option...] [PCI] various PCI subsystem options:
off [X86-32] don't probe for the PCI bus off [X86] don't probe for the PCI bus
bios [X86-32] force use of PCI BIOS, don't access bios [X86-32] force use of PCI BIOS, don't access
the hardware directly. Use this if your machine the hardware directly. Use this if your machine
has a non-standard PCI host bridge. has a non-standard PCI host bridge.
...@@ -1596,9 +1597,9 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1596,9 +1597,9 @@ and is between 256 and 4096 characters. It is defined in the file
hardware access methods are allowed. Use this hardware access methods are allowed. Use this
if you experience crashes upon bootup and you if you experience crashes upon bootup and you
suspect they are caused by the BIOS. suspect they are caused by the BIOS.
conf1 [X86-32] Force use of PCI Configuration conf1 [X86] Force use of PCI Configuration
Mechanism 1. Mechanism 1.
conf2 [X86-32] Force use of PCI Configuration conf2 [X86] Force use of PCI Configuration
Mechanism 2. Mechanism 2.
noaer [PCIE] If the PCIEAER kernel config parameter is noaer [PCIE] If the PCIEAER kernel config parameter is
enabled, this kernel boot option can be used to enabled, this kernel boot option can be used to
...@@ -1618,37 +1619,37 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1618,37 +1619,37 @@ and is between 256 and 4096 characters. It is defined in the file
this option if the kernel is unable to allocate this option if the kernel is unable to allocate
IRQs or discover secondary PCI buses on your IRQs or discover secondary PCI buses on your
motherboard. motherboard.
rom [X86-32] Assign address space to expansion ROMs. rom [X86] Assign address space to expansion ROMs.
Use with caution as certain devices share Use with caution as certain devices share
address decoders between ROMs and other address decoders between ROMs and other
resources. resources.
norom [X86-32,X86_64] Do not assign address space to norom [X86] Do not assign address space to
expansion ROMs that do not already have expansion ROMs that do not already have
BIOS assigned address ranges. BIOS assigned address ranges.
irqmask=0xMMMM [X86-32] Set a bit mask of IRQs allowed to be irqmask=0xMMMM [X86] Set a bit mask of IRQs allowed to be
assigned automatically to PCI devices. You can assigned automatically to PCI devices. You can
make the kernel exclude IRQs of your ISA cards make the kernel exclude IRQs of your ISA cards
this way. this way.
pirqaddr=0xAAAAA [X86-32] Specify the physical address pirqaddr=0xAAAAA [X86] Specify the physical address
of the PIRQ table (normally generated of the PIRQ table (normally generated
by the BIOS) if it is outside the by the BIOS) if it is outside the
F0000h-100000h range. F0000h-100000h range.
lastbus=N [X86-32] Scan all buses thru bus #N. Can be lastbus=N [X86] Scan all buses thru bus #N. Can be
useful if the kernel is unable to find your useful if the kernel is unable to find your
secondary buses and you want to tell it secondary buses and you want to tell it
explicitly which ones they are. explicitly which ones they are.
assign-busses [X86-32] Always assign all PCI bus assign-busses [X86] Always assign all PCI bus
numbers ourselves, overriding numbers ourselves, overriding
whatever the firmware may have done. whatever the firmware may have done.
usepirqmask [X86-32] Honor the possible IRQ mask stored usepirqmask [X86] Honor the possible IRQ mask stored
in the BIOS $PIR table. This is needed on in the BIOS $PIR table. This is needed on
some systems with broken BIOSes, notably some systems with broken BIOSes, notably
some HP Pavilion N5400 and Omnibook XE3 some HP Pavilion N5400 and Omnibook XE3
notebooks. This will have no effect if ACPI notebooks. This will have no effect if ACPI
IRQ routing is enabled. IRQ routing is enabled.
noacpi [X86-32] Do not use ACPI for IRQ routing noacpi [X86] Do not use ACPI for IRQ routing
or for PCI scanning. or for PCI scanning.
use_crs [X86-32] Use _CRS for PCI resource use_crs [X86] Use _CRS for PCI resource
allocation. allocation.
routeirq Do IRQ routing for all PCI devices. routeirq Do IRQ routing for all PCI devices.
This is normally done in pci_enable_device(), This is normally done in pci_enable_device(),
...@@ -1677,6 +1678,12 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1677,6 +1678,12 @@ and is between 256 and 4096 characters. It is defined in the file
reserved for the CardBus bridge's memory reserved for the CardBus bridge's memory
window. The default value is 64 megabytes. window. The default value is 64 megabytes.
pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power
Management.
off Disable ASPM.
force Enable ASPM even on devices that claim not to support it.
WARNING: Forcing ASPM on may cause system lockups.
pcmv= [HW,PCMCIA] BadgePAD 4 pcmv= [HW,PCMCIA] BadgePAD 4
pd. [PARIDE] pd. [PARIDE]
......
...@@ -95,16 +95,8 @@ extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, ...@@ -95,16 +95,8 @@ extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine); enum pci_mmap_state mmap_state, int write_combine);
#define HAVE_PCI_LEGACY #define HAVE_PCI_LEGACY
extern int pci_mmap_legacy_page_range(struct pci_bus *bus, extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
struct vm_area_struct *vma); struct vm_area_struct *vma,
extern ssize_t pci_read_legacy_io(struct kobject *kobj, enum pci_mmap_state mmap_state);
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count);
extern ssize_t pci_write_legacy_io(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count);
extern int pci_mmap_legacy_mem(struct kobject *kobj,
struct bin_attribute *attr,
struct vm_area_struct *vma);
#define pci_get_legacy_mem platform_pci_get_legacy_mem #define pci_get_legacy_mem platform_pci_get_legacy_mem
#define pci_legacy_read platform_pci_legacy_read #define pci_legacy_read platform_pci_legacy_read
......
...@@ -614,12 +614,17 @@ char *ia64_pci_get_legacy_mem(struct pci_bus *bus) ...@@ -614,12 +614,17 @@ char *ia64_pci_get_legacy_mem(struct pci_bus *bus)
* vector to get the base address. * vector to get the base address.
*/ */
int int
pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma) pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
{ {
unsigned long size = vma->vm_end - vma->vm_start; unsigned long size = vma->vm_end - vma->vm_start;
pgprot_t prot; pgprot_t prot;
char *addr; char *addr;
/* We only support mmap'ing of legacy memory space */
if (mmap_state != pci_mmap_mem)
return -ENOSYS;
/* /*
* Avoid attribute aliasing. See Documentation/ia64/aliasing.txt * Avoid attribute aliasing. See Documentation/ia64/aliasing.txt
* for more details. * for more details.
......
...@@ -74,6 +74,13 @@ struct pci_controller { ...@@ -74,6 +74,13 @@ struct pci_controller {
unsigned long pci_io_size; unsigned long pci_io_size;
#endif #endif
/* Some machines have a special region to forward the ISA
* "memory" cycles such as VGA memory regions. Left to 0
* if unsupported
*/
resource_size_t isa_mem_phys;
resource_size_t isa_mem_size;
struct pci_ops *ops; struct pci_ops *ops;
unsigned int __iomem *cfg_addr; unsigned int __iomem *cfg_addr;
void __iomem *cfg_data; void __iomem *cfg_data;
......
...@@ -123,6 +123,16 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, ...@@ -123,6 +123,16 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
#define HAVE_PCI_MMAP 1 #define HAVE_PCI_MMAP 1
extern int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val,
size_t count);
extern int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val,
size_t count);
extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
struct vm_area_struct *vma,
enum pci_mmap_state mmap_state);
#define HAVE_PCI_LEGACY 1
#if defined(CONFIG_PPC64) || defined(CONFIG_NOT_COHERENT_CACHE) #if defined(CONFIG_PPC64) || defined(CONFIG_NOT_COHERENT_CACHE)
/* /*
* For 64-bit kernels, pci_unmap_{single,page} is not a nop. * For 64-bit kernels, pci_unmap_{single,page} is not a nop.
...@@ -226,5 +236,6 @@ extern void pci_resource_to_user(const struct pci_dev *dev, int bar, ...@@ -226,5 +236,6 @@ extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
extern void pcibios_do_bus_setup(struct pci_bus *bus); extern void pcibios_do_bus_setup(struct pci_bus *bus);
extern void pcibios_fixup_of_probed_bus(struct pci_bus *bus); extern void pcibios_fixup_of_probed_bus(struct pci_bus *bus);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __ASM_POWERPC_PCI_H */ #endif /* __ASM_POWERPC_PCI_H */
...@@ -451,7 +451,8 @@ pgprot_t pci_phys_mem_access_prot(struct file *file, ...@@ -451,7 +451,8 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
pci_dev_put(pdev); pci_dev_put(pdev);
} }
DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); DBG("non-PCI map for %llx, prot: %lx\n",
(unsigned long long)offset, prot);
return __pgprot(prot); return __pgprot(prot);
} }
...@@ -490,6 +491,131 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, ...@@ -490,6 +491,131 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
return ret; return ret;
} }
/* This provides legacy IO read access on a bus */
int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val, size_t size)
{
unsigned long offset;
struct pci_controller *hose = pci_bus_to_host(bus);
struct resource *rp = &hose->io_resource;
void __iomem *addr;
/* Check if port can be supported by that bus. We only check
* the ranges of the PHB though, not the bus itself as the rules
* for forwarding legacy cycles down bridges are not our problem
* here. So if the host bridge supports it, we do it.
*/
offset = (unsigned long)hose->io_base_virt - _IO_BASE;
offset += port;
if (!(rp->flags & IORESOURCE_IO))
return -ENXIO;
if (offset < rp->start || (offset + size) > rp->end)
return -ENXIO;
addr = hose->io_base_virt + port;
switch(size) {
case 1:
*((u8 *)val) = in_8(addr);
return 1;
case 2:
if (port & 1)
return -EINVAL;
*((u16 *)val) = in_le16(addr);
return 2;
case 4:
if (port & 3)
return -EINVAL;
*((u32 *)val) = in_le32(addr);
return 4;
}
return -EINVAL;
}
/* This provides legacy IO write access on a bus */
int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val, size_t size)
{
unsigned long offset;
struct pci_controller *hose = pci_bus_to_host(bus);
struct resource *rp = &hose->io_resource;
void __iomem *addr;
/* Check if port can be supported by that bus. We only check
* the ranges of the PHB though, not the bus itself as the rules
* for forwarding legacy cycles down bridges are not our problem
* here. So if the host bridge supports it, we do it.
*/
offset = (unsigned long)hose->io_base_virt - _IO_BASE;
offset += port;
if (!(rp->flags & IORESOURCE_IO))
return -ENXIO;
if (offset < rp->start || (offset + size) > rp->end)
return -ENXIO;
addr = hose->io_base_virt + port;
/* WARNING: The generic code is idiotic. It gets passed a pointer
* to what can be a 1, 2 or 4 byte quantity and always reads that
* as a u32, which means that we have to correct the location of
* the data read within those 32 bits for size 1 and 2
*/
switch(size) {
case 1:
out_8(addr, val >> 24);
return 1;
case 2:
if (port & 1)
return -EINVAL;
out_le16(addr, val >> 16);
return 2;
case 4:
if (port & 3)
return -EINVAL;
out_le32(addr, val);
return 4;
}
return -EINVAL;
}
/* This provides legacy IO or memory mmap access on a bus */
int pci_mmap_legacy_page_range(struct pci_bus *bus,
struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
{
struct pci_controller *hose = pci_bus_to_host(bus);
resource_size_t offset =
((resource_size_t)vma->vm_pgoff) << PAGE_SHIFT;
resource_size_t size = vma->vm_end - vma->vm_start;
struct resource *rp;
pr_debug("pci_mmap_legacy_page_range(%04x:%02x, %s @%llx..%llx)\n",
pci_domain_nr(bus), bus->number,
mmap_state == pci_mmap_mem ? "MEM" : "IO",
(unsigned long long)offset,
(unsigned long long)(offset + size - 1));
if (mmap_state == pci_mmap_mem) {
if ((offset + size) > hose->isa_mem_size)
return -ENXIO;
offset += hose->isa_mem_phys;
} else {
unsigned long io_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
unsigned long roffset = offset + io_offset;
rp = &hose->io_resource;
if (!(rp->flags & IORESOURCE_IO))
return -ENXIO;
if (roffset < rp->start || (roffset + size) > rp->end)
return -ENXIO;
offset += hose->io_base_phys;
}
pr_debug(" -> mapping phys %llx\n", (unsigned long long)offset);
vma->vm_pgoff = offset >> PAGE_SHIFT;
vma->vm_page_prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
}
void pci_resource_to_user(const struct pci_dev *dev, int bar, void pci_resource_to_user(const struct pci_dev *dev, int bar,
const struct resource *rsrc, const struct resource *rsrc,
resource_size_t *start, resource_size_t *end) resource_size_t *start, resource_size_t *end)
...@@ -592,6 +718,12 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, ...@@ -592,6 +718,12 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
cpu_addr = of_translate_address(dev, ranges + 3); cpu_addr = of_translate_address(dev, ranges + 3);
size = of_read_number(ranges + pna + 3, 2); size = of_read_number(ranges + pna + 3, 2);
ranges += np; ranges += np;
/* If we failed translation or got a zero-sized region
* (some FW try to feed us with non sensical zero sized regions
* such as power3 which look like some kind of attempt at exposing
* the VGA memory hole)
*/
if (cpu_addr == OF_BAD_ADDR || size == 0) if (cpu_addr == OF_BAD_ADDR || size == 0)
continue; continue;
...@@ -665,6 +797,8 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, ...@@ -665,6 +797,8 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
isa_hole = memno; isa_hole = memno;
if (primary || isa_mem_base == 0) if (primary || isa_mem_base == 0)
isa_mem_base = cpu_addr; isa_mem_base = cpu_addr;
hose->isa_mem_phys = cpu_addr;
hose->isa_mem_size = size;
} }
/* We get the PCI/Mem offset from the first range or /* We get the PCI/Mem offset from the first range or
......
...@@ -493,7 +493,7 @@ static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq ...@@ -493,7 +493,7 @@ static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq
if (pirq <= 4) if (pirq <= 4)
irq = read_config_nybble(router, 0x56, pirq - 1); irq = read_config_nybble(router, 0x56, pirq - 1);
dev_info(&dev->dev, dev_info(&dev->dev,
"AMD756: dev [%04x/%04x], router PIRQ %d get IRQ %d\n", "AMD756: dev [%04x:%04x], router PIRQ %d get IRQ %d\n",
dev->vendor, dev->device, pirq, irq); dev->vendor, dev->device, pirq, irq);
return irq; return irq;
} }
...@@ -501,7 +501,7 @@ static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq ...@@ -501,7 +501,7 @@ static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq
static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
{ {
dev_info(&dev->dev, dev_info(&dev->dev,
"AMD756: dev [%04x/%04x], router PIRQ %d set IRQ %d\n", "AMD756: dev [%04x:%04x], router PIRQ %d set IRQ %d\n",
dev->vendor, dev->device, pirq, irq); dev->vendor, dev->device, pirq, irq);
if (pirq <= 4) if (pirq <= 4)
write_config_nybble(router, 0x56, pirq - 1, irq); write_config_nybble(router, 0x56, pirq - 1, irq);
...@@ -590,13 +590,20 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route ...@@ -590,13 +590,20 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
case PCI_DEVICE_ID_INTEL_ICH10_1: case PCI_DEVICE_ID_INTEL_ICH10_1:
case PCI_DEVICE_ID_INTEL_ICH10_2: case PCI_DEVICE_ID_INTEL_ICH10_2:
case PCI_DEVICE_ID_INTEL_ICH10_3: case PCI_DEVICE_ID_INTEL_ICH10_3:
case PCI_DEVICE_ID_INTEL_PCH_0:
case PCI_DEVICE_ID_INTEL_PCH_1:
r->name = "PIIX/ICH"; r->name = "PIIX/ICH";
r->get = pirq_piix_get; r->get = pirq_piix_get;
r->set = pirq_piix_set; r->set = pirq_piix_set;
return 1; return 1;
} }
if ((device >= PCI_DEVICE_ID_INTEL_PCH_LPC_MIN) &&
(device <= PCI_DEVICE_ID_INTEL_PCH_LPC_MAX)) {
r->name = "PIIX/ICH";
r->get = pirq_piix_get;
r->set = pirq_piix_set;
return 1;
}
return 0; return 0;
} }
...@@ -823,7 +830,7 @@ static void __init pirq_find_router(struct irq_router *r) ...@@ -823,7 +830,7 @@ static void __init pirq_find_router(struct irq_router *r)
r->get = NULL; r->get = NULL;
r->set = NULL; r->set = NULL;
DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n", DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for [%04x:%04x]\n",
rt->rtr_vendor, rt->rtr_device); rt->rtr_vendor, rt->rtr_device);
pirq_router_dev = pci_get_bus_and_slot(rt->rtr_bus, rt->rtr_devfn); pirq_router_dev = pci_get_bus_and_slot(rt->rtr_bus, rt->rtr_devfn);
...@@ -843,7 +850,7 @@ static void __init pirq_find_router(struct irq_router *r) ...@@ -843,7 +850,7 @@ static void __init pirq_find_router(struct irq_router *r)
h->probe(r, pirq_router_dev, pirq_router_dev->device)) h->probe(r, pirq_router_dev, pirq_router_dev->device))
break; break;
} }
dev_info(&pirq_router_dev->dev, "%s IRQ router [%04x/%04x]\n", dev_info(&pirq_router_dev->dev, "%s IRQ router [%04x:%04x]\n",
pirq_router.name, pirq_router.name,
pirq_router_dev->vendor, pirq_router_dev->device); pirq_router_dev->vendor, pirq_router_dev->device);
......
...@@ -332,10 +332,6 @@ static int __devinit amd756_probe(struct pci_dev *pdev, ...@@ -332,10 +332,6 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
int error; int error;
u8 temp; u8 temp;
/* driver_data might come from user-space, so check it */
if (id->driver_data >= ARRAY_SIZE(chipname))
return -EINVAL;
if (amd756_ioport) { if (amd756_ioport) {
dev_err(&pdev->dev, "Only one device supported " dev_err(&pdev->dev, "Only one device supported "
"(you have a strange motherboard, btw)\n"); "(you have a strange motherboard, btw)\n");
...@@ -412,7 +408,6 @@ static struct pci_driver amd756_driver = { ...@@ -412,7 +408,6 @@ static struct pci_driver amd756_driver = {
.id_table = amd756_ids, .id_table = amd756_ids,
.probe = amd756_probe, .probe = amd756_probe,
.remove = __devexit_p(amd756_remove), .remove = __devexit_p(amd756_remove),
.dynids.use_driver_data = 1,
}; };
static int __init amd756_init(void) static int __init amd756_init(void)
......
...@@ -332,10 +332,6 @@ static int __devinit vt596_probe(struct pci_dev *pdev, ...@@ -332,10 +332,6 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
unsigned char temp; unsigned char temp;
int error = -ENODEV; int error = -ENODEV;
/* driver_data might come from user-space, so check it */
if (id->driver_data & 1 || id->driver_data > 0xff)
return -EINVAL;
/* Determine the address of the SMBus areas */ /* Determine the address of the SMBus areas */
if (force_addr) { if (force_addr) {
vt596_smba = force_addr & 0xfff0; vt596_smba = force_addr & 0xfff0;
...@@ -483,7 +479,6 @@ static struct pci_driver vt596_driver = { ...@@ -483,7 +479,6 @@ static struct pci_driver vt596_driver = {
.name = "vt596_smbus", .name = "vt596_smbus",
.id_table = vt596_ids, .id_table = vt596_ids,
.probe = vt596_probe, .probe = vt596_probe,
.dynids.use_driver_data = 1,
}; };
static int __init i2c_vt596_init(void) static int __init i2c_vt596_init(void)
......
...@@ -151,6 +151,13 @@ void pci_bus_add_devices(struct pci_bus *bus) ...@@ -151,6 +151,13 @@ void pci_bus_add_devices(struct pci_bus *bus)
if (retval) if (retval)
dev_err(&dev->dev, "Error creating cpuaffinity" dev_err(&dev->dev, "Error creating cpuaffinity"
" file, continuing...\n"); " file, continuing...\n");
retval = device_create_file(&child_bus->dev,
&dev_attr_cpulistaffinity);
if (retval)
dev_err(&dev->dev,
"Error creating cpulistaffinity"
" file, continuing...\n");
} }
} }
} }
......
This diff is collapsed.
...@@ -102,13 +102,13 @@ static int get_##name (struct hotplug_slot *slot, type *value) \ ...@@ -102,13 +102,13 @@ static int get_##name (struct hotplug_slot *slot, type *value) \
{ \ { \
struct hotplug_slot_ops *ops = slot->ops; \ struct hotplug_slot_ops *ops = slot->ops; \
int retval = 0; \ int retval = 0; \
if (try_module_get(ops->owner)) { \ if (!try_module_get(ops->owner)) \
return -ENODEV; \
if (ops->get_##name) \ if (ops->get_##name) \
retval = ops->get_##name(slot, value); \ retval = ops->get_##name(slot, value); \
else \ else \
*value = slot->info->name; \ *value = slot->info->name; \
module_put(ops->owner); \ module_put(ops->owner); \
} \
return retval; \ return retval; \
} }
......
...@@ -57,6 +57,19 @@ extern struct workqueue_struct *pciehp_wq; ...@@ -57,6 +57,19 @@ extern struct workqueue_struct *pciehp_wq;
#define warn(format, arg...) \ #define warn(format, arg...) \
printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
#define ctrl_dbg(ctrl, format, arg...) \
do { \
if (pciehp_debug) \
dev_printk(, &ctrl->pcie->device, \
format, ## arg); \
} while (0)
#define ctrl_err(ctrl, format, arg...) \
dev_err(&ctrl->pcie->device, format, ## arg)
#define ctrl_info(ctrl, format, arg...) \
dev_info(&ctrl->pcie->device, format, ## arg)
#define ctrl_warn(ctrl, format, arg...) \
dev_warn(&ctrl->pcie->device, format, ## arg)
#define SLOT_NAME_SIZE 10 #define SLOT_NAME_SIZE 10
struct slot { struct slot {
u8 bus; u8 bus;
...@@ -87,6 +100,7 @@ struct controller { ...@@ -87,6 +100,7 @@ struct controller {
int num_slots; /* Number of slots on ctlr */ int num_slots; /* Number of slots on ctlr */
int slot_num_inc; /* 1 or -1 */ int slot_num_inc; /* 1 or -1 */
struct pci_dev *pci_dev; struct pci_dev *pci_dev;
struct pcie_device *pcie; /* PCI Express port service */
struct list_head slot_list; struct list_head slot_list;
struct hpc_ops *hpc_ops; struct hpc_ops *hpc_ops;
wait_queue_head_t queue; /* sleep & wake process */ wait_queue_head_t queue; /* sleep & wake process */
...@@ -170,7 +184,7 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) ...@@ -170,7 +184,7 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
return slot; return slot;
} }
err("%s: slot (device=0x%x) not found\n", __func__, device); ctrl_err(ctrl, "%s: slot (device=0x%x) not found\n", __func__, device);
return NULL; return NULL;
} }
......
...@@ -144,9 +144,10 @@ static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status) ...@@ -144,9 +144,10 @@ static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status)
* sysfs interface which allows the user to toggle the Electro Mechanical * sysfs interface which allows the user to toggle the Electro Mechanical
* Interlock. Valid values are either 0 or 1. 0 == unlock, 1 == lock * Interlock. Valid values are either 0 or 1. 0 == unlock, 1 == lock
*/ */
static ssize_t lock_write_file(struct hotplug_slot *slot, const char *buf, static ssize_t lock_write_file(struct hotplug_slot *hotplug_slot,
size_t count) const char *buf, size_t count)
{ {
struct slot *slot = hotplug_slot->private;
unsigned long llock; unsigned long llock;
u8 lock; u8 lock;
int retval = 0; int retval = 0;
...@@ -157,10 +158,11 @@ static ssize_t lock_write_file(struct hotplug_slot *slot, const char *buf, ...@@ -157,10 +158,11 @@ static ssize_t lock_write_file(struct hotplug_slot *slot, const char *buf,
switch (lock) { switch (lock) {
case 0: case 0:
case 1: case 1:
retval = set_lock_status(slot, lock); retval = set_lock_status(hotplug_slot, lock);
break; break;
default: default:
err ("%d is an invalid lock value\n", lock); ctrl_err(slot->ctrl, "%d is an invalid lock value\n",
lock);
retval = -EINVAL; retval = -EINVAL;
} }
if (retval) if (retval)
...@@ -180,7 +182,10 @@ static struct hotplug_slot_attribute hotplug_slot_attr_lock = { ...@@ -180,7 +182,10 @@ static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
*/ */
static void release_slot(struct hotplug_slot *hotplug_slot) static void release_slot(struct hotplug_slot *hotplug_slot)
{ {
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); struct slot *slot = hotplug_slot->private;
ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
kfree(hotplug_slot->info); kfree(hotplug_slot->info);
kfree(hotplug_slot); kfree(hotplug_slot);
...@@ -215,7 +220,7 @@ static int init_slots(struct controller *ctrl) ...@@ -215,7 +220,7 @@ static int init_slots(struct controller *ctrl)
get_adapter_status(hotplug_slot, &info->adapter_status); get_adapter_status(hotplug_slot, &info->adapter_status);
slot->hotplug_slot = hotplug_slot; slot->hotplug_slot = hotplug_slot;
dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " ctrl_dbg(ctrl, "Registering bus=%x dev=%x hp_slot=%x sun=%x "
"slot_device_offset=%x\n", slot->bus, slot->device, "slot_device_offset=%x\n", slot->bus, slot->device,
slot->hp_slot, slot->number, ctrl->slot_device_offset); slot->hp_slot, slot->number, ctrl->slot_device_offset);
duplicate_name: duplicate_name:
...@@ -233,9 +238,11 @@ static int init_slots(struct controller *ctrl) ...@@ -233,9 +238,11 @@ static int init_slots(struct controller *ctrl)
if (len < SLOT_NAME_SIZE) if (len < SLOT_NAME_SIZE)
goto duplicate_name; goto duplicate_name;
else else
err("duplicate slot name overflow\n"); ctrl_err(ctrl, "duplicate slot name "
"overflow\n");
} }
err("pci_hp_register failed with error %d\n", retval); ctrl_err(ctrl, "pci_hp_register failed with error %d\n",
retval);
goto error_info; goto error_info;
} }
/* create additional sysfs entries */ /* create additional sysfs entries */
...@@ -244,7 +251,8 @@ static int init_slots(struct controller *ctrl) ...@@ -244,7 +251,8 @@ static int init_slots(struct controller *ctrl)
&hotplug_slot_attr_lock.attr); &hotplug_slot_attr_lock.attr);
if (retval) { if (retval) {
pci_hp_deregister(hotplug_slot); pci_hp_deregister(hotplug_slot);
err("cannot create additional sysfs entries\n"); ctrl_err(ctrl, "cannot create additional sysfs "
"entries\n");
goto error_info; goto error_info;
} }
} }
...@@ -278,7 +286,8 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) ...@@ -278,7 +286,8 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
{ {
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
hotplug_slot->info->attention_status = status; hotplug_slot->info->attention_status = status;
...@@ -293,7 +302,8 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) ...@@ -293,7 +302,8 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
{ {
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
return pciehp_sysfs_enable_slot(slot); return pciehp_sysfs_enable_slot(slot);
} }
...@@ -303,7 +313,8 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) ...@@ -303,7 +313,8 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
{ {
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
return pciehp_sysfs_disable_slot(slot); return pciehp_sysfs_disable_slot(slot);
} }
...@@ -313,7 +324,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -313,7 +324,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
int retval; int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
retval = slot->hpc_ops->get_power_status(slot, value); retval = slot->hpc_ops->get_power_status(slot, value);
if (retval < 0) if (retval < 0)
...@@ -327,7 +339,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -327,7 +339,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
int retval; int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
retval = slot->hpc_ops->get_attention_status(slot, value); retval = slot->hpc_ops->get_attention_status(slot, value);
if (retval < 0) if (retval < 0)
...@@ -341,7 +354,8 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -341,7 +354,8 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
int retval; int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
retval = slot->hpc_ops->get_latch_status(slot, value); retval = slot->hpc_ops->get_latch_status(slot, value);
if (retval < 0) if (retval < 0)
...@@ -355,7 +369,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -355,7 +369,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
int retval; int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
retval = slot->hpc_ops->get_adapter_status(slot, value); retval = slot->hpc_ops->get_adapter_status(slot, value);
if (retval < 0) if (retval < 0)
...@@ -370,7 +385,8 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, ...@@ -370,7 +385,8 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
int retval; int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
retval = slot->hpc_ops->get_max_bus_speed(slot, value); retval = slot->hpc_ops->get_max_bus_speed(slot, value);
if (retval < 0) if (retval < 0)
...@@ -384,7 +400,8 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe ...@@ -384,7 +400,8 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
int retval; int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
retval = slot->hpc_ops->get_cur_bus_speed(slot, value); retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
if (retval < 0) if (retval < 0)
...@@ -402,14 +419,15 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ ...@@ -402,14 +419,15 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
struct pci_dev *pdev = dev->port; struct pci_dev *pdev = dev->port;
if (pciehp_force) if (pciehp_force)
dbg("Bypassing BIOS check for pciehp use on %s\n", dev_info(&dev->device,
"Bypassing BIOS check for pciehp use on %s\n",
pci_name(pdev)); pci_name(pdev));
else if (pciehp_get_hp_hw_control_from_firmware(pdev)) else if (pciehp_get_hp_hw_control_from_firmware(pdev))
goto err_out_none; goto err_out_none;
ctrl = pcie_init(dev); ctrl = pcie_init(dev);
if (!ctrl) { if (!ctrl) {
dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); dev_err(&dev->device, "controller initialization failed\n");
goto err_out_none; goto err_out_none;
} }
set_service_data(dev, ctrl); set_service_data(dev, ctrl);
...@@ -418,11 +436,10 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ ...@@ -418,11 +436,10 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
rc = init_slots(ctrl); rc = init_slots(ctrl);
if (rc) { if (rc) {
if (rc == -EBUSY) if (rc == -EBUSY)
warn("%s: slot already registered by another " ctrl_warn(ctrl, "slot already registered by another "
"hotplug driver\n", PCIE_MODULE_NAME); "hotplug driver\n");
else else
err("%s: slot initialization failed\n", ctrl_err(ctrl, "slot initialization failed\n");
PCIE_MODULE_NAME);
goto err_out_release_ctlr; goto err_out_release_ctlr;
} }
...@@ -461,13 +478,13 @@ static void pciehp_remove (struct pcie_device *dev) ...@@ -461,13 +478,13 @@ static void pciehp_remove (struct pcie_device *dev)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int pciehp_suspend (struct pcie_device *dev, pm_message_t state) static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
{ {
printk("%s ENTRY\n", __func__); dev_info(&dev->device, "%s ENTRY\n", __func__);
return 0; return 0;
} }
static int pciehp_resume (struct pcie_device *dev) static int pciehp_resume (struct pcie_device *dev)
{ {
printk("%s ENTRY\n", __func__); dev_info(&dev->device, "%s ENTRY\n", __func__);
if (pciehp_force) { if (pciehp_force) {
struct controller *ctrl = get_service_data(dev); struct controller *ctrl = get_service_data(dev);
struct slot *t_slot; struct slot *t_slot;
...@@ -497,10 +514,9 @@ static struct pcie_port_service_id port_pci_ids[] = { { ...@@ -497,10 +514,9 @@ static struct pcie_port_service_id port_pci_ids[] = { {
.driver_data = 0, .driver_data = 0,
}, { /* end: all zeroes */ } }, { /* end: all zeroes */ }
}; };
static const char device_name[] = "hpdriver";
static struct pcie_port_service_driver hpdriver_portdrv = { static struct pcie_port_service_driver hpdriver_portdrv = {
.name = (char *)device_name, .name = PCIE_MODULE_NAME,
.id_table = &port_pci_ids[0], .id_table = &port_pci_ids[0],
.probe = pciehp_probe, .probe = pciehp_probe,
......
This diff is collapsed.
This diff is collapsed.
...@@ -198,10 +198,12 @@ int pciehp_configure_device(struct slot *p_slot) ...@@ -198,10 +198,12 @@ int pciehp_configure_device(struct slot *p_slot)
struct pci_dev *dev; struct pci_dev *dev;
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
int num, fn; int num, fn;
struct controller *ctrl = p_slot->ctrl;
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
if (dev) { if (dev) {
err("Device %s already exists at %x:%x, cannot hot-add\n", ctrl_err(ctrl,
"Device %s already exists at %x:%x, cannot hot-add\n",
pci_name(dev), p_slot->bus, p_slot->device); pci_name(dev), p_slot->bus, p_slot->device);
pci_dev_put(dev); pci_dev_put(dev);
return -EINVAL; return -EINVAL;
...@@ -209,7 +211,7 @@ int pciehp_configure_device(struct slot *p_slot) ...@@ -209,7 +211,7 @@ int pciehp_configure_device(struct slot *p_slot)
num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0)); num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
if (num == 0) { if (num == 0) {
err("No new device found\n"); ctrl_err(ctrl, "No new device found\n");
return -ENODEV; return -ENODEV;
} }
...@@ -218,7 +220,7 @@ int pciehp_configure_device(struct slot *p_slot) ...@@ -218,7 +220,7 @@ int pciehp_configure_device(struct slot *p_slot)
if (!dev) if (!dev)
continue; continue;
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
err("Cannot hot-add display device %s\n", ctrl_err(ctrl, "Cannot hot-add display device %s\n",
pci_name(dev)); pci_name(dev));
pci_dev_put(dev); pci_dev_put(dev);
continue; continue;
...@@ -244,9 +246,10 @@ int pciehp_unconfigure_device(struct slot *p_slot) ...@@ -244,9 +246,10 @@ int pciehp_unconfigure_device(struct slot *p_slot)
u8 presence = 0; u8 presence = 0;
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
u16 command; u16 command;
struct controller *ctrl = p_slot->ctrl;
dbg("%s: bus/dev = %x/%x\n", __func__, p_slot->bus, ctrl_dbg(ctrl, "%s: bus/dev = %x/%x\n", __func__,
p_slot->device); p_slot->bus, p_slot->device);
ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence); ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence);
if (ret) if (ret)
presence = 0; presence = 0;
...@@ -257,7 +260,7 @@ int pciehp_unconfigure_device(struct slot *p_slot) ...@@ -257,7 +260,7 @@ int pciehp_unconfigure_device(struct slot *p_slot)
if (!temp) if (!temp)
continue; continue;
if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
err("Cannot remove display device %s\n", ctrl_err(ctrl, "Cannot remove display device %s\n",
pci_name(temp)); pci_name(temp));
pci_dev_put(temp); pci_dev_put(temp);
continue; continue;
...@@ -265,7 +268,8 @@ int pciehp_unconfigure_device(struct slot *p_slot) ...@@ -265,7 +268,8 @@ int pciehp_unconfigure_device(struct slot *p_slot)
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) { if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
if (bctl & PCI_BRIDGE_CTL_VGA) { if (bctl & PCI_BRIDGE_CTL_VGA) {
err("Cannot remove display device %s\n", ctrl_err(ctrl,
"Cannot remove display device %s\n",
pci_name(temp)); pci_name(temp));
pci_dev_put(temp); pci_dev_put(temp);
continue; continue;
......
...@@ -46,10 +46,10 @@ ...@@ -46,10 +46,10 @@
#define PRESENT 1 /* Card in slot */ #define PRESENT 1 /* Card in slot */
#define MY_NAME "rpaphp" #define MY_NAME "rpaphp"
extern int debug; extern int rpaphp_debug;
#define dbg(format, arg...) \ #define dbg(format, arg...) \
do { \ do { \
if (debug) \ if (rpaphp_debug) \
printk(KERN_DEBUG "%s: " format, \ printk(KERN_DEBUG "%s: " format, \
MY_NAME , ## arg); \ MY_NAME , ## arg); \
} while (0) } while (0)
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
/* and pci_do_scan_bus */ /* and pci_do_scan_bus */
#include "rpaphp.h" #include "rpaphp.h"
int debug; int rpaphp_debug;
LIST_HEAD(rpaphp_slot_head); LIST_HEAD(rpaphp_slot_head);
#define DRIVER_VERSION "0.1" #define DRIVER_VERSION "0.1"
...@@ -50,7 +50,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); ...@@ -50,7 +50,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_param(debug, bool, 0644); module_param_named(debug, rpaphp_debug, bool, 0644);
/** /**
* set_attention_status - set attention LED * set_attention_status - set attention LED
......
...@@ -123,7 +123,7 @@ int rpaphp_enable_slot(struct slot *slot) ...@@ -123,7 +123,7 @@ int rpaphp_enable_slot(struct slot *slot)
slot->state = CONFIGURED; slot->state = CONFIGURED;
} }
if (debug) { if (rpaphp_debug) {
struct pci_dev *dev; struct pci_dev *dev;
dbg("%s: pci_devs of slot[%s]\n", __func__, slot->dn->full_name); dbg("%s: pci_devs of slot[%s]\n", __func__, slot->dn->full_name);
list_for_each_entry (dev, &bus->devices, bus_list) list_for_each_entry (dev, &bus->devices, bus_list)
......
...@@ -378,23 +378,21 @@ static int msi_capability_init(struct pci_dev *dev) ...@@ -378,23 +378,21 @@ static int msi_capability_init(struct pci_dev *dev)
entry->msi_attrib.masked = 1; entry->msi_attrib.masked = 1;
entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
entry->msi_attrib.pos = pos; entry->msi_attrib.pos = pos;
if (is_mask_bit_support(control)) { if (entry->msi_attrib.maskbit) {
entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos, entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
is_64bit_address(control)); entry->msi_attrib.is_64);
} }
entry->dev = dev; entry->dev = dev;
if (entry->msi_attrib.maskbit) { if (entry->msi_attrib.maskbit) {
unsigned int maskbits, temp; unsigned int maskbits, temp;
/* All MSIs are unmasked by default, Mask them all */ /* All MSIs are unmasked by default, Mask them all */
pci_read_config_dword(dev, pci_read_config_dword(dev,
msi_mask_bits_reg(pos, is_64bit_address(control)), msi_mask_bits_reg(pos, entry->msi_attrib.is_64),
&maskbits); &maskbits);
temp = (1 << multi_msi_capable(control)); temp = (1 << multi_msi_capable(control));
temp = ((temp - 1) & ~temp); temp = ((temp - 1) & ~temp);
maskbits |= temp; maskbits |= temp;
pci_write_config_dword(dev, pci_write_config_dword(dev, entry->msi_attrib.is_64, maskbits);
msi_mask_bits_reg(pos, is_64bit_address(control)),
maskbits);
entry->msi_attrib.maskbits_mask = temp; entry->msi_attrib.maskbits_mask = temp;
} }
list_add_tail(&entry->list, &dev->msi_list); list_add_tail(&entry->list, &dev->msi_list);
......
...@@ -43,18 +43,32 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) ...@@ -43,18 +43,32 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
{ {
struct pci_dynid *dynid; struct pci_dynid *dynid;
struct pci_driver *pdrv = to_pci_driver(driver); struct pci_driver *pdrv = to_pci_driver(driver);
const struct pci_device_id *ids = pdrv->id_table;
__u32 vendor, device, subvendor=PCI_ANY_ID, __u32 vendor, device, subvendor=PCI_ANY_ID,
subdevice=PCI_ANY_ID, class=0, class_mask=0; subdevice=PCI_ANY_ID, class=0, class_mask=0;
unsigned long driver_data=0; unsigned long driver_data=0;
int fields=0; int fields=0;
int retval = 0; int retval;
fields = sscanf(buf, "%x %x %x %x %x %x %lux", fields = sscanf(buf, "%x %x %x %x %x %x %lx",
&vendor, &device, &subvendor, &subdevice, &vendor, &device, &subvendor, &subdevice,
&class, &class_mask, &driver_data); &class, &class_mask, &driver_data);
if (fields < 2) if (fields < 2)
return -EINVAL; return -EINVAL;
/* Only accept driver_data values that match an existing id_table
entry */
retval = -EINVAL;
while (ids->vendor || ids->subvendor || ids->class_mask) {
if (driver_data == ids->driver_data) {
retval = 0;
break;
}
ids++;
}
if (retval) /* No match */
return retval;
dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
if (!dynid) if (!dynid)
return -ENOMEM; return -ENOMEM;
...@@ -65,8 +79,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) ...@@ -65,8 +79,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
dynid->id.subdevice = subdevice; dynid->id.subdevice = subdevice;
dynid->id.class = class; dynid->id.class = class;
dynid->id.class_mask = class_mask; dynid->id.class_mask = class_mask;
dynid->id.driver_data = pdrv->dynids.use_driver_data ? dynid->id.driver_data = driver_data;
driver_data : 0UL;
spin_lock(&pdrv->dynids.lock); spin_lock(&pdrv->dynids.lock);
list_add_tail(&dynid->node, &pdrv->dynids.list); list_add_tail(&dynid->node, &pdrv->dynids.list);
......
...@@ -423,7 +423,7 @@ pci_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr, ...@@ -423,7 +423,7 @@ pci_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
* Reads 1, 2, or 4 bytes from legacy I/O port space using an arch specific * Reads 1, 2, or 4 bytes from legacy I/O port space using an arch specific
* callback routine (pci_legacy_read). * callback routine (pci_legacy_read).
*/ */
ssize_t static ssize_t
pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count) char *buf, loff_t off, size_t count)
{ {
...@@ -448,7 +448,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, ...@@ -448,7 +448,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
* Writes 1, 2, or 4 bytes from legacy I/O port space using an arch specific * Writes 1, 2, or 4 bytes from legacy I/O port space using an arch specific
* callback routine (pci_legacy_write). * callback routine (pci_legacy_write).
*/ */
ssize_t static ssize_t
pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count) char *buf, loff_t off, size_t count)
{ {
...@@ -468,11 +468,11 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, ...@@ -468,11 +468,11 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
* @attr: struct bin_attribute for this file * @attr: struct bin_attribute for this file
* @vma: struct vm_area_struct passed to mmap * @vma: struct vm_area_struct passed to mmap
* *
* Uses an arch specific callback, pci_mmap_legacy_page_range, to mmap * Uses an arch specific callback, pci_mmap_legacy_mem_page_range, to mmap
* legacy memory space (first meg of bus space) into application virtual * legacy memory space (first meg of bus space) into application virtual
* memory space. * memory space.
*/ */
int static int
pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr, pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
struct vm_area_struct *vma) struct vm_area_struct *vma)
{ {
...@@ -480,7 +480,90 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr, ...@@ -480,7 +480,90 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
struct device, struct device,
kobj)); kobj));
return pci_mmap_legacy_page_range(bus, vma); return pci_mmap_legacy_page_range(bus, vma, pci_mmap_mem);
}
/**
* pci_mmap_legacy_io - map legacy PCI IO into user memory space
* @kobj: kobject corresponding to device to be mapped
* @attr: struct bin_attribute for this file
* @vma: struct vm_area_struct passed to mmap
*
* Uses an arch specific callback, pci_mmap_legacy_io_page_range, to mmap
* legacy IO space (first meg of bus space) into application virtual
* memory space. Returns -ENOSYS if the operation isn't supported
*/
static int
pci_mmap_legacy_io(struct kobject *kobj, struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct pci_bus *bus = to_pci_bus(container_of(kobj,
struct device,
kobj));
return pci_mmap_legacy_page_range(bus, vma, pci_mmap_io);
}
/**
* pci_create_legacy_files - create legacy I/O port and memory files
* @b: bus to create files under
*
* Some platforms allow access to legacy I/O port and ISA memory space on
* a per-bus basis. This routine creates the files and ties them into
* their associated read, write and mmap files from pci-sysfs.c
*
* On error unwind, but don't propogate the error to the caller
* as it is ok to set up the PCI bus without these files.
*/
void pci_create_legacy_files(struct pci_bus *b)
{
int error;
b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2,
GFP_ATOMIC);
if (!b->legacy_io)
goto kzalloc_err;
b->legacy_io->attr.name = "legacy_io";
b->legacy_io->size = 0xffff;
b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
b->legacy_io->read = pci_read_legacy_io;
b->legacy_io->write = pci_write_legacy_io;
b->legacy_io->mmap = pci_mmap_legacy_io;
error = device_create_bin_file(&b->dev, b->legacy_io);
if (error)
goto legacy_io_err;
/* Allocated above after the legacy_io struct */
b->legacy_mem = b->legacy_io + 1;
b->legacy_mem->attr.name = "legacy_mem";
b->legacy_mem->size = 1024*1024;
b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
b->legacy_mem->mmap = pci_mmap_legacy_mem;
error = device_create_bin_file(&b->dev, b->legacy_mem);
if (error)
goto legacy_mem_err;
return;
legacy_mem_err:
device_remove_bin_file(&b->dev, b->legacy_io);
legacy_io_err:
kfree(b->legacy_io);
b->legacy_io = NULL;
kzalloc_err:
printk(KERN_WARNING "pci: warning: could not create legacy I/O port "
"and ISA memory resources to sysfs\n");
return;
}
void pci_remove_legacy_files(struct pci_bus *b)
{
if (b->legacy_io) {
device_remove_bin_file(&b->dev, b->legacy_io);
device_remove_bin_file(&b->dev, b->legacy_mem);
kfree(b->legacy_io); /* both are allocated here */
}
} }
#endif /* HAVE_PCI_LEGACY */ #endif /* HAVE_PCI_LEGACY */
...@@ -715,7 +798,7 @@ static struct bin_attribute pci_config_attr = { ...@@ -715,7 +798,7 @@ static struct bin_attribute pci_config_attr = {
.name = "config", .name = "config",
.mode = S_IRUGO | S_IWUSR, .mode = S_IRUGO | S_IWUSR,
}, },
.size = 256, .size = PCI_CFG_SPACE_SIZE,
.read = pci_read_config, .read = pci_read_config,
.write = pci_write_config, .write = pci_write_config,
}; };
...@@ -725,7 +808,7 @@ static struct bin_attribute pcie_config_attr = { ...@@ -725,7 +808,7 @@ static struct bin_attribute pcie_config_attr = {
.name = "config", .name = "config",
.mode = S_IRUGO | S_IWUSR, .mode = S_IRUGO | S_IWUSR,
}, },
.size = 4096, .size = PCI_CFG_SPACE_EXP_SIZE,
.read = pci_read_config, .read = pci_read_config,
.write = pci_write_config, .write = pci_write_config,
}; };
...@@ -735,86 +818,103 @@ int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev) ...@@ -735,86 +818,103 @@ int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
return 0; return 0;
} }
static int pci_create_capabilities_sysfs(struct pci_dev *dev)
{
int retval;
struct bin_attribute *attr;
/* If the device has VPD, try to expose it in sysfs. */
if (dev->vpd) {
attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
if (!attr)
return -ENOMEM;
attr->size = dev->vpd->len;
attr->attr.name = "vpd";
attr->attr.mode = S_IRUSR | S_IWUSR;
attr->read = pci_read_vpd;
attr->write = pci_write_vpd;
retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
if (retval) {
kfree(dev->vpd->attr);
return retval;
}
dev->vpd->attr = attr;
}
/* Active State Power Management */
pcie_aspm_create_sysfs_dev_files(dev);
return 0;
}
int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
{ {
struct bin_attribute *attr = NULL;
int retval; int retval;
int rom_size = 0;
struct bin_attribute *attr;
if (!sysfs_initialized) if (!sysfs_initialized)
return -EACCES; return -EACCES;
if (pdev->cfg_size < 4096) if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr); retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
else else
retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr); retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
if (retval) if (retval)
goto err; goto err;
/* If the device has VPD, try to expose it in sysfs. */ retval = pci_create_resource_files(pdev);
if (pdev->vpd) {
attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
if (attr) {
pdev->vpd->attr = attr;
attr->size = pdev->vpd->len;
attr->attr.name = "vpd";
attr->attr.mode = S_IRUSR | S_IWUSR;
attr->read = pci_read_vpd;
attr->write = pci_write_vpd;
retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
if (retval) if (retval)
goto err_vpd;
} else {
retval = -ENOMEM;
goto err_config_file; goto err_config_file;
}
}
retval = pci_create_resource_files(pdev); if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
if (retval) rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
goto err_vpd_file; else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
rom_size = 0x20000;
/* If the device has a ROM, try to expose it in sysfs. */ /* If the device has a ROM, try to expose it in sysfs. */
if (pci_resource_len(pdev, PCI_ROM_RESOURCE) || if (rom_size) {
(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) {
attr = kzalloc(sizeof(*attr), GFP_ATOMIC); attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
if (attr) { if (!attr) {
pdev->rom_attr = attr; retval = -ENOMEM;
attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); goto err_resource_files;
}
attr->size = rom_size;
attr->attr.name = "rom"; attr->attr.name = "rom";
attr->attr.mode = S_IRUSR; attr->attr.mode = S_IRUSR;
attr->read = pci_read_rom; attr->read = pci_read_rom;
attr->write = pci_write_rom; attr->write = pci_write_rom;
retval = sysfs_create_bin_file(&pdev->dev.kobj, attr); retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
if (retval) if (retval) {
goto err_rom; kfree(attr);
} else {
retval = -ENOMEM;
goto err_resource_files; goto err_resource_files;
} }
pdev->rom_attr = attr;
} }
/* add platform-specific attributes */ /* add platform-specific attributes */
if (pcibios_add_platform_entries(pdev)) retval = pcibios_add_platform_entries(pdev);
if (retval)
goto err_rom_file; goto err_rom_file;
pcie_aspm_create_sysfs_dev_files(pdev); /* add sysfs entries for various capabilities */
retval = pci_create_capabilities_sysfs(pdev);
if (retval)
goto err_rom_file;
return 0; return 0;
err_rom_file: err_rom_file:
if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) if (rom_size) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
err_rom:
kfree(pdev->rom_attr); kfree(pdev->rom_attr);
pdev->rom_attr = NULL;
}
err_resource_files: err_resource_files:
pci_remove_resource_files(pdev); pci_remove_resource_files(pdev);
err_vpd_file:
if (pdev->vpd) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
err_vpd:
kfree(pdev->vpd->attr);
}
err_config_file: err_config_file:
if (pdev->cfg_size < 4096) if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
else else
sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr); sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
...@@ -822,6 +922,16 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) ...@@ -822,6 +922,16 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
return retval; return retval;
} }
static void pci_remove_capabilities_sysfs(struct pci_dev *dev)
{
if (dev->vpd && dev->vpd->attr) {
sysfs_remove_bin_file(&dev->dev.kobj, dev->vpd->attr);
kfree(dev->vpd->attr);
}
pcie_aspm_remove_sysfs_dev_files(dev);
}
/** /**
* pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files * pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files
* @pdev: device whose entries we should free * @pdev: device whose entries we should free
...@@ -830,28 +940,29 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) ...@@ -830,28 +940,29 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
*/ */
void pci_remove_sysfs_dev_files(struct pci_dev *pdev) void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
{ {
int rom_size = 0;
if (!sysfs_initialized) if (!sysfs_initialized)
return; return;
pcie_aspm_remove_sysfs_dev_files(pdev); pci_remove_capabilities_sysfs(pdev);
if (pdev->vpd) { if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
kfree(pdev->vpd->attr);
}
if (pdev->cfg_size < 4096)
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
else else
sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr); sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
pci_remove_resource_files(pdev); pci_remove_resource_files(pdev);
if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
if (pdev->rom_attr) { rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
rom_size = 0x20000;
if (rom_size && pdev->rom_attr) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
kfree(pdev->rom_attr); kfree(pdev->rom_attr);
} }
}
} }
static int __init pci_sysfs_init(void) static int __init pci_sysfs_init(void)
......
...@@ -213,10 +213,13 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap) ...@@ -213,10 +213,13 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
int pci_find_ext_capability(struct pci_dev *dev, int cap) int pci_find_ext_capability(struct pci_dev *dev, int cap)
{ {
u32 header; u32 header;
int ttl = 480; /* 3840 bytes, minimum 8 bytes per capability */ int ttl;
int pos = 0x100; int pos = PCI_CFG_SPACE_SIZE;
if (dev->cfg_size <= 256) /* minimum 8 bytes per capability */
ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
if (dev->cfg_size <= PCI_CFG_SPACE_SIZE)
return 0; return 0;
if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL) if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
...@@ -234,7 +237,7 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap) ...@@ -234,7 +237,7 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
return pos; return pos;
pos = PCI_EXT_CAP_NEXT(header); pos = PCI_EXT_CAP_NEXT(header);
if (pos < 0x100) if (pos < PCI_CFG_SPACE_SIZE)
break; break;
if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL) if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
...@@ -1126,6 +1129,27 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) ...@@ -1126,6 +1129,27 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
return pme_done ? 0 : error; return pme_done ? 0 : error;
} }
/**
* pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold
* @dev: PCI device to prepare
* @enable: True to enable wake-up event generation; false to disable
*
* Many drivers want the device to wake up the system from D3_hot or D3_cold
* and this function allows them to set that up cleanly - pci_enable_wake()
* should not be called twice in a row to enable wake-up due to PCI PM vs ACPI
* ordering constraints.
*
* This function only returns error code if the device is not capable of
* generating PME# from both D3_hot and D3_cold, and the platform is unable to
* enable wake-up power for it.
*/
int pci_wake_from_d3(struct pci_dev *dev, bool enable)
{
return pci_pme_capable(dev, PCI_D3cold) ?
pci_enable_wake(dev, PCI_D3cold, enable) :
pci_enable_wake(dev, PCI_D3hot, enable);
}
/** /**
* pci_target_state - find an appropriate low power state for a given PCI dev * pci_target_state - find an appropriate low power state for a given PCI dev
* @dev: PCI device * @dev: PCI device
...@@ -1242,20 +1266,20 @@ void pci_pm_init(struct pci_dev *dev) ...@@ -1242,20 +1266,20 @@ void pci_pm_init(struct pci_dev *dev)
dev->d1_support = false; dev->d1_support = false;
dev->d2_support = false; dev->d2_support = false;
if (!pci_no_d1d2(dev)) { if (!pci_no_d1d2(dev)) {
if (pmc & PCI_PM_CAP_D1) { if (pmc & PCI_PM_CAP_D1)
dev_printk(KERN_DEBUG, &dev->dev, "supports D1\n");
dev->d1_support = true; dev->d1_support = true;
} if (pmc & PCI_PM_CAP_D2)
if (pmc & PCI_PM_CAP_D2) {
dev_printk(KERN_DEBUG, &dev->dev, "supports D2\n");
dev->d2_support = true; dev->d2_support = true;
}
if (dev->d1_support || dev->d2_support)
dev_printk(KERN_DEBUG, &dev->dev, "supports%s%s\n",
dev->d1_support ? " D1" : "",
dev->d2_support ? " D2" : "");
} }
pmc &= PCI_PM_CAP_PME_MASK; pmc &= PCI_PM_CAP_PME_MASK;
if (pmc) { if (pmc) {
dev_printk(KERN_INFO, &dev->dev, dev_info(&dev->dev, "PME# supported from%s%s%s%s%s\n",
"PME# supported from%s%s%s%s%s\n",
(pmc & PCI_PM_CAP_PME_D0) ? " D0" : "", (pmc & PCI_PM_CAP_PME_D0) ? " D0" : "",
(pmc & PCI_PM_CAP_PME_D1) ? " D1" : "", (pmc & PCI_PM_CAP_PME_D1) ? " D1" : "",
(pmc & PCI_PM_CAP_PME_D2) ? " D2" : "", (pmc & PCI_PM_CAP_PME_D2) ? " D2" : "",
...@@ -1275,6 +1299,38 @@ void pci_pm_init(struct pci_dev *dev) ...@@ -1275,6 +1299,38 @@ void pci_pm_init(struct pci_dev *dev)
} }
} }
/**
* pci_enable_ari - enable ARI forwarding if hardware support it
* @dev: the PCI device
*/
void pci_enable_ari(struct pci_dev *dev)
{
int pos;
u32 cap;
u16 ctrl;
if (!dev->is_pcie)
return;
if (dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
return;
pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
if (!pos)
return;
pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap);
if (!(cap & PCI_EXP_DEVCAP2_ARI))
return;
pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
ctrl |= PCI_EXP_DEVCTL2_ARI;
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
dev->ari_enabled = 1;
}
int int
pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge) pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
{ {
...@@ -1942,6 +1998,7 @@ EXPORT_SYMBOL(pci_restore_state); ...@@ -1942,6 +1998,7 @@ EXPORT_SYMBOL(pci_restore_state);
EXPORT_SYMBOL(pci_pme_capable); EXPORT_SYMBOL(pci_pme_capable);
EXPORT_SYMBOL(pci_pme_active); EXPORT_SYMBOL(pci_pme_active);
EXPORT_SYMBOL(pci_enable_wake); EXPORT_SYMBOL(pci_enable_wake);
EXPORT_SYMBOL(pci_wake_from_d3);
EXPORT_SYMBOL(pci_target_state); EXPORT_SYMBOL(pci_target_state);
EXPORT_SYMBOL(pci_prepare_to_sleep); EXPORT_SYMBOL(pci_prepare_to_sleep);
EXPORT_SYMBOL(pci_back_from_sleep); EXPORT_SYMBOL(pci_back_from_sleep);
......
#ifndef DRIVERS_PCI_H
#define DRIVERS_PCI_H
#define PCI_CFG_SPACE_SIZE 256
#define PCI_CFG_SPACE_EXP_SIZE 4096
/* Functions internal to the PCI core code */ /* Functions internal to the PCI core code */
extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env); extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
...@@ -76,7 +82,13 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; } ...@@ -76,7 +82,13 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
/* Functions for PCI Hotplug drivers to use */ /* Functions for PCI Hotplug drivers to use */
extern unsigned int pci_do_scan_bus(struct pci_bus *bus); extern unsigned int pci_do_scan_bus(struct pci_bus *bus);
#ifdef HAVE_PCI_LEGACY
extern void pci_create_legacy_files(struct pci_bus *bus);
extern void pci_remove_legacy_files(struct pci_bus *bus); extern void pci_remove_legacy_files(struct pci_bus *bus);
#else
static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
#endif
/* Lock for read/write access to pci device and bus lists */ /* Lock for read/write access to pci device and bus lists */
extern struct rw_semaphore pci_bus_sem; extern struct rw_semaphore pci_bus_sem;
...@@ -109,6 +121,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev) ...@@ -109,6 +121,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
extern int pcie_mch_quirk; extern int pcie_mch_quirk;
extern struct device_attribute pci_dev_attrs[]; extern struct device_attribute pci_dev_attrs[];
extern struct device_attribute dev_attr_cpuaffinity; extern struct device_attribute dev_attr_cpuaffinity;
extern struct device_attribute dev_attr_cpulistaffinity;
/** /**
* pci_match_one_device - Tell if a PCI device structure has a matching * pci_match_one_device - Tell if a PCI device structure has a matching
...@@ -144,3 +157,16 @@ struct pci_slot_attribute { ...@@ -144,3 +157,16 @@ struct pci_slot_attribute {
}; };
#define to_pci_slot_attr(s) container_of(s, struct pci_slot_attribute, attr) #define to_pci_slot_attr(s) container_of(s, struct pci_slot_attribute, attr)
extern void pci_enable_ari(struct pci_dev *dev);
/**
* pci_ari_enabled - query ARI forwarding status
* @dev: the PCI device
*
* Returns 1 if ARI forwarding is enabled, or 0 if not enabled;
*/
static inline int pci_ari_enabled(struct pci_dev *dev)
{
return dev->ari_enabled;
}
#endif /* DRIVERS_PCI_H */
...@@ -105,7 +105,7 @@ static irqreturn_t aer_irq(int irq, void *context) ...@@ -105,7 +105,7 @@ static irqreturn_t aer_irq(int irq, void *context)
unsigned long flags; unsigned long flags;
int pos; int pos;
pos = pci_find_aer_capability(pdev->port); pos = pci_find_ext_capability(pdev->port, PCI_EXT_CAP_ID_ERR);
/* /*
* Must lock access to Root Error Status Reg, Root Error ID Reg, * Must lock access to Root Error Status Reg, Root Error ID Reg,
* and Root error producer/consumer index * and Root error producer/consumer index
...@@ -252,7 +252,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) ...@@ -252,7 +252,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
u32 status; u32 status;
int pos; int pos;
pos = pci_find_aer_capability(dev); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
/* Disable Root's interrupt in response to error messages */ /* Disable Root's interrupt in response to error messages */
pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, 0); pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, 0);
...@@ -316,7 +316,7 @@ static void aer_error_resume(struct pci_dev *dev) ...@@ -316,7 +316,7 @@ static void aer_error_resume(struct pci_dev *dev)
pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16); pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16);
/* Clean AER Root Error Status */ /* Clean AER Root Error Status */
pos = pci_find_aer_capability(dev); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
if (dev->error_state == pci_channel_io_normal) if (dev->error_state == pci_channel_io_normal)
......
...@@ -28,41 +28,15 @@ ...@@ -28,41 +28,15 @@
static int forceload; static int forceload;
module_param(forceload, bool, 0); module_param(forceload, bool, 0);
#define PCI_CFG_SPACE_SIZE (0x100)
int pci_find_aer_capability(struct pci_dev *dev)
{
int pos;
u32 reg32 = 0;
/* Check if it's a pci-express device */
pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
if (!pos)
return 0;
/* Check if it supports pci-express AER */
pos = PCI_CFG_SPACE_SIZE;
while (pos) {
if (pci_read_config_dword(dev, pos, &reg32))
return 0;
/* some broken boards return ~0 */
if (reg32 == 0xffffffff)
return 0;
if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
break;
pos = reg32 >> 20;
}
return pos;
}
int pci_enable_pcie_error_reporting(struct pci_dev *dev) int pci_enable_pcie_error_reporting(struct pci_dev *dev)
{ {
u16 reg16 = 0; u16 reg16 = 0;
int pos; int pos;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos)
return -EIO;
pos = pci_find_capability(dev, PCI_CAP_ID_EXP); pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
if (!pos) if (!pos)
return -EIO; return -EIO;
...@@ -102,7 +76,7 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) ...@@ -102,7 +76,7 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
int pos; int pos;
u32 status, mask; u32 status, mask;
pos = pci_find_aer_capability(dev); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos) if (!pos)
return -EIO; return -EIO;
...@@ -123,7 +97,7 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev) ...@@ -123,7 +97,7 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
int pos; int pos;
u32 status; u32 status;
pos = pci_find_aer_capability(dev); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos) if (!pos)
return -EIO; return -EIO;
...@@ -502,7 +476,7 @@ static void handle_error_source(struct pcie_device * aerdev, ...@@ -502,7 +476,7 @@ static void handle_error_source(struct pcie_device * aerdev,
* Correctable error does not need software intevention. * Correctable error does not need software intevention.
* No need to go through error recovery process. * No need to go through error recovery process.
*/ */
pos = pci_find_aer_capability(dev); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (pos) if (pos)
pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
info.status); info.status);
...@@ -542,7 +516,7 @@ void aer_enable_rootport(struct aer_rpc *rpc) ...@@ -542,7 +516,7 @@ void aer_enable_rootport(struct aer_rpc *rpc)
reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK); reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK);
pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16); pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16);
aer_pos = pci_find_aer_capability(pdev); aer_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
/* Clear error status */ /* Clear error status */
pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32); pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32); pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
...@@ -579,7 +553,7 @@ static void disable_root_aer(struct aer_rpc *rpc) ...@@ -579,7 +553,7 @@ static void disable_root_aer(struct aer_rpc *rpc)
u32 reg32; u32 reg32;
int pos; int pos;
pos = pci_find_aer_capability(pdev); pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
/* Disable Root's interrupt in response to error messages */ /* Disable Root's interrupt in response to error messages */
pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0); pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0);
...@@ -618,7 +592,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) ...@@ -618,7 +592,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
{ {
int pos; int pos;
pos = pci_find_aer_capability(dev); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
/* The device might not support AER */ /* The device might not support AER */
if (!pos) if (!pos)
...@@ -755,7 +729,6 @@ int aer_init(struct pcie_device *dev) ...@@ -755,7 +729,6 @@ int aer_init(struct pcie_device *dev)
return AER_SUCCESS; return AER_SUCCESS;
} }
EXPORT_SYMBOL_GPL(pci_find_aer_capability);
EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting); EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting); EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
......
...@@ -528,9 +528,9 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) ...@@ -528,9 +528,9 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
pci_read_config_dword(child_dev, child_pos + PCI_EXP_DEVCAP, pci_read_config_dword(child_dev, child_pos + PCI_EXP_DEVCAP,
&reg32); &reg32);
if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) { if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
printk("Pre-1.1 PCIe device detected, " dev_printk(KERN_INFO, &child_dev->dev, "disabling ASPM"
"disable ASPM for %s. It can be enabled forcedly" " on pre-1.1 PCIe device. You can enable it"
" with 'pcie_aspm=force'\n", pci_name(pdev)); " with 'pcie_aspm=force'\n");
return -EINVAL; return -EINVAL;
} }
} }
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#define PCIE_CAPABILITIES_REG 0x2 #define PCIE_CAPABILITIES_REG 0x2
#define PCIE_SLOT_CAPABILITIES_REG 0x14 #define PCIE_SLOT_CAPABILITIES_REG 0x14
#define PCIE_PORT_DEVICE_MAXSERVICES 4 #define PCIE_PORT_DEVICE_MAXSERVICES 4
#define PCI_CFG_SPACE_SIZE 256
#define get_descriptor_id(type, service) (((type - 4) << 4) | service) #define get_descriptor_id(type, service) (((type - 4) << 4) | service)
......
...@@ -196,23 +196,10 @@ static int get_port_device_capability(struct pci_dev *dev) ...@@ -196,23 +196,10 @@ static int get_port_device_capability(struct pci_dev *dev)
if (((reg16 >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT) if (((reg16 >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT)
services |= PCIE_PORT_SERVICE_PME; services |= PCIE_PORT_SERVICE_PME;
pos = PCI_CFG_SPACE_SIZE; if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR))
while (pos) {
pci_read_config_dword(dev, pos, &reg32);
switch (reg32 & 0xffff) {
case PCI_EXT_CAP_ID_ERR:
services |= PCIE_PORT_SERVICE_AER; services |= PCIE_PORT_SERVICE_AER;
pos = reg32 >> 20; if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC))
break;
case PCI_EXT_CAP_ID_VC:
services |= PCIE_PORT_SERVICE_VC; services |= PCIE_PORT_SERVICE_VC;
pos = reg32 >> 20;
break;
default:
pos = 0;
break;
}
}
return services; return services;
} }
......
...@@ -91,7 +91,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, ...@@ -91,7 +91,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
pci_set_master(dev); pci_set_master(dev);
if (!dev->irq && dev->pin) { if (!dev->irq && dev->pin) {
dev_warn(&dev->dev, "device [%04x/%04x] has invalid IRQ; " dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
"check vendor BIOS\n", dev->vendor, dev->device); "check vendor BIOS\n", dev->vendor, dev->device);
} }
if (pcie_port_device_register(dev)) { if (pcie_port_device_register(dev)) {
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
#define CARDBUS_RESERVE_BUSNR 3 #define CARDBUS_RESERVE_BUSNR 3
#define PCI_CFG_SPACE_SIZE 256
#define PCI_CFG_SPACE_EXP_SIZE 4096
/* Ugh. Need to stop exporting this to modules. */ /* Ugh. Need to stop exporting this to modules. */
LIST_HEAD(pci_root_buses); LIST_HEAD(pci_root_buses);
...@@ -44,72 +42,6 @@ int no_pci_devices(void) ...@@ -44,72 +42,6 @@ int no_pci_devices(void)
} }
EXPORT_SYMBOL(no_pci_devices); EXPORT_SYMBOL(no_pci_devices);
#ifdef HAVE_PCI_LEGACY
/**
* pci_create_legacy_files - create legacy I/O port and memory files
* @b: bus to create files under
*
* Some platforms allow access to legacy I/O port and ISA memory space on
* a per-bus basis. This routine creates the files and ties them into
* their associated read, write and mmap files from pci-sysfs.c
*
* On error unwind, but don't propogate the error to the caller
* as it is ok to set up the PCI bus without these files.
*/
static void pci_create_legacy_files(struct pci_bus *b)
{
int error;
b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2,
GFP_ATOMIC);
if (!b->legacy_io)
goto kzalloc_err;
b->legacy_io->attr.name = "legacy_io";
b->legacy_io->size = 0xffff;
b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
b->legacy_io->read = pci_read_legacy_io;
b->legacy_io->write = pci_write_legacy_io;
error = device_create_bin_file(&b->dev, b->legacy_io);
if (error)
goto legacy_io_err;
/* Allocated above after the legacy_io struct */
b->legacy_mem = b->legacy_io + 1;
b->legacy_mem->attr.name = "legacy_mem";
b->legacy_mem->size = 1024*1024;
b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
b->legacy_mem->mmap = pci_mmap_legacy_mem;
error = device_create_bin_file(&b->dev, b->legacy_mem);
if (error)
goto legacy_mem_err;
return;
legacy_mem_err:
device_remove_bin_file(&b->dev, b->legacy_io);
legacy_io_err:
kfree(b->legacy_io);
b->legacy_io = NULL;
kzalloc_err:
printk(KERN_WARNING "pci: warning: could not create legacy I/O port "
"and ISA memory resources to sysfs\n");
return;
}
void pci_remove_legacy_files(struct pci_bus *b)
{
if (b->legacy_io) {
device_remove_bin_file(&b->dev, b->legacy_io);
device_remove_bin_file(&b->dev, b->legacy_mem);
kfree(b->legacy_io); /* both are allocated here */
}
}
#else /* !HAVE_PCI_LEGACY */
static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
void pci_remove_legacy_files(struct pci_bus *bus) { return; }
#endif /* HAVE_PCI_LEGACY */
/* /*
* PCI Bus Class Devices * PCI Bus Class Devices
*/ */
...@@ -219,7 +151,7 @@ static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar) ...@@ -219,7 +151,7 @@ static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)
res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK;
if (res->flags == PCI_BASE_ADDRESS_MEM_TYPE_64) if (res->flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
return pci_bar_mem64; return pci_bar_mem64;
return pci_bar_mem32; return pci_bar_mem32;
} }
...@@ -304,8 +236,8 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -304,8 +236,8 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
} else { } else {
res->start = l64; res->start = l64;
res->end = l64 + sz64; res->end = l64 + sz64;
printk(KERN_DEBUG "PCI: %s reg %x 64bit mmio: %pR\n", dev_printk(KERN_DEBUG, &dev->dev,
pci_name(dev), pos, res); "reg %x 64bit mmio: %pR\n", pos, res);
} }
} else { } else {
sz = pci_size(l, sz, mask); sz = pci_size(l, sz, mask);
...@@ -315,9 +247,9 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -315,9 +247,9 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->start = l; res->start = l;
res->end = l + sz; res->end = l + sz;
printk(KERN_DEBUG "PCI: %s reg %x %s: %pR\n",
pci_name(dev), pos, dev_printk(KERN_DEBUG, &dev->dev, "reg %x %s: %pR\n", pos,
(res->flags & IORESOURCE_IO) ? "io port":"32bit mmio", (res->flags & IORESOURCE_IO) ? "io port" : "32bit mmio",
res); res);
} }
...@@ -389,8 +321,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) ...@@ -389,8 +321,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->start = base; res->start = base;
if (!res->end) if (!res->end)
res->end = limit + 0xfff; res->end = limit + 0xfff;
printk(KERN_DEBUG "PCI: bridge %s io port: %pR\n", dev_printk(KERN_DEBUG, &dev->dev, "bridge io port: %pR\n", res);
pci_name(dev), res);
} }
res = child->resource[1]; res = child->resource[1];
...@@ -402,8 +333,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) ...@@ -402,8 +333,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
res->start = base; res->start = base;
res->end = limit + 0xfffff; res->end = limit + 0xfffff;
printk(KERN_DEBUG "PCI: bridge %s 32bit mmio: %pR\n", dev_printk(KERN_DEBUG, &dev->dev, "bridge 32bit mmio: %pR\n",
pci_name(dev), res); res);
} }
res = child->resource[2]; res = child->resource[2];
...@@ -439,9 +370,9 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) ...@@ -439,9 +370,9 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH; res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
res->start = base; res->start = base;
res->end = limit + 0xfffff; res->end = limit + 0xfffff;
printk(KERN_DEBUG "PCI: bridge %s %sbit mmio pref: %pR\n", dev_printk(KERN_DEBUG, &dev->dev, "bridge %sbit mmio pref: %pR\n",
pci_name(dev), (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32",
(res->flags & PCI_PREF_RANGE_TYPE_64) ? "64":"32", res); res);
} }
} }
...@@ -762,7 +693,7 @@ static int pci_setup_device(struct pci_dev * dev) ...@@ -762,7 +693,7 @@ static int pci_setup_device(struct pci_dev * dev)
dev->class = class; dev->class = class;
class >>= 8; class >>= 8;
dev_dbg(&dev->dev, "found [%04x/%04x] class %06x header type %02x\n", dev_dbg(&dev->dev, "found [%04x:%04x] class %06x header type %02x\n",
dev->vendor, dev->device, class, dev->hdr_type); dev->vendor, dev->device, class, dev->hdr_type);
/* "Unknown power state" */ /* "Unknown power state" */
...@@ -844,6 +775,11 @@ static int pci_setup_device(struct pci_dev * dev) ...@@ -844,6 +775,11 @@ static int pci_setup_device(struct pci_dev * dev)
return 0; return 0;
} }
static void pci_release_capabilities(struct pci_dev *dev)
{
pci_vpd_release(dev);
}
/** /**
* pci_release_dev - free a pci device structure when all users of it are finished. * pci_release_dev - free a pci device structure when all users of it are finished.
* @dev: device that's been disconnected * @dev: device that's been disconnected
...@@ -856,7 +792,7 @@ static void pci_release_dev(struct device *dev) ...@@ -856,7 +792,7 @@ static void pci_release_dev(struct device *dev)
struct pci_dev *pci_dev; struct pci_dev *pci_dev;
pci_dev = to_pci_dev(dev); pci_dev = to_pci_dev(dev);
pci_vpd_release(pci_dev); pci_release_capabilities(pci_dev);
kfree(pci_dev); kfree(pci_dev);
} }
...@@ -887,8 +823,9 @@ static void set_pcie_port_type(struct pci_dev *pdev) ...@@ -887,8 +823,9 @@ static void set_pcie_port_type(struct pci_dev *pdev)
int pci_cfg_space_size_ext(struct pci_dev *dev) int pci_cfg_space_size_ext(struct pci_dev *dev)
{ {
u32 status; u32 status;
int pos = PCI_CFG_SPACE_SIZE;
if (pci_read_config_dword(dev, 256, &status) != PCIBIOS_SUCCESSFUL) if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL)
goto fail; goto fail;
if (status == 0xffffffff) if (status == 0xffffffff)
goto fail; goto fail;
...@@ -936,8 +873,6 @@ struct pci_dev *alloc_pci_dev(void) ...@@ -936,8 +873,6 @@ struct pci_dev *alloc_pci_dev(void)
INIT_LIST_HEAD(&dev->bus_list); INIT_LIST_HEAD(&dev->bus_list);
pci_msi_init_pci_dev(dev);
return dev; return dev;
} }
EXPORT_SYMBOL(alloc_pci_dev); EXPORT_SYMBOL(alloc_pci_dev);
...@@ -949,6 +884,7 @@ EXPORT_SYMBOL(alloc_pci_dev); ...@@ -949,6 +884,7 @@ EXPORT_SYMBOL(alloc_pci_dev);
static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
{ {
struct pci_dev *dev; struct pci_dev *dev;
struct pci_slot *slot;
u32 l; u32 l;
u8 hdr_type; u8 hdr_type;
int delay = 1; int delay = 1;
...@@ -997,6 +933,10 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) ...@@ -997,6 +933,10 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
dev->error_state = pci_channel_io_normal; dev->error_state = pci_channel_io_normal;
set_pcie_port_type(dev); set_pcie_port_type(dev);
list_for_each_entry(slot, &bus->slots, list)
if (PCI_SLOT(devfn) == slot->number)
dev->slot = slot;
/* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer) /* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)
set this higher, assuming the system even supports it. */ set this higher, assuming the system even supports it. */
dev->dma_mask = 0xffffffff; dev->dma_mask = 0xffffffff;
...@@ -1005,9 +945,22 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) ...@@ -1005,9 +945,22 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
return NULL; return NULL;
} }
return dev;
}
static void pci_init_capabilities(struct pci_dev *dev)
{
/* MSI/MSI-X list */
pci_msi_init_pci_dev(dev);
/* Power Management */
pci_pm_init(dev);
/* Vital Product Data */
pci_vpd_pci22_init(dev); pci_vpd_pci22_init(dev);
return dev; /* Alternative Routing-ID Forwarding */
pci_enable_ari(dev);
} }
void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
...@@ -1026,8 +979,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) ...@@ -1026,8 +979,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
/* Fix up broken headers */ /* Fix up broken headers */
pci_fixup_device(pci_fixup_header, dev); pci_fixup_device(pci_fixup_header, dev);
/* Initialize power management of the device */ /* Initialize various capabilities */
pci_pm_init(dev); pci_init_capabilities(dev);
/* /*
* Add the device to our list of discovered devices * Add the device to our list of discovered devices
......
...@@ -24,6 +24,14 @@ ...@@ -24,6 +24,14 @@
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include "pci.h" #include "pci.h"
int isa_dma_bridge_buggy;
EXPORT_SYMBOL(isa_dma_bridge_buggy);
int pci_pci_problems;
EXPORT_SYMBOL(pci_pci_problems);
int pcie_mch_quirk;
EXPORT_SYMBOL(pcie_mch_quirk);
#ifdef CONFIG_PCI_QUIRKS
/* The Mellanox Tavor device gives false positive parity errors /* The Mellanox Tavor device gives false positive parity errors
* Mark this device with a broken_parity_status, to allow * Mark this device with a broken_parity_status, to allow
* PCI scanning code to "skip" this now blacklisted device. * PCI scanning code to "skip" this now blacklisted device.
...@@ -62,8 +70,6 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_p ...@@ -62,8 +70,6 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_p
This appears to be BIOS not version dependent. So presumably there is a This appears to be BIOS not version dependent. So presumably there is a
chipset level fix */ chipset level fix */
int isa_dma_bridge_buggy;
EXPORT_SYMBOL(isa_dma_bridge_buggy);
static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev) static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
{ {
...@@ -84,9 +90,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_d ...@@ -84,9 +90,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_d
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs);
int pci_pci_problems;
EXPORT_SYMBOL(pci_pci_problems);
/* /*
* Chipsets where PCI->PCI transfers vanish or hang * Chipsets where PCI->PCI transfers vanish or hang
*/ */
...@@ -1362,9 +1365,6 @@ static void __init quirk_alder_ioapic(struct pci_dev *pdev) ...@@ -1362,9 +1365,6 @@ static void __init quirk_alder_ioapic(struct pci_dev *pdev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic);
#endif #endif
int pcie_mch_quirk;
EXPORT_SYMBOL(pcie_mch_quirk);
static void __devinit quirk_pcie_mch(struct pci_dev *pdev) static void __devinit quirk_pcie_mch(struct pci_dev *pdev)
{ {
pcie_mch_quirk = 1; pcie_mch_quirk = 1;
...@@ -1555,84 +1555,6 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev) ...@@ -1555,84 +1555,6 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
} }
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
{
while (f < end) {
if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
(f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
#ifdef DEBUG
dev_dbg(&dev->dev, "calling %pF\n", f->hook);
#endif
f->hook(dev);
}
f++;
}
}
extern struct pci_fixup __start_pci_fixups_early[];
extern struct pci_fixup __end_pci_fixups_early[];
extern struct pci_fixup __start_pci_fixups_header[];
extern struct pci_fixup __end_pci_fixups_header[];
extern struct pci_fixup __start_pci_fixups_final[];
extern struct pci_fixup __end_pci_fixups_final[];
extern struct pci_fixup __start_pci_fixups_enable[];
extern struct pci_fixup __end_pci_fixups_enable[];
extern struct pci_fixup __start_pci_fixups_resume[];
extern struct pci_fixup __end_pci_fixups_resume[];
extern struct pci_fixup __start_pci_fixups_resume_early[];
extern struct pci_fixup __end_pci_fixups_resume_early[];
extern struct pci_fixup __start_pci_fixups_suspend[];
extern struct pci_fixup __end_pci_fixups_suspend[];
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
{
struct pci_fixup *start, *end;
switch(pass) {
case pci_fixup_early:
start = __start_pci_fixups_early;
end = __end_pci_fixups_early;
break;
case pci_fixup_header:
start = __start_pci_fixups_header;
end = __end_pci_fixups_header;
break;
case pci_fixup_final:
start = __start_pci_fixups_final;
end = __end_pci_fixups_final;
break;
case pci_fixup_enable:
start = __start_pci_fixups_enable;
end = __end_pci_fixups_enable;
break;
case pci_fixup_resume:
start = __start_pci_fixups_resume;
end = __end_pci_fixups_resume;
break;
case pci_fixup_resume_early:
start = __start_pci_fixups_resume_early;
end = __end_pci_fixups_resume_early;
break;
case pci_fixup_suspend:
start = __start_pci_fixups_suspend;
end = __end_pci_fixups_suspend;
break;
default:
/* stupid compiler warning, you would think with an enum... */
return;
}
pci_do_fixups(dev, start, end);
}
EXPORT_SYMBOL(pci_fixup_device);
/* Enable 1k I/O space granularity on the Intel P64H2 */ /* Enable 1k I/O space granularity on the Intel P64H2 */
static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
{ {
...@@ -2006,3 +1928,82 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375, ...@@ -2006,3 +1928,82 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
quirk_msi_intx_disable_bug); quirk_msi_intx_disable_bug);
#endif /* CONFIG_PCI_MSI */ #endif /* CONFIG_PCI_MSI */
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
{
while (f < end) {
if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
(f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
dev_dbg(&dev->dev, "calling %pF\n", f->hook);
f->hook(dev);
}
f++;
}
}
extern struct pci_fixup __start_pci_fixups_early[];
extern struct pci_fixup __end_pci_fixups_early[];
extern struct pci_fixup __start_pci_fixups_header[];
extern struct pci_fixup __end_pci_fixups_header[];
extern struct pci_fixup __start_pci_fixups_final[];
extern struct pci_fixup __end_pci_fixups_final[];
extern struct pci_fixup __start_pci_fixups_enable[];
extern struct pci_fixup __end_pci_fixups_enable[];
extern struct pci_fixup __start_pci_fixups_resume[];
extern struct pci_fixup __end_pci_fixups_resume[];
extern struct pci_fixup __start_pci_fixups_resume_early[];
extern struct pci_fixup __end_pci_fixups_resume_early[];
extern struct pci_fixup __start_pci_fixups_suspend[];
extern struct pci_fixup __end_pci_fixups_suspend[];
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
{
struct pci_fixup *start, *end;
switch(pass) {
case pci_fixup_early:
start = __start_pci_fixups_early;
end = __end_pci_fixups_early;
break;
case pci_fixup_header:
start = __start_pci_fixups_header;
end = __end_pci_fixups_header;
break;
case pci_fixup_final:
start = __start_pci_fixups_final;
end = __end_pci_fixups_final;
break;
case pci_fixup_enable:
start = __start_pci_fixups_enable;
end = __end_pci_fixups_enable;
break;
case pci_fixup_resume:
start = __start_pci_fixups_resume;
end = __end_pci_fixups_resume;
break;
case pci_fixup_resume_early:
start = __start_pci_fixups_resume_early;
end = __end_pci_fixups_resume_early;
break;
case pci_fixup_suspend:
start = __start_pci_fixups_suspend;
end = __end_pci_fixups_suspend;
break;
default:
/* stupid compiler warning, you would think with an enum... */
return;
}
pci_do_fixups(dev, start, end);
}
#else
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {}
#endif
EXPORT_SYMBOL(pci_fixup_device);
...@@ -73,6 +73,7 @@ void pci_remove_bus(struct pci_bus *pci_bus) ...@@ -73,6 +73,7 @@ void pci_remove_bus(struct pci_bus *pci_bus)
up_write(&pci_bus_sem); up_write(&pci_bus_sem);
pci_remove_legacy_files(pci_bus); pci_remove_legacy_files(pci_bus);
device_remove_file(&pci_bus->dev, &dev_attr_cpuaffinity); device_remove_file(&pci_bus->dev, &dev_attr_cpuaffinity);
device_remove_file(&pci_bus->dev, &dev_attr_cpulistaffinity);
device_unregister(&pci_bus->dev); device_unregister(&pci_bus->dev);
} }
EXPORT_SYMBOL(pci_remove_bus); EXPORT_SYMBOL(pci_remove_bus);
...@@ -114,13 +115,9 @@ void pci_remove_behind_bridge(struct pci_dev *dev) ...@@ -114,13 +115,9 @@ void pci_remove_behind_bridge(struct pci_dev *dev)
{ {
struct list_head *l, *n; struct list_head *l, *n;
if (dev->subordinate) { if (dev->subordinate)
list_for_each_safe(l, n, &dev->subordinate->devices) { list_for_each_safe(l, n, &dev->subordinate->devices)
struct pci_dev *dev = pci_dev_b(l); pci_remove_bus_device(pci_dev_b(l));
pci_remove_bus_device(dev);
}
}
} }
static void pci_stop_bus_devices(struct pci_bus *bus) static void pci_stop_bus_devices(struct pci_bus *bus)
......
...@@ -299,7 +299,7 @@ static void pbus_size_io(struct pci_bus *bus) ...@@ -299,7 +299,7 @@ static void pbus_size_io(struct pci_bus *bus)
if (r->parent || !(r->flags & IORESOURCE_IO)) if (r->parent || !(r->flags & IORESOURCE_IO))
continue; continue;
r_size = r->end - r->start + 1; r_size = resource_size(r);
if (r_size < 0x400) if (r_size < 0x400)
/* Might be re-aligned for ISA */ /* Might be re-aligned for ISA */
...@@ -350,7 +350,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long ...@@ -350,7 +350,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
if (r->parent || (r->flags & mask) != type) if (r->parent || (r->flags & mask) != type)
continue; continue;
r_size = r->end - r->start + 1; r_size = resource_size(r);
/* For bridges size != alignment */ /* For bridges size != alignment */
align = resource_alignment(r); align = resource_alignment(r);
order = __ffs(align) - 20; order = __ffs(align) - 20;
......
...@@ -129,7 +129,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno) ...@@ -129,7 +129,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
resource_size_t size, min, align; resource_size_t size, min, align;
int ret; int ret;
size = res->end - res->start + 1; size = resource_size(res);
min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
align = resource_alignment(res); align = resource_alignment(res);
......
...@@ -49,11 +49,16 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf) ...@@ -49,11 +49,16 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf)
static void pci_slot_release(struct kobject *kobj) static void pci_slot_release(struct kobject *kobj)
{ {
struct pci_dev *dev;
struct pci_slot *slot = to_pci_slot(kobj); struct pci_slot *slot = to_pci_slot(kobj);
pr_debug("%s: releasing pci_slot on %x:%d\n", __func__, pr_debug("%s: releasing pci_slot on %x:%d\n", __func__,
slot->bus->number, slot->number); slot->bus->number, slot->number);
list_for_each_entry(dev, &slot->bus->devices, bus_list)
if (PCI_SLOT(dev->devfn) == slot->number)
dev->slot = NULL;
list_del(&slot->list); list_del(&slot->list);
kfree(slot); kfree(slot);
...@@ -108,6 +113,7 @@ static struct kobj_type pci_slot_ktype = { ...@@ -108,6 +113,7 @@ static struct kobj_type pci_slot_ktype = {
struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
const char *name) const char *name)
{ {
struct pci_dev *dev;
struct pci_slot *slot; struct pci_slot *slot;
int err; int err;
...@@ -150,6 +156,10 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, ...@@ -150,6 +156,10 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
INIT_LIST_HEAD(&slot->list); INIT_LIST_HEAD(&slot->list);
list_add(&slot->list, &parent->slots); list_add(&slot->list, &parent->slots);
list_for_each_entry(dev, &parent->devices, bus_list)
if (PCI_SLOT(dev->devfn) == slot_nr)
dev->slot = slot;
/* Don't care if debug printk has a -1 for slot_nr */ /* Don't care if debug printk has a -1 for slot_nr */
pr_debug("%s: created pci_slot on %04x:%02x:%02x\n", pr_debug("%s: created pci_slot on %04x:%02x:%02x\n",
__func__, pci_domain_nr(parent), parent->number, slot_nr); __func__, pci_domain_nr(parent), parent->number, slot_nr);
......
...@@ -7859,7 +7859,6 @@ static struct pci_driver ipr_driver = { ...@@ -7859,7 +7859,6 @@ static struct pci_driver ipr_driver = {
.remove = ipr_remove, .remove = ipr_remove,
.shutdown = ipr_shutdown, .shutdown = ipr_shutdown,
.err_handler = &ipr_err_handler, .err_handler = &ipr_err_handler,
.dynids.use_driver_data = 1
}; };
/** /**
......
...@@ -1566,9 +1566,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1566,9 +1566,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto probe_out; goto probe_out;
} }
if (pci_find_aer_capability(pdev)) /* This may fail but that's ok */
if (pci_enable_pcie_error_reporting(pdev)) pci_enable_pcie_error_reporting(pdev);
goto probe_out;
host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t)); host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
if (host == NULL) { if (host == NULL) {
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#if defined(CONFIG_PCIEAER) #if defined(CONFIG_PCIEAER)
/* pci-e port driver needs this function to enable aer */ /* pci-e port driver needs this function to enable aer */
extern int pci_enable_pcie_error_reporting(struct pci_dev *dev); extern int pci_enable_pcie_error_reporting(struct pci_dev *dev);
extern int pci_find_aer_capability(struct pci_dev *dev);
extern int pci_disable_pcie_error_reporting(struct pci_dev *dev); extern int pci_disable_pcie_error_reporting(struct pci_dev *dev);
extern int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev); extern int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
#else #else
...@@ -18,10 +17,6 @@ static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) ...@@ -18,10 +17,6 @@ static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev)
{ {
return -EINVAL; return -EINVAL;
} }
static inline int pci_find_aer_capability(struct pci_dev *dev)
{
return 0;
}
static inline int pci_disable_pcie_error_reporting(struct pci_dev *dev) static inline int pci_disable_pcie_error_reporting(struct pci_dev *dev)
{ {
return -EINVAL; return -EINVAL;
......
...@@ -214,6 +214,7 @@ struct pci_dev { ...@@ -214,6 +214,7 @@ struct pci_dev {
unsigned int broken_parity_status:1; /* Device generates false positive parity */ unsigned int broken_parity_status:1; /* Device generates false positive parity */
unsigned int msi_enabled:1; unsigned int msi_enabled:1;
unsigned int msix_enabled:1; unsigned int msix_enabled:1;
unsigned int ari_enabled:1; /* ARI forwarding */
unsigned int is_managed:1; unsigned int is_managed:1;
unsigned int is_pcie:1; unsigned int is_pcie:1;
pci_dev_flags_t dev_flags; pci_dev_flags_t dev_flags;
...@@ -347,7 +348,6 @@ struct pci_bus_region { ...@@ -347,7 +348,6 @@ struct pci_bus_region {
struct pci_dynids { struct pci_dynids {
spinlock_t lock; /* protects list, index */ spinlock_t lock; /* protects list, index */
struct list_head list; /* for IDs added at runtime */ struct list_head list; /* for IDs added at runtime */
unsigned int use_driver_data:1; /* pci_device_id->driver_data is used */
}; };
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
...@@ -456,8 +456,8 @@ struct pci_driver { ...@@ -456,8 +456,8 @@ struct pci_driver {
/** /**
* PCI_VDEVICE - macro used to describe a specific pci device in short form * PCI_VDEVICE - macro used to describe a specific pci device in short form
* @vend: the vendor name * @vendor: the vendor name
* @dev: the 16 bit PCI Device ID * @device: the 16 bit PCI Device ID
* *
* This macro is used to create a struct pci_device_id that matches a * This macro is used to create a struct pci_device_id that matches a
* specific PCI device. The subvendor, and subdevice fields will be set * specific PCI device. The subvendor, and subdevice fields will be set
...@@ -645,6 +645,7 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); ...@@ -645,6 +645,7 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
bool pci_pme_capable(struct pci_dev *dev, pci_power_t state); bool pci_pme_capable(struct pci_dev *dev, pci_power_t state);
void pci_pme_active(struct pci_dev *dev, bool enable); void pci_pme_active(struct pci_dev *dev, bool enable);
int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable); int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable);
int pci_wake_from_d3(struct pci_dev *dev, bool enable);
pci_power_t pci_target_state(struct pci_dev *dev); pci_power_t pci_target_state(struct pci_dev *dev);
int pci_prepare_to_sleep(struct pci_dev *dev); int pci_prepare_to_sleep(struct pci_dev *dev);
int pci_back_from_sleep(struct pci_dev *dev); int pci_back_from_sleep(struct pci_dev *dev);
...@@ -1118,5 +1119,20 @@ static inline void pci_mmcfg_early_init(void) { } ...@@ -1118,5 +1119,20 @@ static inline void pci_mmcfg_early_init(void) { }
static inline void pci_mmcfg_late_init(void) { } static inline void pci_mmcfg_late_init(void) { }
#endif #endif
#ifdef CONFIG_HAS_IOMEM
static inline void * pci_ioremap_bar(struct pci_dev *pdev, int bar)
{
/*
* Make sure the BAR is actually a memory resource, not an IO resource
*/
if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
WARN_ON(1);
return NULL;
}
return ioremap_nocache(pci_resource_start(pdev, bar),
pci_resource_len(pdev, bar));
}
#endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* LINUX_PCI_H */ #endif /* LINUX_PCI_H */
...@@ -2454,9 +2454,9 @@ ...@@ -2454,9 +2454,9 @@
#define PCI_DEVICE_ID_INTEL_ICH10_3 0x3a1a #define PCI_DEVICE_ID_INTEL_ICH10_3 0x3a1a
#define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30 #define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30
#define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60 #define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60
#define PCI_DEVICE_ID_INTEL_PCH_0 0x3b10 #define PCI_DEVICE_ID_INTEL_PCH_LPC_MIN 0x3b00
#define PCI_DEVICE_ID_INTEL_PCH_1 0x3b11 #define PCI_DEVICE_ID_INTEL_PCH_LPC_MAX 0x3b1f
#define PCI_DEVICE_ID_INTEL_PCH_2 0x3b30 #define PCI_DEVICE_ID_INTEL_PCH_SMBUS 0x3b30
#define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f #define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f
#define PCI_DEVICE_ID_INTEL_5100_16 0x65f0 #define PCI_DEVICE_ID_INTEL_5100_16 0x65f0
#define PCI_DEVICE_ID_INTEL_5100_21 0x65f5 #define PCI_DEVICE_ID_INTEL_5100_21 0x65f5
......
...@@ -419,6 +419,10 @@ ...@@ -419,6 +419,10 @@
#define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */ #define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */
#define PCI_EXP_RTCAP 30 /* Root Capabilities */ #define PCI_EXP_RTCAP 30 /* Root Capabilities */
#define PCI_EXP_RTSTA 32 /* Root Status */ #define PCI_EXP_RTSTA 32 /* Root Status */
#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */
#define PCI_EXP_DEVCAP2_ARI 0x20 /* Alternative Routing-ID */
#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */
#define PCI_EXP_DEVCTL2_ARI 0x20 /* Alternative Routing-ID */
/* Extended Capabilities (PCI-X 2.0 and Express) */ /* Extended Capabilities (PCI-X 2.0 and Express) */
#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff) #define PCI_EXT_CAP_ID(header) (header & 0x0000ffff)
...@@ -429,6 +433,7 @@ ...@@ -429,6 +433,7 @@
#define PCI_EXT_CAP_ID_VC 2 #define PCI_EXT_CAP_ID_VC 2
#define PCI_EXT_CAP_ID_DSN 3 #define PCI_EXT_CAP_ID_DSN 3
#define PCI_EXT_CAP_ID_PWR 4 #define PCI_EXT_CAP_ID_PWR 4
#define PCI_EXT_CAP_ID_ARI 14
/* Advanced Error Reporting */ /* Advanced Error Reporting */
#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */ #define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */
...@@ -536,5 +541,14 @@ ...@@ -536,5 +541,14 @@
#define HT_CAPTYPE_GEN3 0xD0 /* Generation 3 hypertransport configuration */ #define HT_CAPTYPE_GEN3 0xD0 /* Generation 3 hypertransport configuration */
#define HT_CAPTYPE_PM 0xE0 /* Hypertransport powermanagement configuration */ #define HT_CAPTYPE_PM 0xE0 /* Hypertransport powermanagement configuration */
/* Alternative Routing-ID Interpretation */
#define PCI_ARI_CAP 0x04 /* ARI Capability Register */
#define PCI_ARI_CAP_MFVC 0x0001 /* MFVC Function Groups Capability */
#define PCI_ARI_CAP_ACS 0x0002 /* ACS Function Groups Capability */
#define PCI_ARI_CAP_NFN(x) (((x) >> 8) & 0xff) /* Next Function Number */
#define PCI_ARI_CTRL 0x06 /* ARI Control Register */
#define PCI_ARI_CTRL_MFVC 0x0001 /* MFVC Function Groups Enable */
#define PCI_ARI_CTRL_ACS 0x0002 /* ACS Function Groups Enable */
#define PCI_ARI_CTRL_FG(x) (((x) >> 4) & 7) /* Function Group */
#endif /* LINUX_PCI_REGS_H */ #endif /* LINUX_PCI_REGS_H */
...@@ -737,6 +737,14 @@ config VM_EVENT_COUNTERS ...@@ -737,6 +737,14 @@ config VM_EVENT_COUNTERS
on EMBEDDED systems. /proc/vmstat will only show page counts on EMBEDDED systems. /proc/vmstat will only show page counts
if VM event counters are disabled. if VM event counters are disabled.
config PCI_QUIRKS
default y
bool "Enable PCI quirk workarounds" if EMBEDDED && PCI
help
This enables workarounds for various PCI chipset
bugs/quirks. Disable this only if your target machine is
unaffected by PCI quirks.
config SLUB_DEBUG config SLUB_DEBUG
default y default y
bool "Enable SLUB debugging support" if EMBEDDED bool "Enable SLUB debugging support" if EMBEDDED
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment