mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 11:16:11 +00:00
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 ...
This commit is contained in:
commit
a0bfb673dc
47 changed files with 1024 additions and 679 deletions
|
@ -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
|
||||
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. A device driver is prohibited from requesting the MMIO
|
||||
address space of the MSI-X table/MSI-X PBA. Otherwise, the PCI subsystem
|
||||
will fail enabling MSI-X on its hardware device when it calls the function
|
||||
pci_enable_msix().
|
||||
table/MSI-X PBA. A device driver should not access the MMIO address
|
||||
space of the MSI-X table/MSI-X PBA.
|
||||
|
||||
5.3.2 API pci_enable_msix
|
||||
|
||||
|
|
|
@ -163,6 +163,10 @@ need pass only as many optional fields as necessary:
|
|||
o class and classmask fields default to 0
|
||||
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
|
||||
PCI devices listed in its (newly updated) pci_ids list.
|
||||
|
||||
|
|
|
@ -203,22 +203,17 @@ to mmio_enabled.
|
|||
|
||||
3.3 helper functions
|
||||
|
||||
3.3.1 int pci_find_aer_capability(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);
|
||||
3.3.1 int pci_enable_pcie_error_reporting(struct pci_dev *dev);
|
||||
pci_enable_pcie_error_reporting enables the device to send error
|
||||
messages to root port when an error is detected. Note that devices
|
||||
don't enable the error reporting by default, so device drivers need
|
||||
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
|
||||
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
|
||||
error status register.
|
||||
|
||||
|
|
|
@ -101,6 +101,7 @@ parameter is applicable:
|
|||
X86-64 X86-64 architecture is enabled.
|
||||
More X86-64 boot options can be found in
|
||||
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:
|
||||
|
||||
|
@ -1588,7 +1589,7 @@ and is between 256 and 4096 characters. It is defined in the file
|
|||
See also Documentation/paride.txt.
|
||||
|
||||
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
|
||||
the hardware directly. Use this if your machine
|
||||
has a non-standard PCI host bridge.
|
||||
|
@ -1596,9 +1597,9 @@ and is between 256 and 4096 characters. It is defined in the file
|
|||
hardware access methods are allowed. Use this
|
||||
if you experience crashes upon bootup and you
|
||||
suspect they are caused by the BIOS.
|
||||
conf1 [X86-32] Force use of PCI Configuration
|
||||
conf1 [X86] Force use of PCI Configuration
|
||||
Mechanism 1.
|
||||
conf2 [X86-32] Force use of PCI Configuration
|
||||
conf2 [X86] Force use of PCI Configuration
|
||||
Mechanism 2.
|
||||
noaer [PCIE] If the PCIEAER kernel config parameter is
|
||||
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
|
|||
this option if the kernel is unable to allocate
|
||||
IRQs or discover secondary PCI buses on your
|
||||
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
|
||||
address decoders between ROMs and other
|
||||
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
|
||||
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
|
||||
make the kernel exclude IRQs of your ISA cards
|
||||
this way.
|
||||
pirqaddr=0xAAAAA [X86-32] Specify the physical address
|
||||
pirqaddr=0xAAAAA [X86] Specify the physical address
|
||||
of the PIRQ table (normally generated
|
||||
by the BIOS) if it is outside the
|
||||
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
|
||||
secondary buses and you want to tell it
|
||||
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
|
||||
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
|
||||
some systems with broken BIOSes, notably
|
||||
some HP Pavilion N5400 and Omnibook XE3
|
||||
notebooks. This will have no effect if ACPI
|
||||
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.
|
||||
use_crs [X86-32] Use _CRS for PCI resource
|
||||
use_crs [X86] Use _CRS for PCI resource
|
||||
allocation.
|
||||
routeirq Do IRQ routing for all PCI devices.
|
||||
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
|
|||
reserved for the CardBus bridge's memory
|
||||
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
|
||||
|
||||
pd. [PARIDE]
|
||||
|
|
|
@ -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);
|
||||
#define HAVE_PCI_LEGACY
|
||||
extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
|
||||
struct vm_area_struct *vma);
|
||||
extern ssize_t pci_read_legacy_io(struct kobject *kobj,
|
||||
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);
|
||||
struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state);
|
||||
|
||||
#define pci_get_legacy_mem platform_pci_get_legacy_mem
|
||||
#define pci_legacy_read platform_pci_legacy_read
|
||||
|
|
|
@ -614,12 +614,17 @@ char *ia64_pci_get_legacy_mem(struct pci_bus *bus)
|
|||
* vector to get the base address.
|
||||
*/
|
||||
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;
|
||||
pgprot_t prot;
|
||||
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
|
||||
* for more details.
|
||||
|
|
|
@ -74,6 +74,13 @@ struct pci_controller {
|
|||
unsigned long pci_io_size;
|
||||
#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;
|
||||
unsigned int __iomem *cfg_addr;
|
||||
void __iomem *cfg_data;
|
||||
|
|
|
@ -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() */
|
||||
#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)
|
||||
/*
|
||||
* 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,
|
|||
extern void pcibios_do_bus_setup(struct pci_bus *bus);
|
||||
extern void pcibios_fixup_of_probed_bus(struct pci_bus *bus);
|
||||
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __ASM_POWERPC_PCI_H */
|
||||
|
|
|
@ -451,7 +451,8 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
|
|||
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);
|
||||
}
|
||||
|
@ -490,6 +491,131 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
|||
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,
|
||||
const struct resource *rsrc,
|
||||
resource_size_t *start, resource_size_t *end)
|
||||
|
@ -592,6 +718,12 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
|
|||
cpu_addr = of_translate_address(dev, ranges + 3);
|
||||
size = of_read_number(ranges + pna + 3, 2);
|
||||
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)
|
||||
continue;
|
||||
|
||||
|
@ -665,6 +797,8 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
|
|||
isa_hole = memno;
|
||||
if (primary || isa_mem_base == 0)
|
||||
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
|
||||
|
|
|
@ -493,7 +493,7 @@ static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq
|
|||
if (pirq <= 4)
|
||||
irq = read_config_nybble(router, 0x56, pirq - 1);
|
||||
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);
|
||||
return irq;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
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);
|
||||
if (pirq <= 4)
|
||||
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
|
|||
case PCI_DEVICE_ID_INTEL_ICH10_1:
|
||||
case PCI_DEVICE_ID_INTEL_ICH10_2:
|
||||
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->get = pirq_piix_get;
|
||||
r->set = pirq_piix_set;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -823,7 +830,7 @@ static void __init pirq_find_router(struct irq_router *r)
|
|||
r->get = 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);
|
||||
|
||||
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)
|
|||
h->probe(r, pirq_router_dev, pirq_router_dev->device))
|
||||
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_dev->vendor, pirq_router_dev->device);
|
||||
|
||||
|
|
|
@ -332,10 +332,6 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
|
|||
int error;
|
||||
u8 temp;
|
||||
|
||||
/* driver_data might come from user-space, so check it */
|
||||
if (id->driver_data >= ARRAY_SIZE(chipname))
|
||||
return -EINVAL;
|
||||
|
||||
if (amd756_ioport) {
|
||||
dev_err(&pdev->dev, "Only one device supported "
|
||||
"(you have a strange motherboard, btw)\n");
|
||||
|
@ -412,7 +408,6 @@ static struct pci_driver amd756_driver = {
|
|||
.id_table = amd756_ids,
|
||||
.probe = amd756_probe,
|
||||
.remove = __devexit_p(amd756_remove),
|
||||
.dynids.use_driver_data = 1,
|
||||
};
|
||||
|
||||
static int __init amd756_init(void)
|
||||
|
|
|
@ -332,10 +332,6 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
|
|||
unsigned char temp;
|
||||
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 */
|
||||
if (force_addr) {
|
||||
vt596_smba = force_addr & 0xfff0;
|
||||
|
@ -483,7 +479,6 @@ static struct pci_driver vt596_driver = {
|
|||
.name = "vt596_smbus",
|
||||
.id_table = vt596_ids,
|
||||
.probe = vt596_probe,
|
||||
.dynids.use_driver_data = 1,
|
||||
};
|
||||
|
||||
static int __init i2c_vt596_init(void)
|
||||
|
|
|
@ -151,6 +151,13 @@ void pci_bus_add_devices(struct pci_bus *bus)
|
|||
if (retval)
|
||||
dev_err(&dev->dev, "Error creating cpuaffinity"
|
||||
" 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,10 +123,8 @@ static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void)
|
|||
static void __init print_bus_info (void)
|
||||
{
|
||||
struct bus_info *ptr;
|
||||
struct list_head *ptr1;
|
||||
|
||||
list_for_each (ptr1, &bus_info_head) {
|
||||
ptr = list_entry (ptr1, struct bus_info, bus_info_list);
|
||||
list_for_each_entry(ptr, &bus_info_head, bus_info_list) {
|
||||
debug ("%s - slot_min = %x\n", __func__, ptr->slot_min);
|
||||
debug ("%s - slot_max = %x\n", __func__, ptr->slot_max);
|
||||
debug ("%s - slot_count = %x\n", __func__, ptr->slot_count);
|
||||
|
@ -146,10 +144,8 @@ static void __init print_bus_info (void)
|
|||
static void print_lo_info (void)
|
||||
{
|
||||
struct rio_detail *ptr;
|
||||
struct list_head *ptr1;
|
||||
debug ("print_lo_info ----\n");
|
||||
list_for_each (ptr1, &rio_lo_head) {
|
||||
ptr = list_entry (ptr1, struct rio_detail, rio_detail_list);
|
||||
list_for_each_entry(ptr, &rio_lo_head, rio_detail_list) {
|
||||
debug ("%s - rio_node_id = %x\n", __func__, ptr->rio_node_id);
|
||||
debug ("%s - rio_type = %x\n", __func__, ptr->rio_type);
|
||||
debug ("%s - owner_id = %x\n", __func__, ptr->owner_id);
|
||||
|
@ -163,10 +159,8 @@ static void print_lo_info (void)
|
|||
static void print_vg_info (void)
|
||||
{
|
||||
struct rio_detail *ptr;
|
||||
struct list_head *ptr1;
|
||||
debug ("%s ---\n", __func__);
|
||||
list_for_each (ptr1, &rio_vg_head) {
|
||||
ptr = list_entry (ptr1, struct rio_detail, rio_detail_list);
|
||||
list_for_each_entry(ptr, &rio_vg_head, rio_detail_list) {
|
||||
debug ("%s - rio_node_id = %x\n", __func__, ptr->rio_node_id);
|
||||
debug ("%s - rio_type = %x\n", __func__, ptr->rio_type);
|
||||
debug ("%s - owner_id = %x\n", __func__, ptr->owner_id);
|
||||
|
@ -180,10 +174,8 @@ static void print_vg_info (void)
|
|||
static void __init print_ebda_pci_rsrc (void)
|
||||
{
|
||||
struct ebda_pci_rsrc *ptr;
|
||||
struct list_head *ptr1;
|
||||
|
||||
list_for_each (ptr1, &ibmphp_ebda_pci_rsrc_head) {
|
||||
ptr = list_entry (ptr1, struct ebda_pci_rsrc, ebda_pci_rsrc_list);
|
||||
list_for_each_entry(ptr, &ibmphp_ebda_pci_rsrc_head, ebda_pci_rsrc_list) {
|
||||
debug ("%s - rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n",
|
||||
__func__, ptr->rsrc_type ,ptr->bus_num, ptr->dev_fun,ptr->start_addr, ptr->end_addr);
|
||||
}
|
||||
|
@ -192,10 +184,8 @@ static void __init print_ebda_pci_rsrc (void)
|
|||
static void __init print_ibm_slot (void)
|
||||
{
|
||||
struct slot *ptr;
|
||||
struct list_head *ptr1;
|
||||
|
||||
list_for_each (ptr1, &ibmphp_slot_head) {
|
||||
ptr = list_entry (ptr1, struct slot, ibm_slot_list);
|
||||
list_for_each_entry(ptr, &ibmphp_slot_head, ibm_slot_list) {
|
||||
debug ("%s - slot_number: %x\n", __func__, ptr->number);
|
||||
}
|
||||
}
|
||||
|
@ -203,10 +193,8 @@ static void __init print_ibm_slot (void)
|
|||
static void __init print_opt_vg (void)
|
||||
{
|
||||
struct opt_rio *ptr;
|
||||
struct list_head *ptr1;
|
||||
debug ("%s ---\n", __func__);
|
||||
list_for_each (ptr1, &opt_vg_head) {
|
||||
ptr = list_entry (ptr1, struct opt_rio, opt_rio_list);
|
||||
list_for_each_entry(ptr, &opt_vg_head, opt_rio_list) {
|
||||
debug ("%s - rio_type %x\n", __func__, ptr->rio_type);
|
||||
debug ("%s - chassis_num: %x\n", __func__, ptr->chassis_num);
|
||||
debug ("%s - first_slot_num: %x\n", __func__, ptr->first_slot_num);
|
||||
|
@ -217,13 +205,9 @@ static void __init print_opt_vg (void)
|
|||
static void __init print_ebda_hpc (void)
|
||||
{
|
||||
struct controller *hpc_ptr;
|
||||
struct list_head *ptr1;
|
||||
u16 index;
|
||||
|
||||
list_for_each (ptr1, &ebda_hpc_head) {
|
||||
|
||||
hpc_ptr = list_entry (ptr1, struct controller, ebda_hpc_list);
|
||||
|
||||
list_for_each_entry(hpc_ptr, &ebda_hpc_head, ebda_hpc_list) {
|
||||
for (index = 0; index < hpc_ptr->slot_count; index++) {
|
||||
debug ("%s - physical slot#: %x\n", __func__, hpc_ptr->slots[index].slot_num);
|
||||
debug ("%s - pci bus# of the slot: %x\n", __func__, hpc_ptr->slots[index].slot_bus_num);
|
||||
|
@ -460,9 +444,7 @@ static int __init ebda_rio_table (void)
|
|||
static struct opt_rio *search_opt_vg (u8 chassis_num)
|
||||
{
|
||||
struct opt_rio *ptr;
|
||||
struct list_head *ptr1;
|
||||
list_for_each (ptr1, &opt_vg_head) {
|
||||
ptr = list_entry (ptr1, struct opt_rio, opt_rio_list);
|
||||
list_for_each_entry(ptr, &opt_vg_head, opt_rio_list) {
|
||||
if (ptr->chassis_num == chassis_num)
|
||||
return ptr;
|
||||
}
|
||||
|
@ -473,10 +455,8 @@ static int __init combine_wpg_for_chassis (void)
|
|||
{
|
||||
struct opt_rio *opt_rio_ptr = NULL;
|
||||
struct rio_detail *rio_detail_ptr = NULL;
|
||||
struct list_head *list_head_ptr = NULL;
|
||||
|
||||
list_for_each (list_head_ptr, &rio_vg_head) {
|
||||
rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
|
||||
list_for_each_entry(rio_detail_ptr, &rio_vg_head, rio_detail_list) {
|
||||
opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num);
|
||||
if (!opt_rio_ptr) {
|
||||
opt_rio_ptr = kzalloc(sizeof(struct opt_rio), GFP_KERNEL);
|
||||
|
@ -497,14 +477,12 @@ static int __init combine_wpg_for_chassis (void)
|
|||
}
|
||||
|
||||
/*
|
||||
* reorgnizing linked list of expansion box
|
||||
* reorganizing linked list of expansion box
|
||||
*/
|
||||
static struct opt_rio_lo *search_opt_lo (u8 chassis_num)
|
||||
{
|
||||
struct opt_rio_lo *ptr;
|
||||
struct list_head *ptr1;
|
||||
list_for_each (ptr1, &opt_lo_head) {
|
||||
ptr = list_entry (ptr1, struct opt_rio_lo, opt_rio_lo_list);
|
||||
list_for_each_entry(ptr, &opt_lo_head, opt_rio_lo_list) {
|
||||
if (ptr->chassis_num == chassis_num)
|
||||
return ptr;
|
||||
}
|
||||
|
@ -515,10 +493,8 @@ static int combine_wpg_for_expansion (void)
|
|||
{
|
||||
struct opt_rio_lo *opt_rio_lo_ptr = NULL;
|
||||
struct rio_detail *rio_detail_ptr = NULL;
|
||||
struct list_head *list_head_ptr = NULL;
|
||||
|
||||
list_for_each (list_head_ptr, &rio_lo_head) {
|
||||
rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
|
||||
list_for_each_entry(rio_detail_ptr, &rio_lo_head, rio_detail_list) {
|
||||
opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num);
|
||||
if (!opt_rio_lo_ptr) {
|
||||
opt_rio_lo_ptr = kzalloc(sizeof(struct opt_rio_lo), GFP_KERNEL);
|
||||
|
@ -550,20 +526,17 @@ static int first_slot_num (u8 slot_num, u8 first_slot, u8 var)
|
|||
{
|
||||
struct opt_rio *opt_vg_ptr = NULL;
|
||||
struct opt_rio_lo *opt_lo_ptr = NULL;
|
||||
struct list_head *ptr = NULL;
|
||||
int rc = 0;
|
||||
|
||||
if (!var) {
|
||||
list_for_each (ptr, &opt_vg_head) {
|
||||
opt_vg_ptr = list_entry (ptr, struct opt_rio, opt_rio_list);
|
||||
list_for_each_entry(opt_vg_ptr, &opt_vg_head, opt_rio_list) {
|
||||
if ((first_slot < opt_vg_ptr->first_slot_num) && (slot_num >= opt_vg_ptr->first_slot_num)) {
|
||||
rc = -ENODEV;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
list_for_each (ptr, &opt_lo_head) {
|
||||
opt_lo_ptr = list_entry (ptr, struct opt_rio_lo, opt_rio_lo_list);
|
||||
list_for_each_entry(opt_lo_ptr, &opt_lo_head, opt_rio_lo_list) {
|
||||
if ((first_slot < opt_lo_ptr->first_slot_num) && (slot_num >= opt_lo_ptr->first_slot_num)) {
|
||||
rc = -ENODEV;
|
||||
break;
|
||||
|
@ -576,10 +549,8 @@ static int first_slot_num (u8 slot_num, u8 first_slot, u8 var)
|
|||
static struct opt_rio_lo * find_rxe_num (u8 slot_num)
|
||||
{
|
||||
struct opt_rio_lo *opt_lo_ptr;
|
||||
struct list_head *ptr;
|
||||
|
||||
list_for_each (ptr, &opt_lo_head) {
|
||||
opt_lo_ptr = list_entry (ptr, struct opt_rio_lo, opt_rio_lo_list);
|
||||
list_for_each_entry(opt_lo_ptr, &opt_lo_head, opt_rio_lo_list) {
|
||||
//check to see if this slot_num belongs to expansion box
|
||||
if ((slot_num >= opt_lo_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_lo_ptr->first_slot_num, 1)))
|
||||
return opt_lo_ptr;
|
||||
|
@ -590,10 +561,8 @@ static struct opt_rio_lo * find_rxe_num (u8 slot_num)
|
|||
static struct opt_rio * find_chassis_num (u8 slot_num)
|
||||
{
|
||||
struct opt_rio *opt_vg_ptr;
|
||||
struct list_head *ptr;
|
||||
|
||||
list_for_each (ptr, &opt_vg_head) {
|
||||
opt_vg_ptr = list_entry (ptr, struct opt_rio, opt_rio_list);
|
||||
list_for_each_entry(opt_vg_ptr, &opt_vg_head, opt_rio_list) {
|
||||
//check to see if this slot_num belongs to chassis
|
||||
if ((slot_num >= opt_vg_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_vg_ptr->first_slot_num, 0)))
|
||||
return opt_vg_ptr;
|
||||
|
@ -607,11 +576,9 @@ static struct opt_rio * find_chassis_num (u8 slot_num)
|
|||
static u8 calculate_first_slot (u8 slot_num)
|
||||
{
|
||||
u8 first_slot = 1;
|
||||
struct list_head * list;
|
||||
struct slot * slot_cur;
|
||||
|
||||
list_for_each (list, &ibmphp_slot_head) {
|
||||
slot_cur = list_entry (list, struct slot, ibm_slot_list);
|
||||
list_for_each_entry(slot_cur, &ibmphp_slot_head, ibm_slot_list) {
|
||||
if (slot_cur->ctrl) {
|
||||
if ((slot_cur->ctrl->ctlr_type != 4) && (slot_cur->ctrl->ending_slot_num > first_slot) && (slot_num > slot_cur->ctrl->ending_slot_num))
|
||||
first_slot = slot_cur->ctrl->ending_slot_num;
|
||||
|
@ -767,7 +734,6 @@ static int __init ebda_rsrc_controller (void)
|
|||
struct bus_info *bus_info_ptr1, *bus_info_ptr2;
|
||||
int rc;
|
||||
struct slot *tmp_slot;
|
||||
struct list_head *list;
|
||||
|
||||
addr = hpc_list_ptr->phys_addr;
|
||||
for (ctlr = 0; ctlr < hpc_list_ptr->num_ctlrs; ctlr++) {
|
||||
|
@ -997,9 +963,7 @@ static int __init ebda_rsrc_controller (void)
|
|||
|
||||
} /* each hpc */
|
||||
|
||||
list_for_each (list, &ibmphp_slot_head) {
|
||||
tmp_slot = list_entry (list, struct slot, ibm_slot_list);
|
||||
|
||||
list_for_each_entry(tmp_slot, &ibmphp_slot_head, ibm_slot_list) {
|
||||
snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot));
|
||||
pci_hp_register(tmp_slot->hotplug_slot,
|
||||
pci_find_bus(0, tmp_slot->bus), tmp_slot->device);
|
||||
|
@ -1101,10 +1065,8 @@ u16 ibmphp_get_total_controllers (void)
|
|||
struct slot *ibmphp_get_slot_from_physical_num (u8 physical_num)
|
||||
{
|
||||
struct slot *slot;
|
||||
struct list_head *list;
|
||||
|
||||
list_for_each (list, &ibmphp_slot_head) {
|
||||
slot = list_entry (list, struct slot, ibm_slot_list);
|
||||
list_for_each_entry(slot, &ibmphp_slot_head, ibm_slot_list) {
|
||||
if (slot->number == physical_num)
|
||||
return slot;
|
||||
}
|
||||
|
@ -1120,10 +1082,8 @@ struct slot *ibmphp_get_slot_from_physical_num (u8 physical_num)
|
|||
struct bus_info *ibmphp_find_same_bus_num (u32 num)
|
||||
{
|
||||
struct bus_info *ptr;
|
||||
struct list_head *ptr1;
|
||||
|
||||
list_for_each (ptr1, &bus_info_head) {
|
||||
ptr = list_entry (ptr1, struct bus_info, bus_info_list);
|
||||
list_for_each_entry(ptr, &bus_info_head, bus_info_list) {
|
||||
if (ptr->busno == num)
|
||||
return ptr;
|
||||
}
|
||||
|
@ -1136,10 +1096,8 @@ struct bus_info *ibmphp_find_same_bus_num (u32 num)
|
|||
int ibmphp_get_bus_index (u8 num)
|
||||
{
|
||||
struct bus_info *ptr;
|
||||
struct list_head *ptr1;
|
||||
|
||||
list_for_each (ptr1, &bus_info_head) {
|
||||
ptr = list_entry (ptr1, struct bus_info, bus_info_list);
|
||||
list_for_each_entry(ptr, &bus_info_head, bus_info_list) {
|
||||
if (ptr->busno == num)
|
||||
return ptr->index;
|
||||
}
|
||||
|
@ -1212,11 +1170,9 @@ static struct pci_driver ibmphp_driver = {
|
|||
int ibmphp_register_pci (void)
|
||||
{
|
||||
struct controller *ctrl;
|
||||
struct list_head *tmp;
|
||||
int rc = 0;
|
||||
|
||||
list_for_each (tmp, &ebda_hpc_head) {
|
||||
ctrl = list_entry (tmp, struct controller, ebda_hpc_list);
|
||||
list_for_each_entry(ctrl, &ebda_hpc_head, ebda_hpc_list) {
|
||||
if (ctrl->ctlr_type == 1) {
|
||||
rc = pci_register_driver(&ibmphp_driver);
|
||||
break;
|
||||
|
@ -1227,12 +1183,10 @@ int ibmphp_register_pci (void)
|
|||
static int ibmphp_probe (struct pci_dev * dev, const struct pci_device_id *ids)
|
||||
{
|
||||
struct controller *ctrl;
|
||||
struct list_head *tmp;
|
||||
|
||||
debug ("inside ibmphp_probe\n");
|
||||
|
||||
list_for_each (tmp, &ebda_hpc_head) {
|
||||
ctrl = list_entry (tmp, struct controller, ebda_hpc_list);
|
||||
list_for_each_entry(ctrl, &ebda_hpc_head, ebda_hpc_list) {
|
||||
if (ctrl->ctlr_type == 1) {
|
||||
if ((dev->devfn == ctrl->u.pci_ctlr.dev_fun) && (dev->bus->number == ctrl->u.pci_ctlr.bus)) {
|
||||
ctrl->ctrl_dev = dev;
|
||||
|
|
|
@ -102,13 +102,13 @@ static int get_##name (struct hotplug_slot *slot, type *value) \
|
|||
{ \
|
||||
struct hotplug_slot_ops *ops = slot->ops; \
|
||||
int retval = 0; \
|
||||
if (try_module_get(ops->owner)) { \
|
||||
if (ops->get_##name) \
|
||||
retval = ops->get_##name(slot, value); \
|
||||
else \
|
||||
*value = slot->info->name; \
|
||||
module_put(ops->owner); \
|
||||
} \
|
||||
if (!try_module_get(ops->owner)) \
|
||||
return -ENODEV; \
|
||||
if (ops->get_##name) \
|
||||
retval = ops->get_##name(slot, value); \
|
||||
else \
|
||||
*value = slot->info->name; \
|
||||
module_put(ops->owner); \
|
||||
return retval; \
|
||||
}
|
||||
|
||||
|
|
|
@ -57,6 +57,19 @@ extern struct workqueue_struct *pciehp_wq;
|
|||
#define warn(format, 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
|
||||
struct slot {
|
||||
u8 bus;
|
||||
|
@ -87,6 +100,7 @@ struct controller {
|
|||
int num_slots; /* Number of slots on ctlr */
|
||||
int slot_num_inc; /* 1 or -1 */
|
||||
struct pci_dev *pci_dev;
|
||||
struct pcie_device *pcie; /* PCI Express port service */
|
||||
struct list_head slot_list;
|
||||
struct hpc_ops *hpc_ops;
|
||||
wait_queue_head_t queue; /* sleep & wake process */
|
||||
|
@ -170,7 +184,7 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -144,9 +144,10 @@ set_lock_exit:
|
|||
* sysfs interface which allows the user to toggle the Electro Mechanical
|
||||
* 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,
|
||||
size_t count)
|
||||
static ssize_t lock_write_file(struct hotplug_slot *hotplug_slot,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct slot *slot = hotplug_slot->private;
|
||||
unsigned long llock;
|
||||
u8 lock;
|
||||
int retval = 0;
|
||||
|
@ -157,10 +158,11 @@ static ssize_t lock_write_file(struct hotplug_slot *slot, const char *buf,
|
|||
switch (lock) {
|
||||
case 0:
|
||||
case 1:
|
||||
retval = set_lock_status(slot, lock);
|
||||
retval = set_lock_status(hotplug_slot, lock);
|
||||
break;
|
||||
default:
|
||||
err ("%d is an invalid lock value\n", lock);
|
||||
ctrl_err(slot->ctrl, "%d is an invalid lock value\n",
|
||||
lock);
|
||||
retval = -EINVAL;
|
||||
}
|
||||
if (retval)
|
||||
|
@ -180,7 +182,10 @@ static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
|
|||
*/
|
||||
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);
|
||||
|
@ -215,9 +220,9 @@ static int init_slots(struct controller *ctrl)
|
|||
get_adapter_status(hotplug_slot, &info->adapter_status);
|
||||
slot->hotplug_slot = hotplug_slot;
|
||||
|
||||
dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
|
||||
"slot_device_offset=%x\n", slot->bus, slot->device,
|
||||
slot->hp_slot, slot->number, ctrl->slot_device_offset);
|
||||
ctrl_dbg(ctrl, "Registering bus=%x dev=%x hp_slot=%x sun=%x "
|
||||
"slot_device_offset=%x\n", slot->bus, slot->device,
|
||||
slot->hp_slot, slot->number, ctrl->slot_device_offset);
|
||||
duplicate_name:
|
||||
retval = pci_hp_register(hotplug_slot,
|
||||
ctrl->pci_dev->subordinate,
|
||||
|
@ -233,9 +238,11 @@ duplicate_name:
|
|||
if (len < SLOT_NAME_SIZE)
|
||||
goto duplicate_name;
|
||||
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;
|
||||
}
|
||||
/* create additional sysfs entries */
|
||||
|
@ -244,7 +251,8 @@ duplicate_name:
|
|||
&hotplug_slot_attr_lock.attr);
|
||||
if (retval) {
|
||||
pci_hp_deregister(hotplug_slot);
|
||||
err("cannot create additional sysfs entries\n");
|
||||
ctrl_err(ctrl, "cannot create additional sysfs "
|
||||
"entries\n");
|
||||
goto error_info;
|
||||
}
|
||||
}
|
||||
|
@ -278,7 +286,8 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
|
|||
{
|
||||
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;
|
||||
|
||||
|
@ -293,7 +302,8 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
@ -303,7 +313,8 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
@ -313,7 +324,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
|
|||
struct slot *slot = hotplug_slot->private;
|
||||
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);
|
||||
if (retval < 0)
|
||||
|
@ -327,7 +339,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
|
|||
struct slot *slot = hotplug_slot->private;
|
||||
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);
|
||||
if (retval < 0)
|
||||
|
@ -341,7 +354,8 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
|
|||
struct slot *slot = hotplug_slot->private;
|
||||
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);
|
||||
if (retval < 0)
|
||||
|
@ -355,7 +369,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
|
|||
struct slot *slot = hotplug_slot->private;
|
||||
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);
|
||||
if (retval < 0)
|
||||
|
@ -370,7 +385,8 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
|
|||
struct slot *slot = hotplug_slot->private;
|
||||
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);
|
||||
if (retval < 0)
|
||||
|
@ -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;
|
||||
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);
|
||||
if (retval < 0)
|
||||
|
@ -402,14 +419,15 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
struct pci_dev *pdev = dev->port;
|
||||
|
||||
if (pciehp_force)
|
||||
dbg("Bypassing BIOS check for pciehp use on %s\n",
|
||||
pci_name(pdev));
|
||||
dev_info(&dev->device,
|
||||
"Bypassing BIOS check for pciehp use on %s\n",
|
||||
pci_name(pdev));
|
||||
else if (pciehp_get_hp_hw_control_from_firmware(pdev))
|
||||
goto err_out_none;
|
||||
|
||||
ctrl = pcie_init(dev);
|
||||
if (!ctrl) {
|
||||
dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
|
||||
dev_err(&dev->device, "controller initialization failed\n");
|
||||
goto err_out_none;
|
||||
}
|
||||
set_service_data(dev, ctrl);
|
||||
|
@ -418,11 +436,10 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
rc = init_slots(ctrl);
|
||||
if (rc) {
|
||||
if (rc == -EBUSY)
|
||||
warn("%s: slot already registered by another "
|
||||
"hotplug driver\n", PCIE_MODULE_NAME);
|
||||
ctrl_warn(ctrl, "slot already registered by another "
|
||||
"hotplug driver\n");
|
||||
else
|
||||
err("%s: slot initialization failed\n",
|
||||
PCIE_MODULE_NAME);
|
||||
ctrl_err(ctrl, "slot initialization failed\n");
|
||||
goto err_out_release_ctlr;
|
||||
}
|
||||
|
||||
|
@ -461,13 +478,13 @@ static void pciehp_remove (struct pcie_device *dev)
|
|||
#ifdef CONFIG_PM
|
||||
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;
|
||||
}
|
||||
|
||||
static int pciehp_resume (struct pcie_device *dev)
|
||||
{
|
||||
printk("%s ENTRY\n", __func__);
|
||||
dev_info(&dev->device, "%s ENTRY\n", __func__);
|
||||
if (pciehp_force) {
|
||||
struct controller *ctrl = get_service_data(dev);
|
||||
struct slot *t_slot;
|
||||
|
@ -497,10 +514,9 @@ static struct pcie_port_service_id port_pci_ids[] = { {
|
|||
.driver_data = 0,
|
||||
}, { /* end: all zeroes */ }
|
||||
};
|
||||
static const char device_name[] = "hpdriver";
|
||||
|
||||
static struct pcie_port_service_driver hpdriver_portdrv = {
|
||||
.name = (char *)device_name,
|
||||
.name = PCIE_MODULE_NAME,
|
||||
.id_table = &port_pci_ids[0],
|
||||
|
||||
.probe = pciehp_probe,
|
||||
|
|
|
@ -58,14 +58,15 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
|
|||
u8 pciehp_handle_attention_button(struct slot *p_slot)
|
||||
{
|
||||
u32 event_type;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
/* Attention Button Change */
|
||||
dbg("pciehp: Attention button interrupt received.\n");
|
||||
ctrl_dbg(ctrl, "Attention button interrupt received.\n");
|
||||
|
||||
/*
|
||||
* Button pressed - See if need to TAKE ACTION!!!
|
||||
*/
|
||||
info("Button pressed on Slot(%s)\n", p_slot->name);
|
||||
ctrl_info(ctrl, "Button pressed on Slot(%s)\n", p_slot->name);
|
||||
event_type = INT_BUTTON_PRESS;
|
||||
|
||||
queue_interrupt_event(p_slot, event_type);
|
||||
|
@ -77,22 +78,23 @@ u8 pciehp_handle_switch_change(struct slot *p_slot)
|
|||
{
|
||||
u8 getstatus;
|
||||
u32 event_type;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
/* Switch Change */
|
||||
dbg("pciehp: Switch interrupt received.\n");
|
||||
ctrl_dbg(ctrl, "Switch interrupt received.\n");
|
||||
|
||||
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
||||
if (getstatus) {
|
||||
/*
|
||||
* Switch opened
|
||||
*/
|
||||
info("Latch open on Slot(%s)\n", p_slot->name);
|
||||
ctrl_info(ctrl, "Latch open on Slot(%s)\n", p_slot->name);
|
||||
event_type = INT_SWITCH_OPEN;
|
||||
} else {
|
||||
/*
|
||||
* Switch closed
|
||||
*/
|
||||
info("Latch close on Slot(%s)\n", p_slot->name);
|
||||
ctrl_info(ctrl, "Latch close on Slot(%s)\n", p_slot->name);
|
||||
event_type = INT_SWITCH_CLOSE;
|
||||
}
|
||||
|
||||
|
@ -105,9 +107,10 @@ u8 pciehp_handle_presence_change(struct slot *p_slot)
|
|||
{
|
||||
u32 event_type;
|
||||
u8 presence_save;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
/* Presence Change */
|
||||
dbg("pciehp: Presence/Notify input change.\n");
|
||||
ctrl_dbg(ctrl, "Presence/Notify input change.\n");
|
||||
|
||||
/* Switch is open, assume a presence change
|
||||
* Save the presence state
|
||||
|
@ -117,13 +120,13 @@ u8 pciehp_handle_presence_change(struct slot *p_slot)
|
|||
/*
|
||||
* Card Present
|
||||
*/
|
||||
info("Card present on Slot(%s)\n", p_slot->name);
|
||||
ctrl_info(ctrl, "Card present on Slot(%s)\n", p_slot->name);
|
||||
event_type = INT_PRESENCE_ON;
|
||||
} else {
|
||||
/*
|
||||
* Not Present
|
||||
*/
|
||||
info("Card not present on Slot(%s)\n", p_slot->name);
|
||||
ctrl_info(ctrl, "Card not present on Slot(%s)\n", p_slot->name);
|
||||
event_type = INT_PRESENCE_OFF;
|
||||
}
|
||||
|
||||
|
@ -135,23 +138,25 @@ u8 pciehp_handle_presence_change(struct slot *p_slot)
|
|||
u8 pciehp_handle_power_fault(struct slot *p_slot)
|
||||
{
|
||||
u32 event_type;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
/* power fault */
|
||||
dbg("pciehp: Power fault interrupt received.\n");
|
||||
ctrl_dbg(ctrl, "Power fault interrupt received.\n");
|
||||
|
||||
if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
|
||||
/*
|
||||
* power fault Cleared
|
||||
*/
|
||||
info("Power fault cleared on Slot(%s)\n", p_slot->name);
|
||||
ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n",
|
||||
p_slot->name);
|
||||
event_type = INT_POWER_FAULT_CLEAR;
|
||||
} else {
|
||||
/*
|
||||
* power fault
|
||||
*/
|
||||
info("Power fault on Slot(%s)\n", p_slot->name);
|
||||
ctrl_info(ctrl, "Power fault on Slot(%s)\n", p_slot->name);
|
||||
event_type = INT_POWER_FAULT;
|
||||
info("power fault bit %x set\n", 0);
|
||||
ctrl_info(ctrl, "power fault bit %x set\n", 0);
|
||||
}
|
||||
|
||||
queue_interrupt_event(p_slot, event_type);
|
||||
|
@ -168,8 +173,9 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
|
|||
/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
|
||||
if (POWER_CTRL(ctrl)) {
|
||||
if (pslot->hpc_ops->power_off_slot(pslot)) {
|
||||
err("%s: Issue of Slot Power Off command failed\n",
|
||||
__func__);
|
||||
ctrl_err(ctrl,
|
||||
"%s: Issue of Slot Power Off command failed\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -186,8 +192,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
|
|||
|
||||
if (ATTN_LED(ctrl)) {
|
||||
if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
|
||||
err("%s: Issue of Set Attention Led command failed\n",
|
||||
__func__);
|
||||
ctrl_err(ctrl, "%s: Issue of Set Attention "
|
||||
"Led command failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -205,9 +211,9 @@ static int board_added(struct slot *p_slot)
|
|||
int retval = 0;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
|
||||
__func__, p_slot->device,
|
||||
ctrl->slot_device_offset, p_slot->hp_slot);
|
||||
ctrl_dbg(ctrl, "%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
|
||||
__func__, p_slot->device, ctrl->slot_device_offset,
|
||||
p_slot->hp_slot);
|
||||
|
||||
if (POWER_CTRL(ctrl)) {
|
||||
/* Power on slot */
|
||||
|
@ -225,22 +231,22 @@ static int board_added(struct slot *p_slot)
|
|||
/* Check link training status */
|
||||
retval = p_slot->hpc_ops->check_lnk_status(ctrl);
|
||||
if (retval) {
|
||||
err("%s: Failed to check link status\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Failed to check link status\n", __func__);
|
||||
set_slot_off(ctrl, p_slot);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Check for a power fault */
|
||||
if (p_slot->hpc_ops->query_power_fault(p_slot)) {
|
||||
dbg("%s: power fault detected\n", __func__);
|
||||
ctrl_dbg(ctrl, "%s: power fault detected\n", __func__);
|
||||
retval = POWER_FAILURE;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
retval = pciehp_configure_device(p_slot);
|
||||
if (retval) {
|
||||
err("Cannot add device 0x%x:%x\n", p_slot->bus,
|
||||
p_slot->device);
|
||||
ctrl_err(ctrl, "Cannot add device 0x%x:%x\n",
|
||||
p_slot->bus, p_slot->device);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
|
@ -272,14 +278,14 @@ static int remove_board(struct slot *p_slot)
|
|||
if (retval)
|
||||
return retval;
|
||||
|
||||
dbg("In %s, hp_slot = %d\n", __func__, p_slot->hp_slot);
|
||||
ctrl_dbg(ctrl, "In %s, hp_slot = %d\n", __func__, p_slot->hp_slot);
|
||||
|
||||
if (POWER_CTRL(ctrl)) {
|
||||
/* power off slot */
|
||||
retval = p_slot->hpc_ops->power_off_slot(p_slot);
|
||||
if (retval) {
|
||||
err("%s: Issue of Slot Disable command failed\n",
|
||||
__func__);
|
||||
ctrl_err(ctrl, "%s: Issue of Slot Disable command "
|
||||
"failed\n", __func__);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
@ -320,8 +326,8 @@ static void pciehp_power_thread(struct work_struct *work)
|
|||
switch (p_slot->state) {
|
||||
case POWEROFF_STATE:
|
||||
mutex_unlock(&p_slot->lock);
|
||||
dbg("%s: disabling bus:device(%x:%x)\n",
|
||||
__func__, p_slot->bus, p_slot->device);
|
||||
ctrl_dbg(p_slot->ctrl, "%s: disabling bus:device(%x:%x)\n",
|
||||
__func__, p_slot->bus, p_slot->device);
|
||||
pciehp_disable_slot(p_slot);
|
||||
mutex_lock(&p_slot->lock);
|
||||
p_slot->state = STATIC_STATE;
|
||||
|
@ -349,7 +355,8 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
|
|||
|
||||
info = kmalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info) {
|
||||
err("%s: Cannot allocate memory\n", __func__);
|
||||
ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
info->p_slot = p_slot;
|
||||
|
@ -403,12 +410,14 @@ static void handle_button_press_event(struct slot *p_slot)
|
|||
p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||
if (getstatus) {
|
||||
p_slot->state = BLINKINGOFF_STATE;
|
||||
info("PCI slot #%s - powering off due to button "
|
||||
"press.\n", p_slot->name);
|
||||
ctrl_info(ctrl,
|
||||
"PCI slot #%s - powering off due to button "
|
||||
"press.\n", p_slot->name);
|
||||
} else {
|
||||
p_slot->state = BLINKINGON_STATE;
|
||||
info("PCI slot #%s - powering on due to button "
|
||||
"press.\n", p_slot->name);
|
||||
ctrl_info(ctrl,
|
||||
"PCI slot #%s - powering on due to button "
|
||||
"press.\n", p_slot->name);
|
||||
}
|
||||
/* blink green LED and turn off amber */
|
||||
if (PWR_LED(ctrl))
|
||||
|
@ -425,8 +434,8 @@ static void handle_button_press_event(struct slot *p_slot)
|
|||
* press the attention again before the 5 sec. limit
|
||||
* expires to cancel hot-add or hot-remove
|
||||
*/
|
||||
info("Button cancel on Slot(%s)\n", p_slot->name);
|
||||
dbg("%s: button cancel\n", __func__);
|
||||
ctrl_info(ctrl, "Button cancel on Slot(%s)\n", p_slot->name);
|
||||
ctrl_dbg(ctrl, "%s: button cancel\n", __func__);
|
||||
cancel_delayed_work(&p_slot->work);
|
||||
if (p_slot->state == BLINKINGOFF_STATE) {
|
||||
if (PWR_LED(ctrl))
|
||||
|
@ -437,8 +446,8 @@ static void handle_button_press_event(struct slot *p_slot)
|
|||
}
|
||||
if (ATTN_LED(ctrl))
|
||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||
info("PCI slot #%s - action canceled due to button press\n",
|
||||
p_slot->name);
|
||||
ctrl_info(ctrl, "PCI slot #%s - action canceled "
|
||||
"due to button press\n", p_slot->name);
|
||||
p_slot->state = STATIC_STATE;
|
||||
break;
|
||||
case POWEROFF_STATE:
|
||||
|
@ -448,11 +457,11 @@ static void handle_button_press_event(struct slot *p_slot)
|
|||
* this means that the previous attention button action
|
||||
* to hot-add or hot-remove is undergoing
|
||||
*/
|
||||
info("Button ignore on Slot(%s)\n", p_slot->name);
|
||||
ctrl_info(ctrl, "Button ignore on Slot(%s)\n", p_slot->name);
|
||||
update_slot_info(p_slot);
|
||||
break;
|
||||
default:
|
||||
warn("Not a valid state\n");
|
||||
ctrl_warn(ctrl, "Not a valid state\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -467,7 +476,8 @@ static void handle_surprise_event(struct slot *p_slot)
|
|||
|
||||
info = kmalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info) {
|
||||
err("%s: Cannot allocate memory\n", __func__);
|
||||
ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
info->p_slot = p_slot;
|
||||
|
@ -505,7 +515,7 @@ static void interrupt_event_handler(struct work_struct *work)
|
|||
case INT_PRESENCE_OFF:
|
||||
if (!HP_SUPR_RM(ctrl))
|
||||
break;
|
||||
dbg("Surprise Removal\n");
|
||||
ctrl_dbg(ctrl, "Surprise Removal\n");
|
||||
update_slot_info(p_slot);
|
||||
handle_surprise_event(p_slot);
|
||||
break;
|
||||
|
@ -522,22 +532,23 @@ int pciehp_enable_slot(struct slot *p_slot)
|
|||
{
|
||||
u8 getstatus = 0;
|
||||
int rc;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
/* Check to see if (latch closed, card present, power off) */
|
||||
mutex_lock(&p_slot->ctrl->crit_sect);
|
||||
|
||||
rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
|
||||
if (rc || !getstatus) {
|
||||
info("%s: no adapter on slot(%s)\n", __func__,
|
||||
p_slot->name);
|
||||
ctrl_info(ctrl, "%s: no adapter on slot(%s)\n",
|
||||
__func__, p_slot->name);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (MRL_SENS(p_slot->ctrl)) {
|
||||
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
||||
if (rc || getstatus) {
|
||||
info("%s: latch open on slot(%s)\n", __func__,
|
||||
p_slot->name);
|
||||
ctrl_info(ctrl, "%s: latch open on slot(%s)\n",
|
||||
__func__, p_slot->name);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -546,8 +557,8 @@ int pciehp_enable_slot(struct slot *p_slot)
|
|||
if (POWER_CTRL(p_slot->ctrl)) {
|
||||
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||
if (rc || getstatus) {
|
||||
info("%s: already enabled on slot(%s)\n", __func__,
|
||||
p_slot->name);
|
||||
ctrl_info(ctrl, "%s: already enabled on slot(%s)\n",
|
||||
__func__, p_slot->name);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -571,6 +582,7 @@ int pciehp_disable_slot(struct slot *p_slot)
|
|||
{
|
||||
u8 getstatus = 0;
|
||||
int ret = 0;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
if (!p_slot->ctrl)
|
||||
return 1;
|
||||
|
@ -581,8 +593,8 @@ int pciehp_disable_slot(struct slot *p_slot)
|
|||
if (!HP_SUPR_RM(p_slot->ctrl)) {
|
||||
ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
|
||||
if (ret || !getstatus) {
|
||||
info("%s: no adapter on slot(%s)\n", __func__,
|
||||
p_slot->name);
|
||||
ctrl_info(ctrl, "%s: no adapter on slot(%s)\n",
|
||||
__func__, p_slot->name);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -591,8 +603,8 @@ int pciehp_disable_slot(struct slot *p_slot)
|
|||
if (MRL_SENS(p_slot->ctrl)) {
|
||||
ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
||||
if (ret || getstatus) {
|
||||
info("%s: latch open on slot(%s)\n", __func__,
|
||||
p_slot->name);
|
||||
ctrl_info(ctrl, "%s: latch open on slot(%s)\n",
|
||||
__func__, p_slot->name);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -601,8 +613,8 @@ int pciehp_disable_slot(struct slot *p_slot)
|
|||
if (POWER_CTRL(p_slot->ctrl)) {
|
||||
ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||
if (ret || !getstatus) {
|
||||
info("%s: already disabled slot(%s)\n", __func__,
|
||||
p_slot->name);
|
||||
ctrl_info(ctrl, "%s: already disabled slot(%s)\n",
|
||||
__func__, p_slot->name);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -618,6 +630,7 @@ int pciehp_disable_slot(struct slot *p_slot)
|
|||
int pciehp_sysfs_enable_slot(struct slot *p_slot)
|
||||
{
|
||||
int retval = -ENODEV;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
mutex_lock(&p_slot->lock);
|
||||
switch (p_slot->state) {
|
||||
|
@ -631,15 +644,15 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)
|
|||
p_slot->state = STATIC_STATE;
|
||||
break;
|
||||
case POWERON_STATE:
|
||||
info("Slot %s is already in powering on state\n",
|
||||
p_slot->name);
|
||||
ctrl_info(ctrl, "Slot %s is already in powering on state\n",
|
||||
p_slot->name);
|
||||
break;
|
||||
case BLINKINGOFF_STATE:
|
||||
case POWEROFF_STATE:
|
||||
info("Already enabled on slot %s\n", p_slot->name);
|
||||
ctrl_info(ctrl, "Already enabled on slot %s\n", p_slot->name);
|
||||
break;
|
||||
default:
|
||||
err("Not a valid state on slot %s\n", p_slot->name);
|
||||
ctrl_err(ctrl, "Not a valid state on slot %s\n", p_slot->name);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&p_slot->lock);
|
||||
|
@ -650,6 +663,7 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)
|
|||
int pciehp_sysfs_disable_slot(struct slot *p_slot)
|
||||
{
|
||||
int retval = -ENODEV;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
mutex_lock(&p_slot->lock);
|
||||
switch (p_slot->state) {
|
||||
|
@ -663,15 +677,15 @@ int pciehp_sysfs_disable_slot(struct slot *p_slot)
|
|||
p_slot->state = STATIC_STATE;
|
||||
break;
|
||||
case POWEROFF_STATE:
|
||||
info("Slot %s is already in powering off state\n",
|
||||
p_slot->name);
|
||||
ctrl_info(ctrl, "Slot %s is already in powering off state\n",
|
||||
p_slot->name);
|
||||
break;
|
||||
case BLINKINGON_STATE:
|
||||
case POWERON_STATE:
|
||||
info("Already disabled on slot %s\n", p_slot->name);
|
||||
ctrl_info(ctrl, "Already disabled on slot %s\n", p_slot->name);
|
||||
break;
|
||||
default:
|
||||
err("Not a valid state on slot %s\n", p_slot->name);
|
||||
ctrl_err(ctrl, "Not a valid state on slot %s\n", p_slot->name);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&p_slot->lock);
|
||||
|
|
|
@ -223,7 +223,7 @@ static void start_int_poll_timer(struct controller *ctrl, int sec)
|
|||
|
||||
static inline int pciehp_request_irq(struct controller *ctrl)
|
||||
{
|
||||
int retval, irq = ctrl->pci_dev->irq;
|
||||
int retval, irq = ctrl->pcie->irq;
|
||||
|
||||
/* Install interrupt polling timer. Start with 10 sec delay */
|
||||
if (pciehp_poll_mode) {
|
||||
|
@ -235,7 +235,8 @@ static inline int pciehp_request_irq(struct controller *ctrl)
|
|||
/* Installs the interrupt handler */
|
||||
retval = request_irq(irq, pcie_isr, IRQF_SHARED, MY_NAME, ctrl);
|
||||
if (retval)
|
||||
err("Cannot get irq %d for the hotplug controller\n", irq);
|
||||
ctrl_err(ctrl, "Cannot get irq %d for the hotplug controller\n",
|
||||
irq);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -244,7 +245,7 @@ static inline void pciehp_free_irq(struct controller *ctrl)
|
|||
if (pciehp_poll_mode)
|
||||
del_timer_sync(&ctrl->poll_timer);
|
||||
else
|
||||
free_irq(ctrl->pci_dev->irq, ctrl);
|
||||
free_irq(ctrl->pcie->irq, ctrl);
|
||||
}
|
||||
|
||||
static int pcie_poll_cmd(struct controller *ctrl)
|
||||
|
@ -282,7 +283,7 @@ static void pcie_wait_cmd(struct controller *ctrl, int poll)
|
|||
else
|
||||
rc = wait_event_timeout(ctrl->queue, !ctrl->cmd_busy, timeout);
|
||||
if (!rc)
|
||||
dbg("Command not completed in 1000 msec\n");
|
||||
ctrl_dbg(ctrl, "Command not completed in 1000 msec\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -301,7 +302,8 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
|
|||
|
||||
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot read SLOTSTATUS register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
|
||||
__func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -312,26 +314,28 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
|
|||
* proceed forward to issue the next command according
|
||||
* to spec. Just print out the error message.
|
||||
*/
|
||||
dbg("%s: CMD_COMPLETED not clear after 1 sec.\n",
|
||||
__func__);
|
||||
ctrl_dbg(ctrl,
|
||||
"%s: CMD_COMPLETED not clear after 1 sec.\n",
|
||||
__func__);
|
||||
} else if (!NO_CMD_CMPL(ctrl)) {
|
||||
/*
|
||||
* This controller semms to notify of command completed
|
||||
* event even though it supports none of power
|
||||
* controller, attention led, power led and EMI.
|
||||
*/
|
||||
dbg("%s: Unexpected CMD_COMPLETED. Need to wait for "
|
||||
"command completed event.\n", __func__);
|
||||
ctrl_dbg(ctrl, "%s: Unexpected CMD_COMPLETED. Need to "
|
||||
"wait for command completed event.\n",
|
||||
__func__);
|
||||
ctrl->no_cmd_complete = 0;
|
||||
} else {
|
||||
dbg("%s: Unexpected CMD_COMPLETED. Maybe the "
|
||||
"controller is broken.\n", __func__);
|
||||
ctrl_dbg(ctrl, "%s: Unexpected CMD_COMPLETED. Maybe "
|
||||
"the controller is broken.\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
|
||||
if (retval) {
|
||||
err("%s: Cannot read SLOTCTRL register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -341,7 +345,8 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
|
|||
smp_mb();
|
||||
retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
|
||||
if (retval)
|
||||
err("%s: Cannot write to SLOTCTRL register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot write to SLOTCTRL register\n",
|
||||
__func__);
|
||||
|
||||
/*
|
||||
* Wait for command completion.
|
||||
|
@ -370,14 +375,15 @@ static int hpc_check_lnk_status(struct controller *ctrl)
|
|||
|
||||
retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot read LNKSTATUS register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n",
|
||||
__func__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
dbg("%s: lnk_status = %x\n", __func__, lnk_status);
|
||||
ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status);
|
||||
if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) ||
|
||||
!(lnk_status & NEG_LINK_WD)) {
|
||||
err("%s : Link Training Error occurs \n", __func__);
|
||||
ctrl_err(ctrl, "%s : Link Training Error occurs \n", __func__);
|
||||
retval = -1;
|
||||
return retval;
|
||||
}
|
||||
|
@ -394,12 +400,12 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
|
|||
|
||||
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
|
||||
if (retval) {
|
||||
err("%s: Cannot read SLOTCTRL register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
dbg("%s: SLOTCTRL %x, value read %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
|
||||
ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
|
||||
|
||||
atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
|
||||
|
||||
|
@ -433,11 +439,11 @@ static int hpc_get_power_status(struct slot *slot, u8 *status)
|
|||
|
||||
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
|
||||
if (retval) {
|
||||
err("%s: Cannot read SLOTCTRL register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
|
||||
return retval;
|
||||
}
|
||||
dbg("%s: SLOTCTRL %x value read %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
|
||||
ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
|
||||
|
||||
pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
|
||||
|
||||
|
@ -464,7 +470,8 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
|
|||
|
||||
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot read SLOTSTATUS register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
|
||||
__func__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -482,7 +489,8 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
|
|||
|
||||
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot read SLOTSTATUS register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
|
||||
__func__);
|
||||
return retval;
|
||||
}
|
||||
card_state = (u8)((slot_status & PRSN_STATE) >> 6);
|
||||
|
@ -500,7 +508,7 @@ static int hpc_query_power_fault(struct slot *slot)
|
|||
|
||||
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot check for power fault\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot check for power fault\n", __func__);
|
||||
return retval;
|
||||
}
|
||||
pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
|
||||
|
@ -516,7 +524,7 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status)
|
|||
|
||||
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
||||
if (retval) {
|
||||
err("%s : Cannot check EMI status\n", __func__);
|
||||
ctrl_err(ctrl, "%s : Cannot check EMI status\n", __func__);
|
||||
return retval;
|
||||
}
|
||||
*status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT;
|
||||
|
@ -560,8 +568,8 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
|
|||
return -1;
|
||||
}
|
||||
rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
|
||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -575,8 +583,8 @@ static void hpc_set_green_led_on(struct slot *slot)
|
|||
slot_cmd = 0x0100;
|
||||
cmd_mask = PWR_LED_CTRL;
|
||||
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
|
||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
}
|
||||
|
||||
static void hpc_set_green_led_off(struct slot *slot)
|
||||
|
@ -588,8 +596,8 @@ static void hpc_set_green_led_off(struct slot *slot)
|
|||
slot_cmd = 0x0300;
|
||||
cmd_mask = PWR_LED_CTRL;
|
||||
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
|
||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
}
|
||||
|
||||
static void hpc_set_green_led_blink(struct slot *slot)
|
||||
|
@ -601,8 +609,8 @@ static void hpc_set_green_led_blink(struct slot *slot)
|
|||
slot_cmd = 0x0200;
|
||||
cmd_mask = PWR_LED_CTRL;
|
||||
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
|
||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
}
|
||||
|
||||
static int hpc_power_on_slot(struct slot * slot)
|
||||
|
@ -613,20 +621,22 @@ static int hpc_power_on_slot(struct slot * slot)
|
|||
u16 slot_status;
|
||||
int retval = 0;
|
||||
|
||||
dbg("%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
|
||||
ctrl_dbg(ctrl, "%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
|
||||
|
||||
/* Clear sticky power-fault bit from previous power failures */
|
||||
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot read SLOTSTATUS register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
|
||||
__func__);
|
||||
return retval;
|
||||
}
|
||||
slot_status &= PWR_FAULT_DETECTED;
|
||||
if (slot_status) {
|
||||
retval = pciehp_writew(ctrl, SLOTSTATUS, slot_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot write to SLOTSTATUS register\n",
|
||||
__func__);
|
||||
ctrl_err(ctrl,
|
||||
"%s: Cannot write to SLOTSTATUS register\n",
|
||||
__func__);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
@ -644,11 +654,12 @@ static int hpc_power_on_slot(struct slot * slot)
|
|||
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
|
||||
|
||||
if (retval) {
|
||||
err("%s: Write %x command failed!\n", __func__, slot_cmd);
|
||||
ctrl_err(ctrl, "%s: Write %x command failed!\n",
|
||||
__func__, slot_cmd);
|
||||
return -1;
|
||||
}
|
||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -694,7 +705,7 @@ static int hpc_power_off_slot(struct slot * slot)
|
|||
int retval = 0;
|
||||
int changed;
|
||||
|
||||
dbg("%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
|
||||
ctrl_dbg(ctrl, "%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
|
||||
|
||||
/*
|
||||
* Set Bad DLLP Mask bit in Correctable Error Mask
|
||||
|
@ -722,12 +733,12 @@ static int hpc_power_off_slot(struct slot * slot)
|
|||
|
||||
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
|
||||
if (retval) {
|
||||
err("%s: Write command failed!\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Write command failed!\n", __func__);
|
||||
retval = -1;
|
||||
goto out;
|
||||
}
|
||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
|
||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
out:
|
||||
if (changed)
|
||||
pcie_unmask_bad_dllp(ctrl);
|
||||
|
@ -749,7 +760,8 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
|
|||
intr_loc = 0;
|
||||
do {
|
||||
if (pciehp_readw(ctrl, SLOTSTATUS, &detected)) {
|
||||
err("%s: Cannot read SLOTSTATUS\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS\n",
|
||||
__func__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
|
@ -760,12 +772,13 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
|
|||
if (!intr_loc)
|
||||
return IRQ_NONE;
|
||||
if (detected && pciehp_writew(ctrl, SLOTSTATUS, detected)) {
|
||||
err("%s: Cannot write to SLOTSTATUS\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS\n",
|
||||
__func__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
} while (detected);
|
||||
|
||||
dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
|
||||
ctrl_dbg(ctrl, "%s: intr_loc %x\n", __func__, intr_loc);
|
||||
|
||||
/* Check Command Complete Interrupt Pending */
|
||||
if (intr_loc & CMD_COMPLETED) {
|
||||
|
@ -807,7 +820,7 @@ static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
|
|||
|
||||
retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
|
||||
if (retval) {
|
||||
err("%s: Cannot read LNKCAP register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -821,7 +834,7 @@ static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
|
|||
}
|
||||
|
||||
*value = lnk_speed;
|
||||
dbg("Max link speed = %d\n", lnk_speed);
|
||||
ctrl_dbg(ctrl, "Max link speed = %d\n", lnk_speed);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -836,7 +849,7 @@ static int hpc_get_max_lnk_width(struct slot *slot,
|
|||
|
||||
retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
|
||||
if (retval) {
|
||||
err("%s: Cannot read LNKCAP register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -871,7 +884,7 @@ static int hpc_get_max_lnk_width(struct slot *slot,
|
|||
}
|
||||
|
||||
*value = lnk_wdth;
|
||||
dbg("Max link width = %d\n", lnk_wdth);
|
||||
ctrl_dbg(ctrl, "Max link width = %d\n", lnk_wdth);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -885,7 +898,8 @@ static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
|
|||
|
||||
retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot read LNKSTATUS register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n",
|
||||
__func__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -899,7 +913,7 @@ static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
|
|||
}
|
||||
|
||||
*value = lnk_speed;
|
||||
dbg("Current link speed = %d\n", lnk_speed);
|
||||
ctrl_dbg(ctrl, "Current link speed = %d\n", lnk_speed);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -914,7 +928,8 @@ static int hpc_get_cur_lnk_width(struct slot *slot,
|
|||
|
||||
retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot read LNKSTATUS register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n",
|
||||
__func__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -949,7 +964,7 @@ static int hpc_get_cur_lnk_width(struct slot *slot,
|
|||
}
|
||||
|
||||
*value = lnk_wdth;
|
||||
dbg("Current link width = %d\n", lnk_wdth);
|
||||
ctrl_dbg(ctrl, "Current link width = %d\n", lnk_wdth);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -998,7 +1013,8 @@ int pcie_enable_notification(struct controller *ctrl)
|
|||
PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE;
|
||||
|
||||
if (pcie_write_cmd(ctrl, cmd, mask)) {
|
||||
err("%s: Cannot enable software notification\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot enable software notification\n",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1010,7 +1026,8 @@ static void pcie_disable_notification(struct controller *ctrl)
|
|||
mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | MRL_DETECT_ENABLE |
|
||||
PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE;
|
||||
if (pcie_write_cmd(ctrl, 0, mask))
|
||||
warn("%s: Cannot disable software notification\n", __func__);
|
||||
ctrl_warn(ctrl, "%s: Cannot disable software notification\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
static int pcie_init_notification(struct controller *ctrl)
|
||||
|
@ -1071,34 +1088,45 @@ static inline void dbg_ctrl(struct controller *ctrl)
|
|||
if (!pciehp_debug)
|
||||
return;
|
||||
|
||||
dbg("Hotplug Controller:\n");
|
||||
dbg(" Seg/Bus/Dev/Func/IRQ : %s IRQ %d\n", pci_name(pdev), pdev->irq);
|
||||
dbg(" Vendor ID : 0x%04x\n", pdev->vendor);
|
||||
dbg(" Device ID : 0x%04x\n", pdev->device);
|
||||
dbg(" Subsystem ID : 0x%04x\n", pdev->subsystem_device);
|
||||
dbg(" Subsystem Vendor ID : 0x%04x\n", pdev->subsystem_vendor);
|
||||
dbg(" PCIe Cap offset : 0x%02x\n", ctrl->cap_base);
|
||||
ctrl_info(ctrl, "Hotplug Controller:\n");
|
||||
ctrl_info(ctrl, " Seg/Bus/Dev/Func/IRQ : %s IRQ %d\n",
|
||||
pci_name(pdev), pdev->irq);
|
||||
ctrl_info(ctrl, " Vendor ID : 0x%04x\n", pdev->vendor);
|
||||
ctrl_info(ctrl, " Device ID : 0x%04x\n", pdev->device);
|
||||
ctrl_info(ctrl, " Subsystem ID : 0x%04x\n",
|
||||
pdev->subsystem_device);
|
||||
ctrl_info(ctrl, " Subsystem Vendor ID : 0x%04x\n",
|
||||
pdev->subsystem_vendor);
|
||||
ctrl_info(ctrl, " PCIe Cap offset : 0x%02x\n", ctrl->cap_base);
|
||||
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
|
||||
if (!pci_resource_len(pdev, i))
|
||||
continue;
|
||||
dbg(" PCI resource [%d] : 0x%llx@0x%llx\n", i,
|
||||
(unsigned long long)pci_resource_len(pdev, i),
|
||||
(unsigned long long)pci_resource_start(pdev, i));
|
||||
ctrl_info(ctrl, " PCI resource [%d] : 0x%llx@0x%llx\n",
|
||||
i, (unsigned long long)pci_resource_len(pdev, i),
|
||||
(unsigned long long)pci_resource_start(pdev, i));
|
||||
}
|
||||
dbg("Slot Capabilities : 0x%08x\n", ctrl->slot_cap);
|
||||
dbg(" Physical Slot Number : %d\n", ctrl->first_slot);
|
||||
dbg(" Attention Button : %3s\n", ATTN_BUTTN(ctrl) ? "yes" : "no");
|
||||
dbg(" Power Controller : %3s\n", POWER_CTRL(ctrl) ? "yes" : "no");
|
||||
dbg(" MRL Sensor : %3s\n", MRL_SENS(ctrl) ? "yes" : "no");
|
||||
dbg(" Attention Indicator : %3s\n", ATTN_LED(ctrl) ? "yes" : "no");
|
||||
dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no");
|
||||
dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no");
|
||||
dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no");
|
||||
dbg(" Command Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes");
|
||||
ctrl_info(ctrl, "Slot Capabilities : 0x%08x\n", ctrl->slot_cap);
|
||||
ctrl_info(ctrl, " Physical Slot Number : %d\n", ctrl->first_slot);
|
||||
ctrl_info(ctrl, " Attention Button : %3s\n",
|
||||
ATTN_BUTTN(ctrl) ? "yes" : "no");
|
||||
ctrl_info(ctrl, " Power Controller : %3s\n",
|
||||
POWER_CTRL(ctrl) ? "yes" : "no");
|
||||
ctrl_info(ctrl, " MRL Sensor : %3s\n",
|
||||
MRL_SENS(ctrl) ? "yes" : "no");
|
||||
ctrl_info(ctrl, " Attention Indicator : %3s\n",
|
||||
ATTN_LED(ctrl) ? "yes" : "no");
|
||||
ctrl_info(ctrl, " Power Indicator : %3s\n",
|
||||
PWR_LED(ctrl) ? "yes" : "no");
|
||||
ctrl_info(ctrl, " Hot-Plug Surprise : %3s\n",
|
||||
HP_SUPR_RM(ctrl) ? "yes" : "no");
|
||||
ctrl_info(ctrl, " EMI Present : %3s\n",
|
||||
EMI(ctrl) ? "yes" : "no");
|
||||
ctrl_info(ctrl, " Command Completed : %3s\n",
|
||||
NO_CMD_CMPL(ctrl) ? "no" : "yes");
|
||||
pciehp_readw(ctrl, SLOTSTATUS, ®16);
|
||||
dbg("Slot Status : 0x%04x\n", reg16);
|
||||
ctrl_info(ctrl, "Slot Status : 0x%04x\n", reg16);
|
||||
pciehp_readw(ctrl, SLOTCTRL, ®16);
|
||||
dbg("Slot Control : 0x%04x\n", reg16);
|
||||
ctrl_info(ctrl, "Slot Control : 0x%04x\n", reg16);
|
||||
}
|
||||
|
||||
struct controller *pcie_init(struct pcie_device *dev)
|
||||
|
@ -1109,19 +1137,21 @@ struct controller *pcie_init(struct pcie_device *dev)
|
|||
|
||||
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
|
||||
if (!ctrl) {
|
||||
err("%s : out of memory\n", __func__);
|
||||
dev_err(&dev->device, "%s : out of memory\n", __func__);
|
||||
goto abort;
|
||||
}
|
||||
INIT_LIST_HEAD(&ctrl->slot_list);
|
||||
|
||||
ctrl->pcie = dev;
|
||||
ctrl->pci_dev = pdev;
|
||||
ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
|
||||
if (!ctrl->cap_base) {
|
||||
err("%s: Cannot find PCI Express capability\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot find PCI Express capability\n",
|
||||
__func__);
|
||||
goto abort;
|
||||
}
|
||||
if (pciehp_readl(ctrl, SLOTCAP, &slot_cap)) {
|
||||
err("%s: Cannot read SLOTCAP register\n", __func__);
|
||||
ctrl_err(ctrl, "%s: Cannot read SLOTCAP register\n", __func__);
|
||||
goto abort;
|
||||
}
|
||||
|
||||
|
@ -1161,9 +1191,9 @@ struct controller *pcie_init(struct pcie_device *dev)
|
|||
goto abort_ctrl;
|
||||
}
|
||||
|
||||
info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
|
||||
pdev->vendor, pdev->device,
|
||||
pdev->subsystem_vendor, pdev->subsystem_device);
|
||||
ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
|
||||
pdev->vendor, pdev->device, pdev->subsystem_vendor,
|
||||
pdev->subsystem_device);
|
||||
|
||||
if (pcie_init_slot(ctrl))
|
||||
goto abort_ctrl;
|
||||
|
|
|
@ -198,18 +198,20 @@ int pciehp_configure_device(struct slot *p_slot)
|
|||
struct pci_dev *dev;
|
||||
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
|
||||
int num, fn;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
|
||||
if (dev) {
|
||||
err("Device %s already exists at %x:%x, cannot hot-add\n",
|
||||
pci_name(dev), p_slot->bus, p_slot->device);
|
||||
ctrl_err(ctrl,
|
||||
"Device %s already exists at %x:%x, cannot hot-add\n",
|
||||
pci_name(dev), p_slot->bus, p_slot->device);
|
||||
pci_dev_put(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
|
||||
if (num == 0) {
|
||||
err("No new device found\n");
|
||||
ctrl_err(ctrl, "No new device found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -218,8 +220,8 @@ int pciehp_configure_device(struct slot *p_slot)
|
|||
if (!dev)
|
||||
continue;
|
||||
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
|
||||
err("Cannot hot-add display device %s\n",
|
||||
pci_name(dev));
|
||||
ctrl_err(ctrl, "Cannot hot-add display device %s\n",
|
||||
pci_name(dev));
|
||||
pci_dev_put(dev);
|
||||
continue;
|
||||
}
|
||||
|
@ -244,9 +246,10 @@ int pciehp_unconfigure_device(struct slot *p_slot)
|
|||
u8 presence = 0;
|
||||
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
|
||||
u16 command;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
dbg("%s: bus/dev = %x/%x\n", __func__, p_slot->bus,
|
||||
p_slot->device);
|
||||
ctrl_dbg(ctrl, "%s: bus/dev = %x/%x\n", __func__,
|
||||
p_slot->bus, p_slot->device);
|
||||
ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence);
|
||||
if (ret)
|
||||
presence = 0;
|
||||
|
@ -257,16 +260,17 @@ int pciehp_unconfigure_device(struct slot *p_slot)
|
|||
if (!temp)
|
||||
continue;
|
||||
if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
|
||||
err("Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
ctrl_err(ctrl, "Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
pci_dev_put(temp);
|
||||
continue;
|
||||
}
|
||||
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
|
||||
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
|
||||
if (bctl & PCI_BRIDGE_CTL_VGA) {
|
||||
err("Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
ctrl_err(ctrl,
|
||||
"Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
pci_dev_put(temp);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -46,10 +46,10 @@
|
|||
#define PRESENT 1 /* Card in slot */
|
||||
|
||||
#define MY_NAME "rpaphp"
|
||||
extern int debug;
|
||||
extern int rpaphp_debug;
|
||||
#define dbg(format, arg...) \
|
||||
do { \
|
||||
if (debug) \
|
||||
if (rpaphp_debug) \
|
||||
printk(KERN_DEBUG "%s: " format, \
|
||||
MY_NAME , ## arg); \
|
||||
} while (0)
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
/* and pci_do_scan_bus */
|
||||
#include "rpaphp.h"
|
||||
|
||||
int debug;
|
||||
int rpaphp_debug;
|
||||
LIST_HEAD(rpaphp_slot_head);
|
||||
|
||||
#define DRIVER_VERSION "0.1"
|
||||
|
@ -50,7 +50,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
|
|||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_param(debug, bool, 0644);
|
||||
module_param_named(debug, rpaphp_debug, bool, 0644);
|
||||
|
||||
/**
|
||||
* set_attention_status - set attention LED
|
||||
|
|
|
@ -123,7 +123,7 @@ int rpaphp_enable_slot(struct slot *slot)
|
|||
slot->state = CONFIGURED;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
if (rpaphp_debug) {
|
||||
struct pci_dev *dev;
|
||||
dbg("%s: pci_devs of slot[%s]\n", __func__, slot->dn->full_name);
|
||||
list_for_each_entry (dev, &bus->devices, bus_list)
|
||||
|
|
|
@ -378,23 +378,21 @@ static int msi_capability_init(struct pci_dev *dev)
|
|||
entry->msi_attrib.masked = 1;
|
||||
entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
|
||||
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,
|
||||
is_64bit_address(control));
|
||||
entry->msi_attrib.is_64);
|
||||
}
|
||||
entry->dev = dev;
|
||||
if (entry->msi_attrib.maskbit) {
|
||||
unsigned int maskbits, temp;
|
||||
/* All MSIs are unmasked by default, Mask them all */
|
||||
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);
|
||||
temp = (1 << multi_msi_capable(control));
|
||||
temp = ((temp - 1) & ~temp);
|
||||
maskbits |= temp;
|
||||
pci_write_config_dword(dev,
|
||||
msi_mask_bits_reg(pos, is_64bit_address(control)),
|
||||
maskbits);
|
||||
pci_write_config_dword(dev, entry->msi_attrib.is_64, maskbits);
|
||||
entry->msi_attrib.maskbits_mask = temp;
|
||||
}
|
||||
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)
|
|||
{
|
||||
struct pci_dynid *dynid;
|
||||
struct pci_driver *pdrv = to_pci_driver(driver);
|
||||
const struct pci_device_id *ids = pdrv->id_table;
|
||||
__u32 vendor, device, subvendor=PCI_ANY_ID,
|
||||
subdevice=PCI_ANY_ID, class=0, class_mask=0;
|
||||
unsigned long driver_data=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,
|
||||
&class, &class_mask, &driver_data);
|
||||
if (fields < 2)
|
||||
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);
|
||||
if (!dynid)
|
||||
return -ENOMEM;
|
||||
|
@ -65,8 +79,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
|
|||
dynid->id.subdevice = subdevice;
|
||||
dynid->id.class = class;
|
||||
dynid->id.class_mask = class_mask;
|
||||
dynid->id.driver_data = pdrv->dynids.use_driver_data ?
|
||||
driver_data : 0UL;
|
||||
dynid->id.driver_data = driver_data;
|
||||
|
||||
spin_lock(&pdrv->dynids.lock);
|
||||
list_add_tail(&dynid->node, &pdrv->dynids.list);
|
||||
|
|
|
@ -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
|
||||
* callback routine (pci_legacy_read).
|
||||
*/
|
||||
ssize_t
|
||||
static ssize_t
|
||||
pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
{
|
||||
|
@ -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
|
||||
* callback routine (pci_legacy_write).
|
||||
*/
|
||||
ssize_t
|
||||
static ssize_t
|
||||
pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
{
|
||||
|
@ -468,11 +468,11 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
|
|||
* @attr: struct bin_attribute for this file
|
||||
* @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
|
||||
* memory space.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
|
@ -480,7 +480,90 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
|
|||
struct device,
|
||||
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 */
|
||||
|
||||
|
@ -715,7 +798,7 @@ static struct bin_attribute pci_config_attr = {
|
|||
.name = "config",
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
},
|
||||
.size = 256,
|
||||
.size = PCI_CFG_SPACE_SIZE,
|
||||
.read = pci_read_config,
|
||||
.write = pci_write_config,
|
||||
};
|
||||
|
@ -725,7 +808,7 @@ static struct bin_attribute pcie_config_attr = {
|
|||
.name = "config",
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
},
|
||||
.size = 4096,
|
||||
.size = PCI_CFG_SPACE_EXP_SIZE,
|
||||
.read = pci_read_config,
|
||||
.write = pci_write_config,
|
||||
};
|
||||
|
@ -735,86 +818,103 @@ int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
|
|||
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)
|
||||
{
|
||||
struct bin_attribute *attr = NULL;
|
||||
int retval;
|
||||
int rom_size = 0;
|
||||
struct bin_attribute *attr;
|
||||
|
||||
if (!sysfs_initialized)
|
||||
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);
|
||||
else
|
||||
retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
|
||||
if (retval)
|
||||
goto err;
|
||||
|
||||
/* If the device has VPD, try to expose it in sysfs. */
|
||||
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)
|
||||
goto err_vpd;
|
||||
} else {
|
||||
retval = -ENOMEM;
|
||||
goto err_config_file;
|
||||
}
|
||||
}
|
||||
|
||||
retval = pci_create_resource_files(pdev);
|
||||
if (retval)
|
||||
goto err_vpd_file;
|
||||
goto err_config_file;
|
||||
|
||||
if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
|
||||
rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
|
||||
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 (pci_resource_len(pdev, PCI_ROM_RESOURCE) ||
|
||||
(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) {
|
||||
if (rom_size) {
|
||||
attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
|
||||
if (attr) {
|
||||
pdev->rom_attr = attr;
|
||||
attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
|
||||
attr->attr.name = "rom";
|
||||
attr->attr.mode = S_IRUSR;
|
||||
attr->read = pci_read_rom;
|
||||
attr->write = pci_write_rom;
|
||||
retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
|
||||
if (retval)
|
||||
goto err_rom;
|
||||
} else {
|
||||
if (!attr) {
|
||||
retval = -ENOMEM;
|
||||
goto err_resource_files;
|
||||
}
|
||||
attr->size = rom_size;
|
||||
attr->attr.name = "rom";
|
||||
attr->attr.mode = S_IRUSR;
|
||||
attr->read = pci_read_rom;
|
||||
attr->write = pci_write_rom;
|
||||
retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
|
||||
if (retval) {
|
||||
kfree(attr);
|
||||
goto err_resource_files;
|
||||
}
|
||||
pdev->rom_attr = attr;
|
||||
}
|
||||
|
||||
/* add platform-specific attributes */
|
||||
if (pcibios_add_platform_entries(pdev))
|
||||
retval = pcibios_add_platform_entries(pdev);
|
||||
if (retval)
|
||||
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;
|
||||
|
||||
err_rom_file:
|
||||
if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
|
||||
if (rom_size) {
|
||||
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:
|
||||
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:
|
||||
if (pdev->cfg_size < 4096)
|
||||
if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
|
||||
else
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
|
||||
|
@ -822,6 +922,16 @@ err:
|
|||
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
|
||||
* @pdev: device whose entries we should free
|
||||
|
@ -830,27 +940,28 @@ err:
|
|||
*/
|
||||
void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
|
||||
{
|
||||
int rom_size = 0;
|
||||
|
||||
if (!sysfs_initialized)
|
||||
return;
|
||||
|
||||
pcie_aspm_remove_sysfs_dev_files(pdev);
|
||||
pci_remove_capabilities_sysfs(pdev);
|
||||
|
||||
if (pdev->vpd) {
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
|
||||
kfree(pdev->vpd->attr);
|
||||
}
|
||||
if (pdev->cfg_size < 4096)
|
||||
if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
|
||||
else
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
|
||||
|
||||
pci_remove_resource_files(pdev);
|
||||
|
||||
if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
|
||||
if (pdev->rom_attr) {
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
|
||||
kfree(pdev->rom_attr);
|
||||
}
|
||||
if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
|
||||
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);
|
||||
kfree(pdev->rom_attr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
u32 header;
|
||||
int ttl = 480; /* 3840 bytes, minimum 8 bytes per capability */
|
||||
int pos = 0x100;
|
||||
int ttl;
|
||||
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;
|
||||
|
||||
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)
|
|||
return pos;
|
||||
|
||||
pos = PCI_EXT_CAP_NEXT(header);
|
||||
if (pos < 0x100)
|
||||
if (pos < PCI_CFG_SPACE_SIZE)
|
||||
break;
|
||||
|
||||
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)
|
|||
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
|
||||
* @dev: PCI device
|
||||
|
@ -1242,25 +1266,25 @@ void pci_pm_init(struct pci_dev *dev)
|
|||
dev->d1_support = false;
|
||||
dev->d2_support = false;
|
||||
if (!pci_no_d1d2(dev)) {
|
||||
if (pmc & PCI_PM_CAP_D1) {
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "supports D1\n");
|
||||
if (pmc & PCI_PM_CAP_D1)
|
||||
dev->d1_support = true;
|
||||
}
|
||||
if (pmc & PCI_PM_CAP_D2) {
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "supports D2\n");
|
||||
if (pmc & PCI_PM_CAP_D2)
|
||||
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;
|
||||
if (pmc) {
|
||||
dev_printk(KERN_INFO, &dev->dev,
|
||||
"PME# supported from%s%s%s%s%s\n",
|
||||
(pmc & PCI_PM_CAP_PME_D0) ? " D0" : "",
|
||||
(pmc & PCI_PM_CAP_PME_D1) ? " D1" : "",
|
||||
(pmc & PCI_PM_CAP_PME_D2) ? " D2" : "",
|
||||
(pmc & PCI_PM_CAP_PME_D3) ? " D3hot" : "",
|
||||
(pmc & PCI_PM_CAP_PME_D3cold) ? " D3cold" : "");
|
||||
dev_info(&dev->dev, "PME# supported from%s%s%s%s%s\n",
|
||||
(pmc & PCI_PM_CAP_PME_D0) ? " D0" : "",
|
||||
(pmc & PCI_PM_CAP_PME_D1) ? " D1" : "",
|
||||
(pmc & PCI_PM_CAP_PME_D2) ? " D2" : "",
|
||||
(pmc & PCI_PM_CAP_PME_D3) ? " D3hot" : "",
|
||||
(pmc & PCI_PM_CAP_PME_D3cold) ? " D3cold" : "");
|
||||
dev->pme_support = pmc >> PCI_PM_CAP_PME_SHIFT;
|
||||
/*
|
||||
* Make device's PM flags reflect the wake-up capability, but
|
||||
|
@ -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
|
||||
pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
|
||||
{
|
||||
|
@ -1942,6 +1998,7 @@ EXPORT_SYMBOL(pci_restore_state);
|
|||
EXPORT_SYMBOL(pci_pme_capable);
|
||||
EXPORT_SYMBOL(pci_pme_active);
|
||||
EXPORT_SYMBOL(pci_enable_wake);
|
||||
EXPORT_SYMBOL(pci_wake_from_d3);
|
||||
EXPORT_SYMBOL(pci_target_state);
|
||||
EXPORT_SYMBOL(pci_prepare_to_sleep);
|
||||
EXPORT_SYMBOL(pci_back_from_sleep);
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
#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 */
|
||||
|
||||
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; }
|
|||
/* Functions for PCI Hotplug drivers to use */
|
||||
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);
|
||||
#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 */
|
||||
extern struct rw_semaphore pci_bus_sem;
|
||||
|
@ -109,6 +121,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
|
|||
extern int pcie_mch_quirk;
|
||||
extern struct device_attribute pci_dev_attrs[];
|
||||
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
|
||||
|
@ -144,3 +157,16 @@ struct pci_slot_attribute {
|
|||
};
|
||||
#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)
|
|||
unsigned long flags;
|
||||
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,
|
||||
* and Root error producer/consumer index
|
||||
|
@ -252,7 +252,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
|
|||
u32 status;
|
||||
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 */
|
||||
pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, 0);
|
||||
|
@ -316,7 +316,7 @@ static void aer_error_resume(struct pci_dev *dev)
|
|||
pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16);
|
||||
|
||||
/* 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_SEVER, &mask);
|
||||
if (dev->error_state == pci_channel_io_normal)
|
||||
|
|
|
@ -28,41 +28,15 @@
|
|||
static int forceload;
|
||||
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, ®32))
|
||||
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)
|
||||
{
|
||||
u16 reg16 = 0;
|
||||
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);
|
||||
if (!pos)
|
||||
return -EIO;
|
||||
|
@ -102,7 +76,7 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
|
|||
int pos;
|
||||
u32 status, mask;
|
||||
|
||||
pos = pci_find_aer_capability(dev);
|
||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
|
||||
if (!pos)
|
||||
return -EIO;
|
||||
|
||||
|
@ -123,7 +97,7 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
|
|||
int pos;
|
||||
u32 status;
|
||||
|
||||
pos = pci_find_aer_capability(dev);
|
||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
|
||||
if (!pos)
|
||||
return -EIO;
|
||||
|
||||
|
@ -502,7 +476,7 @@ static void handle_error_source(struct pcie_device * aerdev,
|
|||
* Correctable error does not need software intevention.
|
||||
* 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)
|
||||
pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
|
||||
info.status);
|
||||
|
@ -542,7 +516,7 @@ void aer_enable_rootport(struct aer_rpc *rpc)
|
|||
reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK);
|
||||
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 */
|
||||
pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, ®32);
|
||||
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)
|
|||
u32 reg32;
|
||||
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 */
|
||||
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)
|
|||
{
|
||||
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 */
|
||||
if (!pos)
|
||||
|
@ -755,7 +729,6 @@ int aer_init(struct pcie_device *dev)
|
|||
return AER_SUCCESS;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(pci_find_aer_capability);
|
||||
EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
|
||||
EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
|
||||
EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
|
||||
|
|
|
@ -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,
|
||||
®32);
|
||||
if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
|
||||
printk("Pre-1.1 PCIe device detected, "
|
||||
"disable ASPM for %s. It can be enabled forcedly"
|
||||
" with 'pcie_aspm=force'\n", pci_name(pdev));
|
||||
dev_printk(KERN_INFO, &child_dev->dev, "disabling ASPM"
|
||||
" on pre-1.1 PCIe device. You can enable it"
|
||||
" with 'pcie_aspm=force'\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#define PCIE_CAPABILITIES_REG 0x2
|
||||
#define PCIE_SLOT_CAPABILITIES_REG 0x14
|
||||
#define PCIE_PORT_DEVICE_MAXSERVICES 4
|
||||
#define PCI_CFG_SPACE_SIZE 256
|
||||
|
||||
#define get_descriptor_id(type, service) (((type - 4) << 4) | service)
|
||||
|
||||
|
|
|
@ -195,24 +195,11 @@ static int get_port_device_capability(struct pci_dev *dev)
|
|||
/* PME Capable - root port capability */
|
||||
if (((reg16 >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT)
|
||||
services |= PCIE_PORT_SERVICE_PME;
|
||||
|
||||
pos = PCI_CFG_SPACE_SIZE;
|
||||
while (pos) {
|
||||
pci_read_config_dword(dev, pos, ®32);
|
||||
switch (reg32 & 0xffff) {
|
||||
case PCI_EXT_CAP_ID_ERR:
|
||||
services |= PCIE_PORT_SERVICE_AER;
|
||||
pos = reg32 >> 20;
|
||||
break;
|
||||
case PCI_EXT_CAP_ID_VC:
|
||||
services |= PCIE_PORT_SERVICE_VC;
|
||||
pos = reg32 >> 20;
|
||||
break;
|
||||
default:
|
||||
pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR))
|
||||
services |= PCIE_PORT_SERVICE_AER;
|
||||
if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC))
|
||||
services |= PCIE_PORT_SERVICE_VC;
|
||||
|
||||
return services;
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
|
|||
|
||||
pci_set_master(dev);
|
||||
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);
|
||||
}
|
||||
if (pcie_port_device_register(dev)) {
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
|
||||
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
|
||||
#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. */
|
||||
LIST_HEAD(pci_root_buses);
|
||||
|
@ -44,72 +42,6 @@ int no_pci_devices(void)
|
|||
}
|
||||
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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
||||
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_mem32;
|
||||
}
|
||||
|
@ -304,8 +236,8 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|||
} else {
|
||||
res->start = l64;
|
||||
res->end = l64 + sz64;
|
||||
printk(KERN_DEBUG "PCI: %s reg %x 64bit mmio: %pR\n",
|
||||
pci_name(dev), pos, res);
|
||||
dev_printk(KERN_DEBUG, &dev->dev,
|
||||
"reg %x 64bit mmio: %pR\n", pos, res);
|
||||
}
|
||||
} else {
|
||||
sz = pci_size(l, sz, mask);
|
||||
|
@ -315,10 +247,10 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|||
|
||||
res->start = l;
|
||||
res->end = l + sz;
|
||||
printk(KERN_DEBUG "PCI: %s reg %x %s: %pR\n",
|
||||
pci_name(dev), pos,
|
||||
(res->flags & IORESOURCE_IO) ? "io port":"32bit mmio",
|
||||
res);
|
||||
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "reg %x %s: %pR\n", pos,
|
||||
(res->flags & IORESOURCE_IO) ? "io port" : "32bit mmio",
|
||||
res);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -389,8 +321,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
|
|||
res->start = base;
|
||||
if (!res->end)
|
||||
res->end = limit + 0xfff;
|
||||
printk(KERN_DEBUG "PCI: bridge %s io port: %pR\n",
|
||||
pci_name(dev), res);
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "bridge io port: %pR\n", res);
|
||||
}
|
||||
|
||||
res = child->resource[1];
|
||||
|
@ -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->start = base;
|
||||
res->end = limit + 0xfffff;
|
||||
printk(KERN_DEBUG "PCI: bridge %s 32bit mmio: %pR\n",
|
||||
pci_name(dev), res);
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "bridge 32bit mmio: %pR\n",
|
||||
res);
|
||||
}
|
||||
|
||||
res = child->resource[2];
|
||||
|
@ -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->start = base;
|
||||
res->end = limit + 0xfffff;
|
||||
printk(KERN_DEBUG "PCI: bridge %s %sbit mmio pref: %pR\n",
|
||||
pci_name(dev),
|
||||
(res->flags & PCI_PREF_RANGE_TYPE_64) ? "64":"32", res);
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "bridge %sbit mmio pref: %pR\n",
|
||||
(res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32",
|
||||
res);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -762,7 +693,7 @@ static int pci_setup_device(struct pci_dev * dev)
|
|||
dev->class = class;
|
||||
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);
|
||||
|
||||
/* "Unknown power state" */
|
||||
|
@ -844,6 +775,11 @@ static int pci_setup_device(struct pci_dev * dev)
|
|||
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.
|
||||
* @dev: device that's been disconnected
|
||||
|
@ -856,7 +792,7 @@ static void pci_release_dev(struct device *dev)
|
|||
struct pci_dev *pci_dev;
|
||||
|
||||
pci_dev = to_pci_dev(dev);
|
||||
pci_vpd_release(pci_dev);
|
||||
pci_release_capabilities(pci_dev);
|
||||
kfree(pci_dev);
|
||||
}
|
||||
|
||||
|
@ -887,8 +823,9 @@ static void set_pcie_port_type(struct pci_dev *pdev)
|
|||
int pci_cfg_space_size_ext(struct pci_dev *dev)
|
||||
{
|
||||
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;
|
||||
if (status == 0xffffffff)
|
||||
goto fail;
|
||||
|
@ -936,8 +873,6 @@ struct pci_dev *alloc_pci_dev(void)
|
|||
|
||||
INIT_LIST_HEAD(&dev->bus_list);
|
||||
|
||||
pci_msi_init_pci_dev(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
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)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
struct pci_slot *slot;
|
||||
u32 l;
|
||||
u8 hdr_type;
|
||||
int delay = 1;
|
||||
|
@ -997,6 +933,10 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
|
|||
dev->error_state = pci_channel_io_normal;
|
||||
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)
|
||||
set this higher, assuming the system even supports it. */
|
||||
dev->dma_mask = 0xffffffff;
|
||||
|
@ -1005,9 +945,22 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
|
|||
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);
|
||||
|
||||
return dev;
|
||||
/* Alternative Routing-ID Forwarding */
|
||||
pci_enable_ari(dev);
|
||||
}
|
||||
|
||||
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 */
|
||||
pci_fixup_device(pci_fixup_header, dev);
|
||||
|
||||
/* Initialize power management of the device */
|
||||
pci_pm_init(dev);
|
||||
/* Initialize various capabilities */
|
||||
pci_init_capabilities(dev);
|
||||
|
||||
/*
|
||||
* Add the device to our list of discovered devices
|
||||
|
|
|
@ -24,6 +24,14 @@
|
|||
#include <linux/kallsyms.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
|
||||
* Mark this device with a broken_parity_status, to allow
|
||||
* 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
|
|||
|
||||
This appears to be BIOS not version dependent. So presumably there is a
|
||||
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)
|
||||
{
|
||||
|
@ -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_3, quirk_isa_dma_hangs);
|
||||
|
||||
int pci_pci_problems;
|
||||
EXPORT_SYMBOL(pci_pci_problems);
|
||||
|
||||
/*
|
||||
* Chipsets where PCI->PCI transfers vanish or hang
|
||||
*/
|
||||
|
@ -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);
|
||||
#endif
|
||||
|
||||
int pcie_mch_quirk;
|
||||
EXPORT_SYMBOL(pcie_mch_quirk);
|
||||
|
||||
static void __devinit quirk_pcie_mch(struct pci_dev *pdev)
|
||||
{
|
||||
pcie_mch_quirk = 1;
|
||||
|
@ -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);
|
||||
|
||||
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 */
|
||||
static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
|
||||
{
|
||||
|
@ -2006,3 +1928,82 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
|
|||
quirk_msi_intx_disable_bug);
|
||||
|
||||
#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)
|
|||
up_write(&pci_bus_sem);
|
||||
pci_remove_legacy_files(pci_bus);
|
||||
device_remove_file(&pci_bus->dev, &dev_attr_cpuaffinity);
|
||||
device_remove_file(&pci_bus->dev, &dev_attr_cpulistaffinity);
|
||||
device_unregister(&pci_bus->dev);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_remove_bus);
|
||||
|
@ -114,13 +115,9 @@ void pci_remove_behind_bridge(struct pci_dev *dev)
|
|||
{
|
||||
struct list_head *l, *n;
|
||||
|
||||
if (dev->subordinate) {
|
||||
list_for_each_safe(l, n, &dev->subordinate->devices) {
|
||||
struct pci_dev *dev = pci_dev_b(l);
|
||||
|
||||
pci_remove_bus_device(dev);
|
||||
}
|
||||
}
|
||||
if (dev->subordinate)
|
||||
list_for_each_safe(l, n, &dev->subordinate->devices)
|
||||
pci_remove_bus_device(pci_dev_b(l));
|
||||
}
|
||||
|
||||
static void pci_stop_bus_devices(struct pci_bus *bus)
|
||||
|
|
|
@ -299,7 +299,7 @@ static void pbus_size_io(struct pci_bus *bus)
|
|||
|
||||
if (r->parent || !(r->flags & IORESOURCE_IO))
|
||||
continue;
|
||||
r_size = r->end - r->start + 1;
|
||||
r_size = resource_size(r);
|
||||
|
||||
if (r_size < 0x400)
|
||||
/* Might be re-aligned for ISA */
|
||||
|
@ -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)
|
||||
continue;
|
||||
r_size = r->end - r->start + 1;
|
||||
r_size = resource_size(r);
|
||||
/* For bridges size != alignment */
|
||||
align = resource_alignment(r);
|
||||
order = __ffs(align) - 20;
|
||||
|
|
|
@ -129,7 +129,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
|
|||
resource_size_t size, min, align;
|
||||
int ret;
|
||||
|
||||
size = res->end - res->start + 1;
|
||||
size = resource_size(res);
|
||||
min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
|
||||
|
||||
align = resource_alignment(res);
|
||||
|
|
|
@ -49,11 +49,16 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf)
|
|||
|
||||
static void pci_slot_release(struct kobject *kobj)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
struct pci_slot *slot = to_pci_slot(kobj);
|
||||
|
||||
pr_debug("%s: releasing pci_slot on %x:%d\n", __func__,
|
||||
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);
|
||||
|
||||
kfree(slot);
|
||||
|
@ -108,6 +113,7 @@ static struct kobj_type pci_slot_ktype = {
|
|||
struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
|
||||
const char *name)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
struct pci_slot *slot;
|
||||
int err;
|
||||
|
||||
|
@ -150,6 +156,10 @@ placeholder:
|
|||
INIT_LIST_HEAD(&slot->list);
|
||||
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 */
|
||||
pr_debug("%s: created pci_slot on %04x:%02x:%02x\n",
|
||||
__func__, pci_domain_nr(parent), parent->number, slot_nr);
|
||||
|
|
|
@ -7859,7 +7859,6 @@ static struct pci_driver ipr_driver = {
|
|||
.remove = ipr_remove,
|
||||
.shutdown = ipr_shutdown,
|
||||
.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)
|
|||
goto probe_out;
|
||||
}
|
||||
|
||||
if (pci_find_aer_capability(pdev))
|
||||
if (pci_enable_pcie_error_reporting(pdev))
|
||||
goto probe_out;
|
||||
/* This may fail but that's ok */
|
||||
pci_enable_pcie_error_reporting(pdev);
|
||||
|
||||
host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
|
||||
if (host == NULL) {
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#if defined(CONFIG_PCIEAER)
|
||||
/* pci-e port driver needs this function to enable aer */
|
||||
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_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
|
||||
#else
|
||||
|
@ -18,10 +17,6 @@ static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev)
|
|||
{
|
||||
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)
|
||||
{
|
||||
return -EINVAL;
|
||||
|
|
|
@ -214,6 +214,7 @@ struct pci_dev {
|
|||
unsigned int broken_parity_status:1; /* Device generates false positive parity */
|
||||
unsigned int msi_enabled:1;
|
||||
unsigned int msix_enabled:1;
|
||||
unsigned int ari_enabled:1; /* ARI forwarding */
|
||||
unsigned int is_managed:1;
|
||||
unsigned int is_pcie:1;
|
||||
pci_dev_flags_t dev_flags;
|
||||
|
@ -347,7 +348,6 @@ struct pci_bus_region {
|
|||
struct pci_dynids {
|
||||
spinlock_t lock; /* protects list, index */
|
||||
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 {
|
|||
|
||||
/**
|
||||
* PCI_VDEVICE - macro used to describe a specific pci device in short form
|
||||
* @vend: the vendor name
|
||||
* @dev: the 16 bit PCI Device ID
|
||||
* @vendor: the vendor name
|
||||
* @device: the 16 bit PCI Device ID
|
||||
*
|
||||
* 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
|
||||
|
@ -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);
|
||||
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_wake_from_d3(struct pci_dev *dev, bool enable);
|
||||
pci_power_t pci_target_state(struct pci_dev *dev);
|
||||
int pci_prepare_to_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) { }
|
|||
static inline void pci_mmcfg_late_init(void) { }
|
||||
#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 /* LINUX_PCI_H */
|
||||
|
|
|
@ -2454,9 +2454,9 @@
|
|||
#define PCI_DEVICE_ID_INTEL_ICH10_3 0x3a1a
|
||||
#define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30
|
||||
#define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60
|
||||
#define PCI_DEVICE_ID_INTEL_PCH_0 0x3b10
|
||||
#define PCI_DEVICE_ID_INTEL_PCH_1 0x3b11
|
||||
#define PCI_DEVICE_ID_INTEL_PCH_2 0x3b30
|
||||
#define PCI_DEVICE_ID_INTEL_PCH_LPC_MIN 0x3b00
|
||||
#define PCI_DEVICE_ID_INTEL_PCH_LPC_MAX 0x3b1f
|
||||
#define PCI_DEVICE_ID_INTEL_PCH_SMBUS 0x3b30
|
||||
#define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f
|
||||
#define PCI_DEVICE_ID_INTEL_5100_16 0x65f0
|
||||
#define PCI_DEVICE_ID_INTEL_5100_21 0x65f5
|
||||
|
|
|
@ -419,6 +419,10 @@
|
|||
#define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */
|
||||
#define PCI_EXP_RTCAP 30 /* Root Capabilities */
|
||||
#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) */
|
||||
#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff)
|
||||
|
@ -429,6 +433,7 @@
|
|||
#define PCI_EXT_CAP_ID_VC 2
|
||||
#define PCI_EXT_CAP_ID_DSN 3
|
||||
#define PCI_EXT_CAP_ID_PWR 4
|
||||
#define PCI_EXT_CAP_ID_ARI 14
|
||||
|
||||
/* Advanced Error Reporting */
|
||||
#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */
|
||||
|
@ -536,5 +541,14 @@
|
|||
#define HT_CAPTYPE_GEN3 0xD0 /* Generation 3 hypertransport 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 */
|
||||
|
|
|
@ -737,6 +737,14 @@ config VM_EVENT_COUNTERS
|
|||
on EMBEDDED systems. /proc/vmstat will only show page counts
|
||||
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
|
||||
default y
|
||||
bool "Enable SLUB debugging support" if EMBEDDED
|
||||
|
|
Loading…
Reference in a new issue