mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 13:41:51 +00:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6: (49 commits) [PATCH] acpiphp: fix acpi_path_name [PATCH] ibmphp: remove TRUE and FALSE [PATCH] PCI Hotplug: add common acpi functions to core [PATCH] PCI: kzalloc() conversion in drivers/pci [PATCH] acpiphp: Scan slots under the nested P2P bridge [PATCH] PCI Hotplug: SN: Fix cleanup on hotplug removal of PPB [PATCH] shpchp: cleanup bus speed handling [PATCH] PCI: fix pci_request_region[s] arg [PATCH] PCI: Provide a boot parameter to disable MSI [PATCH] PCI: the scheduled removal of PCI_LEGACY_PROC [PATCH] PCI: cpqphp_ctrl.c: board_replaced(): remove dead code [PATCH] acpiphp: fix bridge handle [PATCH] acpiphp - slot management fix - V4 [PATCH] acpi: remove dock event handling from ibm_acpi [PATCH] acpiphp: add dock event handling [PATCH] acpi: export acpi_bus_trim [PATCH] acpiphp: add new bus to acpi [PATCH] PCI: Move pci_dev_put outside a spinlock [PATCH] PCI: PCI/Cardbus cards hidden, needs pci=assign-busses to fix [PATCH] PCI: fix problems with MSI-X on ia64 ...
This commit is contained in:
commit
a3ea9b584e
@ -158,13 +158,6 @@ Who: Adrian Bunk <bunk@stusta.de>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: Legacy /proc/pci interface (PCI_LEGACY_PROC)
|
||||
When: March 2006
|
||||
Why: deprecated since 2.5.53 in favor of lspci(8)
|
||||
Who: Adrian Bunk <bunk@stusta.de>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: pci_module_init(driver)
|
||||
When: January 2007
|
||||
Why: Is replaced by pci_register_driver(pci_driver).
|
||||
|
@ -49,6 +49,7 @@ restrictions referred to are that the relevant option is valid if:
|
||||
MCA MCA bus support is enabled.
|
||||
MDA MDA console support is enabled.
|
||||
MOUSE Appropriate mouse support is enabled.
|
||||
MSI Message Signaled Interrupts (PCI).
|
||||
MTD MTD support is enabled.
|
||||
NET Appropriate network support is enabled.
|
||||
NUMA NUMA support is enabled.
|
||||
@ -1152,6 +1153,9 @@ running once the system is up.
|
||||
Mechanism 2.
|
||||
nommconf [IA-32,X86_64] Disable use of MMCONFIG for PCI
|
||||
Configuration
|
||||
nomsi [MSI] If the PCI_MSI kernel config parameter is
|
||||
enabled, this kernel boot option can be used to
|
||||
disable the use of MSI interrupts system-wide.
|
||||
nosort [IA-32] Don't sort PCI devices according to
|
||||
order given by the PCI BIOS. This sorting is
|
||||
done to get a device order compatible with
|
||||
|
@ -543,7 +543,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
|
||||
if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >
|
||||
0x100000000ULL)
|
||||
continue;
|
||||
res = alloc_bootmem_low(sizeof(struct resource));
|
||||
res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
|
||||
switch (md->type) {
|
||||
case EFI_RESERVED_TYPE:
|
||||
res->name = "Reserved Memory";
|
||||
|
@ -1288,7 +1288,7 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
|
||||
struct resource *res;
|
||||
if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
|
||||
continue;
|
||||
res = alloc_bootmem_low(sizeof(struct resource));
|
||||
res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
|
||||
switch (e820.map[i].type) {
|
||||
case E820_RAM: res->name = "System RAM"; break;
|
||||
case E820_ACPI: res->name = "ACPI Tables"; break;
|
||||
@ -1316,13 +1316,15 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
|
||||
|
||||
/*
|
||||
* Request address space for all standard resources
|
||||
*
|
||||
* This is called just before pcibios_assign_resources(), which is also
|
||||
* an fs_initcall, but is linked in later (in arch/i386/pci/i386.c).
|
||||
*/
|
||||
static void __init register_memory(void)
|
||||
static int __init request_standard_resources(void)
|
||||
{
|
||||
unsigned long gapstart, gapsize, round;
|
||||
unsigned long long last;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
printk("Setting up standard PCI resources\n");
|
||||
if (efi_enabled)
|
||||
efi_initialize_iomem_resources(&code_resource, &data_resource);
|
||||
else
|
||||
@ -1334,6 +1336,16 @@ static void __init register_memory(void)
|
||||
/* request I/O space for devices used on all i[345]86 PCs */
|
||||
for (i = 0; i < STANDARD_IO_RESOURCES; i++)
|
||||
request_resource(&ioport_resource, &standard_io_resources[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fs_initcall(request_standard_resources);
|
||||
|
||||
static void __init register_memory(void)
|
||||
{
|
||||
unsigned long gapstart, gapsize, round;
|
||||
unsigned long long last;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Search for the bigest gap in the low 32 bits of the e820
|
||||
|
@ -1,4 +1,4 @@
|
||||
obj-y := i386.o
|
||||
obj-y := i386.o init.o
|
||||
|
||||
obj-$(CONFIG_PCI_BIOS) += pcbios.o
|
||||
obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#include <asm/acpi.h>
|
||||
#include <asm/segment.h>
|
||||
@ -120,11 +121,42 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b)
|
||||
pci_read_bridge_bases(b);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus)
|
||||
*/
|
||||
#ifdef __i386__
|
||||
static int __devinit assign_all_busses(struct dmi_system_id *d)
|
||||
{
|
||||
pci_probe |= PCI_ASSIGN_ALL_BUSSES;
|
||||
printk(KERN_INFO "%s detected: enabling PCI bus# renumbering"
|
||||
" (pci=assign-busses)\n", d->ident);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Laptops which need pci=assign-busses to see Cardbus cards
|
||||
*/
|
||||
static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
|
||||
#ifdef __i386__
|
||||
{
|
||||
.callback = assign_all_busses,
|
||||
.ident = "Samsung X20 Laptop",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"),
|
||||
},
|
||||
},
|
||||
#endif /* __i386__ */
|
||||
{}
|
||||
};
|
||||
|
||||
struct pci_bus * __devinit pcibios_scan_root(int busnum)
|
||||
{
|
||||
struct pci_bus *bus = NULL;
|
||||
|
||||
dmi_check_system(pciprobe_dmi_table);
|
||||
|
||||
while ((bus = pci_find_next_bus(bus)) != NULL) {
|
||||
if (bus->number == busnum) {
|
||||
/* Already scanned */
|
||||
|
@ -245,7 +245,7 @@ static int __init pci_check_type2(void)
|
||||
return works;
|
||||
}
|
||||
|
||||
static int __init pci_direct_init(void)
|
||||
void __init pci_direct_init(void)
|
||||
{
|
||||
struct resource *region, *region2;
|
||||
|
||||
@ -258,16 +258,16 @@ static int __init pci_direct_init(void)
|
||||
if (pci_check_type1()) {
|
||||
printk(KERN_INFO "PCI: Using configuration type 1\n");
|
||||
raw_pci_ops = &pci_direct_conf1;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
release_resource(region);
|
||||
|
||||
type2:
|
||||
if ((pci_probe & PCI_PROBE_CONF2) == 0)
|
||||
goto out;
|
||||
return;
|
||||
region = request_region(0xCF8, 4, "PCI conf2");
|
||||
if (!region)
|
||||
goto out;
|
||||
return;
|
||||
region2 = request_region(0xC000, 0x1000, "PCI conf2");
|
||||
if (!region2)
|
||||
goto fail2;
|
||||
@ -275,15 +275,10 @@ static int __init pci_direct_init(void)
|
||||
if (pci_check_type2()) {
|
||||
printk(KERN_INFO "PCI: Using configuration type 2\n");
|
||||
raw_pci_ops = &pci_direct_conf2;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
release_resource(region2);
|
||||
fail2:
|
||||
release_resource(region);
|
||||
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(pci_direct_init);
|
||||
|
25
arch/i386/pci/init.c
Normal file
25
arch/i386/pci/init.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include <linux/config.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include "pci.h"
|
||||
|
||||
/* arch_initcall has too random ordering, so call the initializers
|
||||
in the right sequence from here. */
|
||||
static __init int pci_access_init(void)
|
||||
{
|
||||
#ifdef CONFIG_PCI_MMCONFIG
|
||||
pci_mmcfg_init();
|
||||
#endif
|
||||
if (raw_pci_ops)
|
||||
return 0;
|
||||
#ifdef CONFIG_PCI_BIOS
|
||||
pci_pcbios_init();
|
||||
#endif
|
||||
if (raw_pci_ops)
|
||||
return 0;
|
||||
#ifdef CONFIG_PCI_DIRECT
|
||||
pci_direct_init();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(pci_access_init);
|
@ -172,25 +172,20 @@ static __init void unreachable_devices(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int __init pci_mmcfg_init(void)
|
||||
void __init pci_mmcfg_init(void)
|
||||
{
|
||||
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
|
||||
if ((pci_mmcfg_config_num == 0) ||
|
||||
(pci_mmcfg_config == NULL) ||
|
||||
(pci_mmcfg_config[0].base_address == 0))
|
||||
goto out;
|
||||
return;
|
||||
|
||||
printk(KERN_INFO "PCI: Using MMCONFIG\n");
|
||||
raw_pci_ops = &pci_mmcfg;
|
||||
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
|
||||
|
||||
unreachable_devices();
|
||||
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(pci_mmcfg_init);
|
||||
|
@ -476,14 +476,12 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
|
||||
}
|
||||
EXPORT_SYMBOL(pcibios_set_irq_routing);
|
||||
|
||||
static int __init pci_pcbios_init(void)
|
||||
void __init pci_pcbios_init(void)
|
||||
{
|
||||
if ((pci_probe & PCI_PROBE_BIOS)
|
||||
&& ((raw_pci_ops = pci_find_bios()))) {
|
||||
pci_probe |= PCI_BIOS_SORT;
|
||||
pci_bios_present = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(pci_pcbios_init);
|
||||
|
@ -80,4 +80,7 @@ extern int pci_conf1_write(unsigned int seg, unsigned int bus,
|
||||
extern int pci_conf1_read(unsigned int seg, unsigned int bus,
|
||||
unsigned int devfn, int reg, int len, u32 *value);
|
||||
|
||||
extern void pci_direct_init(void);
|
||||
extern void pci_pcbios_init(void);
|
||||
extern void pci_mmcfg_init(void);
|
||||
|
||||
|
@ -7,7 +7,7 @@ CFLAGS += -Iarch/i386/pci
|
||||
|
||||
obj-y := i386.o
|
||||
obj-$(CONFIG_PCI_DIRECT)+= direct.o
|
||||
obj-y += fixup.o
|
||||
obj-y += fixup.o init.o
|
||||
obj-$(CONFIG_ACPI) += acpi.o
|
||||
obj-y += legacy.o irq.o common.o
|
||||
# mmconfig has a 64bit special
|
||||
@ -22,3 +22,4 @@ irq-y += ../../i386/pci/irq.o
|
||||
common-y += ../../i386/pci/common.o
|
||||
fixup-y += ../../i386/pci/fixup.o
|
||||
i386-y += ../../i386/pci/i386.o
|
||||
init-y += ../../i386/pci/init.o
|
||||
|
@ -205,6 +205,18 @@ config ACPI_IBM
|
||||
|
||||
If you have an IBM ThinkPad laptop, say Y or M here.
|
||||
|
||||
config ACPI_IBM_DOCK
|
||||
bool "Legacy Docking Station Support"
|
||||
depends on ACPI_IBM
|
||||
default n
|
||||
---help---
|
||||
Allows the ibm_acpi driver to handle docking station events.
|
||||
This support is obsoleted by CONFIG_HOTPLUG_PCI_ACPI. It will
|
||||
allow locking and removing the laptop from the docking station,
|
||||
but will not properly connect PCI devices.
|
||||
|
||||
If you are not sure, say N here.
|
||||
|
||||
config ACPI_TOSHIBA
|
||||
tristate "Toshiba Laptop Extras"
|
||||
depends on X86
|
||||
|
@ -160,13 +160,13 @@ IBM_HANDLE(cmos, root, "\\UCMS", /* R50, R50e, R50p, R51, T4x, X31, X40 */
|
||||
"\\CMOS", /* A3x, G4x, R32, T23, T30, X22-24, X30 */
|
||||
"\\CMS", /* R40, R40e */
|
||||
); /* all others */
|
||||
|
||||
#ifdef CONFIG_ACPI_IBM_DOCK
|
||||
IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */
|
||||
"\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
|
||||
"\\_SB.PCI0.PCI1.DOCK", /* all others */
|
||||
"\\_SB.PCI.ISA.SLCE", /* 570 */
|
||||
); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
|
||||
|
||||
#endif
|
||||
IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */
|
||||
"\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
|
||||
"\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */
|
||||
@ -844,7 +844,7 @@ static int _sta(acpi_handle handle)
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_IBM_DOCK
|
||||
#define dock_docked() (_sta(dock_handle) & 1)
|
||||
|
||||
static int dock_read(char *p)
|
||||
@ -907,6 +907,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event)
|
||||
acpi_bus_generate_event(ibm->device, event, 0); /* unknown */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int bay_status_supported;
|
||||
static int bay_status2_supported;
|
||||
@ -1574,6 +1575,7 @@ static struct ibm_struct ibms[] = {
|
||||
.read = light_read,
|
||||
.write = light_write,
|
||||
},
|
||||
#ifdef CONFIG_ACPI_IBM_DOCK
|
||||
{
|
||||
.name = "dock",
|
||||
.read = dock_read,
|
||||
@ -1589,6 +1591,7 @@ static struct ibm_struct ibms[] = {
|
||||
.handle = &pci_handle,
|
||||
.type = ACPI_SYSTEM_NOTIFY,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.name = "bay",
|
||||
.init = bay_init,
|
||||
@ -1880,7 +1883,9 @@ IBM_PARAM(hotkey);
|
||||
IBM_PARAM(bluetooth);
|
||||
IBM_PARAM(video);
|
||||
IBM_PARAM(light);
|
||||
#ifdef CONFIG_ACPI_IBM_DOCK
|
||||
IBM_PARAM(dock);
|
||||
#endif
|
||||
IBM_PARAM(bay);
|
||||
IBM_PARAM(cmos);
|
||||
IBM_PARAM(led);
|
||||
@ -1927,7 +1932,9 @@ static int __init acpi_ibm_init(void)
|
||||
IBM_HANDLE_INIT(hkey);
|
||||
IBM_HANDLE_INIT(lght);
|
||||
IBM_HANDLE_INIT(cmos);
|
||||
#ifdef CONFIG_ACPI_IBM_DOCK
|
||||
IBM_HANDLE_INIT(dock);
|
||||
#endif
|
||||
IBM_HANDLE_INIT(pci);
|
||||
IBM_HANDLE_INIT(bay);
|
||||
if (bay_handle)
|
||||
|
@ -23,7 +23,6 @@ static LIST_HEAD(acpi_device_list);
|
||||
DEFINE_SPINLOCK(acpi_device_lock);
|
||||
LIST_HEAD(acpi_wakeup_device_list);
|
||||
|
||||
static int acpi_bus_trim(struct acpi_device *start, int rmdevice);
|
||||
|
||||
static void acpi_device_release(struct kobject *kobj)
|
||||
{
|
||||
@ -1284,7 +1283,7 @@ int acpi_bus_start(struct acpi_device *device)
|
||||
|
||||
EXPORT_SYMBOL(acpi_bus_start);
|
||||
|
||||
static int acpi_bus_trim(struct acpi_device *start, int rmdevice)
|
||||
int acpi_bus_trim(struct acpi_device *start, int rmdevice)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_device *parent, *child;
|
||||
@ -1337,6 +1336,8 @@ static int acpi_bus_trim(struct acpi_device *start, int rmdevice)
|
||||
}
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_bus_trim);
|
||||
|
||||
|
||||
static int acpi_bus_scan_fixed(struct acpi_device *root)
|
||||
{
|
||||
|
@ -11,25 +11,12 @@ config PCI_MSI
|
||||
generate an interrupt using an inbound Memory Write on its
|
||||
PCI bus instead of asserting a device IRQ pin.
|
||||
|
||||
Use of PCI MSI interrupts can be disabled at kernel boot time
|
||||
by using the 'pci=nomsi' option. This disables MSI for the
|
||||
entire system.
|
||||
|
||||
If you don't know what to do here, say N.
|
||||
|
||||
config PCI_LEGACY_PROC
|
||||
bool "Legacy /proc/pci interface"
|
||||
depends on PCI
|
||||
---help---
|
||||
This feature enables a procfs file -- /proc/pci -- that provides a
|
||||
summary of PCI devices in the system.
|
||||
|
||||
This feature has been deprecated as of v2.5.53, in favor of using the
|
||||
tool lspci(8). This feature may be removed at a future date.
|
||||
|
||||
lspci can provide the same data, as well as much more. lspci is a part of
|
||||
the pci-utils package, which should be installed by your distribution.
|
||||
See <file:Documentation/Changes> for information on where to get the latest
|
||||
version.
|
||||
|
||||
When in doubt, say N.
|
||||
|
||||
config PCI_DEBUG
|
||||
bool "PCI Debugging"
|
||||
depends on PCI && DEBUG_KERNEL
|
||||
|
@ -22,6 +22,9 @@ ifdef CONFIG_HOTPLUG_PCI_CPCI
|
||||
pci_hotplug-objs += cpci_hotplug_core.o \
|
||||
cpci_hotplug_pci.o
|
||||
endif
|
||||
ifdef CONFIG_ACPI
|
||||
pci_hotplug-objs += acpi_pcihp.o
|
||||
endif
|
||||
|
||||
cpqphp-objs := cpqphp_core.o \
|
||||
cpqphp_ctrl.o \
|
||||
@ -37,7 +40,8 @@ ibmphp-objs := ibmphp_core.o \
|
||||
ibmphp_hpc.o
|
||||
|
||||
acpiphp-objs := acpiphp_core.o \
|
||||
acpiphp_glue.o
|
||||
acpiphp_glue.o \
|
||||
acpiphp_dock.o
|
||||
|
||||
rpaphp-objs := rpaphp_core.o \
|
||||
rpaphp_pci.o \
|
||||
@ -50,23 +54,9 @@ pciehp-objs := pciehp_core.o \
|
||||
pciehp_ctrl.o \
|
||||
pciehp_pci.o \
|
||||
pciehp_hpc.o
|
||||
ifdef CONFIG_ACPI
|
||||
pciehp-objs += pciehprm_acpi.o
|
||||
else
|
||||
pciehp-objs += pciehprm_nonacpi.o
|
||||
endif
|
||||
|
||||
shpchp-objs := shpchp_core.o \
|
||||
shpchp_ctrl.o \
|
||||
shpchp_pci.o \
|
||||
shpchp_sysfs.o \
|
||||
shpchp_hpc.o
|
||||
ifdef CONFIG_ACPI
|
||||
shpchp-objs += shpchprm_acpi.o
|
||||
else
|
||||
ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
|
||||
shpchp-objs += shpchprm_legacy.o
|
||||
else
|
||||
shpchp-objs += shpchprm_nonacpi.o
|
||||
endif
|
||||
endif
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SHPCHPRM ACPI: PHP Resource Manager for ACPI platform
|
||||
* Common ACPI functions for hot plug platforms
|
||||
*
|
||||
* Copyright (C) 2003-2004 Intel Corporation
|
||||
* Copyright (C) 2006 Intel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -31,26 +31,12 @@
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/actypes.h>
|
||||
#include "shpchp.h"
|
||||
#include "pci_hotplug.h"
|
||||
|
||||
#define METHOD_NAME__SUN "_SUN"
|
||||
#define METHOD_NAME__HPP "_HPP"
|
||||
#define METHOD_NAME_OSHP "OSHP"
|
||||
|
||||
static u8 * acpi_path_name( acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
static u8 path_name[ACPI_PATHNAME_MAX];
|
||||
struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
|
||||
|
||||
memset(path_name, 0, sizeof (path_name));
|
||||
status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
return NULL;
|
||||
else
|
||||
return path_name;
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
|
||||
@ -58,18 +44,21 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
|
||||
acpi_status status;
|
||||
u8 nui[4];
|
||||
struct acpi_buffer ret_buf = { 0, NULL};
|
||||
struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *ext_obj, *package;
|
||||
u8 *path_name = acpi_path_name(handle);
|
||||
int i, len = 0;
|
||||
|
||||
acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
|
||||
|
||||
/* get _hpp */
|
||||
status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
|
||||
switch (status) {
|
||||
case AE_BUFFER_OVERFLOW:
|
||||
ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
|
||||
if (!ret_buf.pointer) {
|
||||
err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
|
||||
path_name);
|
||||
printk(KERN_ERR "%s:%s alloc for _HPP fail\n",
|
||||
__FUNCTION__, (char *)string.pointer);
|
||||
acpi_os_free(string.pointer);
|
||||
return AE_NO_MEMORY;
|
||||
}
|
||||
status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
|
||||
@ -78,16 +67,17 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
|
||||
break;
|
||||
default:
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
|
||||
path_name, status);
|
||||
pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
|
||||
(char *)string.pointer, status);
|
||||
acpi_os_free(string.pointer);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
ext_obj = (union acpi_object *) ret_buf.pointer;
|
||||
if (ext_obj->type != ACPI_TYPE_PACKAGE) {
|
||||
err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
|
||||
path_name);
|
||||
printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__,
|
||||
(char *)string.pointer);
|
||||
status = AE_ERROR;
|
||||
goto free_and_return;
|
||||
}
|
||||
@ -101,8 +91,8 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
|
||||
nui[i] = (u8)ext_obj->integer.value;
|
||||
break;
|
||||
default:
|
||||
err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
|
||||
path_name);
|
||||
printk(KERN_ERR "%s:%s _HPP obj type incorrect\n",
|
||||
__FUNCTION__, (char *)string.pointer);
|
||||
status = AE_ERROR;
|
||||
goto free_and_return;
|
||||
}
|
||||
@ -113,54 +103,52 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
|
||||
hpp->enable_serr = nui[2];
|
||||
hpp->enable_perr = nui[3];
|
||||
|
||||
dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
|
||||
dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
|
||||
dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
|
||||
dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
|
||||
pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
|
||||
pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
|
||||
pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
|
||||
pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
|
||||
|
||||
free_and_return:
|
||||
kfree(ret_buf.pointer);
|
||||
acpi_os_free(string.pointer);
|
||||
acpi_os_free(ret_buf.pointer);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void acpi_run_oshp(acpi_handle handle)
|
||||
|
||||
|
||||
/* acpi_run_oshp - get control of hotplug from the firmware
|
||||
*
|
||||
* @handle - the handle of the hotplug controller.
|
||||
*/
|
||||
acpi_status acpi_run_oshp(acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
u8 *path_name = acpi_path_name(handle);
|
||||
struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
|
||||
acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
|
||||
|
||||
/* run OSHP */
|
||||
status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
|
||||
status);
|
||||
} else {
|
||||
dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
|
||||
}
|
||||
if (ACPI_FAILURE(status))
|
||||
printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__,
|
||||
(char *)string.pointer, status);
|
||||
else
|
||||
pr_debug("%s:%s OSHP passes\n", __FUNCTION__,
|
||||
(char *)string.pointer);
|
||||
|
||||
acpi_os_free(string.pointer);
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_run_oshp);
|
||||
|
||||
int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
|
||||
{
|
||||
int offset = devnum - ctrl->slot_device_offset;
|
||||
|
||||
dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
|
||||
*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||
{
|
||||
/*
|
||||
* OSHP is an optional ACPI firmware control method. If present,
|
||||
* we need to run it to inform BIOS that we will control SHPC
|
||||
* hardware from now on.
|
||||
*/
|
||||
acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
|
||||
if (!handle)
|
||||
return;
|
||||
acpi_run_oshp(handle);
|
||||
}
|
||||
|
||||
void get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
/* acpi_get_hp_params_from_firmware
|
||||
*
|
||||
* @dev - the pci_dev of the newly added device
|
||||
* @hpp - allocated by the caller
|
||||
*/
|
||||
acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp)
|
||||
{
|
||||
acpi_status status = AE_NOT_FOUND;
|
||||
@ -182,5 +170,42 @@ void get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
/* Check if a parent object supports _HPP */
|
||||
pdev = pdev->bus->parent->self;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
|
||||
|
||||
|
||||
/* acpi_root_bridge - check to see if this acpi object is a root bridge
|
||||
*
|
||||
* @handle - the acpi object in question.
|
||||
*/
|
||||
int acpi_root_bridge(acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_device_info *info;
|
||||
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
int i;
|
||||
|
||||
status = acpi_get_object_info(handle, &buffer);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
info = buffer.pointer;
|
||||
if ((info->valid & ACPI_VALID_HID) &&
|
||||
!strcmp(PCI_ROOT_HID_STRING,
|
||||
info->hardware_id.value)) {
|
||||
acpi_os_free(buffer.pointer);
|
||||
return 1;
|
||||
}
|
||||
if (info->valid & ACPI_VALID_CID) {
|
||||
for (i=0; i < info->compatibility_id.count; i++) {
|
||||
if (!strcmp(PCI_ROOT_HID_STRING,
|
||||
info->compatibility_id.id[i].value)) {
|
||||
acpi_os_free(buffer.pointer);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
acpi_os_free(buffer.pointer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_root_bridge);
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/kobject.h> /* for KOBJ_NAME_LEN */
|
||||
#include <linux/mutex.h>
|
||||
#include "pci_hotplug.h"
|
||||
|
||||
#define dbg(format, arg...) \
|
||||
@ -59,26 +60,10 @@ struct acpiphp_slot;
|
||||
* struct slot - slot information for each *physical* slot
|
||||
*/
|
||||
struct slot {
|
||||
u8 number;
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct list_head slot_list;
|
||||
|
||||
struct acpiphp_slot *acpi_slot;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters
|
||||
* @cache_line_size in DWORD
|
||||
* @latency_timer in PCI clock
|
||||
* @enable_SERR 0 or 1
|
||||
* @enable_PERR 0 or 1
|
||||
*/
|
||||
struct hpp_param {
|
||||
u8 cache_line_size;
|
||||
u8 latency_timer;
|
||||
u8 enable_SERR;
|
||||
u8 enable_PERR;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@ -102,7 +87,7 @@ struct acpiphp_bridge {
|
||||
struct pci_dev *pci_dev;
|
||||
|
||||
/* ACPI 2.0 _HPP parameters */
|
||||
struct hpp_param hpp;
|
||||
struct hotplug_params hpp;
|
||||
|
||||
spinlock_t res_lock;
|
||||
};
|
||||
@ -118,9 +103,9 @@ struct acpiphp_slot {
|
||||
struct acpiphp_bridge *bridge; /* parent */
|
||||
struct list_head funcs; /* one slot may have different
|
||||
objects (i.e. for each function) */
|
||||
struct semaphore crit_sect;
|
||||
struct slot *slot;
|
||||
struct mutex crit_sect;
|
||||
|
||||
u32 id; /* slot id (serial #) for hotplug core */
|
||||
u8 device; /* pci device# */
|
||||
|
||||
u32 sun; /* ACPI _SUN (slot unique number) */
|
||||
@ -160,6 +145,25 @@ struct acpiphp_attention_info
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
|
||||
struct dependent_device {
|
||||
struct list_head device_list;
|
||||
struct list_head pci_list;
|
||||
acpi_handle handle;
|
||||
struct acpiphp_func *func;
|
||||
};
|
||||
|
||||
|
||||
struct acpiphp_dock_station {
|
||||
acpi_handle handle;
|
||||
u32 last_dock_time;
|
||||
u32 flags;
|
||||
struct acpiphp_func *dock_bridge;
|
||||
struct list_head dependent_devices;
|
||||
struct list_head pci_dependent_devices;
|
||||
};
|
||||
|
||||
|
||||
/* PCI bus bridge HID */
|
||||
#define ACPI_PCI_HOST_HID "PNP0A03"
|
||||
|
||||
@ -197,19 +201,27 @@ struct acpiphp_attention_info
|
||||
#define FUNC_HAS_PS1 (0x00000020)
|
||||
#define FUNC_HAS_PS2 (0x00000040)
|
||||
#define FUNC_HAS_PS3 (0x00000080)
|
||||
#define FUNC_HAS_DCK (0x00000100)
|
||||
#define FUNC_IS_DD (0x00000200)
|
||||
|
||||
/* dock station flags */
|
||||
#define DOCK_DOCKING (0x00000001)
|
||||
#define DOCK_HAS_BRIDGE (0x00000002)
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
/* acpiphp_core.c */
|
||||
extern int acpiphp_register_attention(struct acpiphp_attention_info*info);
|
||||
extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
|
||||
extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot);
|
||||
extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
|
||||
|
||||
/* acpiphp_glue.c */
|
||||
extern int acpiphp_glue_init (void);
|
||||
extern void acpiphp_glue_exit (void);
|
||||
extern int acpiphp_get_num_slots (void);
|
||||
extern struct acpiphp_slot *get_slot_from_id (int id);
|
||||
typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
|
||||
void handle_hotplug_event_func(acpi_handle, u32, void*);
|
||||
|
||||
extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
|
||||
extern int acpiphp_disable_slot (struct acpiphp_slot *slot);
|
||||
@ -219,6 +231,16 @@ extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
|
||||
extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
|
||||
extern u32 acpiphp_get_address (struct acpiphp_slot *slot);
|
||||
|
||||
/* acpiphp_dock.c */
|
||||
extern int find_dock_station(void);
|
||||
extern void remove_dock_station(void);
|
||||
extern void add_dependent_device(struct dependent_device *new_dd);
|
||||
extern void add_pci_dependent_device(struct dependent_device *new_dd);
|
||||
extern struct dependent_device *get_dependent_device(acpi_handle handle);
|
||||
extern int is_dependent_device(acpi_handle handle);
|
||||
extern int detect_dependent_devices(acpi_handle *bridge_handle);
|
||||
extern struct dependent_device *alloc_dependent_device(acpi_handle handle);
|
||||
|
||||
/* variables */
|
||||
extern int acpiphp_debug;
|
||||
|
||||
|
@ -44,8 +44,6 @@
|
||||
#include "pci_hotplug.h"
|
||||
#include "acpiphp.h"
|
||||
|
||||
static LIST_HEAD(slot_list);
|
||||
|
||||
#define MY_NAME "acpiphp"
|
||||
|
||||
static int debug;
|
||||
@ -341,62 +339,53 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
|
||||
kfree(slot);
|
||||
}
|
||||
|
||||
/**
|
||||
* init_slots - initialize 'struct slot' structures for each slot
|
||||
*
|
||||
*/
|
||||
static int __init init_slots(void)
|
||||
/* callback routine to initialize 'struct slot' for each slot */
|
||||
int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
|
||||
{
|
||||
struct slot *slot;
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct hotplug_slot_info *hotplug_slot_info;
|
||||
int retval = -ENOMEM;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_slots; ++i) {
|
||||
slot = kmalloc(sizeof(struct slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
goto error;
|
||||
memset(slot, 0, sizeof(struct slot));
|
||||
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
goto error;
|
||||
|
||||
slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
|
||||
if (!slot->hotplug_slot)
|
||||
goto error_slot;
|
||||
memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot));
|
||||
slot->hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
|
||||
if (!slot->hotplug_slot)
|
||||
goto error_slot;
|
||||
|
||||
slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
|
||||
if (!slot->hotplug_slot->info)
|
||||
goto error_hpslot;
|
||||
memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info));
|
||||
slot->hotplug_slot->info = kzalloc(sizeof(*hotplug_slot_info),
|
||||
GFP_KERNEL);
|
||||
if (!slot->hotplug_slot->info)
|
||||
goto error_hpslot;
|
||||
|
||||
slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
|
||||
if (!slot->hotplug_slot->name)
|
||||
goto error_info;
|
||||
slot->hotplug_slot->name = kzalloc(SLOT_NAME_SIZE, GFP_KERNEL);
|
||||
if (!slot->hotplug_slot->name)
|
||||
goto error_info;
|
||||
|
||||
slot->number = i;
|
||||
slot->hotplug_slot->private = slot;
|
||||
slot->hotplug_slot->release = &release_slot;
|
||||
slot->hotplug_slot->ops = &acpi_hotplug_slot_ops;
|
||||
|
||||
slot->hotplug_slot->private = slot;
|
||||
slot->hotplug_slot->release = &release_slot;
|
||||
slot->hotplug_slot->ops = &acpi_hotplug_slot_ops;
|
||||
slot->acpi_slot = acpiphp_slot;
|
||||
slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot);
|
||||
slot->hotplug_slot->info->attention_status = 0;
|
||||
slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot);
|
||||
slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
|
||||
slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
|
||||
slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
|
||||
|
||||
slot->acpi_slot = get_slot_from_id(i);
|
||||
slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot);
|
||||
slot->hotplug_slot->info->attention_status = 0;
|
||||
slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot);
|
||||
slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
|
||||
slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
|
||||
slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
|
||||
acpiphp_slot->slot = slot;
|
||||
make_slot_name(slot);
|
||||
|
||||
make_slot_name(slot);
|
||||
retval = pci_hp_register(slot->hotplug_slot);
|
||||
if (retval) {
|
||||
err("pci_hp_register failed with error %d\n", retval);
|
||||
goto error_name;
|
||||
}
|
||||
|
||||
retval = pci_hp_register(slot->hotplug_slot);
|
||||
if (retval) {
|
||||
err("pci_hp_register failed with error %d\n", retval);
|
||||
goto error_name;
|
||||
}
|
||||
|
||||
/* add slot to our internal list */
|
||||
list_add(&slot->slot_list, &slot_list);
|
||||
info("Slot [%s] registered\n", slot->hotplug_slot->name);
|
||||
}
|
||||
info("Slot [%s] registered\n", slot->hotplug_slot->name);
|
||||
|
||||
return 0;
|
||||
error_name:
|
||||
@ -412,42 +401,51 @@ error:
|
||||
}
|
||||
|
||||
|
||||
static void __exit cleanup_slots (void)
|
||||
void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
|
||||
{
|
||||
struct list_head *tmp, *n;
|
||||
struct slot *slot;
|
||||
struct slot *slot = acpiphp_slot->slot;
|
||||
int retval = 0;
|
||||
|
||||
list_for_each_safe (tmp, n, &slot_list) {
|
||||
/* memory will be freed in release_slot callback */
|
||||
slot = list_entry(tmp, struct slot, slot_list);
|
||||
list_del(&slot->slot_list);
|
||||
pci_hp_deregister(slot->hotplug_slot);
|
||||
}
|
||||
info ("Slot [%s] unregistered\n", slot->hotplug_slot->name);
|
||||
|
||||
retval = pci_hp_deregister(slot->hotplug_slot);
|
||||
if (retval)
|
||||
err("pci_hp_deregister failed with error %d\n", retval);
|
||||
}
|
||||
|
||||
|
||||
static int __init acpiphp_init(void)
|
||||
{
|
||||
int retval;
|
||||
int docking_station;
|
||||
|
||||
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
|
||||
|
||||
acpiphp_debug = debug;
|
||||
|
||||
docking_station = find_dock_station();
|
||||
|
||||
/* read all the ACPI info from the system */
|
||||
retval = init_acpi();
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return init_slots();
|
||||
/* if we have found a docking station, we should
|
||||
* go ahead and load even if init_acpi has found
|
||||
* no slots. This handles the case when the _DCK
|
||||
* method not defined under the actual dock bridge
|
||||
*/
|
||||
if (docking_station)
|
||||
return 0;
|
||||
else
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static void __exit acpiphp_exit(void)
|
||||
{
|
||||
cleanup_slots();
|
||||
/* deallocate internal data structures etc. */
|
||||
acpiphp_glue_exit();
|
||||
|
||||
remove_dock_station();
|
||||
}
|
||||
|
||||
module_init(acpiphp_init);
|
||||
|
438
drivers/pci/hotplug/acpiphp_dock.c
Normal file
438
drivers/pci/hotplug/acpiphp_dock.c
Normal file
@ -0,0 +1,438 @@
|
||||
/*
|
||||
* ACPI PCI HotPlug dock functions to ACPI CA subsystem
|
||||
*
|
||||
* Copyright (C) 2006 Kristen Carlson Accardi (kristen.c.accardi@intel.com)
|
||||
* Copyright (C) 2006 Intel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* Send feedback to <kristen.c.accardi@intel.com>
|
||||
*
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include "../pci.h"
|
||||
#include "pci_hotplug.h"
|
||||
#include "acpiphp.h"
|
||||
|
||||
static struct acpiphp_dock_station *ds;
|
||||
#define MY_NAME "acpiphp_dock"
|
||||
|
||||
|
||||
int is_dependent_device(acpi_handle handle)
|
||||
{
|
||||
return (get_dependent_device(handle) ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
static acpi_status
|
||||
find_dependent_device(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
int *count = (int *)context;
|
||||
|
||||
if (is_dependent_device(handle)) {
|
||||
(*count)++;
|
||||
return AE_CTRL_TERMINATE;
|
||||
} else {
|
||||
return AE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void add_dependent_device(struct dependent_device *new_dd)
|
||||
{
|
||||
list_add_tail(&new_dd->device_list, &ds->dependent_devices);
|
||||
}
|
||||
|
||||
|
||||
void add_pci_dependent_device(struct dependent_device *new_dd)
|
||||
{
|
||||
list_add_tail(&new_dd->pci_list, &ds->pci_dependent_devices);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct dependent_device * get_dependent_device(acpi_handle handle)
|
||||
{
|
||||
struct dependent_device *dd;
|
||||
|
||||
if (!ds)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(dd, &ds->dependent_devices, device_list) {
|
||||
if (handle == dd->handle)
|
||||
return dd;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct dependent_device *alloc_dependent_device(acpi_handle handle)
|
||||
{
|
||||
struct dependent_device *dd;
|
||||
|
||||
dd = kzalloc(sizeof(*dd), GFP_KERNEL);
|
||||
if (dd) {
|
||||
INIT_LIST_HEAD(&dd->pci_list);
|
||||
INIT_LIST_HEAD(&dd->device_list);
|
||||
dd->handle = handle;
|
||||
}
|
||||
return dd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int is_dock(acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle tmp;
|
||||
|
||||
status = acpi_get_handle(handle, "_DCK", &tmp);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int dock_present(void)
|
||||
{
|
||||
unsigned long sta;
|
||||
acpi_status status;
|
||||
|
||||
if (ds) {
|
||||
status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta);
|
||||
if (ACPI_SUCCESS(status) && sta)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void eject_dock(void)
|
||||
{
|
||||
struct acpi_object_list arg_list;
|
||||
union acpi_object arg;
|
||||
|
||||
arg_list.count = 1;
|
||||
arg_list.pointer = &arg;
|
||||
arg.type = ACPI_TYPE_INTEGER;
|
||||
arg.integer.value = 1;
|
||||
|
||||
if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0",
|
||||
&arg_list, NULL)) || dock_present())
|
||||
warn("%s: failed to eject dock!\n", __FUNCTION__);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static acpi_status handle_dock(int dock)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_object_list arg_list;
|
||||
union acpi_object arg;
|
||||
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
|
||||
dbg("%s: %s\n", __FUNCTION__, dock ? "docking" : "undocking");
|
||||
|
||||
/* _DCK method has one argument */
|
||||
arg_list.count = 1;
|
||||
arg_list.pointer = &arg;
|
||||
arg.type = ACPI_TYPE_INTEGER;
|
||||
arg.integer.value = dock;
|
||||
status = acpi_evaluate_object(ds->handle, "_DCK",
|
||||
&arg_list, &buffer);
|
||||
if (ACPI_FAILURE(status))
|
||||
err("%s: failed to execute _DCK\n", __FUNCTION__);
|
||||
acpi_os_free(buffer.pointer);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline void dock(void)
|
||||
{
|
||||
handle_dock(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline void undock(void)
|
||||
{
|
||||
handle_dock(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* the _DCK method can do funny things... and sometimes not
|
||||
* hah-hah funny.
|
||||
*
|
||||
* TBD - figure out a way to only call fixups for
|
||||
* systems that require them.
|
||||
*/
|
||||
static void post_dock_fixups(void)
|
||||
{
|
||||
struct pci_bus *bus;
|
||||
u32 buses;
|
||||
struct dependent_device *dd;
|
||||
|
||||
list_for_each_entry(dd, &ds->pci_dependent_devices, pci_list) {
|
||||
bus = dd->func->slot->bridge->pci_bus;
|
||||
|
||||
/* fixup bad _DCK function that rewrites
|
||||
* secondary bridge on slot
|
||||
*/
|
||||
pci_read_config_dword(bus->self,
|
||||
PCI_PRIMARY_BUS,
|
||||
&buses);
|
||||
|
||||
if (((buses >> 8) & 0xff) != bus->secondary) {
|
||||
buses = (buses & 0xff000000)
|
||||
| ((unsigned int)(bus->primary) << 0)
|
||||
| ((unsigned int)(bus->secondary) << 8)
|
||||
| ((unsigned int)(bus->subordinate) << 16);
|
||||
pci_write_config_dword(bus->self,
|
||||
PCI_PRIMARY_BUS,
|
||||
buses);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void hotplug_pci(u32 type)
|
||||
{
|
||||
struct dependent_device *dd;
|
||||
|
||||
list_for_each_entry(dd, &ds->pci_dependent_devices, pci_list)
|
||||
handle_hotplug_event_func(dd->handle, type, dd->func);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline void begin_dock(void)
|
||||
{
|
||||
ds->flags |= DOCK_DOCKING;
|
||||
}
|
||||
|
||||
|
||||
static inline void complete_dock(void)
|
||||
{
|
||||
ds->flags &= ~(DOCK_DOCKING);
|
||||
ds->last_dock_time = jiffies;
|
||||
}
|
||||
|
||||
|
||||
static int dock_in_progress(void)
|
||||
{
|
||||
if (ds->flags & DOCK_DOCKING ||
|
||||
ds->last_dock_time == jiffies) {
|
||||
dbg("dock in progress\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handle_hotplug_event_dock(acpi_handle handle, u32 type, void *context)
|
||||
{
|
||||
dbg("%s: enter\n", __FUNCTION__);
|
||||
|
||||
switch (type) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
dbg("BUS Check\n");
|
||||
if (!dock_in_progress() && dock_present()) {
|
||||
begin_dock();
|
||||
dock();
|
||||
if (!dock_present()) {
|
||||
err("Unable to dock!\n");
|
||||
break;
|
||||
}
|
||||
post_dock_fixups();
|
||||
hotplug_pci(type);
|
||||
complete_dock();
|
||||
}
|
||||
break;
|
||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||
dbg("EJECT request\n");
|
||||
if (!dock_in_progress() && dock_present()) {
|
||||
hotplug_pci(type);
|
||||
undock();
|
||||
eject_dock();
|
||||
if (dock_present())
|
||||
err("Unable to undock!\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static acpi_status
|
||||
find_dock_ejd(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle tmp;
|
||||
acpi_handle dck_handle = (acpi_handle) context;
|
||||
char objname[64];
|
||||
struct acpi_buffer buffer = { .length = sizeof(objname),
|
||||
.pointer = objname };
|
||||
struct acpi_buffer ejd_buffer = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
union acpi_object *ejd_obj;
|
||||
|
||||
status = acpi_get_handle(handle, "_EJD", &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
return AE_OK;
|
||||
|
||||
/* make sure we are dependent on the dock device,
|
||||
* by executing the _EJD method, then getting a handle
|
||||
* to the device referenced by that name. If that
|
||||
* device handle is the same handle as the dock station
|
||||
* handle, then we are a device dependent on the dock station
|
||||
*/
|
||||
acpi_get_name(dck_handle, ACPI_FULL_PATHNAME, &buffer);
|
||||
status = acpi_evaluate_object(handle, "_EJD", NULL, &ejd_buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
err("Unable to execute _EJD!\n");
|
||||
goto find_ejd_out;
|
||||
}
|
||||
ejd_obj = ejd_buffer.pointer;
|
||||
status = acpi_get_handle(NULL, ejd_obj->string.pointer, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
goto find_ejd_out;
|
||||
|
||||
if (tmp == dck_handle) {
|
||||
struct dependent_device *dd;
|
||||
dbg("%s: found device dependent on dock\n", __FUNCTION__);
|
||||
dd = alloc_dependent_device(handle);
|
||||
if (!dd) {
|
||||
err("Can't allocate memory for dependent device!\n");
|
||||
goto find_ejd_out;
|
||||
}
|
||||
add_dependent_device(dd);
|
||||
}
|
||||
|
||||
find_ejd_out:
|
||||
acpi_os_free(ejd_buffer.pointer);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int detect_dependent_devices(acpi_handle *bridge_handle)
|
||||
{
|
||||
acpi_status status;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle,
|
||||
(u32)1, find_dependent_device,
|
||||
(void *)&count, NULL);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static acpi_status
|
||||
find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
int *count = (int *)context;
|
||||
|
||||
if (is_dock(handle)) {
|
||||
dbg("%s: found dock\n", __FUNCTION__);
|
||||
ds = kzalloc(sizeof(*ds), GFP_KERNEL);
|
||||
ds->handle = handle;
|
||||
INIT_LIST_HEAD(&ds->dependent_devices);
|
||||
INIT_LIST_HEAD(&ds->pci_dependent_devices);
|
||||
|
||||
/* look for devices dependent on dock station */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, find_dock_ejd, handle, NULL);
|
||||
|
||||
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
||||
handle_hotplug_event_dock, ds);
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int find_dock_station(void)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
ds = NULL;
|
||||
|
||||
/* start from the root object, because some laptops define
|
||||
* _DCK methods outside the scope of PCI (IBM x-series laptop)
|
||||
*/
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, find_dock, &num, NULL);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void remove_dock_station(void)
|
||||
{
|
||||
struct dependent_device *dd, *tmp;
|
||||
if (ds) {
|
||||
if (ACPI_FAILURE(acpi_remove_notify_handler(ds->handle,
|
||||
ACPI_SYSTEM_NOTIFY, handle_hotplug_event_dock)))
|
||||
err("failed to remove dock notify handler\n");
|
||||
|
||||
/* free all dependent devices */
|
||||
list_for_each_entry_safe(dd, tmp, &ds->dependent_devices,
|
||||
device_list)
|
||||
kfree(dd);
|
||||
|
||||
/* no need to touch the pci_dependent_device list,
|
||||
* cause all memory was freed above
|
||||
*/
|
||||
kfree(ds);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include "../pci.h"
|
||||
#include "pci_hotplug.h"
|
||||
@ -57,7 +57,6 @@ static LIST_HEAD(bridge_list);
|
||||
#define MY_NAME "acpiphp_glue"
|
||||
|
||||
static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
|
||||
static void handle_hotplug_event_func (acpi_handle, u32, void *);
|
||||
static void acpiphp_sanitize_bus(struct pci_bus *bus);
|
||||
static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus);
|
||||
|
||||
@ -125,11 +124,11 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context;
|
||||
struct acpiphp_slot *slot;
|
||||
struct acpiphp_func *newfunc;
|
||||
struct dependent_device *dd;
|
||||
acpi_handle tmp;
|
||||
acpi_status status = AE_OK;
|
||||
unsigned long adr, sun;
|
||||
int device, function;
|
||||
static int num_slots = 0; /* XXX if we support I/O node hotplug... */
|
||||
int device, function, retval;
|
||||
|
||||
status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
|
||||
|
||||
@ -138,21 +137,21 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
|
||||
status = acpi_get_handle(handle, "_EJ0", &tmp);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
if (ACPI_FAILURE(status) && !(is_dependent_device(handle)))
|
||||
return AE_OK;
|
||||
|
||||
device = (adr >> 16) & 0xffff;
|
||||
function = adr & 0xffff;
|
||||
|
||||
newfunc = kmalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
|
||||
newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
|
||||
if (!newfunc)
|
||||
return AE_NO_MEMORY;
|
||||
memset(newfunc, 0, sizeof(struct acpiphp_func));
|
||||
|
||||
INIT_LIST_HEAD(&newfunc->sibling);
|
||||
newfunc->handle = handle;
|
||||
newfunc->function = function;
|
||||
newfunc->flags = FUNC_HAS_EJ0;
|
||||
if (ACPI_SUCCESS(status))
|
||||
newfunc->flags = FUNC_HAS_EJ0;
|
||||
|
||||
if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp)))
|
||||
newfunc->flags |= FUNC_HAS_STA;
|
||||
@ -163,6 +162,19 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp)))
|
||||
newfunc->flags |= FUNC_HAS_PS3;
|
||||
|
||||
if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp))) {
|
||||
newfunc->flags |= FUNC_HAS_DCK;
|
||||
/* add to devices dependent on dock station,
|
||||
* because this may actually be the dock bridge
|
||||
*/
|
||||
dd = alloc_dependent_device(handle);
|
||||
if (!dd)
|
||||
err("Can't allocate memory for "
|
||||
"new dependent device!\n");
|
||||
else
|
||||
add_dependent_device(dd);
|
||||
}
|
||||
|
||||
status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
|
||||
if (ACPI_FAILURE(status))
|
||||
sun = -1;
|
||||
@ -176,19 +188,17 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
}
|
||||
|
||||
if (!slot) {
|
||||
slot = kmalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
|
||||
slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
|
||||
if (!slot) {
|
||||
kfree(newfunc);
|
||||
return AE_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(slot, 0, sizeof(struct acpiphp_slot));
|
||||
slot->bridge = bridge;
|
||||
slot->id = num_slots++;
|
||||
slot->device = device;
|
||||
slot->sun = sun;
|
||||
INIT_LIST_HEAD(&slot->funcs);
|
||||
init_MUTEX(&slot->crit_sect);
|
||||
mutex_init(&slot->crit_sect);
|
||||
|
||||
slot->next = bridge->slots;
|
||||
bridge->slots = slot;
|
||||
@ -198,6 +208,11 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n",
|
||||
slot->sun, pci_domain_nr(bridge->pci_bus),
|
||||
bridge->pci_bus->number, slot->device);
|
||||
retval = acpiphp_register_hotplug_slot(slot);
|
||||
if (retval) {
|
||||
warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval);
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
|
||||
newfunc->slot = slot;
|
||||
@ -210,16 +225,41 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
|
||||
}
|
||||
|
||||
/* if this is a device dependent on a dock station,
|
||||
* associate the acpiphp_func to the dependent_device
|
||||
* struct.
|
||||
*/
|
||||
if ((dd = get_dependent_device(handle))) {
|
||||
newfunc->flags |= FUNC_IS_DD;
|
||||
/*
|
||||
* we don't want any devices which is dependent
|
||||
* on the dock to have it's _EJ0 method executed.
|
||||
* because we need to run _DCK first.
|
||||
*/
|
||||
newfunc->flags &= ~FUNC_HAS_EJ0;
|
||||
dd->func = newfunc;
|
||||
add_pci_dependent_device(dd);
|
||||
}
|
||||
|
||||
/* install notify handler */
|
||||
status = acpi_install_notify_handler(handle,
|
||||
if (!(newfunc->flags & FUNC_HAS_DCK)) {
|
||||
status = acpi_install_notify_handler(handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
handle_hotplug_event_func,
|
||||
newfunc);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
err("failed to register interrupt notify handler\n");
|
||||
return status;
|
||||
}
|
||||
if (ACPI_FAILURE(status))
|
||||
err("failed to register interrupt notify handler\n");
|
||||
} else
|
||||
status = AE_OK;
|
||||
|
||||
return status;
|
||||
|
||||
err_exit:
|
||||
bridge->nr_slots--;
|
||||
bridge->slots = slot->next;
|
||||
kfree(slot);
|
||||
kfree(newfunc);
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
@ -245,57 +285,19 @@ static int detect_ejectable_slots(acpi_handle *bridge_handle)
|
||||
static void decode_hpp(struct acpiphp_bridge *bridge)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER,
|
||||
.pointer = NULL};
|
||||
union acpi_object *package;
|
||||
int i;
|
||||
|
||||
/* default numbers */
|
||||
bridge->hpp.cache_line_size = 0x10;
|
||||
bridge->hpp.latency_timer = 0x40;
|
||||
bridge->hpp.enable_SERR = 0;
|
||||
bridge->hpp.enable_PERR = 0;
|
||||
|
||||
status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer);
|
||||
|
||||
status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dbg("_HPP evaluation failed\n");
|
||||
return;
|
||||
/* use default numbers */
|
||||
bridge->hpp.cache_line_size = 0x10;
|
||||
bridge->hpp.latency_timer = 0x40;
|
||||
bridge->hpp.enable_serr = 0;
|
||||
bridge->hpp.enable_perr = 0;
|
||||
}
|
||||
|
||||
package = (union acpi_object *) buffer.pointer;
|
||||
|
||||
if (!package || package->type != ACPI_TYPE_PACKAGE ||
|
||||
package->package.count != 4 || !package->package.elements) {
|
||||
err("invalid _HPP object; ignoring\n");
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (package->package.elements[i].type != ACPI_TYPE_INTEGER) {
|
||||
err("invalid _HPP parameter type; ignoring\n");
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
|
||||
bridge->hpp.cache_line_size = package->package.elements[0].integer.value;
|
||||
bridge->hpp.latency_timer = package->package.elements[1].integer.value;
|
||||
bridge->hpp.enable_SERR = package->package.elements[2].integer.value;
|
||||
bridge->hpp.enable_PERR = package->package.elements[3].integer.value;
|
||||
|
||||
dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n",
|
||||
bridge->hpp.cache_line_size,
|
||||
bridge->hpp.latency_timer,
|
||||
bridge->hpp.enable_SERR,
|
||||
bridge->hpp.enable_PERR);
|
||||
|
||||
bridge->flags |= BRIDGE_HAS_HPP;
|
||||
|
||||
err_exit:
|
||||
kfree(buffer.pointer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */
|
||||
static void init_bridge_misc(struct acpiphp_bridge *bridge)
|
||||
{
|
||||
@ -304,9 +306,16 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
|
||||
/* decode ACPI 2.0 _HPP (hot plug parameters) */
|
||||
decode_hpp(bridge);
|
||||
|
||||
/* must be added to the list prior to calling register_slot */
|
||||
list_add(&bridge->list, &bridge_list);
|
||||
|
||||
/* register all slot objects under this bridge */
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
|
||||
register_slot, bridge, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
list_del(&bridge->list);
|
||||
return;
|
||||
}
|
||||
|
||||
/* install notify handler */
|
||||
if (bridge->type != BRIDGE_TYPE_HOST) {
|
||||
@ -319,8 +328,6 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
|
||||
err("failed to register interrupt notify handler\n");
|
||||
}
|
||||
}
|
||||
|
||||
list_add(&bridge->list, &bridge_list);
|
||||
}
|
||||
|
||||
|
||||
@ -329,12 +336,10 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus)
|
||||
{
|
||||
struct acpiphp_bridge *bridge;
|
||||
|
||||
bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
|
||||
bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
|
||||
if (bridge == NULL)
|
||||
return;
|
||||
|
||||
memset(bridge, 0, sizeof(struct acpiphp_bridge));
|
||||
|
||||
bridge->type = BRIDGE_TYPE_HOST;
|
||||
bridge->handle = handle;
|
||||
|
||||
@ -351,14 +356,12 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
|
||||
{
|
||||
struct acpiphp_bridge *bridge;
|
||||
|
||||
bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
|
||||
bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
|
||||
if (bridge == NULL) {
|
||||
err("out of memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(bridge, 0, sizeof(struct acpiphp_bridge));
|
||||
|
||||
bridge->type = BRIDGE_TYPE_P2P;
|
||||
bridge->handle = handle;
|
||||
|
||||
@ -410,11 +413,18 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
goto out;
|
||||
|
||||
/* check if this bridge has ejectable slots */
|
||||
if (detect_ejectable_slots(handle) > 0) {
|
||||
if ((detect_ejectable_slots(handle) > 0) ||
|
||||
(detect_dependent_devices(handle) > 0)) {
|
||||
dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
|
||||
add_p2p_bridge(handle, dev);
|
||||
}
|
||||
|
||||
/* search P2P bridges under this p2p bridge */
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
|
||||
find_p2p_bridge, dev->subordinate, NULL);
|
||||
if (ACPI_FAILURE(status))
|
||||
warn("find_p2p_bridge faied (error code = 0x%x)\n", status);
|
||||
|
||||
out:
|
||||
pci_dev_put(dev);
|
||||
return AE_OK;
|
||||
@ -512,15 +522,19 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
|
||||
list_for_each_safe (list, tmp, &slot->funcs) {
|
||||
struct acpiphp_func *func;
|
||||
func = list_entry(list, struct acpiphp_func, sibling);
|
||||
status = acpi_remove_notify_handler(func->handle,
|
||||
if (!(func->flags & FUNC_HAS_DCK)) {
|
||||
status = acpi_remove_notify_handler(func->handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
handle_hotplug_event_func);
|
||||
if (ACPI_FAILURE(status))
|
||||
err("failed to remove notify handler\n");
|
||||
if (ACPI_FAILURE(status))
|
||||
err("failed to remove notify handler\n");
|
||||
}
|
||||
pci_dev_put(func->pci_dev);
|
||||
list_del(list);
|
||||
kfree(func);
|
||||
}
|
||||
acpiphp_unregister_hotplug_slot(slot);
|
||||
list_del(&slot->funcs);
|
||||
kfree(slot);
|
||||
slot = next;
|
||||
}
|
||||
@ -551,7 +565,8 @@ static void remove_bridge(acpi_handle handle)
|
||||
} else {
|
||||
/* clean-up p2p bridges under this host bridge */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
|
||||
(u32)1, cleanup_p2p_bridge, NULL, NULL);
|
||||
ACPI_UINT32_MAX, cleanup_p2p_bridge,
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -751,6 +766,113 @@ static int power_off_slot(struct acpiphp_slot *slot)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* acpiphp_max_busnr - return the highest reserved bus number under
|
||||
* the given bus.
|
||||
* @bus: bus to start search with
|
||||
*
|
||||
*/
|
||||
static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
|
||||
{
|
||||
struct list_head *tmp;
|
||||
unsigned char max, n;
|
||||
|
||||
/*
|
||||
* pci_bus_max_busnr will return the highest
|
||||
* reserved busnr for all these children.
|
||||
* that is equivalent to the bus->subordinate
|
||||
* value. We don't want to use the parent's
|
||||
* bus->subordinate value because it could have
|
||||
* padding in it.
|
||||
*/
|
||||
max = bus->secondary;
|
||||
|
||||
list_for_each(tmp, &bus->children) {
|
||||
n = pci_bus_max_busnr(pci_bus_b(tmp));
|
||||
if (n > max)
|
||||
max = n;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* get_func - get a pointer to acpiphp_func given a slot, device
|
||||
* @slot: slot to search
|
||||
* @dev: pci_dev struct to match.
|
||||
*
|
||||
* This function will increase the reference count of pci_dev,
|
||||
* so callers should call pci_dev_put when complete.
|
||||
*
|
||||
*/
|
||||
static struct acpiphp_func *
|
||||
get_func(struct acpiphp_slot *slot, struct pci_dev *dev)
|
||||
{
|
||||
struct acpiphp_func *func = NULL;
|
||||
struct pci_bus *bus = slot->bridge->pci_bus;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
list_for_each_entry(func, &slot->funcs, sibling) {
|
||||
pdev = pci_get_slot(bus, PCI_DEVFN(slot->device,
|
||||
func->function));
|
||||
if (pdev) {
|
||||
if (pdev == dev)
|
||||
break;
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
}
|
||||
return func;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* acpiphp_bus_add - add a new bus to acpi subsystem
|
||||
* @func: acpiphp_func of the bridge
|
||||
*
|
||||
*/
|
||||
static int acpiphp_bus_add(struct acpiphp_func *func)
|
||||
{
|
||||
acpi_handle phandle;
|
||||
struct acpi_device *device, *pdevice;
|
||||
int ret_val;
|
||||
|
||||
acpi_get_parent(func->handle, &phandle);
|
||||
if (acpi_bus_get_device(phandle, &pdevice)) {
|
||||
dbg("no parent device, assuming NULL\n");
|
||||
pdevice = NULL;
|
||||
}
|
||||
if (!acpi_bus_get_device(func->handle, &device)) {
|
||||
dbg("bus exists... trim\n");
|
||||
/* this shouldn't be in here, so remove
|
||||
* the bus then re-add it...
|
||||
*/
|
||||
ret_val = acpi_bus_trim(device, 1);
|
||||
dbg("acpi_bus_trim return %x\n", ret_val);
|
||||
}
|
||||
|
||||
ret_val = acpi_bus_add(&device, pdevice, func->handle,
|
||||
ACPI_BUS_TYPE_DEVICE);
|
||||
if (ret_val) {
|
||||
dbg("error adding bus, %x\n",
|
||||
-ret_val);
|
||||
goto acpiphp_bus_add_out;
|
||||
}
|
||||
/*
|
||||
* try to start anyway. We could have failed to add
|
||||
* simply because this bus had previously been added
|
||||
* on another add. Don't bother with the return value
|
||||
* we just keep going.
|
||||
*/
|
||||
ret_val = acpi_bus_start(device);
|
||||
|
||||
acpiphp_bus_add_out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* enable_device - enable, configure a slot
|
||||
* @slot: slot to be enabled
|
||||
@ -788,7 +910,7 @@ static int enable_device(struct acpiphp_slot *slot)
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
max = bus->secondary;
|
||||
max = acpiphp_max_busnr(bus);
|
||||
for (pass = 0; pass < 2; pass++) {
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
if (PCI_SLOT(dev->devfn) != slot->device)
|
||||
@ -796,8 +918,15 @@ static int enable_device(struct acpiphp_slot *slot)
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
||||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
|
||||
max = pci_scan_bridge(bus, dev, max, pass);
|
||||
if (pass && dev->subordinate)
|
||||
if (pass && dev->subordinate) {
|
||||
pci_bus_size_bridges(dev->subordinate);
|
||||
func = get_func(slot, dev);
|
||||
if (func) {
|
||||
acpiphp_bus_add(func);
|
||||
/* side effect of get_func */
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -806,8 +935,8 @@ static int enable_device(struct acpiphp_slot *slot)
|
||||
acpiphp_sanitize_bus(bus);
|
||||
pci_enable_bridges(bus);
|
||||
pci_bus_add_devices(bus);
|
||||
acpiphp_set_hpp_values(DEVICE_ACPI_HANDLE(&bus->self->dev), bus);
|
||||
acpiphp_configure_ioapics(DEVICE_ACPI_HANDLE(&bus->self->dev));
|
||||
acpiphp_set_hpp_values(slot->bridge->handle, bus);
|
||||
acpiphp_configure_ioapics(slot->bridge->handle);
|
||||
|
||||
/* associate pci_dev to our representation */
|
||||
list_for_each (l, &slot->funcs) {
|
||||
@ -987,11 +1116,11 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER,
|
||||
bridge->hpp.latency_timer);
|
||||
pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
|
||||
if (bridge->hpp.enable_SERR)
|
||||
if (bridge->hpp.enable_serr)
|
||||
pci_cmd |= PCI_COMMAND_SERR;
|
||||
else
|
||||
pci_cmd &= ~PCI_COMMAND_SERR;
|
||||
if (bridge->hpp.enable_PERR)
|
||||
if (bridge->hpp.enable_perr)
|
||||
pci_cmd |= PCI_COMMAND_PARITY;
|
||||
else
|
||||
pci_cmd &= ~PCI_COMMAND_PARITY;
|
||||
@ -1002,11 +1131,11 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
|
||||
pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
|
||||
bridge->hpp.latency_timer);
|
||||
pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
|
||||
if (bridge->hpp.enable_SERR)
|
||||
if (bridge->hpp.enable_serr)
|
||||
pci_bctl |= PCI_BRIDGE_CTL_SERR;
|
||||
else
|
||||
pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
|
||||
if (bridge->hpp.enable_PERR)
|
||||
if (bridge->hpp.enable_perr)
|
||||
pci_bctl |= PCI_BRIDGE_CTL_PARITY;
|
||||
else
|
||||
pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
|
||||
@ -1026,6 +1155,7 @@ static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus)
|
||||
|
||||
memset(&bridge, 0, sizeof(bridge));
|
||||
bridge.handle = handle;
|
||||
bridge.pci_dev = bus->self;
|
||||
decode_hpp(&bridge);
|
||||
list_for_each_entry(dev, &bus->devices, bus_list)
|
||||
program_hpp(dev, &bridge);
|
||||
@ -1200,7 +1330,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
|
||||
* handles ACPI event notification on slots
|
||||
*
|
||||
*/
|
||||
static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context)
|
||||
void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context)
|
||||
{
|
||||
struct acpiphp_func *func;
|
||||
char objname[64];
|
||||
@ -1242,41 +1372,13 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
|
||||
}
|
||||
}
|
||||
|
||||
static int is_root_bridge(acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_device_info *info;
|
||||
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
int i;
|
||||
|
||||
status = acpi_get_object_info(handle, &buffer);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
info = buffer.pointer;
|
||||
if ((info->valid & ACPI_VALID_HID) &&
|
||||
!strcmp(PCI_ROOT_HID_STRING,
|
||||
info->hardware_id.value)) {
|
||||
acpi_os_free(buffer.pointer);
|
||||
return 1;
|
||||
}
|
||||
if (info->valid & ACPI_VALID_CID) {
|
||||
for (i=0; i < info->compatibility_id.count; i++) {
|
||||
if (!strcmp(PCI_ROOT_HID_STRING,
|
||||
info->compatibility_id.id[i].value)) {
|
||||
acpi_os_free(buffer.pointer);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
int *count = (int *)context;
|
||||
|
||||
if (is_root_bridge(handle)) {
|
||||
if (acpi_root_bridge(handle)) {
|
||||
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
||||
handle_hotplug_event_bridge, NULL);
|
||||
(*count)++;
|
||||
@ -1373,26 +1475,6 @@ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* search matching slot from id */
|
||||
struct acpiphp_slot *get_slot_from_id(int id)
|
||||
{
|
||||
struct list_head *node;
|
||||
struct acpiphp_bridge *bridge;
|
||||
struct acpiphp_slot *slot;
|
||||
|
||||
list_for_each (node, &bridge_list) {
|
||||
bridge = (struct acpiphp_bridge *)node;
|
||||
for (slot = bridge->slots; slot; slot = slot->next)
|
||||
if (slot->id == id)
|
||||
return slot;
|
||||
}
|
||||
|
||||
/* should never happen! */
|
||||
err("%s: no object for id %d\n", __FUNCTION__, id);
|
||||
WARN_ON(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* acpiphp_enable_slot - power on slot
|
||||
@ -1401,7 +1483,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
|
||||
{
|
||||
int retval;
|
||||
|
||||
down(&slot->crit_sect);
|
||||
mutex_lock(&slot->crit_sect);
|
||||
|
||||
/* wake up all functions */
|
||||
retval = power_on_slot(slot);
|
||||
@ -1413,7 +1495,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
|
||||
retval = enable_device(slot);
|
||||
|
||||
err_exit:
|
||||
up(&slot->crit_sect);
|
||||
mutex_unlock(&slot->crit_sect);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -1424,7 +1506,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
down(&slot->crit_sect);
|
||||
mutex_lock(&slot->crit_sect);
|
||||
|
||||
/* unconfigure all functions */
|
||||
retval = disable_device(slot);
|
||||
@ -1437,7 +1519,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot)
|
||||
goto err_exit;
|
||||
|
||||
err_exit:
|
||||
up(&slot->crit_sect);
|
||||
mutex_unlock(&slot->crit_sect);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -248,22 +248,19 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
|
||||
* with the pci_hotplug subsystem.
|
||||
*/
|
||||
for (i = first; i <= last; ++i) {
|
||||
slot = kmalloc(sizeof (struct slot), GFP_KERNEL);
|
||||
slot = kzalloc(sizeof (struct slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
goto error;
|
||||
memset(slot, 0, sizeof (struct slot));
|
||||
|
||||
hotplug_slot =
|
||||
kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
|
||||
kzalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
|
||||
if (!hotplug_slot)
|
||||
goto error_slot;
|
||||
memset(hotplug_slot, 0, sizeof (struct hotplug_slot));
|
||||
slot->hotplug_slot = hotplug_slot;
|
||||
|
||||
info = kmalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL);
|
||||
info = kzalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL);
|
||||
if (!info)
|
||||
goto error_hpslot;
|
||||
memset(info, 0, sizeof (struct hotplug_slot_info));
|
||||
hotplug_slot->info = info;
|
||||
|
||||
name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/io.h> /* for read? and write? functions */
|
||||
#include <linux/delay.h> /* for delays */
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#define MY_NAME "cpqphp"
|
||||
|
||||
@ -286,7 +287,7 @@ struct event_info {
|
||||
struct controller {
|
||||
struct controller *next;
|
||||
u32 ctrl_int_comp;
|
||||
struct semaphore crit_sect; /* critical section semaphore */
|
||||
struct mutex crit_sect; /* critical section mutex */
|
||||
void __iomem *hpc_reg; /* cookie for our pci controller location */
|
||||
struct pci_resource *mem_head;
|
||||
struct pci_resource *p_mem_head;
|
||||
|
@ -347,26 +347,22 @@ static int ctrl_slot_setup(struct controller *ctrl,
|
||||
slot_number = ctrl->first_slot;
|
||||
|
||||
while (number_of_slots) {
|
||||
slot = kmalloc(sizeof(*slot), GFP_KERNEL);
|
||||
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
goto error;
|
||||
|
||||
memset(slot, 0, sizeof(struct slot));
|
||||
slot->hotplug_slot = kmalloc(sizeof(*(slot->hotplug_slot)),
|
||||
slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)),
|
||||
GFP_KERNEL);
|
||||
if (!slot->hotplug_slot)
|
||||
goto error_slot;
|
||||
hotplug_slot = slot->hotplug_slot;
|
||||
memset(hotplug_slot, 0, sizeof(struct hotplug_slot));
|
||||
|
||||
hotplug_slot->info =
|
||||
kmalloc(sizeof(*(hotplug_slot->info)),
|
||||
kzalloc(sizeof(*(hotplug_slot->info)),
|
||||
GFP_KERNEL);
|
||||
if (!hotplug_slot->info)
|
||||
goto error_hpslot;
|
||||
hotplug_slot_info = hotplug_slot->info;
|
||||
memset(hotplug_slot_info, 0,
|
||||
sizeof(struct hotplug_slot_info));
|
||||
hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
|
||||
|
||||
if (!hotplug_slot->name)
|
||||
@ -599,7 +595,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
|
||||
hp_slot = func->device - ctrl->slot_device_offset;
|
||||
|
||||
// Wait for exclusive access to hardware
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
if (status == 1) {
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
@ -607,7 +603,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
|
||||
amber_LED_off (ctrl, hp_slot);
|
||||
} else {
|
||||
// Done with exclusive hardware access
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -617,7 +613,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
// Done with exclusive hardware access
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
return(0);
|
||||
}
|
||||
@ -854,13 +850,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
goto err_disable_device;
|
||||
}
|
||||
|
||||
ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
|
||||
ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL);
|
||||
if (!ctrl) {
|
||||
err("%s : out of memory\n", __FUNCTION__);
|
||||
rc = -ENOMEM;
|
||||
goto err_disable_device;
|
||||
}
|
||||
memset(ctrl, 0, sizeof(struct controller));
|
||||
|
||||
rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
|
||||
if (rc) {
|
||||
@ -1084,7 +1079,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
dbg("bus device function rev: %d %d %d %d\n", ctrl->bus,
|
||||
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev);
|
||||
|
||||
init_MUTEX(&ctrl->crit_sect);
|
||||
mutex_init(&ctrl->crit_sect);
|
||||
init_waitqueue_head(&ctrl->queue);
|
||||
|
||||
/* initialize our threads if they haven't already been started up */
|
||||
@ -1223,7 +1218,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
// turn off empty slots here unless command line option "ON" set
|
||||
// Wait for exclusive access to hardware
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;
|
||||
|
||||
@ -1270,12 +1265,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
rc = init_SERR(ctrl);
|
||||
if (rc) {
|
||||
err("init_SERR failed\n");
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
// Done with exclusive hardware access
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
cpqhp_create_debugfs_files(ctrl);
|
||||
|
||||
|
@ -1282,9 +1282,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
|
||||
u8 hp_slot;
|
||||
u8 temp_byte;
|
||||
u8 adapter_speed;
|
||||
u32 index;
|
||||
u32 rc = 0;
|
||||
u32 src = 8;
|
||||
|
||||
hp_slot = func->device - ctrl->slot_device_offset;
|
||||
|
||||
@ -1299,7 +1297,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
|
||||
**********************************/
|
||||
rc = CARD_FUNCTIONING;
|
||||
} else {
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
/* turn on board without attaching to the bus */
|
||||
enable_slot_power (ctrl, hp_slot);
|
||||
@ -1333,12 +1331,12 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
slot_enable (ctrl, hp_slot);
|
||||
green_LED_blink (ctrl, hp_slot);
|
||||
@ -1350,7 +1348,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
/* Wait for ~1 second because of hot plug spec */
|
||||
long_delay(1*HZ);
|
||||
@ -1368,84 +1366,13 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
|
||||
|
||||
rc = cpqhp_configure_board(ctrl, func);
|
||||
|
||||
if (rc || src) {
|
||||
/* If configuration fails, turn it off
|
||||
* Get slot won't work for devices behind
|
||||
* bridges, but in this case it will always be
|
||||
* called for the "base" bus/dev/func of an
|
||||
* adapter. */
|
||||
/* If configuration fails, turn it off
|
||||
* Get slot won't work for devices behind
|
||||
* bridges, but in this case it will always be
|
||||
* called for the "base" bus/dev/func of an
|
||||
* adapter. */
|
||||
|
||||
down(&ctrl->crit_sect);
|
||||
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
slot_disable (ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
func->status = 0;
|
||||
func->switch_save = 0x10;
|
||||
|
||||
index = 1;
|
||||
while (((func = cpqhp_slot_find(func->bus, func->device, index)) != NULL) && !rc) {
|
||||
rc |= cpqhp_configure_board(ctrl, func);
|
||||
index++;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
/* If configuration fails, turn it off
|
||||
* Get slot won't work for devices behind
|
||||
* bridges, but in this case it will always be
|
||||
* called for the "base" bus/dev/func of an
|
||||
* adapter. */
|
||||
|
||||
down(&ctrl->crit_sect);
|
||||
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
slot_disable (ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
|
||||
return rc;
|
||||
}
|
||||
/* Done configuring so turn LED on full time */
|
||||
|
||||
down(&ctrl->crit_sect);
|
||||
|
||||
green_LED_on (ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
rc = 0;
|
||||
} else {
|
||||
/* Something is wrong
|
||||
|
||||
* Get slot won't work for devices behind bridges, but
|
||||
* in this case it will always be called for the "base"
|
||||
* bus/dev/func of an adapter. */
|
||||
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
@ -1456,7 +1383,32 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
else
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
/* Something is wrong
|
||||
|
||||
* Get slot won't work for devices behind bridges, but
|
||||
* in this case it will always be called for the "base"
|
||||
* bus/dev/func of an adapter. */
|
||||
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
slot_disable (ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1488,7 +1440,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n",
|
||||
__FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
|
||||
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
/* turn on board without attaching to the bus */
|
||||
enable_slot_power(ctrl, hp_slot);
|
||||
@ -1522,7 +1474,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -1532,7 +1484,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
/* turn on board and blink green LED */
|
||||
|
||||
dbg("%s: before down\n", __FUNCTION__);
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
dbg("%s: after down\n", __FUNCTION__);
|
||||
|
||||
dbg("%s: before slot_enable\n", __FUNCTION__);
|
||||
@ -1553,7 +1505,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__);
|
||||
|
||||
dbg("%s: before up\n", __FUNCTION__);
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
dbg("%s: after up\n", __FUNCTION__);
|
||||
|
||||
/* Wait for ~1 second because of hot plug spec */
|
||||
@ -1607,7 +1559,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
|
||||
|
||||
if (rc) {
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
@ -1618,7 +1570,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
return rc;
|
||||
} else {
|
||||
cpqhp_save_slot_config(ctrl, func);
|
||||
@ -1640,7 +1592,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
}
|
||||
} while (new_slot);
|
||||
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
green_LED_on (ctrl, hp_slot);
|
||||
|
||||
@ -1649,9 +1601,9 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
} else {
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
@ -1662,7 +1614,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -1721,7 +1673,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control
|
||||
func->status = 0x01;
|
||||
func->configured = 0;
|
||||
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
slot_disable (ctrl, hp_slot);
|
||||
@ -1736,7 +1688,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
if (!replace_flag && ctrl->add_support) {
|
||||
while (func) {
|
||||
@ -1899,7 +1851,7 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
dbg("button cancel\n");
|
||||
del_timer(&p_slot->task_event);
|
||||
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
if (p_slot->state == BLINKINGOFF_STATE) {
|
||||
/* slot is on */
|
||||
@ -1922,7 +1874,7 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
}
|
||||
/*** button Released (No action on press...) */
|
||||
else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) {
|
||||
@ -1937,7 +1889,7 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
p_slot->state = BLINKINGON_STATE;
|
||||
info(msg_button_on, p_slot->number);
|
||||
}
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
dbg("blink green LED and turn off amber\n");
|
||||
|
||||
@ -1949,7 +1901,7 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
init_timer(&p_slot->task_event);
|
||||
p_slot->hp_slot = hp_slot;
|
||||
p_slot->ctrl = ctrl;
|
||||
|
@ -95,15 +95,13 @@ static int add_slot(struct pci_dev *dev)
|
||||
struct hotplug_slot *slot;
|
||||
int retval = -ENOMEM;
|
||||
|
||||
slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
|
||||
slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
goto error;
|
||||
memset(slot, 0, sizeof(*slot));
|
||||
|
||||
slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
|
||||
slot->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
|
||||
if (!slot->info)
|
||||
goto error_slot;
|
||||
memset(slot->info, 0, sizeof(struct hotplug_slot_info));
|
||||
|
||||
slot->info->power_status = 1;
|
||||
slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
|
||||
@ -227,11 +225,10 @@ static void pci_rescan_bus(const struct pci_bus *bus)
|
||||
{
|
||||
unsigned int devfn;
|
||||
struct pci_dev *dev;
|
||||
dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
|
||||
dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
memset(dev, 0, sizeof(dev));
|
||||
dev->bus = (struct pci_bus*)bus;
|
||||
dev->sysdata = bus->sysdata;
|
||||
for (devfn = 0; devfn < 0x100; devfn += 8) {
|
||||
|
@ -406,8 +406,6 @@ extern void ibmphp_hpc_stop_poll_thread (void);
|
||||
//----------------------------------------------------------------------------
|
||||
// HPC return codes
|
||||
//----------------------------------------------------------------------------
|
||||
#define FALSE 0x00
|
||||
#define TRUE 0x01
|
||||
#define HPC_ERROR 0xFF
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1141,7 +1141,7 @@ static int enable_slot(struct hotplug_slot *hs)
|
||||
goto error_power;
|
||||
}
|
||||
|
||||
slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL);
|
||||
slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL);
|
||||
if (!slot_cur->func) {
|
||||
/* We cannot do update_slot_info here, since no memory for
|
||||
* kmalloc n.e.ways, and update_slot_info allocates some */
|
||||
@ -1149,7 +1149,6 @@ static int enable_slot(struct hotplug_slot *hs)
|
||||
rc = -ENOMEM;
|
||||
goto error_power;
|
||||
}
|
||||
memset(slot_cur->func, 0, sizeof(struct pci_func));
|
||||
slot_cur->func->busno = slot_cur->bus;
|
||||
slot_cur->func->device = slot_cur->device;
|
||||
for (i = 0; i < 4; i++)
|
||||
@ -1240,9 +1239,9 @@ int ibmphp_do_disable_slot(struct slot *slot_cur)
|
||||
}
|
||||
|
||||
flag = slot_cur->flag;
|
||||
slot_cur->flag = TRUE;
|
||||
slot_cur->flag = 1;
|
||||
|
||||
if (flag == TRUE) {
|
||||
if (flag == 1) {
|
||||
rc = validate(slot_cur, DISABLE);
|
||||
/* checking if powered off already & valid slot # */
|
||||
if (rc)
|
||||
@ -1252,13 +1251,12 @@ int ibmphp_do_disable_slot(struct slot *slot_cur)
|
||||
|
||||
if (slot_cur->func == NULL) {
|
||||
/* We need this for fncs's that were there on bootup */
|
||||
slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL);
|
||||
slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL);
|
||||
if (!slot_cur->func) {
|
||||
err("out of system memory\n");
|
||||
rc = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
memset(slot_cur->func, 0, sizeof(struct pci_func));
|
||||
slot_cur->func->busno = slot_cur->bus;
|
||||
slot_cur->func->device = slot_cur->device;
|
||||
}
|
||||
|
@ -72,13 +72,7 @@ static int ebda_rio_table (void);
|
||||
|
||||
static struct ebda_hpc_list * __init alloc_ebda_hpc_list (void)
|
||||
{
|
||||
struct ebda_hpc_list *list;
|
||||
|
||||
list = kmalloc (sizeof (struct ebda_hpc_list), GFP_KERNEL);
|
||||
if (!list)
|
||||
return NULL;
|
||||
memset (list, 0, sizeof (*list));
|
||||
return list;
|
||||
return kzalloc(sizeof(struct ebda_hpc_list), GFP_KERNEL);
|
||||
}
|
||||
|
||||
static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count)
|
||||
@ -87,21 +81,18 @@ static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count)
|
||||
struct ebda_hpc_slot *slots;
|
||||
struct ebda_hpc_bus *buses;
|
||||
|
||||
controller = kmalloc (sizeof (struct controller), GFP_KERNEL);
|
||||
controller = kzalloc(sizeof(struct controller), GFP_KERNEL);
|
||||
if (!controller)
|
||||
goto error;
|
||||
memset (controller, 0, sizeof (*controller));
|
||||
|
||||
slots = kmalloc (sizeof (struct ebda_hpc_slot) * slot_count, GFP_KERNEL);
|
||||
slots = kcalloc(slot_count, sizeof(struct ebda_hpc_slot), GFP_KERNEL);
|
||||
if (!slots)
|
||||
goto error_contr;
|
||||
memset (slots, 0, sizeof (*slots) * slot_count);
|
||||
controller->slots = slots;
|
||||
|
||||
buses = kmalloc (sizeof (struct ebda_hpc_bus) * bus_count, GFP_KERNEL);
|
||||
buses = kcalloc(bus_count, sizeof(struct ebda_hpc_bus), GFP_KERNEL);
|
||||
if (!buses)
|
||||
goto error_slots;
|
||||
memset (buses, 0, sizeof (*buses) * bus_count);
|
||||
controller->buses = buses;
|
||||
|
||||
return controller;
|
||||
@ -122,24 +113,12 @@ static void free_ebda_hpc (struct controller *controller)
|
||||
|
||||
static struct ebda_rsrc_list * __init alloc_ebda_rsrc_list (void)
|
||||
{
|
||||
struct ebda_rsrc_list *list;
|
||||
|
||||
list = kmalloc (sizeof (struct ebda_rsrc_list), GFP_KERNEL);
|
||||
if (!list)
|
||||
return NULL;
|
||||
memset (list, 0, sizeof (*list));
|
||||
return list;
|
||||
return kzalloc(sizeof(struct ebda_rsrc_list), GFP_KERNEL);
|
||||
}
|
||||
|
||||
static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void)
|
||||
{
|
||||
struct ebda_pci_rsrc *resource;
|
||||
|
||||
resource = kmalloc (sizeof (struct ebda_pci_rsrc), GFP_KERNEL);
|
||||
if (!resource)
|
||||
return NULL;
|
||||
memset (resource, 0, sizeof (*resource));
|
||||
return resource;
|
||||
return kzalloc(sizeof(struct ebda_pci_rsrc), GFP_KERNEL);
|
||||
}
|
||||
|
||||
static void __init print_bus_info (void)
|
||||
@ -390,10 +369,9 @@ int __init ibmphp_access_ebda (void)
|
||||
debug ("now enter io table ---\n");
|
||||
debug ("rio blk id: %x\n", blk_id);
|
||||
|
||||
rio_table_ptr = kmalloc (sizeof (struct rio_table_hdr), GFP_KERNEL);
|
||||
rio_table_ptr = kzalloc(sizeof(struct rio_table_hdr), GFP_KERNEL);
|
||||
if (!rio_table_ptr)
|
||||
return -ENOMEM;
|
||||
memset (rio_table_ptr, 0, sizeof (struct rio_table_hdr) );
|
||||
rio_table_ptr->ver_num = readb (io_mem + offset);
|
||||
rio_table_ptr->scal_count = readb (io_mem + offset + 1);
|
||||
rio_table_ptr->riodev_count = readb (io_mem + offset + 2);
|
||||
@ -445,10 +423,9 @@ static int __init ebda_rio_table (void)
|
||||
|
||||
// we do concern about rio details
|
||||
for (i = 0; i < rio_table_ptr->riodev_count; i++) {
|
||||
rio_detail_ptr = kmalloc (sizeof (struct rio_detail), GFP_KERNEL);
|
||||
rio_detail_ptr = kzalloc(sizeof(struct rio_detail), GFP_KERNEL);
|
||||
if (!rio_detail_ptr)
|
||||
return -ENOMEM;
|
||||
memset (rio_detail_ptr, 0, sizeof (struct rio_detail));
|
||||
rio_detail_ptr->rio_node_id = readb (io_mem + offset);
|
||||
rio_detail_ptr->bbar = readl (io_mem + offset + 1);
|
||||
rio_detail_ptr->rio_type = readb (io_mem + offset + 5);
|
||||
@ -503,10 +480,9 @@ static int __init combine_wpg_for_chassis (void)
|
||||
rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
|
||||
opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num);
|
||||
if (!opt_rio_ptr) {
|
||||
opt_rio_ptr = (struct opt_rio *) kmalloc (sizeof (struct opt_rio), GFP_KERNEL);
|
||||
opt_rio_ptr = kzalloc(sizeof(struct opt_rio), GFP_KERNEL);
|
||||
if (!opt_rio_ptr)
|
||||
return -ENOMEM;
|
||||
memset (opt_rio_ptr, 0, sizeof (struct opt_rio));
|
||||
opt_rio_ptr->rio_type = rio_detail_ptr->rio_type;
|
||||
opt_rio_ptr->chassis_num = rio_detail_ptr->chassis_num;
|
||||
opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num;
|
||||
@ -546,10 +522,9 @@ static int combine_wpg_for_expansion (void)
|
||||
rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
|
||||
opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num);
|
||||
if (!opt_rio_lo_ptr) {
|
||||
opt_rio_lo_ptr = (struct opt_rio_lo *) kmalloc (sizeof (struct opt_rio_lo), GFP_KERNEL);
|
||||
opt_rio_lo_ptr = kzalloc(sizeof(struct opt_rio_lo), GFP_KERNEL);
|
||||
if (!opt_rio_lo_ptr)
|
||||
return -ENOMEM;
|
||||
memset (opt_rio_lo_ptr, 0, sizeof (struct opt_rio_lo));
|
||||
opt_rio_lo_ptr->rio_type = rio_detail_ptr->rio_type;
|
||||
opt_rio_lo_ptr->chassis_num = rio_detail_ptr->chassis_num;
|
||||
opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num;
|
||||
@ -842,12 +817,11 @@ static int __init ebda_rsrc_controller (void)
|
||||
|
||||
bus_info_ptr2 = ibmphp_find_same_bus_num (slot_ptr->slot_bus_num);
|
||||
if (!bus_info_ptr2) {
|
||||
bus_info_ptr1 = (struct bus_info *) kmalloc (sizeof (struct bus_info), GFP_KERNEL);
|
||||
bus_info_ptr1 = kzalloc(sizeof(struct bus_info), GFP_KERNEL);
|
||||
if (!bus_info_ptr1) {
|
||||
rc = -ENOMEM;
|
||||
goto error_no_hp_slot;
|
||||
}
|
||||
memset (bus_info_ptr1, 0, sizeof (struct bus_info));
|
||||
bus_info_ptr1->slot_min = slot_ptr->slot_num;
|
||||
bus_info_ptr1->slot_max = slot_ptr->slot_num;
|
||||
bus_info_ptr1->slot_count += 1;
|
||||
@ -946,19 +920,17 @@ static int __init ebda_rsrc_controller (void)
|
||||
// register slots with hpc core as well as create linked list of ibm slot
|
||||
for (index = 0; index < hpc_ptr->slot_count; index++) {
|
||||
|
||||
hp_slot_ptr = kmalloc(sizeof(*hp_slot_ptr), GFP_KERNEL);
|
||||
hp_slot_ptr = kzalloc(sizeof(*hp_slot_ptr), GFP_KERNEL);
|
||||
if (!hp_slot_ptr) {
|
||||
rc = -ENOMEM;
|
||||
goto error_no_hp_slot;
|
||||
}
|
||||
memset(hp_slot_ptr, 0, sizeof(*hp_slot_ptr));
|
||||
|
||||
hp_slot_ptr->info = kmalloc (sizeof(struct hotplug_slot_info), GFP_KERNEL);
|
||||
hp_slot_ptr->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
|
||||
if (!hp_slot_ptr->info) {
|
||||
rc = -ENOMEM;
|
||||
goto error_no_hp_info;
|
||||
}
|
||||
memset(hp_slot_ptr->info, 0, sizeof(struct hotplug_slot_info));
|
||||
|
||||
hp_slot_ptr->name = kmalloc(30, GFP_KERNEL);
|
||||
if (!hp_slot_ptr->name) {
|
||||
@ -966,14 +938,13 @@ static int __init ebda_rsrc_controller (void)
|
||||
goto error_no_hp_name;
|
||||
}
|
||||
|
||||
tmp_slot = kmalloc(sizeof(*tmp_slot), GFP_KERNEL);
|
||||
tmp_slot = kzalloc(sizeof(*tmp_slot), GFP_KERNEL);
|
||||
if (!tmp_slot) {
|
||||
rc = -ENOMEM;
|
||||
goto error_no_slot;
|
||||
}
|
||||
memset(tmp_slot, 0, sizeof(*tmp_slot));
|
||||
|
||||
tmp_slot->flag = TRUE;
|
||||
tmp_slot->flag = 1;
|
||||
|
||||
tmp_slot->capabilities = hpc_ptr->slots[index].slot_cap;
|
||||
if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX)
|
||||
|
@ -34,9 +34,11 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include "ibmphp.h"
|
||||
|
||||
static int to_debug = FALSE;
|
||||
static int to_debug = 0;
|
||||
#define debug_polling(fmt, arg...) do { if (to_debug) debug (fmt, arg); } while (0)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -93,15 +95,15 @@ static int to_debug = FALSE;
|
||||
//----------------------------------------------------------------------------
|
||||
// macro utilities
|
||||
//----------------------------------------------------------------------------
|
||||
// if bits 20,22,25,26,27,29,30 are OFF return TRUE
|
||||
#define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? FALSE : TRUE))
|
||||
// if bits 20,22,25,26,27,29,30 are OFF return 1
|
||||
#define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? 0 : 1))
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// global variables
|
||||
//----------------------------------------------------------------------------
|
||||
static int ibmphp_shutdown;
|
||||
static int tid_poll;
|
||||
static struct semaphore sem_hpcaccess; // lock access to HPC
|
||||
static struct mutex sem_hpcaccess; // lock access to HPC
|
||||
static struct semaphore semOperations; // lock all operations and
|
||||
// access to data structures
|
||||
static struct semaphore sem_exit; // make sure polling thread goes away
|
||||
@ -131,11 +133,11 @@ void __init ibmphp_hpc_initvars (void)
|
||||
{
|
||||
debug ("%s - Entry\n", __FUNCTION__);
|
||||
|
||||
init_MUTEX (&sem_hpcaccess);
|
||||
mutex_init(&sem_hpcaccess);
|
||||
init_MUTEX (&semOperations);
|
||||
init_MUTEX_LOCKED (&sem_exit);
|
||||
to_debug = FALSE;
|
||||
ibmphp_shutdown = FALSE;
|
||||
to_debug = 0;
|
||||
ibmphp_shutdown = 0;
|
||||
tid_poll = 0;
|
||||
|
||||
debug ("%s - Exit\n", __FUNCTION__);
|
||||
@ -737,21 +739,21 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
|
||||
// check controller is still not working on the command
|
||||
//--------------------------------------------------------------------
|
||||
timeout = CMD_COMPLETE_TOUT_SEC;
|
||||
done = FALSE;
|
||||
done = 0;
|
||||
while (!done) {
|
||||
rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
|
||||
&status);
|
||||
if (!rc) {
|
||||
if (NEEDTOCHECK_CMDSTATUS (cmd)) {
|
||||
if (CTLR_FINISHED (status) == HPC_CTLR_FINISHED_YES)
|
||||
done = TRUE;
|
||||
done = 1;
|
||||
} else
|
||||
done = TRUE;
|
||||
done = 1;
|
||||
}
|
||||
if (!done) {
|
||||
msleep(1000);
|
||||
if (timeout < 1) {
|
||||
done = TRUE;
|
||||
done = 1;
|
||||
err ("%s - Error command complete timeout\n", __FUNCTION__);
|
||||
rc = -EFAULT;
|
||||
} else
|
||||
@ -778,7 +780,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
|
||||
*---------------------------------------------------------------------*/
|
||||
static void get_hpc_access (void)
|
||||
{
|
||||
down (&sem_hpcaccess);
|
||||
mutex_lock(&sem_hpcaccess);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@ -786,7 +788,7 @@ static void get_hpc_access (void)
|
||||
*---------------------------------------------------------------------*/
|
||||
void free_hpc_access (void)
|
||||
{
|
||||
up (&sem_hpcaccess);
|
||||
mutex_unlock(&sem_hpcaccess);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@ -797,7 +799,7 @@ void free_hpc_access (void)
|
||||
void ibmphp_lock_operations (void)
|
||||
{
|
||||
down (&semOperations);
|
||||
to_debug = TRUE;
|
||||
to_debug = 1;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@ -807,7 +809,7 @@ void ibmphp_unlock_operations (void)
|
||||
{
|
||||
debug ("%s - Entry\n", __FUNCTION__);
|
||||
up (&semOperations);
|
||||
to_debug = FALSE;
|
||||
to_debug = 0;
|
||||
debug ("%s - Exit\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
@ -935,40 +937,40 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
|
||||
{
|
||||
u8 status;
|
||||
int rc = 0;
|
||||
u8 disable = FALSE;
|
||||
u8 update = FALSE;
|
||||
u8 disable = 0;
|
||||
u8 update = 0;
|
||||
|
||||
debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot);
|
||||
|
||||
// bit 0 - HPC_SLOT_POWER
|
||||
if ((pslot->status & 0x01) != (poldslot->status & 0x01))
|
||||
update = TRUE;
|
||||
update = 1;
|
||||
|
||||
// bit 1 - HPC_SLOT_CONNECT
|
||||
// ignore
|
||||
|
||||
// bit 2 - HPC_SLOT_ATTN
|
||||
if ((pslot->status & 0x04) != (poldslot->status & 0x04))
|
||||
update = TRUE;
|
||||
update = 1;
|
||||
|
||||
// bit 3 - HPC_SLOT_PRSNT2
|
||||
// bit 4 - HPC_SLOT_PRSNT1
|
||||
if (((pslot->status & 0x08) != (poldslot->status & 0x08))
|
||||
|| ((pslot->status & 0x10) != (poldslot->status & 0x10)))
|
||||
update = TRUE;
|
||||
update = 1;
|
||||
|
||||
// bit 5 - HPC_SLOT_PWRGD
|
||||
if ((pslot->status & 0x20) != (poldslot->status & 0x20))
|
||||
// OFF -> ON: ignore, ON -> OFF: disable slot
|
||||
if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status)))
|
||||
disable = TRUE;
|
||||
disable = 1;
|
||||
|
||||
// bit 6 - HPC_SLOT_BUS_SPEED
|
||||
// ignore
|
||||
|
||||
// bit 7 - HPC_SLOT_LATCH
|
||||
if ((pslot->status & 0x80) != (poldslot->status & 0x80)) {
|
||||
update = TRUE;
|
||||
update = 1;
|
||||
// OPEN -> CLOSE
|
||||
if (pslot->status & 0x80) {
|
||||
if (SLOT_PWRGD (pslot->status)) {
|
||||
@ -977,7 +979,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
|
||||
msleep(1000);
|
||||
rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status);
|
||||
if (SLOT_PWRGD (status))
|
||||
update = TRUE;
|
||||
update = 1;
|
||||
else // overwrite power in pslot to OFF
|
||||
pslot->status &= ~HPC_SLOT_POWER;
|
||||
}
|
||||
@ -985,17 +987,17 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
|
||||
// CLOSE -> OPEN
|
||||
else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD)
|
||||
&& (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) {
|
||||
disable = TRUE;
|
||||
disable = 1;
|
||||
}
|
||||
// else - ignore
|
||||
}
|
||||
// bit 4 - HPC_SLOT_BLINK_ATTN
|
||||
if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08))
|
||||
update = TRUE;
|
||||
update = 1;
|
||||
|
||||
if (disable) {
|
||||
debug ("process_changeinstatus - disable slot\n");
|
||||
pslot->flag = FALSE;
|
||||
pslot->flag = 0;
|
||||
rc = ibmphp_do_disable_slot (pslot);
|
||||
}
|
||||
|
||||
@ -1100,7 +1102,7 @@ void __exit ibmphp_hpc_stop_poll_thread (void)
|
||||
{
|
||||
debug ("%s - Entry\n", __FUNCTION__);
|
||||
|
||||
ibmphp_shutdown = TRUE;
|
||||
ibmphp_shutdown = 1;
|
||||
debug ("before locking operations \n");
|
||||
ibmphp_lock_operations ();
|
||||
debug ("after locking operations \n");
|
||||
@ -1134,7 +1136,7 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v
|
||||
u8 * pstatus)
|
||||
{
|
||||
int rc = 0;
|
||||
u8 done = FALSE;
|
||||
u8 done = 0;
|
||||
|
||||
debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout);
|
||||
|
||||
@ -1142,14 +1144,14 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v
|
||||
*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX);
|
||||
if (*pstatus == HPC_ERROR) {
|
||||
rc = HPC_ERROR;
|
||||
done = TRUE;
|
||||
done = 1;
|
||||
}
|
||||
if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO)
|
||||
done = TRUE;
|
||||
done = 1;
|
||||
if (!done) {
|
||||
msleep(1000);
|
||||
if (timeout < 1) {
|
||||
done = TRUE;
|
||||
done = 1;
|
||||
err ("HPCreadslot - Error ctlr timeout\n");
|
||||
rc = HPC_ERROR;
|
||||
} else
|
||||
|
@ -164,12 +164,11 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
|
||||
cleanup_count = 6;
|
||||
goto error;
|
||||
}
|
||||
newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL);
|
||||
newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL);
|
||||
if (!newfunc) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (newfunc, 0, sizeof (struct pci_func));
|
||||
newfunc->busno = cur_func->busno;
|
||||
newfunc->device = device;
|
||||
cur_func->next = newfunc;
|
||||
@ -200,15 +199,14 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
|
||||
}
|
||||
|
||||
pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
|
||||
flag = FALSE;
|
||||
flag = 0;
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (func->devices[i]) {
|
||||
newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL);
|
||||
newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL);
|
||||
if (!newfunc) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (newfunc, 0, sizeof (struct pci_func));
|
||||
newfunc->busno = sec_number;
|
||||
newfunc->device = (u8) i;
|
||||
for (j = 0; j < 4; j++)
|
||||
@ -228,16 +226,15 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
|
||||
cleanup_count = 2;
|
||||
goto error;
|
||||
}
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL);
|
||||
newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL);
|
||||
if (!newfunc) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (newfunc, 0, sizeof (struct pci_func));
|
||||
newfunc->busno = cur_func->busno;
|
||||
newfunc->device = device;
|
||||
for (j = 0; j < 4; j++)
|
||||
@ -275,16 +272,15 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
|
||||
cur_func->busno, device, function);
|
||||
pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
|
||||
debug ("after configuring bridge..., sec_number = %x\n", sec_number);
|
||||
flag = FALSE;
|
||||
flag = 0;
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (func->devices[i]) {
|
||||
debug ("inside for loop, device is %x\n", i);
|
||||
newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL);
|
||||
newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL);
|
||||
if (!newfunc) {
|
||||
err (" out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (newfunc, 0, sizeof (struct pci_func));
|
||||
newfunc->busno = sec_number;
|
||||
newfunc->device = (u8) i;
|
||||
for (j = 0; j < 4; j++)
|
||||
@ -305,7 +301,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
|
||||
cleanup_count = 2;
|
||||
goto error;
|
||||
}
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -405,13 +401,12 @@ static int configure_device (struct pci_func *func)
|
||||
|
||||
debug ("len[count] in IO %x, count %d\n", len[count], count);
|
||||
|
||||
io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
|
||||
io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
|
||||
|
||||
if (!io[count]) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (io[count], 0, sizeof (struct resource_node));
|
||||
io[count]->type = IO;
|
||||
io[count]->busno = func->busno;
|
||||
io[count]->devfunc = PCI_DEVFN(func->device, func->function);
|
||||
@ -444,29 +439,27 @@ static int configure_device (struct pci_func *func)
|
||||
|
||||
debug ("len[count] in PFMEM %x, count %d\n", len[count], count);
|
||||
|
||||
pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
|
||||
pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
|
||||
if (!pfmem[count]) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (pfmem[count], 0, sizeof (struct resource_node));
|
||||
pfmem[count]->type = PFMEM;
|
||||
pfmem[count]->busno = func->busno;
|
||||
pfmem[count]->devfunc = PCI_DEVFN(func->device,
|
||||
func->function);
|
||||
pfmem[count]->len = len[count];
|
||||
pfmem[count]->fromMem = FALSE;
|
||||
pfmem[count]->fromMem = 0;
|
||||
if (ibmphp_check_resource (pfmem[count], 0) == 0) {
|
||||
ibmphp_add_resource (pfmem[count]);
|
||||
func->pfmem[count] = pfmem[count];
|
||||
} else {
|
||||
mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL);
|
||||
mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL);
|
||||
if (!mem_tmp) {
|
||||
err ("out of system memory\n");
|
||||
kfree (pfmem[count]);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (mem_tmp, 0, sizeof (struct resource_node));
|
||||
mem_tmp->type = MEM;
|
||||
mem_tmp->busno = pfmem[count]->busno;
|
||||
mem_tmp->devfunc = pfmem[count]->devfunc;
|
||||
@ -474,7 +467,7 @@ static int configure_device (struct pci_func *func)
|
||||
debug ("there's no pfmem... going into mem.\n");
|
||||
if (ibmphp_check_resource (mem_tmp, 0) == 0) {
|
||||
ibmphp_add_resource (mem_tmp);
|
||||
pfmem[count]->fromMem = TRUE;
|
||||
pfmem[count]->fromMem = 1;
|
||||
pfmem[count]->rangeno = mem_tmp->rangeno;
|
||||
pfmem[count]->start = mem_tmp->start;
|
||||
pfmem[count]->end = mem_tmp->end;
|
||||
@ -512,12 +505,11 @@ static int configure_device (struct pci_func *func)
|
||||
|
||||
debug ("len[count] in Mem %x, count %d\n", len[count], count);
|
||||
|
||||
mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
|
||||
mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
|
||||
if (!mem[count]) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (mem[count], 0, sizeof (struct resource_node));
|
||||
mem[count]->type = MEM;
|
||||
mem[count]->busno = func->busno;
|
||||
mem[count]->devfunc = PCI_DEVFN(func->device,
|
||||
@ -579,11 +571,11 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
|
||||
u16 pfmem_base;
|
||||
u32 bar[2];
|
||||
u32 len[2];
|
||||
u8 flag_io = FALSE;
|
||||
u8 flag_mem = FALSE;
|
||||
u8 flag_pfmem = FALSE;
|
||||
u8 need_io_upper = FALSE;
|
||||
u8 need_pfmem_upper = FALSE;
|
||||
u8 flag_io = 0;
|
||||
u8 flag_mem = 0;
|
||||
u8 flag_pfmem = 0;
|
||||
u8 need_io_upper = 0;
|
||||
u8 need_pfmem_upper = 0;
|
||||
struct res_needed *amount_needed = NULL;
|
||||
struct resource_node *io = NULL;
|
||||
struct resource_node *bus_io[2] = {NULL, NULL};
|
||||
@ -677,14 +669,13 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
|
||||
|
||||
debug ("len[count] in IO = %x\n", len[count]);
|
||||
|
||||
bus_io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
|
||||
bus_io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
|
||||
|
||||
if (!bus_io[count]) {
|
||||
err ("out of system memory\n");
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
memset (bus_io[count], 0, sizeof (struct resource_node));
|
||||
bus_io[count]->type = IO;
|
||||
bus_io[count]->busno = func->busno;
|
||||
bus_io[count]->devfunc = PCI_DEVFN(func->device,
|
||||
@ -711,37 +702,35 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
|
||||
|
||||
debug ("len[count] in PFMEM = %x\n", len[count]);
|
||||
|
||||
bus_pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
|
||||
bus_pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
|
||||
if (!bus_pfmem[count]) {
|
||||
err ("out of system memory\n");
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
memset (bus_pfmem[count], 0, sizeof (struct resource_node));
|
||||
bus_pfmem[count]->type = PFMEM;
|
||||
bus_pfmem[count]->busno = func->busno;
|
||||
bus_pfmem[count]->devfunc = PCI_DEVFN(func->device,
|
||||
func->function);
|
||||
bus_pfmem[count]->len = len[count];
|
||||
bus_pfmem[count]->fromMem = FALSE;
|
||||
bus_pfmem[count]->fromMem = 0;
|
||||
if (ibmphp_check_resource (bus_pfmem[count], 0) == 0) {
|
||||
ibmphp_add_resource (bus_pfmem[count]);
|
||||
func->pfmem[count] = bus_pfmem[count];
|
||||
} else {
|
||||
mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL);
|
||||
mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL);
|
||||
if (!mem_tmp) {
|
||||
err ("out of system memory\n");
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
memset (mem_tmp, 0, sizeof (struct resource_node));
|
||||
mem_tmp->type = MEM;
|
||||
mem_tmp->busno = bus_pfmem[count]->busno;
|
||||
mem_tmp->devfunc = bus_pfmem[count]->devfunc;
|
||||
mem_tmp->len = bus_pfmem[count]->len;
|
||||
if (ibmphp_check_resource (mem_tmp, 0) == 0) {
|
||||
ibmphp_add_resource (mem_tmp);
|
||||
bus_pfmem[count]->fromMem = TRUE;
|
||||
bus_pfmem[count]->fromMem = 1;
|
||||
bus_pfmem[count]->rangeno = mem_tmp->rangeno;
|
||||
ibmphp_add_pfmem_from_mem (bus_pfmem[count]);
|
||||
func->pfmem[count] = bus_pfmem[count];
|
||||
@ -770,13 +759,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
|
||||
|
||||
debug ("len[count] in Memory is %x\n", len[count]);
|
||||
|
||||
bus_mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
|
||||
bus_mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
|
||||
if (!bus_mem[count]) {
|
||||
err ("out of system memory\n");
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
memset (bus_mem[count], 0, sizeof (struct resource_node));
|
||||
bus_mem[count]->type = MEM;
|
||||
bus_mem[count]->busno = func->busno;
|
||||
bus_mem[count]->devfunc = PCI_DEVFN(func->device,
|
||||
@ -838,17 +826,16 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
|
||||
|
||||
if (!amount_needed->io) {
|
||||
debug ("it doesn't want IO?\n");
|
||||
flag_io = TRUE;
|
||||
flag_io = 1;
|
||||
} else {
|
||||
debug ("it wants %x IO behind the bridge\n", amount_needed->io);
|
||||
io = kmalloc(sizeof(*io), GFP_KERNEL);
|
||||
io = kzalloc(sizeof(*io), GFP_KERNEL);
|
||||
|
||||
if (!io) {
|
||||
err ("out of system memory\n");
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
memset (io, 0, sizeof (struct resource_node));
|
||||
io->type = IO;
|
||||
io->busno = func->busno;
|
||||
io->devfunc = PCI_DEVFN(func->device, func->function);
|
||||
@ -856,71 +843,68 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
|
||||
if (ibmphp_check_resource (io, 1) == 0) {
|
||||
debug ("were we able to add io\n");
|
||||
ibmphp_add_resource (io);
|
||||
flag_io = TRUE;
|
||||
flag_io = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!amount_needed->mem) {
|
||||
debug ("it doesn't want n.e.memory?\n");
|
||||
flag_mem = TRUE;
|
||||
flag_mem = 1;
|
||||
} else {
|
||||
debug ("it wants %x memory behind the bridge\n", amount_needed->mem);
|
||||
mem = kmalloc(sizeof(*mem), GFP_KERNEL);
|
||||
mem = kzalloc(sizeof(*mem), GFP_KERNEL);
|
||||
if (!mem) {
|
||||
err ("out of system memory\n");
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
memset (mem, 0, sizeof (struct resource_node));
|
||||
mem->type = MEM;
|
||||
mem->busno = func->busno;
|
||||
mem->devfunc = PCI_DEVFN(func->device, func->function);
|
||||
mem->len = amount_needed->mem;
|
||||
if (ibmphp_check_resource (mem, 1) == 0) {
|
||||
ibmphp_add_resource (mem);
|
||||
flag_mem = TRUE;
|
||||
flag_mem = 1;
|
||||
debug ("were we able to add mem\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!amount_needed->pfmem) {
|
||||
debug ("it doesn't want n.e.pfmem mem?\n");
|
||||
flag_pfmem = TRUE;
|
||||
flag_pfmem = 1;
|
||||
} else {
|
||||
debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem);
|
||||
pfmem = kmalloc(sizeof(*pfmem), GFP_KERNEL);
|
||||
pfmem = kzalloc(sizeof(*pfmem), GFP_KERNEL);
|
||||
if (!pfmem) {
|
||||
err ("out of system memory\n");
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
memset (pfmem, 0, sizeof (struct resource_node));
|
||||
pfmem->type = PFMEM;
|
||||
pfmem->busno = func->busno;
|
||||
pfmem->devfunc = PCI_DEVFN(func->device, func->function);
|
||||
pfmem->len = amount_needed->pfmem;
|
||||
pfmem->fromMem = FALSE;
|
||||
pfmem->fromMem = 0;
|
||||
if (ibmphp_check_resource (pfmem, 1) == 0) {
|
||||
ibmphp_add_resource (pfmem);
|
||||
flag_pfmem = TRUE;
|
||||
flag_pfmem = 1;
|
||||
} else {
|
||||
mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL);
|
||||
mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL);
|
||||
if (!mem_tmp) {
|
||||
err ("out of system memory\n");
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
memset (mem_tmp, 0, sizeof (struct resource_node));
|
||||
mem_tmp->type = MEM;
|
||||
mem_tmp->busno = pfmem->busno;
|
||||
mem_tmp->devfunc = pfmem->devfunc;
|
||||
mem_tmp->len = pfmem->len;
|
||||
if (ibmphp_check_resource (mem_tmp, 1) == 0) {
|
||||
ibmphp_add_resource (mem_tmp);
|
||||
pfmem->fromMem = TRUE;
|
||||
pfmem->fromMem = 1;
|
||||
pfmem->rangeno = mem_tmp->rangeno;
|
||||
ibmphp_add_pfmem_from_mem (pfmem);
|
||||
flag_pfmem = TRUE;
|
||||
flag_pfmem = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -936,13 +920,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
|
||||
*/
|
||||
bus = ibmphp_find_res_bus (sec_number);
|
||||
if (!bus) {
|
||||
bus = kmalloc(sizeof(*bus), GFP_KERNEL);
|
||||
bus = kzalloc(sizeof(*bus), GFP_KERNEL);
|
||||
if (!bus) {
|
||||
err ("out of system memory\n");
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
memset (bus, 0, sizeof (struct bus_node));
|
||||
bus->busno = sec_number;
|
||||
debug ("b4 adding new bus\n");
|
||||
rc = add_new_bus (bus, io, mem, pfmem, func->busno);
|
||||
@ -967,11 +950,11 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
|
||||
|
||||
if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
|
||||
debug ("io 32\n");
|
||||
need_io_upper = TRUE;
|
||||
need_io_upper = 1;
|
||||
}
|
||||
if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
|
||||
debug ("pfmem 64\n");
|
||||
need_pfmem_upper = TRUE;
|
||||
need_pfmem_upper = 1;
|
||||
}
|
||||
|
||||
if (bus->noIORanges) {
|
||||
@ -1111,10 +1094,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)
|
||||
};
|
||||
struct res_needed *amount;
|
||||
|
||||
amount = kmalloc(sizeof(*amount), GFP_KERNEL);
|
||||
amount = kzalloc(sizeof(*amount), GFP_KERNEL);
|
||||
if (amount == NULL)
|
||||
return NULL;
|
||||
memset (amount, 0, sizeof (struct res_needed));
|
||||
|
||||
ibmphp_pci_bus->number = busno;
|
||||
|
||||
@ -1137,7 +1119,7 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)
|
||||
debug ("hdr_type behind the bridge is %x\n", hdr_type);
|
||||
if (hdr_type & PCI_HEADER_TYPE_BRIDGE) {
|
||||
err ("embedded bridges not supported for hot-plugging.\n");
|
||||
amount->not_correct = TRUE;
|
||||
amount->not_correct = 1;
|
||||
return amount;
|
||||
}
|
||||
|
||||
@ -1145,12 +1127,12 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)
|
||||
if (class == PCI_CLASS_NOT_DEFINED_VGA) {
|
||||
err ("The device %x is VGA compatible and as is not supported for hot plugging. "
|
||||
"Please choose another device.\n", device);
|
||||
amount->not_correct = TRUE;
|
||||
amount->not_correct = 1;
|
||||
return amount;
|
||||
} else if (class == PCI_CLASS_DISPLAY_VGA) {
|
||||
err ("The device %x is not supported for hot plugging. "
|
||||
"Please choose another device.\n", device);
|
||||
amount->not_correct = TRUE;
|
||||
amount->not_correct = 1;
|
||||
return amount;
|
||||
}
|
||||
|
||||
@ -1210,9 +1192,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)
|
||||
} /* end for */
|
||||
|
||||
if (!howmany)
|
||||
amount->not_correct = TRUE;
|
||||
amount->not_correct = 1;
|
||||
else
|
||||
amount->not_correct = FALSE;
|
||||
amount->not_correct = 0;
|
||||
if ((amount->io) && (amount->io < IOBRIDGE))
|
||||
amount->io = IOBRIDGE;
|
||||
if ((amount->mem) && (amount->mem < MEMBRIDGE))
|
||||
@ -1672,12 +1654,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r
|
||||
list_add (&bus->bus_list, &cur_bus->bus_list);
|
||||
}
|
||||
if (io) {
|
||||
io_range = kmalloc(sizeof(*io_range), GFP_KERNEL);
|
||||
io_range = kzalloc(sizeof(*io_range), GFP_KERNEL);
|
||||
if (!io_range) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (io_range, 0, sizeof (struct range_node));
|
||||
io_range->start = io->start;
|
||||
io_range->end = io->end;
|
||||
io_range->rangeno = 1;
|
||||
@ -1685,12 +1666,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r
|
||||
bus->rangeIO = io_range;
|
||||
}
|
||||
if (mem) {
|
||||
mem_range = kmalloc(sizeof(*mem_range), GFP_KERNEL);
|
||||
mem_range = kzalloc(sizeof(*mem_range), GFP_KERNEL);
|
||||
if (!mem_range) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (mem_range, 0, sizeof (struct range_node));
|
||||
mem_range->start = mem->start;
|
||||
mem_range->end = mem->end;
|
||||
mem_range->rangeno = 1;
|
||||
@ -1698,12 +1678,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r
|
||||
bus->rangeMem = mem_range;
|
||||
}
|
||||
if (pfmem) {
|
||||
pfmem_range = kmalloc(sizeof(*pfmem_range), GFP_KERNEL);
|
||||
pfmem_range = kzalloc(sizeof(*pfmem_range), GFP_KERNEL);
|
||||
if (!pfmem_range) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (pfmem_range, 0, sizeof (struct range_node));
|
||||
pfmem_range->start = pfmem->start;
|
||||
pfmem_range->end = pfmem->end;
|
||||
pfmem_range->rangeno = 1;
|
||||
|
@ -55,13 +55,12 @@ static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL);
|
||||
newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL);
|
||||
if (!newbus) {
|
||||
err ("out of system memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset (newbus, 0, sizeof (struct bus_node));
|
||||
if (flag)
|
||||
newbus->busno = busno;
|
||||
else
|
||||
@ -79,12 +78,11 @@ static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * cur
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
|
||||
rs = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
|
||||
if (!rs) {
|
||||
err ("out of system memory\n");
|
||||
return NULL;
|
||||
}
|
||||
memset (rs, 0, sizeof (struct resource_node));
|
||||
rs->busno = curr->bus_num;
|
||||
rs->devfunc = curr->dev_fun;
|
||||
rs->start = curr->start_addr;
|
||||
@ -100,12 +98,11 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node
|
||||
u8 num_ranges = 0;
|
||||
|
||||
if (first_bus) {
|
||||
newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL);
|
||||
newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL);
|
||||
if (!newbus) {
|
||||
err ("out of system memory.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (newbus, 0, sizeof (struct bus_node));
|
||||
newbus->busno = curr->bus_num;
|
||||
} else {
|
||||
newbus = *new_bus;
|
||||
@ -122,14 +119,13 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node
|
||||
}
|
||||
}
|
||||
|
||||
newrange = kmalloc (sizeof (struct range_node), GFP_KERNEL);
|
||||
newrange = kzalloc(sizeof(struct range_node), GFP_KERNEL);
|
||||
if (!newrange) {
|
||||
if (first_bus)
|
||||
kfree (newbus);
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (newrange, 0, sizeof (struct range_node));
|
||||
newrange->start = curr->start_addr;
|
||||
newrange->end = curr->end_addr;
|
||||
|
||||
@ -329,7 +325,7 @@ int __init ibmphp_rsrc_init (void)
|
||||
if (!new_pfmem)
|
||||
return -ENOMEM;
|
||||
new_pfmem->type = PFMEM;
|
||||
new_pfmem->fromMem = FALSE;
|
||||
new_pfmem->fromMem = 0;
|
||||
if (ibmphp_add_resource (new_pfmem) < 0) {
|
||||
newbus = alloc_error_bus (curr, 0, 0);
|
||||
if (!newbus)
|
||||
@ -466,7 +462,7 @@ static int add_range (int type, struct range_node *range, struct bus_node *bus_c
|
||||
static void update_resources (struct bus_node *bus_cur, int type, int rangeno)
|
||||
{
|
||||
struct resource_node *res = NULL;
|
||||
u8 eol = FALSE; /* end of list indicator */
|
||||
u8 eol = 0; /* end of list indicator */
|
||||
|
||||
switch (type) {
|
||||
case MEM:
|
||||
@ -492,7 +488,7 @@ static void update_resources (struct bus_node *bus_cur, int type, int rangeno)
|
||||
else if (res->nextRange)
|
||||
res = res->nextRange;
|
||||
else {
|
||||
eol = TRUE;
|
||||
eol = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -983,7 +979,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
|
||||
int noranges = 0;
|
||||
u32 tmp_start; /* this is to make sure start address is divisible by the length needed */
|
||||
u32 tmp_divide;
|
||||
u8 flag = FALSE;
|
||||
u8 flag = 0;
|
||||
|
||||
if (!res)
|
||||
return -EINVAL;
|
||||
@ -1050,17 +1046,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
|
||||
|
||||
if ((range->start % tmp_divide) == 0) {
|
||||
/* just perfect, starting address is divisible by length */
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
len_cur = len_tmp;
|
||||
start_cur = range->start;
|
||||
} else {
|
||||
/* Needs adjusting */
|
||||
tmp_start = range->start;
|
||||
flag = FALSE;
|
||||
flag = 0;
|
||||
|
||||
while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
|
||||
if ((tmp_start % tmp_divide) == 0) {
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
len_cur = len_tmp;
|
||||
start_cur = tmp_start;
|
||||
break;
|
||||
@ -1089,17 +1085,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
|
||||
|
||||
if (((res_cur->end + 1) % tmp_divide) == 0) {
|
||||
/* just perfect, starting address is divisible by length */
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
len_cur = len_tmp;
|
||||
start_cur = res_cur->end + 1;
|
||||
} else {
|
||||
/* Needs adjusting */
|
||||
tmp_start = res_cur->end + 1;
|
||||
flag = FALSE;
|
||||
flag = 0;
|
||||
|
||||
while ((len_tmp = range->end - tmp_start) >= res->len) {
|
||||
if ((tmp_start % tmp_divide) == 0) {
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
len_cur = len_tmp;
|
||||
start_cur = tmp_start;
|
||||
break;
|
||||
@ -1127,17 +1123,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
|
||||
if ((len_tmp < len_cur) || (len_cur == 0)) {
|
||||
if ((range->start % tmp_divide) == 0) {
|
||||
/* just perfect, starting address is divisible by length */
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
len_cur = len_tmp;
|
||||
start_cur = range->start;
|
||||
} else {
|
||||
/* Needs adjusting */
|
||||
tmp_start = range->start;
|
||||
flag = FALSE;
|
||||
flag = 0;
|
||||
|
||||
while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
|
||||
if ((tmp_start % tmp_divide) == 0) {
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
len_cur = len_tmp;
|
||||
start_cur = tmp_start;
|
||||
break;
|
||||
@ -1162,17 +1158,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
|
||||
if ((len_tmp < len_cur) || (len_cur == 0)) {
|
||||
if (((res_prev->end + 1) % tmp_divide) == 0) {
|
||||
/* just perfect, starting address's divisible by length */
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
len_cur = len_tmp;
|
||||
start_cur = res_prev->end + 1;
|
||||
} else {
|
||||
/* Needs adjusting */
|
||||
tmp_start = res_prev->end + 1;
|
||||
flag = FALSE;
|
||||
flag = 0;
|
||||
|
||||
while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
|
||||
if ((tmp_start % tmp_divide) == 0) {
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
len_cur = len_tmp;
|
||||
start_cur = tmp_start;
|
||||
break;
|
||||
@ -1221,17 +1217,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
|
||||
if ((len_tmp < len_cur) || (len_cur == 0)) {
|
||||
if ((range->start % tmp_divide) == 0) {
|
||||
/* just perfect, starting address's divisible by length */
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
len_cur = len_tmp;
|
||||
start_cur = range->start;
|
||||
} else {
|
||||
/* Needs adjusting */
|
||||
tmp_start = range->start;
|
||||
flag = FALSE;
|
||||
flag = 0;
|
||||
|
||||
while ((len_tmp = range->end - tmp_start) >= res->len) {
|
||||
if ((tmp_start % tmp_divide) == 0) {
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
len_cur = len_tmp;
|
||||
start_cur = tmp_start;
|
||||
break;
|
||||
@ -1285,17 +1281,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
|
||||
if ((len_tmp < len_cur) || (len_cur == 0)) {
|
||||
if ((range->start % tmp_divide) == 0) {
|
||||
/* just perfect, starting address's divisible by length */
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
len_cur = len_tmp;
|
||||
start_cur = range->start;
|
||||
} else {
|
||||
/* Needs adjusting */
|
||||
tmp_start = range->start;
|
||||
flag = FALSE;
|
||||
flag = 0;
|
||||
|
||||
while ((len_tmp = range->end - tmp_start) >= res->len) {
|
||||
if ((tmp_start % tmp_divide) == 0) {
|
||||
flag = TRUE;
|
||||
flag = 1;
|
||||
len_cur = len_tmp;
|
||||
start_cur = tmp_start;
|
||||
break;
|
||||
@ -1688,7 +1684,7 @@ static int __init once_over (void)
|
||||
bus_cur = list_entry (tmp, struct bus_node, bus_list);
|
||||
if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) {
|
||||
for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) {
|
||||
pfmem_cur->fromMem = TRUE;
|
||||
pfmem_cur->fromMem = 1;
|
||||
if (pfmem_prev)
|
||||
pfmem_prev->next = pfmem_cur->next;
|
||||
else
|
||||
@ -1705,12 +1701,11 @@ static int __init once_over (void)
|
||||
|
||||
bus_cur->firstPFMemFromMem = pfmem_cur;
|
||||
|
||||
mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
|
||||
mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
|
||||
if (!mem) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (mem, 0, sizeof (struct resource_node));
|
||||
mem->type = MEM;
|
||||
mem->busno = pfmem_cur->busno;
|
||||
mem->devfunc = pfmem_cur->devfunc;
|
||||
@ -1994,12 +1989,11 @@ static int __init update_bridge_ranges (struct bus_node **bus)
|
||||
end_address |= (upper_io_end << 16);
|
||||
|
||||
if ((start_address) && (start_address <= end_address)) {
|
||||
range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
|
||||
range = kzalloc(sizeof(struct range_node), GFP_KERNEL);
|
||||
if (!range) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (range, 0, sizeof (struct range_node));
|
||||
range->start = start_address;
|
||||
range->end = end_address + 0xfff;
|
||||
|
||||
@ -2020,13 +2014,12 @@ static int __init update_bridge_ranges (struct bus_node **bus)
|
||||
fix_resources (bus_sec);
|
||||
|
||||
if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) {
|
||||
io = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
|
||||
io = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
|
||||
if (!io) {
|
||||
kfree (range);
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (io, 0, sizeof (struct resource_node));
|
||||
io->type = IO;
|
||||
io->busno = bus_cur->busno;
|
||||
io->devfunc = ((device << 3) | (function & 0x7));
|
||||
@ -2045,12 +2038,11 @@ static int __init update_bridge_ranges (struct bus_node **bus)
|
||||
|
||||
if ((start_address) && (start_address <= end_address)) {
|
||||
|
||||
range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
|
||||
range = kzalloc(sizeof(struct range_node), GFP_KERNEL);
|
||||
if (!range) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (range, 0, sizeof (struct range_node));
|
||||
range->start = start_address;
|
||||
range->end = end_address + 0xfffff;
|
||||
|
||||
@ -2072,13 +2064,12 @@ static int __init update_bridge_ranges (struct bus_node **bus)
|
||||
fix_resources (bus_sec);
|
||||
|
||||
if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) {
|
||||
mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
|
||||
mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
|
||||
if (!mem) {
|
||||
kfree (range);
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (mem, 0, sizeof (struct resource_node));
|
||||
mem->type = MEM;
|
||||
mem->busno = bus_cur->busno;
|
||||
mem->devfunc = ((device << 3) | (function & 0x7));
|
||||
@ -2101,12 +2092,11 @@ static int __init update_bridge_ranges (struct bus_node **bus)
|
||||
|
||||
if ((start_address) && (start_address <= end_address)) {
|
||||
|
||||
range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
|
||||
range = kzalloc(sizeof(struct range_node), GFP_KERNEL);
|
||||
if (!range) {
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (range, 0, sizeof (struct range_node));
|
||||
range->start = start_address;
|
||||
range->end = end_address + 0xfffff;
|
||||
|
||||
@ -2127,20 +2117,19 @@ static int __init update_bridge_ranges (struct bus_node **bus)
|
||||
|
||||
fix_resources (bus_sec);
|
||||
if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) {
|
||||
pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
|
||||
pfmem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
|
||||
if (!pfmem) {
|
||||
kfree (range);
|
||||
err ("out of system memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (pfmem, 0, sizeof (struct resource_node));
|
||||
pfmem->type = PFMEM;
|
||||
pfmem->busno = bus_cur->busno;
|
||||
pfmem->devfunc = ((device << 3) | (function & 0x7));
|
||||
pfmem->start = start_address;
|
||||
pfmem->end = end_address + 0xfffff;
|
||||
pfmem->len = pfmem->end - pfmem->start + 1;
|
||||
pfmem->fromMem = FALSE;
|
||||
pfmem->fromMem = 0;
|
||||
|
||||
ibmphp_add_resource (pfmem);
|
||||
}
|
||||
|
@ -176,5 +176,21 @@ extern int pci_hp_change_slot_info (struct hotplug_slot *slot,
|
||||
struct hotplug_slot_info *info);
|
||||
extern struct subsystem pci_hotplug_slots_subsys;
|
||||
|
||||
struct hotplug_params {
|
||||
u8 cache_line_size;
|
||||
u8 latency_timer;
|
||||
u8 enable_serr;
|
||||
u8 enable_perr;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/actypes.h>
|
||||
extern acpi_status acpi_run_oshp(acpi_handle handle);
|
||||
extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp);
|
||||
int acpi_root_bridge(acpi_handle handle);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h> /* signal_pending() */
|
||||
#include <linux/pcieport_if.h>
|
||||
#include <linux/mutex.h>
|
||||
#include "pci_hotplug.h"
|
||||
|
||||
#define MY_NAME "pciehp"
|
||||
@ -49,12 +50,6 @@ extern int pciehp_force;
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
|
||||
|
||||
struct hotplug_params {
|
||||
u8 cache_line_size;
|
||||
u8 latency_timer;
|
||||
u8 enable_serr;
|
||||
u8 enable_perr;
|
||||
};
|
||||
|
||||
struct slot {
|
||||
struct slot *next;
|
||||
@ -96,7 +91,7 @@ struct php_ctlr_state_s {
|
||||
#define MAX_EVENTS 10
|
||||
struct controller {
|
||||
struct controller *next;
|
||||
struct semaphore crit_sect; /* critical section semaphore */
|
||||
struct mutex crit_sect; /* critical section mutex */
|
||||
struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
|
||||
int num_slots; /* Number of slots on ctlr */
|
||||
int slot_num_inc; /* 1 or -1 */
|
||||
@ -191,9 +186,6 @@ extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id);
|
||||
/* pci functions */
|
||||
extern int pciehp_configure_device (struct slot *p_slot);
|
||||
extern int pciehp_unconfigure_device (struct slot *p_slot);
|
||||
extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev);
|
||||
extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp);
|
||||
|
||||
|
||||
|
||||
@ -285,4 +277,19 @@ struct hpc_ops {
|
||||
int (*check_lnk_status) (struct controller *ctrl);
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
#define pciehp_get_hp_hw_control_from_firmware(dev) \
|
||||
pciehp_acpi_get_hp_hw_control_from_firmware(dev)
|
||||
static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp)
|
||||
{
|
||||
if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp)))
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define pciehp_get_hp_hw_control_from_firmware(dev) 0
|
||||
#define pciehp_get_hp_params_from_firmware(dev, hpp) (-ENODEV)
|
||||
#endif /* CONFIG_ACPI */
|
||||
#endif /* _PCIEHP_H */
|
||||
|
@ -117,27 +117,23 @@ static int init_slots(struct controller *ctrl)
|
||||
slot_number = ctrl->first_slot;
|
||||
|
||||
while (number_of_slots) {
|
||||
slot = kmalloc(sizeof(*slot), GFP_KERNEL);
|
||||
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
goto error;
|
||||
|
||||
memset(slot, 0, sizeof(struct slot));
|
||||
slot->hotplug_slot =
|
||||
kmalloc(sizeof(*(slot->hotplug_slot)),
|
||||
kzalloc(sizeof(*(slot->hotplug_slot)),
|
||||
GFP_KERNEL);
|
||||
if (!slot->hotplug_slot)
|
||||
goto error_slot;
|
||||
hotplug_slot = slot->hotplug_slot;
|
||||
memset(hotplug_slot, 0, sizeof(struct hotplug_slot));
|
||||
|
||||
hotplug_slot->info =
|
||||
kmalloc(sizeof(*(hotplug_slot->info)),
|
||||
kzalloc(sizeof(*(hotplug_slot->info)),
|
||||
GFP_KERNEL);
|
||||
if (!hotplug_slot->info)
|
||||
goto error_hpslot;
|
||||
hotplug_slot_info = hotplug_slot->info;
|
||||
memset(hotplug_slot_info, 0,
|
||||
sizeof(struct hotplug_slot_info));
|
||||
hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
|
||||
if (!hotplug_slot->name)
|
||||
goto error_info;
|
||||
@ -373,12 +369,11 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
||||
u8 value;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL);
|
||||
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
|
||||
if (!ctrl) {
|
||||
err("%s : out of memory\n", __FUNCTION__);
|
||||
goto err_out_none;
|
||||
}
|
||||
memset(ctrl, 0, sizeof(struct controller));
|
||||
|
||||
pdev = dev->port;
|
||||
ctrl->pci_dev = pdev;
|
||||
@ -439,7 +434,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
||||
}
|
||||
|
||||
/* Wait for exclusive access to hardware */
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
|
||||
|
||||
@ -447,7 +442,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
||||
rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
|
||||
if (rc) {
|
||||
/* Done with exclusive hardware access */
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
goto err_out_free_ctrl_slot;
|
||||
} else
|
||||
/* Wait for the command to complete */
|
||||
@ -455,7 +450,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
||||
}
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -229,13 +229,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
|
||||
static void set_slot_off(struct controller *ctrl, struct slot * pslot)
|
||||
{
|
||||
/* Wait for exclusive access to hardware */
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
|
||||
if (POWER_CTRL(ctrl->ctrlcap)) {
|
||||
if (pslot->hpc_ops->power_off_slot(pslot)) {
|
||||
err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
return;
|
||||
}
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
@ -249,14 +249,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
|
||||
if (ATTN_LED(ctrl->ctrlcap)) {
|
||||
if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
|
||||
err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
return;
|
||||
}
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -279,13 +279,13 @@ static int board_added(struct slot *p_slot)
|
||||
ctrl->slot_device_offset, hp_slot);
|
||||
|
||||
/* Wait for exclusive access to hardware */
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
if (POWER_CTRL(ctrl->ctrlcap)) {
|
||||
/* Power on slot */
|
||||
rc = p_slot->hpc_ops->power_on_slot(p_slot);
|
||||
if (rc) {
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -301,7 +301,7 @@ static int board_added(struct slot *p_slot)
|
||||
}
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
/* Wait for ~1 second */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
@ -335,7 +335,7 @@ static int board_added(struct slot *p_slot)
|
||||
pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
|
||||
if (PWR_LED(ctrl->ctrlcap)) {
|
||||
/* Wait for exclusive access to hardware */
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
p_slot->hpc_ops->green_led_on(p_slot);
|
||||
|
||||
@ -343,7 +343,7 @@ static int board_added(struct slot *p_slot)
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@ -375,14 +375,14 @@ static int remove_board(struct slot *p_slot)
|
||||
dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
|
||||
|
||||
/* Wait for exclusive access to hardware */
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
if (POWER_CTRL(ctrl->ctrlcap)) {
|
||||
/* power off slot */
|
||||
rc = p_slot->hpc_ops->power_off_slot(p_slot);
|
||||
if (rc) {
|
||||
err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
return rc;
|
||||
}
|
||||
/* Wait for the command to complete */
|
||||
@ -398,7 +398,7 @@ static int remove_board(struct slot *p_slot)
|
||||
}
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -445,7 +445,7 @@ static void pciehp_pushbutton_thread(unsigned long slot)
|
||||
|
||||
if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
|
||||
/* Wait for exclusive access to hardware */
|
||||
down(&p_slot->ctrl->crit_sect);
|
||||
mutex_lock(&p_slot->ctrl->crit_sect);
|
||||
|
||||
p_slot->hpc_ops->green_led_off(p_slot);
|
||||
|
||||
@ -453,7 +453,7 @@ static void pciehp_pushbutton_thread(unsigned long slot)
|
||||
wait_for_ctrl_irq (p_slot->ctrl);
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
up(&p_slot->ctrl->crit_sect);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
}
|
||||
p_slot->state = STATIC_STATE;
|
||||
}
|
||||
@ -495,7 +495,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot)
|
||||
|
||||
if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
|
||||
/* Wait for exclusive access to hardware */
|
||||
down(&p_slot->ctrl->crit_sect);
|
||||
mutex_lock(&p_slot->ctrl->crit_sect);
|
||||
|
||||
p_slot->hpc_ops->green_led_off(p_slot);
|
||||
|
||||
@ -503,7 +503,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot)
|
||||
wait_for_ctrl_irq (p_slot->ctrl);
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
up(&p_slot->ctrl->crit_sect);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
}
|
||||
p_slot->state = STATIC_STATE;
|
||||
}
|
||||
@ -616,7 +616,7 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
switch (p_slot->state) {
|
||||
case BLINKINGOFF_STATE:
|
||||
/* Wait for exclusive access to hardware */
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
if (PWR_LED(ctrl->ctrlcap)) {
|
||||
p_slot->hpc_ops->green_led_on(p_slot);
|
||||
@ -630,11 +630,11 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
/* Done with exclusive hardware access */
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
break;
|
||||
case BLINKINGON_STATE:
|
||||
/* Wait for exclusive access to hardware */
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
if (PWR_LED(ctrl->ctrlcap)) {
|
||||
p_slot->hpc_ops->green_led_off(p_slot);
|
||||
@ -647,7 +647,7 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
/* Done with exclusive hardware access */
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -676,7 +676,7 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
}
|
||||
|
||||
/* Wait for exclusive access to hardware */
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
/* blink green LED and turn off amber */
|
||||
if (PWR_LED(ctrl->ctrlcap)) {
|
||||
@ -693,7 +693,7 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
}
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
init_timer(&p_slot->task_event);
|
||||
p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */
|
||||
@ -708,7 +708,7 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
if (POWER_CTRL(ctrl->ctrlcap)) {
|
||||
dbg("power fault\n");
|
||||
/* Wait for exclusive access to hardware */
|
||||
down(&ctrl->crit_sect);
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
if (ATTN_LED(ctrl->ctrlcap)) {
|
||||
p_slot->hpc_ops->set_attention_status(p_slot, 1);
|
||||
@ -721,7 +721,7 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
}
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
up(&ctrl->crit_sect);
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
}
|
||||
}
|
||||
/***********SURPRISE REMOVAL********************/
|
||||
@ -756,19 +756,19 @@ int pciehp_enable_slot(struct slot *p_slot)
|
||||
int rc;
|
||||
|
||||
/* Check to see if (latch closed, card present, power off) */
|
||||
down(&p_slot->ctrl->crit_sect);
|
||||
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(%x)\n", __FUNCTION__, p_slot->number);
|
||||
up(&p_slot->ctrl->crit_sect);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return 1;
|
||||
}
|
||||
if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
|
||||
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
||||
if (rc || getstatus) {
|
||||
info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
|
||||
up(&p_slot->ctrl->crit_sect);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -777,11 +777,11 @@ int pciehp_enable_slot(struct slot *p_slot)
|
||||
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||
if (rc || getstatus) {
|
||||
info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
|
||||
up(&p_slot->ctrl->crit_sect);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
up(&p_slot->ctrl->crit_sect);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
|
||||
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
||||
|
||||
@ -806,13 +806,13 @@ int pciehp_disable_slot(struct slot *p_slot)
|
||||
return 1;
|
||||
|
||||
/* Check to see if (latch closed, card present, power on) */
|
||||
down(&p_slot->ctrl->crit_sect);
|
||||
mutex_lock(&p_slot->ctrl->crit_sect);
|
||||
|
||||
if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {
|
||||
ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
|
||||
if (ret || !getstatus) {
|
||||
info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
|
||||
up(&p_slot->ctrl->crit_sect);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -821,7 +821,7 @@ int pciehp_disable_slot(struct slot *p_slot)
|
||||
ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
||||
if (ret || getstatus) {
|
||||
info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
|
||||
up(&p_slot->ctrl->crit_sect);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -830,12 +830,12 @@ int pciehp_disable_slot(struct slot *p_slot)
|
||||
ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||
if (ret || !getstatus) {
|
||||
info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
|
||||
up(&p_slot->ctrl->crit_sect);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
up(&p_slot->ctrl->crit_sect);
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
|
||||
ret = remove_board(p_slot);
|
||||
update_slot_info(p_slot);
|
||||
|
@ -38,7 +38,10 @@
|
||||
|
||||
#include "../pci.h"
|
||||
#include "pciehp.h"
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/actypes.h>
|
||||
#include <linux/pci-acpi.h>
|
||||
#ifdef DEBUG
|
||||
#define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */
|
||||
#define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */
|
||||
@ -1236,6 +1239,76 @@ static struct hpc_ops pciehp_hpc_ops = {
|
||||
.check_lnk_status = hpc_check_lnk_status,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
|
||||
struct pci_dev *pdev = dev;
|
||||
struct pci_bus *parent;
|
||||
struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
|
||||
/*
|
||||
* Per PCI firmware specification, we should run the ACPI _OSC
|
||||
* method to get control of hotplug hardware before using it.
|
||||
* If an _OSC is missing, we look for an OSHP to do the same thing.
|
||||
* To handle different BIOS behavior, we look for _OSC and OSHP
|
||||
* within the scope of the hotplug controller and its parents, upto
|
||||
* the host bridge under which this controller exists.
|
||||
*/
|
||||
while (!handle) {
|
||||
/*
|
||||
* This hotplug controller was not listed in the ACPI name
|
||||
* space at all. Try to get acpi handle of parent pci bus.
|
||||
*/
|
||||
if (!pdev || !pdev->bus->parent)
|
||||
break;
|
||||
parent = pdev->bus->parent;
|
||||
dbg("Could not find %s in acpi namespace, trying parent\n",
|
||||
pci_name(pdev));
|
||||
if (!parent->self)
|
||||
/* Parent must be a host bridge */
|
||||
handle = acpi_get_pci_rootbridge_handle(
|
||||
pci_domain_nr(parent),
|
||||
parent->number);
|
||||
else
|
||||
handle = DEVICE_ACPI_HANDLE(
|
||||
&(parent->self->dev));
|
||||
pdev = parent->self;
|
||||
}
|
||||
|
||||
while (handle) {
|
||||
acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
|
||||
dbg("Trying to get hotplug control for %s \n",
|
||||
(char *)string.pointer);
|
||||
status = pci_osc_control_set(handle,
|
||||
OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
|
||||
if (status == AE_NOT_FOUND)
|
||||
status = acpi_run_oshp(handle);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
dbg("Gained control for hotplug HW for pci %s (%s)\n",
|
||||
pci_name(dev), (char *)string.pointer);
|
||||
acpi_os_free(string.pointer);
|
||||
return 0;
|
||||
}
|
||||
if (acpi_root_bridge(handle))
|
||||
break;
|
||||
chandle = handle;
|
||||
status = acpi_get_parent(chandle, &handle);
|
||||
if (ACPI_FAILURE(status))
|
||||
break;
|
||||
}
|
||||
|
||||
err("Cannot get control of hotplug hardware for pci %s\n",
|
||||
pci_name(dev));
|
||||
|
||||
acpi_os_free(string.pointer);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
{
|
||||
struct php_ctlr_state_s *php_ctlr, *p;
|
||||
@ -1334,7 +1407,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
if (pci_enable_device(pdev))
|
||||
goto abort_free_ctlr;
|
||||
|
||||
init_MUTEX(&ctrl->crit_sect);
|
||||
mutex_init(&ctrl->crit_sect);
|
||||
/* setup wait queue */
|
||||
init_waitqueue_head(&ctrl->queue);
|
||||
|
||||
|
@ -1,257 +0,0 @@
|
||||
/*
|
||||
* PCIEHPRM ACPI: PHP Resource Manager for ACPI platform
|
||||
*
|
||||
* Copyright (C) 2003-2004 Intel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* Send feedback to <kristen.c.accardi@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pci-acpi.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/actypes.h>
|
||||
#include "pciehp.h"
|
||||
|
||||
#define METHOD_NAME__SUN "_SUN"
|
||||
#define METHOD_NAME__HPP "_HPP"
|
||||
#define METHOD_NAME_OSHP "OSHP"
|
||||
|
||||
static u8 * acpi_path_name( acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
static u8 path_name[ACPI_PATHNAME_MAX];
|
||||
struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
|
||||
|
||||
memset(path_name, 0, sizeof (path_name));
|
||||
status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
return NULL;
|
||||
else
|
||||
return path_name;
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
|
||||
{
|
||||
acpi_status status;
|
||||
u8 nui[4];
|
||||
struct acpi_buffer ret_buf = { 0, NULL};
|
||||
union acpi_object *ext_obj, *package;
|
||||
u8 *path_name = acpi_path_name(handle);
|
||||
int i, len = 0;
|
||||
|
||||
/* get _hpp */
|
||||
status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
|
||||
switch (status) {
|
||||
case AE_BUFFER_OVERFLOW:
|
||||
ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
|
||||
if (!ret_buf.pointer) {
|
||||
err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
|
||||
path_name);
|
||||
return AE_NO_MEMORY;
|
||||
}
|
||||
status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
|
||||
NULL, &ret_buf);
|
||||
if (ACPI_SUCCESS(status))
|
||||
break;
|
||||
default:
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
|
||||
path_name, status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
ext_obj = (union acpi_object *) ret_buf.pointer;
|
||||
if (ext_obj->type != ACPI_TYPE_PACKAGE) {
|
||||
err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
|
||||
path_name);
|
||||
status = AE_ERROR;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
len = ext_obj->package.count;
|
||||
package = (union acpi_object *) ret_buf.pointer;
|
||||
for ( i = 0; (i < len) || (i < 4); i++) {
|
||||
ext_obj = (union acpi_object *) &package->package.elements[i];
|
||||
switch (ext_obj->type) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
nui[i] = (u8)ext_obj->integer.value;
|
||||
break;
|
||||
default:
|
||||
err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
|
||||
path_name);
|
||||
status = AE_ERROR;
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
|
||||
hpp->cache_line_size = nui[0];
|
||||
hpp->latency_timer = nui[1];
|
||||
hpp->enable_serr = nui[2];
|
||||
hpp->enable_perr = nui[3];
|
||||
|
||||
dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
|
||||
dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
|
||||
dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
|
||||
dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
|
||||
|
||||
free_and_return:
|
||||
kfree(ret_buf.pointer);
|
||||
return status;
|
||||
}
|
||||
|
||||
static acpi_status acpi_run_oshp(acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
u8 *path_name = acpi_path_name(handle);
|
||||
|
||||
/* run OSHP */
|
||||
status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
|
||||
status);
|
||||
} else {
|
||||
dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static int is_root_bridge(acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_device_info *info;
|
||||
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
int i;
|
||||
|
||||
status = acpi_get_object_info(handle, &buffer);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
info = buffer.pointer;
|
||||
if ((info->valid & ACPI_VALID_HID) &&
|
||||
!strcmp(PCI_ROOT_HID_STRING,
|
||||
info->hardware_id.value)) {
|
||||
acpi_os_free(buffer.pointer);
|
||||
return 1;
|
||||
}
|
||||
if (info->valid & ACPI_VALID_CID) {
|
||||
for (i=0; i < info->compatibility_id.count; i++) {
|
||||
if (!strcmp(PCI_ROOT_HID_STRING,
|
||||
info->compatibility_id.id[i].value)) {
|
||||
acpi_os_free(buffer.pointer);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
|
||||
struct pci_dev *pdev = dev;
|
||||
struct pci_bus *parent;
|
||||
u8 *path_name;
|
||||
|
||||
/*
|
||||
* Per PCI firmware specification, we should run the ACPI _OSC
|
||||
* method to get control of hotplug hardware before using it.
|
||||
* If an _OSC is missing, we look for an OSHP to do the same thing.
|
||||
* To handle different BIOS behavior, we look for _OSC and OSHP
|
||||
* within the scope of the hotplug controller and its parents, upto
|
||||
* the host bridge under which this controller exists.
|
||||
*/
|
||||
while (!handle) {
|
||||
/*
|
||||
* This hotplug controller was not listed in the ACPI name
|
||||
* space at all. Try to get acpi handle of parent pci bus.
|
||||
*/
|
||||
if (!pdev || !pdev->bus->parent)
|
||||
break;
|
||||
parent = pdev->bus->parent;
|
||||
dbg("Could not find %s in acpi namespace, trying parent\n",
|
||||
pci_name(pdev));
|
||||
if (!parent->self)
|
||||
/* Parent must be a host bridge */
|
||||
handle = acpi_get_pci_rootbridge_handle(
|
||||
pci_domain_nr(parent),
|
||||
parent->number);
|
||||
else
|
||||
handle = DEVICE_ACPI_HANDLE(
|
||||
&(parent->self->dev));
|
||||
pdev = parent->self;
|
||||
}
|
||||
|
||||
while (handle) {
|
||||
path_name = acpi_path_name(handle);
|
||||
dbg("Trying to get hotplug control for %s \n", path_name);
|
||||
status = pci_osc_control_set(handle,
|
||||
OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
|
||||
if (status == AE_NOT_FOUND)
|
||||
status = acpi_run_oshp(handle);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
dbg("Gained control for hotplug HW for pci %s (%s)\n",
|
||||
pci_name(dev), path_name);
|
||||
return 0;
|
||||
}
|
||||
if (is_root_bridge(handle))
|
||||
break;
|
||||
chandle = handle;
|
||||
status = acpi_get_parent(chandle, &handle);
|
||||
if (ACPI_FAILURE(status))
|
||||
break;
|
||||
}
|
||||
|
||||
err("Cannot get control of hotplug hardware for pci %s\n",
|
||||
pci_name(dev));
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp)
|
||||
{
|
||||
acpi_status status = AE_NOT_FOUND;
|
||||
struct pci_dev *pdev = dev;
|
||||
|
||||
/*
|
||||
* _HPP settings apply to all child buses, until another _HPP is
|
||||
* encountered. If we don't find an _HPP for the input pci dev,
|
||||
* look for it in the parent device scope since that would apply to
|
||||
* this pci dev. If we don't find any _HPP, use hardcoded defaults
|
||||
*/
|
||||
while (pdev && (ACPI_FAILURE(status))) {
|
||||
acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
|
||||
if (!handle)
|
||||
break;
|
||||
status = acpi_run_hpp(handle, hpp);
|
||||
if (!(pdev->bus->parent))
|
||||
break;
|
||||
/* Check if a parent object supports _HPP */
|
||||
pdev = pdev->bus->parent->self;
|
||||
}
|
||||
}
|
||||
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
|
||||
*
|
||||
* Copyright (C) 1995,2001 Compaq Computer Corporation
|
||||
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
|
||||
* Copyright (C) 2001 IBM Corp.
|
||||
* Copyright (C) 2003-2004 Intel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include "pciehp.h"
|
||||
|
||||
void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -37,10 +37,12 @@
|
||||
#include <linux/init.h>
|
||||
#include "pci_hotplug.h"
|
||||
|
||||
#define SLOT_NAME_SIZE 10
|
||||
struct slot {
|
||||
u8 number;
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct list_head slot_list;
|
||||
char name[SLOT_NAME_SIZE];
|
||||
};
|
||||
|
||||
static LIST_HEAD(slot_list);
|
||||
@ -233,12 +235,10 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
kfree(slot->hotplug_slot->info);
|
||||
kfree(slot->hotplug_slot->name);
|
||||
kfree(slot->hotplug_slot);
|
||||
kfree(slot);
|
||||
}
|
||||
|
||||
#define SLOT_NAME_SIZE 10
|
||||
static void make_slot_name(struct slot *slot)
|
||||
{
|
||||
/*
|
||||
@ -257,7 +257,6 @@ static int __init init_slots(void)
|
||||
struct slot *slot;
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct hotplug_slot_info *info;
|
||||
char *name;
|
||||
int retval = -ENOMEM;
|
||||
int i;
|
||||
|
||||
@ -266,31 +265,23 @@ static int __init init_slots(void)
|
||||
* with the pci_hotplug subsystem.
|
||||
*/
|
||||
for (i = 0; i < num_slots; ++i) {
|
||||
slot = kmalloc(sizeof(struct slot), GFP_KERNEL);
|
||||
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
goto error;
|
||||
memset(slot, 0, sizeof(struct slot));
|
||||
|
||||
hotplug_slot = kmalloc(sizeof(struct hotplug_slot),
|
||||
GFP_KERNEL);
|
||||
hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
|
||||
if (!hotplug_slot)
|
||||
goto error_slot;
|
||||
memset(hotplug_slot, 0, sizeof (struct hotplug_slot));
|
||||
slot->hotplug_slot = hotplug_slot;
|
||||
|
||||
info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
goto error_hpslot;
|
||||
memset(info, 0, sizeof (struct hotplug_slot_info));
|
||||
hotplug_slot->info = info;
|
||||
|
||||
name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
|
||||
if (!name)
|
||||
goto error_info;
|
||||
hotplug_slot->name = name;
|
||||
|
||||
slot->number = i;
|
||||
|
||||
hotplug_slot->name = slot->name;
|
||||
hotplug_slot->private = slot;
|
||||
hotplug_slot->release = &release_slot;
|
||||
make_slot_name(slot);
|
||||
@ -300,16 +291,16 @@ static int __init init_slots(void)
|
||||
* Initialize the slot info structure with some known
|
||||
* good values.
|
||||
*/
|
||||
info->power_status = get_power_status(slot);
|
||||
info->attention_status = get_attention_status(slot);
|
||||
info->latch_status = get_latch_status(slot);
|
||||
info->adapter_status = get_adapter_status(slot);
|
||||
get_power_status(hotplug_slot, &info->power_status);
|
||||
get_attention_status(hotplug_slot, &info->attention_status);
|
||||
get_latch_status(hotplug_slot, &info->latch_status);
|
||||
get_adapter_status(hotplug_slot, &info->adapter_status);
|
||||
|
||||
dbg("registering slot %d\n", i);
|
||||
retval = pci_hp_register(slot->hotplug_slot);
|
||||
if (retval) {
|
||||
err("pci_hp_register failed with error %d\n", retval);
|
||||
goto error_name;
|
||||
goto error_info;
|
||||
}
|
||||
|
||||
/* add slot to our internal list */
|
||||
@ -317,8 +308,6 @@ static int __init init_slots(void)
|
||||
}
|
||||
|
||||
return 0;
|
||||
error_name:
|
||||
kfree(name);
|
||||
error_info:
|
||||
kfree(info);
|
||||
error_hpslot:
|
||||
|
@ -84,19 +84,16 @@ struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_
|
||||
{
|
||||
struct slot *slot;
|
||||
|
||||
slot = kmalloc(sizeof (struct slot), GFP_KERNEL);
|
||||
slot = kzalloc(sizeof(struct slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
goto error_nomem;
|
||||
memset(slot, 0, sizeof (struct slot));
|
||||
slot->hotplug_slot = kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
|
||||
slot->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
|
||||
if (!slot->hotplug_slot)
|
||||
goto error_slot;
|
||||
memset(slot->hotplug_slot, 0, sizeof (struct hotplug_slot));
|
||||
slot->hotplug_slot->info = kmalloc(sizeof (struct hotplug_slot_info),
|
||||
slot->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
|
||||
GFP_KERNEL);
|
||||
if (!slot->hotplug_slot->info)
|
||||
goto error_hpslot;
|
||||
memset(slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info));
|
||||
slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL);
|
||||
if (!slot->hotplug_slot->name)
|
||||
goto error_info;
|
||||
|
@ -3,7 +3,7 @@
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2005 Silicon Graphics, Inc. All rights reserved.
|
||||
* Copyright (C) 2005-2006 Silicon Graphics, Inc. All rights reserved.
|
||||
*
|
||||
* This work was based on the 2.4/2.6 kernel development by Dick Reigner.
|
||||
* Work to add BIOS PROM support was completed by Mike Habeck.
|
||||
@ -230,6 +230,13 @@ static void sn_bus_free_data(struct pci_dev *dev)
|
||||
list_for_each_entry(child, &subordinate_bus->devices, bus_list)
|
||||
sn_bus_free_data(child);
|
||||
}
|
||||
/*
|
||||
* Some drivers may use dma accesses during the
|
||||
* driver remove function. We release the sysdata
|
||||
* areas after the driver remove functions have
|
||||
* been called.
|
||||
*/
|
||||
sn_bus_store_sysdata(dev);
|
||||
sn_pci_unfixup_slot(dev);
|
||||
}
|
||||
|
||||
@ -429,13 +436,6 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
|
||||
PCI_DEVFN(slot->device_num + 1,
|
||||
PCI_FUNC(func)));
|
||||
if (dev) {
|
||||
/*
|
||||
* Some drivers may use dma accesses during the
|
||||
* driver remove function. We release the sysdata
|
||||
* areas after the driver remove functions have
|
||||
* been called.
|
||||
*/
|
||||
sn_bus_store_sysdata(dev);
|
||||
sn_bus_free_data(dev);
|
||||
pci_remove_bus_device(dev);
|
||||
pci_dev_put(dev);
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h> /* signal_pending(), struct timer_list */
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include "pci_hotplug.h"
|
||||
|
||||
@ -45,6 +46,7 @@
|
||||
extern int shpchp_poll_mode;
|
||||
extern int shpchp_poll_time;
|
||||
extern int shpchp_debug;
|
||||
extern struct workqueue_struct *shpchp_wq;
|
||||
|
||||
/*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/
|
||||
#define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0)
|
||||
@ -52,10 +54,8 @@ extern int shpchp_debug;
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
|
||||
|
||||
#define SLOT_MAGIC 0x67267321
|
||||
#define SLOT_NAME_SIZE 10
|
||||
struct slot {
|
||||
u32 magic;
|
||||
struct slot *next;
|
||||
u8 bus;
|
||||
u8 device;
|
||||
u16 status;
|
||||
@ -70,26 +70,27 @@ struct slot {
|
||||
struct hpc_ops *hpc_ops;
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct list_head slot_list;
|
||||
char name[SLOT_NAME_SIZE];
|
||||
struct work_struct work; /* work for button event */
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
struct event_info {
|
||||
u32 event_type;
|
||||
u8 hp_slot;
|
||||
struct slot *p_slot;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
struct controller {
|
||||
struct controller *next;
|
||||
struct semaphore crit_sect; /* critical section semaphore */
|
||||
struct mutex crit_sect; /* critical section mutex */
|
||||
struct mutex cmd_lock; /* command lock */
|
||||
struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
|
||||
int num_slots; /* Number of slots on ctlr */
|
||||
int slot_num_inc; /* 1 or -1 */
|
||||
struct pci_dev *pci_dev;
|
||||
struct pci_bus *pci_bus;
|
||||
struct event_info event_queue[10];
|
||||
struct slot *slot;
|
||||
struct list_head slot_list;
|
||||
struct hpc_ops *hpc_ops;
|
||||
wait_queue_head_t queue; /* sleep & wake process */
|
||||
u8 next_event;
|
||||
u8 bus;
|
||||
u8 device;
|
||||
u8 function;
|
||||
@ -105,12 +106,6 @@ struct controller {
|
||||
volatile int cmd_busy;
|
||||
};
|
||||
|
||||
struct hotplug_params {
|
||||
u8 cache_line_size;
|
||||
u8 latency_timer;
|
||||
u8 enable_serr;
|
||||
u8 enable_perr;
|
||||
};
|
||||
|
||||
/* Define AMD SHPC ID */
|
||||
#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
|
||||
@ -180,11 +175,8 @@ struct hotplug_params {
|
||||
/* sysfs functions for the hotplug controller info */
|
||||
extern void shpchp_create_ctrl_files (struct controller *ctrl);
|
||||
|
||||
/* controller functions */
|
||||
extern int shpchp_event_start_thread(void);
|
||||
extern void shpchp_event_stop_thread(void);
|
||||
extern int shpchp_enable_slot(struct slot *slot);
|
||||
extern int shpchp_disable_slot(struct slot *slot);
|
||||
extern int shpchp_sysfs_enable_slot(struct slot *slot);
|
||||
extern int shpchp_sysfs_disable_slot(struct slot *slot);
|
||||
|
||||
extern u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id);
|
||||
extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id);
|
||||
@ -195,16 +187,28 @@ extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id);
|
||||
extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
|
||||
extern int shpchp_configure_device(struct slot *p_slot);
|
||||
extern int shpchp_unconfigure_device(struct slot *p_slot);
|
||||
extern void get_hp_hw_control_from_firmware(struct pci_dev *dev);
|
||||
extern void get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp);
|
||||
extern int shpchprm_get_physical_slot_number(struct controller *ctrl,
|
||||
u32 *sun, u8 busnum, u8 devnum);
|
||||
extern void shpchp_remove_ctrl_files(struct controller *ctrl);
|
||||
extern void cleanup_slots(struct controller *ctrl);
|
||||
extern void queue_pushbutton_work(void *data);
|
||||
|
||||
|
||||
/* Global variables */
|
||||
extern struct controller *shpchp_ctrl_list;
|
||||
#ifdef CONFIG_ACPI
|
||||
static inline int get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp)
|
||||
{
|
||||
if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp)))
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
#define get_hp_hw_control_from_firmware(pdev) \
|
||||
do { \
|
||||
if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
|
||||
acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \
|
||||
} while (0)
|
||||
#else
|
||||
#define get_hp_params_from_firmware(dev, hpp) (-ENODEV)
|
||||
#define get_hp_hw_control_from_firmware(dev) do { } while (0)
|
||||
#endif
|
||||
|
||||
struct ctrl_reg {
|
||||
volatile u32 base_offset;
|
||||
@ -286,10 +290,6 @@ static inline int slot_paranoia_check (struct slot *slot, const char *function)
|
||||
dbg("%s - slot == NULL", function);
|
||||
return -1;
|
||||
}
|
||||
if (slot->magic != SLOT_MAGIC) {
|
||||
dbg("%s - bad magic number for slot", function);
|
||||
return -1;
|
||||
}
|
||||
if (!slot->hotplug_slot) {
|
||||
dbg("%s - slot->hotplug_slot == NULL!", function);
|
||||
return -1;
|
||||
@ -314,44 +314,19 @@ static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const ch
|
||||
|
||||
static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device)
|
||||
{
|
||||
struct slot *p_slot, *tmp_slot = NULL;
|
||||
struct slot *slot;
|
||||
|
||||
if (!ctrl)
|
||||
return NULL;
|
||||
|
||||
p_slot = ctrl->slot;
|
||||
|
||||
while (p_slot && (p_slot->device != device)) {
|
||||
tmp_slot = p_slot;
|
||||
p_slot = p_slot->next;
|
||||
}
|
||||
if (p_slot == NULL) {
|
||||
err("ERROR: shpchp_find_slot device=0x%x\n", device);
|
||||
p_slot = tmp_slot;
|
||||
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
|
||||
if (slot->device == device)
|
||||
return slot;
|
||||
}
|
||||
|
||||
return (p_slot);
|
||||
}
|
||||
err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device);
|
||||
|
||||
static inline int wait_for_ctrl_irq (struct controller *ctrl)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
int retval = 0;
|
||||
|
||||
add_wait_queue(&ctrl->queue, &wait);
|
||||
|
||||
if (!shpchp_poll_mode) {
|
||||
/* Sleep for up to 1 second */
|
||||
msleep_interruptible(1000);
|
||||
} else {
|
||||
/* Sleep for up to 2 seconds */
|
||||
msleep_interruptible(2000);
|
||||
}
|
||||
remove_wait_queue(&ctrl->queue, &wait);
|
||||
if (signal_pending(current))
|
||||
retval = -EINTR;
|
||||
|
||||
return retval;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot)
|
||||
@ -427,13 +402,6 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
|
||||
pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
|
||||
}
|
||||
|
||||
#define SLOT_NAME_SIZE 10
|
||||
|
||||
static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
|
||||
{
|
||||
snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number);
|
||||
}
|
||||
|
||||
enum php_ctlr_type {
|
||||
PCI,
|
||||
ISA,
|
||||
|
@ -32,13 +32,14 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include "shpchp.h"
|
||||
|
||||
/* Global variables */
|
||||
int shpchp_debug;
|
||||
int shpchp_poll_mode;
|
||||
int shpchp_poll_time;
|
||||
struct controller *shpchp_ctrl_list; /* = NULL */
|
||||
struct workqueue_struct *shpchp_wq;
|
||||
|
||||
#define DRIVER_VERSION "0.4"
|
||||
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
|
||||
@ -57,7 +58,6 @@ MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
|
||||
|
||||
#define SHPC_MODULE_NAME "shpchp"
|
||||
|
||||
static int shpc_start_thread (void);
|
||||
static int set_attention_status (struct hotplug_slot *slot, u8 value);
|
||||
static int enable_slot (struct hotplug_slot *slot);
|
||||
static int disable_slot (struct hotplug_slot *slot);
|
||||
@ -94,107 +94,120 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
kfree(slot->hotplug_slot->info);
|
||||
kfree(slot->hotplug_slot->name);
|
||||
kfree(slot->hotplug_slot);
|
||||
kfree(slot);
|
||||
}
|
||||
|
||||
static void make_slot_name(struct slot *slot)
|
||||
{
|
||||
snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
|
||||
slot->bus, slot->number);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun,
|
||||
u8 busnum, u8 devnum)
|
||||
{
|
||||
int offset = devnum - ctrl->slot_device_offset;
|
||||
|
||||
dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__,
|
||||
ctrl->slot_num_inc, offset);
|
||||
*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int init_slots(struct controller *ctrl)
|
||||
{
|
||||
struct slot *new_slot;
|
||||
u8 number_of_slots;
|
||||
u8 slot_device;
|
||||
u32 slot_number, sun;
|
||||
int result = -ENOMEM;
|
||||
struct slot *slot;
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct hotplug_slot_info *info;
|
||||
int retval = -ENOMEM;
|
||||
int i;
|
||||
u32 sun;
|
||||
|
||||
number_of_slots = ctrl->num_slots;
|
||||
slot_device = ctrl->slot_device_offset;
|
||||
slot_number = ctrl->first_slot;
|
||||
|
||||
while (number_of_slots) {
|
||||
new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL);
|
||||
if (!new_slot)
|
||||
for (i = 0; i < ctrl->num_slots; i++) {
|
||||
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
goto error;
|
||||
|
||||
memset(new_slot, 0, sizeof(struct slot));
|
||||
new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL);
|
||||
if (!new_slot->hotplug_slot)
|
||||
hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
|
||||
if (!hotplug_slot)
|
||||
goto error_slot;
|
||||
memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot));
|
||||
slot->hotplug_slot = hotplug_slot;
|
||||
|
||||
new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
|
||||
if (!new_slot->hotplug_slot->info)
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
goto error_hpslot;
|
||||
memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info));
|
||||
new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL);
|
||||
if (!new_slot->hotplug_slot->name)
|
||||
goto error_info;
|
||||
hotplug_slot->info = info;
|
||||
|
||||
new_slot->magic = SLOT_MAGIC;
|
||||
new_slot->ctrl = ctrl;
|
||||
new_slot->bus = ctrl->slot_bus;
|
||||
new_slot->device = slot_device;
|
||||
new_slot->hpc_ops = ctrl->hpc_ops;
|
||||
hotplug_slot->name = slot->name;
|
||||
|
||||
slot->hp_slot = i;
|
||||
slot->ctrl = ctrl;
|
||||
slot->bus = ctrl->slot_bus;
|
||||
slot->device = ctrl->slot_device_offset + i;
|
||||
slot->hpc_ops = ctrl->hpc_ops;
|
||||
mutex_init(&slot->lock);
|
||||
|
||||
if (shpchprm_get_physical_slot_number(ctrl, &sun,
|
||||
new_slot->bus, new_slot->device))
|
||||
goto error_name;
|
||||
slot->bus, slot->device))
|
||||
goto error_info;
|
||||
|
||||
new_slot->number = sun;
|
||||
new_slot->hp_slot = slot_device - ctrl->slot_device_offset;
|
||||
slot->number = sun;
|
||||
INIT_WORK(&slot->work, queue_pushbutton_work, slot);
|
||||
|
||||
/* register this slot with the hotplug pci core */
|
||||
new_slot->hotplug_slot->private = new_slot;
|
||||
new_slot->hotplug_slot->release = &release_slot;
|
||||
make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
|
||||
new_slot->hotplug_slot->ops = &shpchp_hotplug_slot_ops;
|
||||
hotplug_slot->private = slot;
|
||||
hotplug_slot->release = &release_slot;
|
||||
make_slot_name(slot);
|
||||
hotplug_slot->ops = &shpchp_hotplug_slot_ops;
|
||||
|
||||
new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status));
|
||||
new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status));
|
||||
new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status));
|
||||
new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status));
|
||||
get_power_status(hotplug_slot, &info->power_status);
|
||||
get_attention_status(hotplug_slot, &info->attention_status);
|
||||
get_latch_status(hotplug_slot, &info->latch_status);
|
||||
get_adapter_status(hotplug_slot, &info->adapter_status);
|
||||
|
||||
dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n", new_slot->bus,
|
||||
new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset);
|
||||
result = pci_hp_register (new_slot->hotplug_slot);
|
||||
if (result) {
|
||||
err ("pci_hp_register failed with error %d\n", result);
|
||||
goto error_name;
|
||||
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);
|
||||
retval = pci_hp_register(slot->hotplug_slot);
|
||||
if (retval) {
|
||||
err("pci_hp_register failed with error %d\n", retval);
|
||||
goto error_info;
|
||||
}
|
||||
|
||||
new_slot->next = ctrl->slot;
|
||||
ctrl->slot = new_slot;
|
||||
|
||||
number_of_slots--;
|
||||
slot_device++;
|
||||
slot_number += ctrl->slot_num_inc;
|
||||
list_add(&slot->slot_list, &ctrl->slot_list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_name:
|
||||
kfree(new_slot->hotplug_slot->name);
|
||||
error_info:
|
||||
kfree(new_slot->hotplug_slot->info);
|
||||
kfree(info);
|
||||
error_hpslot:
|
||||
kfree(new_slot->hotplug_slot);
|
||||
kfree(hotplug_slot);
|
||||
error_slot:
|
||||
kfree(new_slot);
|
||||
kfree(slot);
|
||||
error:
|
||||
return result;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void cleanup_slots(struct controller *ctrl)
|
||||
void cleanup_slots(struct controller *ctrl)
|
||||
{
|
||||
struct slot *old_slot, *next_slot;
|
||||
struct list_head *tmp;
|
||||
struct list_head *next;
|
||||
struct slot *slot;
|
||||
|
||||
old_slot = ctrl->slot;
|
||||
ctrl->slot = NULL;
|
||||
|
||||
while (old_slot) {
|
||||
next_slot = old_slot->next;
|
||||
pci_hp_deregister(old_slot->hotplug_slot);
|
||||
old_slot = next_slot;
|
||||
list_for_each_safe(tmp, next, &ctrl->slot_list) {
|
||||
slot = list_entry(tmp, struct slot, slot_list);
|
||||
list_del(&slot->slot_list);
|
||||
cancel_delayed_work(&slot->work);
|
||||
flush_scheduled_work();
|
||||
flush_workqueue(shpchp_wq);
|
||||
pci_hp_deregister(slot->hotplug_slot);
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,9 +220,12 @@ static int get_ctlr_slot_config(struct controller *ctrl)
|
||||
int rc;
|
||||
int flags;
|
||||
|
||||
rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags);
|
||||
rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots,
|
||||
&first_device_num, &physical_slot_num,
|
||||
&updown, &flags);
|
||||
if (rc) {
|
||||
err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device);
|
||||
err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n",
|
||||
__FUNCTION__, ctrl->bus, ctrl->device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -218,19 +234,19 @@ static int get_ctlr_slot_config(struct controller *ctrl)
|
||||
ctrl->first_slot = physical_slot_num;
|
||||
ctrl->slot_num_inc = updown; /* either -1 or 1 */
|
||||
|
||||
dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n",
|
||||
__FUNCTION__, num_ctlr_slots, first_device_num, physical_slot_num, updown, ctrl->bus, ctrl->device);
|
||||
dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d "
|
||||
"(%x:%x)\n", __FUNCTION__, num_ctlr_slots, first_device_num,
|
||||
physical_slot_num, updown, ctrl->bus, ctrl->device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set_attention_status - Turns the Amber LED for a slot on, off or blink
|
||||
*/
|
||||
static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
|
||||
{
|
||||
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
@ -240,29 +256,27 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int enable_slot (struct hotplug_slot *hotplug_slot)
|
||||
{
|
||||
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
return shpchp_enable_slot(slot);
|
||||
return shpchp_sysfs_enable_slot(slot);
|
||||
}
|
||||
|
||||
|
||||
static int disable_slot (struct hotplug_slot *hotplug_slot)
|
||||
{
|
||||
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
return shpchp_disable_slot(slot);
|
||||
return shpchp_sysfs_disable_slot(slot);
|
||||
}
|
||||
|
||||
static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
@ -276,7 +290,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
|
||||
static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
@ -290,7 +304,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
|
||||
static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
@ -304,7 +318,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
|
||||
static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
@ -318,7 +332,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
|
||||
static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
|
||||
{
|
||||
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
@ -330,11 +344,11 @@ static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
|
||||
|
||||
static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
|
||||
{
|
||||
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
|
||||
retval = slot->hpc_ops->get_max_bus_speed(slot, value);
|
||||
if (retval < 0)
|
||||
*value = PCI_SPEED_UNKNOWN;
|
||||
@ -344,11 +358,11 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
|
||||
|
||||
static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
|
||||
{
|
||||
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
|
||||
retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
|
||||
if (retval < 0)
|
||||
*value = PCI_SPEED_UNKNOWN;
|
||||
@ -372,61 +386,54 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
int rc;
|
||||
struct controller *ctrl;
|
||||
struct slot *t_slot;
|
||||
int first_device_num; /* first PCI device number supported by this SHPC */
|
||||
int num_ctlr_slots; /* number of slots supported by this SHPC */
|
||||
int first_device_num; /* first PCI device number */
|
||||
int num_ctlr_slots; /* number of slots implemented */
|
||||
|
||||
if (!is_shpc_capable(pdev))
|
||||
return -ENODEV;
|
||||
|
||||
ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
|
||||
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
|
||||
if (!ctrl) {
|
||||
err("%s : out of memory\n", __FUNCTION__);
|
||||
goto err_out_none;
|
||||
}
|
||||
memset(ctrl, 0, sizeof(struct controller));
|
||||
INIT_LIST_HEAD(&ctrl->slot_list);
|
||||
|
||||
rc = shpc_init(ctrl, pdev);
|
||||
if (rc) {
|
||||
dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME);
|
||||
dbg("%s: controller initialization failed\n",
|
||||
SHPC_MODULE_NAME);
|
||||
goto err_out_free_ctrl;
|
||||
}
|
||||
|
||||
pci_set_drvdata(pdev, ctrl);
|
||||
|
||||
ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL);
|
||||
if (!ctrl->pci_bus) {
|
||||
err("out of memory\n");
|
||||
rc = -ENOMEM;
|
||||
goto err_out_unmap_mmio_region;
|
||||
}
|
||||
|
||||
memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus));
|
||||
ctrl->bus = pdev->bus->number;
|
||||
ctrl->slot_bus = pdev->subordinate->number;
|
||||
|
||||
ctrl->device = PCI_SLOT(pdev->devfn);
|
||||
ctrl->function = PCI_FUNC(pdev->devfn);
|
||||
dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
|
||||
|
||||
dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
|
||||
ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
|
||||
|
||||
/*
|
||||
* Save configuration headers for this and subordinate PCI buses
|
||||
* Save configuration headers for this and subordinate PCI buses
|
||||
*/
|
||||
|
||||
rc = get_ctlr_slot_config(ctrl);
|
||||
if (rc) {
|
||||
err(msg_initialization_err, rc);
|
||||
goto err_out_free_ctrl_bus;
|
||||
goto err_out_release_ctlr;
|
||||
}
|
||||
first_device_num = ctrl->slot_device_offset;
|
||||
num_ctlr_slots = ctrl->num_slots;
|
||||
|
||||
ctrl->add_support = 1;
|
||||
|
||||
|
||||
/* Setup the slot information structures */
|
||||
rc = init_slots(ctrl);
|
||||
if (rc) {
|
||||
err(msg_initialization_err, 6);
|
||||
goto err_out_free_ctrl_slot;
|
||||
goto err_out_release_ctlr;
|
||||
}
|
||||
|
||||
/* Now hpc_functions (slot->hpc_ops->functions) are ready */
|
||||
@ -437,30 +444,16 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot);
|
||||
|
||||
if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) {
|
||||
err(SHPC_MODULE_NAME ": Can't get current bus speed. Set to 33MHz PCI.\n");
|
||||
err(SHPC_MODULE_NAME ": Can't get current bus speed. "
|
||||
"Set to 33MHz PCI.\n");
|
||||
ctrl->speed = PCI_SPEED_33MHz;
|
||||
}
|
||||
|
||||
/* Finish setting up the hot plug ctrl device */
|
||||
ctrl->next_event = 0;
|
||||
|
||||
if (!shpchp_ctrl_list) {
|
||||
shpchp_ctrl_list = ctrl;
|
||||
ctrl->next = NULL;
|
||||
} else {
|
||||
ctrl->next = shpchp_ctrl_list;
|
||||
shpchp_ctrl_list = ctrl;
|
||||
}
|
||||
|
||||
shpchp_create_ctrl_files(ctrl);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_free_ctrl_slot:
|
||||
cleanup_slots(ctrl);
|
||||
err_out_free_ctrl_bus:
|
||||
kfree(ctrl->pci_bus);
|
||||
err_out_unmap_mmio_region:
|
||||
err_out_release_ctlr:
|
||||
ctrl->hpc_ops->release_ctlr(ctrl);
|
||||
err_out_free_ctrl:
|
||||
kfree(ctrl);
|
||||
@ -468,74 +461,28 @@ err_out_none:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
static int shpc_start_thread(void)
|
||||
static void shpc_remove(struct pci_dev *dev)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
dbg("Initialize + Start the notification/polling mechanism \n");
|
||||
struct controller *ctrl = pci_get_drvdata(dev);
|
||||
|
||||
retval = shpchp_event_start_thread();
|
||||
if (retval) {
|
||||
dbg("shpchp_event_start_thread() failed\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
return retval;
|
||||
shpchp_remove_ctrl_files(ctrl);
|
||||
ctrl->hpc_ops->release_ctlr(ctrl);
|
||||
kfree(ctrl);
|
||||
}
|
||||
|
||||
static void __exit unload_shpchpd(void)
|
||||
{
|
||||
struct controller *ctrl;
|
||||
struct controller *tctrl;
|
||||
|
||||
ctrl = shpchp_ctrl_list;
|
||||
|
||||
while (ctrl) {
|
||||
shpchp_remove_ctrl_files(ctrl);
|
||||
cleanup_slots(ctrl);
|
||||
|
||||
kfree (ctrl->pci_bus);
|
||||
ctrl->hpc_ops->release_ctlr(ctrl);
|
||||
|
||||
tctrl = ctrl;
|
||||
ctrl = ctrl->next;
|
||||
|
||||
kfree(tctrl);
|
||||
}
|
||||
|
||||
/* Stop the notification mechanism */
|
||||
shpchp_event_stop_thread();
|
||||
|
||||
}
|
||||
|
||||
|
||||
static struct pci_device_id shpcd_pci_tbl[] = {
|
||||
{
|
||||
.class = ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00),
|
||||
.class_mask = ~0,
|
||||
.vendor = PCI_ANY_ID,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
},
|
||||
|
||||
{PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0)},
|
||||
{ /* end: all zeroes */ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, shpcd_pci_tbl);
|
||||
|
||||
|
||||
|
||||
static struct pci_driver shpc_driver = {
|
||||
.name = SHPC_MODULE_NAME,
|
||||
.id_table = shpcd_pci_tbl,
|
||||
.probe = shpc_probe,
|
||||
/* remove: shpc_remove_one, */
|
||||
.remove = shpc_remove,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int __init shpcd_init(void)
|
||||
{
|
||||
int retval = 0;
|
||||
@ -544,17 +491,15 @@ static int __init shpcd_init(void)
|
||||
shpchp_poll_mode = 1;
|
||||
#endif
|
||||
|
||||
retval = shpc_start_thread();
|
||||
if (retval)
|
||||
goto error_hpc_init;
|
||||
shpchp_wq = create_singlethread_workqueue("shpchpd");
|
||||
if (!shpchp_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
retval = pci_register_driver(&shpc_driver);
|
||||
dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
|
||||
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
|
||||
|
||||
error_hpc_init:
|
||||
if (retval) {
|
||||
shpchp_event_stop_thread();
|
||||
destroy_workqueue(shpchp_wq);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
@ -562,10 +507,8 @@ error_hpc_init:
|
||||
static void __exit shpcd_cleanup(void)
|
||||
{
|
||||
dbg("unload_shpchpd()\n");
|
||||
unload_shpchpd();
|
||||
|
||||
pci_unregister_driver(&shpc_driver);
|
||||
|
||||
destroy_workqueue(shpchp_wq);
|
||||
info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -82,31 +82,6 @@
|
||||
#define SLOT_100MHZ_PCIX_533 0x0f000000
|
||||
#define SLOT_133MHZ_PCIX_533 0xf0000000
|
||||
|
||||
|
||||
/* Secondary Bus Configuration Register */
|
||||
/* For PI = 1, Bits 0 to 2 have been encoded as follows to show current bus speed/mode */
|
||||
#define PCI_33MHZ 0x0
|
||||
#define PCI_66MHZ 0x1
|
||||
#define PCIX_66MHZ 0x2
|
||||
#define PCIX_100MHZ 0x3
|
||||
#define PCIX_133MHZ 0x4
|
||||
|
||||
/* For PI = 2, Bits 0 to 3 have been encoded as follows to show current bus speed/mode */
|
||||
#define PCI_33MHZ 0x0
|
||||
#define PCI_66MHZ 0x1
|
||||
#define PCIX_66MHZ 0x2
|
||||
#define PCIX_100MHZ 0x3
|
||||
#define PCIX_133MHZ 0x4
|
||||
#define PCIX_66MHZ_ECC 0x5
|
||||
#define PCIX_100MHZ_ECC 0x6
|
||||
#define PCIX_133MHZ_ECC 0x7
|
||||
#define PCIX_66MHZ_266 0x9
|
||||
#define PCIX_100MHZ_266 0xa
|
||||
#define PCIX_133MHZ_266 0xb
|
||||
#define PCIX_66MHZ_533 0x11
|
||||
#define PCIX_100MHZ_533 0x12
|
||||
#define PCIX_133MHZ_533 0x13
|
||||
|
||||
/* Slot Configuration */
|
||||
#define SLOT_NUM 0x0000001F
|
||||
#define FIRST_DEV_NUM 0x00001F00
|
||||
@ -231,6 +206,7 @@ static spinlock_t list_lock;
|
||||
static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs);
|
||||
|
||||
static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
|
||||
static int hpc_check_cmd_status(struct controller *ctrl);
|
||||
|
||||
/* This is the interrupt polling timeout function. */
|
||||
static void int_poll_timeout(unsigned long lphp_ctlr)
|
||||
@ -303,10 +279,13 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
|
||||
int i;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
|
||||
mutex_lock(&slot->ctrl->cmd_lock);
|
||||
|
||||
if (!php_ctlr) {
|
||||
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
|
||||
return -1;
|
||||
retval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
@ -323,7 +302,8 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
|
||||
if (cmd_status & 0x1) {
|
||||
/* After 1 sec and and the controller is still busy */
|
||||
err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__);
|
||||
return -1;
|
||||
retval = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
++t_slot;
|
||||
@ -340,6 +320,17 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
|
||||
* Wait for command completion.
|
||||
*/
|
||||
retval = shpc_wait_cmd(slot->ctrl);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
cmd_status = hpc_check_cmd_status(slot->ctrl);
|
||||
if (cmd_status) {
|
||||
err("%s: Failed to issued command 0x%x (error code = %d)\n",
|
||||
__FUNCTION__, cmd, cmd_status);
|
||||
retval = -EIO;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&slot->ctrl->cmd_lock);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
@ -532,81 +523,41 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
|
||||
|
||||
static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
|
||||
{
|
||||
struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
|
||||
u32 slot_reg;
|
||||
u16 slot_status, sec_bus_status;
|
||||
u8 m66_cap, pcix_cap, pi;
|
||||
int retval = 0;
|
||||
struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
|
||||
u32 slot_reg = readl(php_ctlr->creg + SLOT1 + 4 * slot->hp_slot);
|
||||
u8 pcix_cap = (slot_reg >> 12) & 7;
|
||||
u8 m66_cap = (slot_reg >> 9) & 1;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
if (!slot->ctrl->hpc_ctlr_handle) {
|
||||
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n",
|
||||
__FUNCTION__, slot_reg, pcix_cap, m66_cap);
|
||||
|
||||
if (slot->hp_slot >= php_ctlr->num_slots) {
|
||||
err("%s: Invalid HPC slot number!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pi = readb(php_ctlr->creg + PROG_INTERFACE);
|
||||
slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
|
||||
dbg("%s: pi = %d, slot_reg = %x\n", __FUNCTION__, pi, slot_reg);
|
||||
slot_status = (u16) slot_reg;
|
||||
dbg("%s: slot_status = %x\n", __FUNCTION__, slot_status);
|
||||
sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG);
|
||||
|
||||
pcix_cap = (u8) ((slot_status & 0x3000) >> 12);
|
||||
dbg("%s: pcix_cap = %x\n", __FUNCTION__, pcix_cap);
|
||||
m66_cap = (u8) ((slot_status & 0x0200) >> 9);
|
||||
dbg("%s: m66_cap = %x\n", __FUNCTION__, m66_cap);
|
||||
|
||||
|
||||
if (pi == 2) {
|
||||
switch (pcix_cap) {
|
||||
case 0:
|
||||
*value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
|
||||
break;
|
||||
case 1:
|
||||
*value = PCI_SPEED_66MHz_PCIX;
|
||||
break;
|
||||
case 3:
|
||||
*value = PCI_SPEED_133MHz_PCIX;
|
||||
break;
|
||||
case 4:
|
||||
*value = PCI_SPEED_133MHz_PCIX_266;
|
||||
break;
|
||||
case 5:
|
||||
*value = PCI_SPEED_133MHz_PCIX_533;
|
||||
break;
|
||||
case 2: /* Reserved */
|
||||
default:
|
||||
*value = PCI_SPEED_UNKNOWN;
|
||||
retval = -ENODEV;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (pcix_cap) {
|
||||
case 0:
|
||||
*value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
|
||||
break;
|
||||
case 1:
|
||||
*value = PCI_SPEED_66MHz_PCIX;
|
||||
break;
|
||||
case 3:
|
||||
*value = PCI_SPEED_133MHz_PCIX;
|
||||
break;
|
||||
case 2: /* Reserved */
|
||||
default:
|
||||
*value = PCI_SPEED_UNKNOWN;
|
||||
retval = -ENODEV;
|
||||
break;
|
||||
}
|
||||
switch (pcix_cap) {
|
||||
case 0x0:
|
||||
*value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
|
||||
break;
|
||||
case 0x1:
|
||||
*value = PCI_SPEED_66MHz_PCIX;
|
||||
break;
|
||||
case 0x3:
|
||||
*value = PCI_SPEED_133MHz_PCIX;
|
||||
break;
|
||||
case 0x4:
|
||||
*value = PCI_SPEED_133MHz_PCIX_266;
|
||||
break;
|
||||
case 0x5:
|
||||
*value = PCI_SPEED_133MHz_PCIX_533;
|
||||
break;
|
||||
case 0x2:
|
||||
default:
|
||||
*value = PCI_SPEED_UNKNOWN;
|
||||
retval = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
dbg("Adapter speed = %d\n", *value);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
}
|
||||
@ -797,6 +748,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
|
||||
{
|
||||
struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
|
||||
struct php_ctlr_state_s *p, *p_prev;
|
||||
int i;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
@ -805,6 +757,14 @@ static void hpc_release_ctlr(struct controller *ctrl)
|
||||
return ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mask all slot event interrupts
|
||||
*/
|
||||
for (i = 0; i < ctrl->num_slots; i++)
|
||||
writel(0xffff3fff, php_ctlr->creg + SLOT1 + (4 * i));
|
||||
|
||||
cleanup_slots(ctrl);
|
||||
|
||||
if (shpchp_poll_mode) {
|
||||
del_timer(&php_ctlr->int_poll_timer);
|
||||
} else {
|
||||
@ -814,6 +774,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
|
||||
pci_disable_msi(php_ctlr->pci_dev);
|
||||
}
|
||||
}
|
||||
|
||||
if (php_ctlr->pci_dev) {
|
||||
iounmap(php_ctlr->creg);
|
||||
release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
|
||||
@ -939,98 +900,66 @@ static int hpc_slot_disable(struct slot * slot)
|
||||
|
||||
static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
|
||||
{
|
||||
u8 slot_cmd;
|
||||
u8 pi;
|
||||
int retval = 0;
|
||||
int retval;
|
||||
struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
|
||||
u8 pi, cmd;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
if (!slot->ctrl->hpc_ctlr_handle) {
|
||||
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pi = readb(php_ctlr->creg + PROG_INTERFACE);
|
||||
|
||||
if (pi == 1) {
|
||||
switch (value) {
|
||||
case 0:
|
||||
slot_cmd = SETA_PCI_33MHZ;
|
||||
break;
|
||||
case 1:
|
||||
slot_cmd = SETA_PCI_66MHZ;
|
||||
break;
|
||||
case 2:
|
||||
slot_cmd = SETA_PCIX_66MHZ;
|
||||
break;
|
||||
case 3:
|
||||
slot_cmd = SETA_PCIX_100MHZ;
|
||||
break;
|
||||
case 4:
|
||||
slot_cmd = SETA_PCIX_133MHZ;
|
||||
break;
|
||||
default:
|
||||
slot_cmd = PCI_SPEED_UNKNOWN;
|
||||
retval = -ENODEV;
|
||||
return retval;
|
||||
}
|
||||
} else {
|
||||
switch (value) {
|
||||
case 0:
|
||||
slot_cmd = SETB_PCI_33MHZ;
|
||||
break;
|
||||
case 1:
|
||||
slot_cmd = SETB_PCI_66MHZ;
|
||||
break;
|
||||
case 2:
|
||||
slot_cmd = SETB_PCIX_66MHZ_PM;
|
||||
break;
|
||||
case 3:
|
||||
slot_cmd = SETB_PCIX_100MHZ_PM;
|
||||
break;
|
||||
case 4:
|
||||
slot_cmd = SETB_PCIX_133MHZ_PM;
|
||||
break;
|
||||
case 5:
|
||||
slot_cmd = SETB_PCIX_66MHZ_EM;
|
||||
break;
|
||||
case 6:
|
||||
slot_cmd = SETB_PCIX_100MHZ_EM;
|
||||
break;
|
||||
case 7:
|
||||
slot_cmd = SETB_PCIX_133MHZ_EM;
|
||||
break;
|
||||
case 8:
|
||||
slot_cmd = SETB_PCIX_66MHZ_266;
|
||||
break;
|
||||
case 0x9:
|
||||
slot_cmd = SETB_PCIX_100MHZ_266;
|
||||
break;
|
||||
case 0xa:
|
||||
slot_cmd = SETB_PCIX_133MHZ_266;
|
||||
break;
|
||||
case 0xb:
|
||||
slot_cmd = SETB_PCIX_66MHZ_533;
|
||||
break;
|
||||
case 0xc:
|
||||
slot_cmd = SETB_PCIX_100MHZ_533;
|
||||
break;
|
||||
case 0xd:
|
||||
slot_cmd = SETB_PCIX_133MHZ_533;
|
||||
break;
|
||||
default:
|
||||
slot_cmd = PCI_SPEED_UNKNOWN;
|
||||
retval = -ENODEV;
|
||||
return retval;
|
||||
}
|
||||
if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX))
|
||||
return -EINVAL;
|
||||
|
||||
switch (value) {
|
||||
case PCI_SPEED_33MHz:
|
||||
cmd = SETA_PCI_33MHZ;
|
||||
break;
|
||||
case PCI_SPEED_66MHz:
|
||||
cmd = SETA_PCI_66MHZ;
|
||||
break;
|
||||
case PCI_SPEED_66MHz_PCIX:
|
||||
cmd = SETA_PCIX_66MHZ;
|
||||
break;
|
||||
case PCI_SPEED_100MHz_PCIX:
|
||||
cmd = SETA_PCIX_100MHZ;
|
||||
break;
|
||||
case PCI_SPEED_133MHz_PCIX:
|
||||
cmd = SETA_PCIX_133MHZ;
|
||||
break;
|
||||
case PCI_SPEED_66MHz_PCIX_ECC:
|
||||
cmd = SETB_PCIX_66MHZ_EM;
|
||||
break;
|
||||
case PCI_SPEED_100MHz_PCIX_ECC:
|
||||
cmd = SETB_PCIX_100MHZ_EM;
|
||||
break;
|
||||
case PCI_SPEED_133MHz_PCIX_ECC:
|
||||
cmd = SETB_PCIX_133MHZ_EM;
|
||||
break;
|
||||
case PCI_SPEED_66MHz_PCIX_266:
|
||||
cmd = SETB_PCIX_66MHZ_266;
|
||||
break;
|
||||
case PCI_SPEED_100MHz_PCIX_266:
|
||||
cmd = SETB_PCIX_100MHZ_266;
|
||||
break;
|
||||
case PCI_SPEED_133MHz_PCIX_266:
|
||||
cmd = SETB_PCIX_133MHZ_266;
|
||||
break;
|
||||
case PCI_SPEED_66MHz_PCIX_533:
|
||||
cmd = SETB_PCIX_66MHZ_533;
|
||||
break;
|
||||
case PCI_SPEED_100MHz_PCIX_533:
|
||||
cmd = SETB_PCIX_100MHZ_533;
|
||||
break;
|
||||
case PCI_SPEED_133MHz_PCIX_533:
|
||||
cmd = SETB_PCIX_133MHZ_533;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
retval = shpc_write_cmd(slot, 0, slot_cmd);
|
||||
if (retval) {
|
||||
|
||||
retval = shpc_write_cmd(slot, 0, cmd);
|
||||
if (retval)
|
||||
err("%s: Write command failed!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
@ -1093,14 +1022,8 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
|
||||
wake_up_interruptible(&ctrl->queue);
|
||||
}
|
||||
|
||||
if ((intr_loc = (intr_loc >> 1)) == 0) {
|
||||
/* Unmask Global Interrupt Mask */
|
||||
temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
|
||||
temp_dword &= 0xfffffffe;
|
||||
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
|
||||
|
||||
return IRQ_NONE;
|
||||
}
|
||||
if ((intr_loc = (intr_loc >> 1)) == 0)
|
||||
goto out;
|
||||
|
||||
for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
|
||||
/* To find out which slot has interrupt pending */
|
||||
@ -1130,6 +1053,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
|
||||
dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2);
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (!shpchp_poll_mode) {
|
||||
/* Unmask Global Interrupt Mask */
|
||||
temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
|
||||
@ -1142,64 +1066,43 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
|
||||
|
||||
static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
|
||||
{
|
||||
int retval = 0;
|
||||
struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
|
||||
enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
|
||||
int retval = 0;
|
||||
u8 pi;
|
||||
u32 slot_avail1, slot_avail2;
|
||||
u8 pi = readb(php_ctlr->creg + PROG_INTERFACE);
|
||||
u32 slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1);
|
||||
u32 slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2);
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
if (!slot->ctrl->hpc_ctlr_handle) {
|
||||
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (slot->hp_slot >= php_ctlr->num_slots) {
|
||||
err("%s: Invalid HPC slot number!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pi = readb(php_ctlr->creg + PROG_INTERFACE);
|
||||
slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1);
|
||||
slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2);
|
||||
|
||||
if (pi == 2) {
|
||||
if (slot_avail2 & SLOT_133MHZ_PCIX_533)
|
||||
bus_speed = PCIX_133MHZ_533;
|
||||
bus_speed = PCI_SPEED_133MHz_PCIX_533;
|
||||
else if (slot_avail2 & SLOT_100MHZ_PCIX_533)
|
||||
bus_speed = PCIX_100MHZ_533;
|
||||
bus_speed = PCI_SPEED_100MHz_PCIX_533;
|
||||
else if (slot_avail2 & SLOT_66MHZ_PCIX_533)
|
||||
bus_speed = PCIX_66MHZ_533;
|
||||
bus_speed = PCI_SPEED_66MHz_PCIX_533;
|
||||
else if (slot_avail2 & SLOT_133MHZ_PCIX_266)
|
||||
bus_speed = PCIX_133MHZ_266;
|
||||
bus_speed = PCI_SPEED_133MHz_PCIX_266;
|
||||
else if (slot_avail2 & SLOT_100MHZ_PCIX_266)
|
||||
bus_speed = PCIX_100MHZ_266;
|
||||
bus_speed = PCI_SPEED_100MHz_PCIX_266;
|
||||
else if (slot_avail2 & SLOT_66MHZ_PCIX_266)
|
||||
bus_speed = PCIX_66MHZ_266;
|
||||
else if (slot_avail1 & SLOT_133MHZ_PCIX)
|
||||
bus_speed = PCIX_133MHZ;
|
||||
else if (slot_avail1 & SLOT_100MHZ_PCIX)
|
||||
bus_speed = PCIX_100MHZ;
|
||||
else if (slot_avail1 & SLOT_66MHZ_PCIX)
|
||||
bus_speed = PCIX_66MHZ;
|
||||
else if (slot_avail2 & SLOT_66MHZ)
|
||||
bus_speed = PCI_66MHZ;
|
||||
else if (slot_avail1 & SLOT_33MHZ)
|
||||
bus_speed = PCI_33MHZ;
|
||||
else bus_speed = PCI_SPEED_UNKNOWN;
|
||||
} else {
|
||||
bus_speed = PCI_SPEED_66MHz_PCIX_266;
|
||||
}
|
||||
|
||||
if (bus_speed == PCI_SPEED_UNKNOWN) {
|
||||
if (slot_avail1 & SLOT_133MHZ_PCIX)
|
||||
bus_speed = PCIX_133MHZ;
|
||||
bus_speed = PCI_SPEED_133MHz_PCIX;
|
||||
else if (slot_avail1 & SLOT_100MHZ_PCIX)
|
||||
bus_speed = PCIX_100MHZ;
|
||||
bus_speed = PCI_SPEED_100MHz_PCIX;
|
||||
else if (slot_avail1 & SLOT_66MHZ_PCIX)
|
||||
bus_speed = PCIX_66MHZ;
|
||||
bus_speed = PCI_SPEED_66MHz_PCIX;
|
||||
else if (slot_avail2 & SLOT_66MHZ)
|
||||
bus_speed = PCI_66MHZ;
|
||||
bus_speed = PCI_SPEED_66MHz;
|
||||
else if (slot_avail1 & SLOT_33MHZ)
|
||||
bus_speed = PCI_33MHZ;
|
||||
else bus_speed = PCI_SPEED_UNKNOWN;
|
||||
bus_speed = PCI_SPEED_33MHz;
|
||||
else
|
||||
retval = -ENODEV;
|
||||
}
|
||||
|
||||
*value = bus_speed;
|
||||
@ -1210,111 +1113,69 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
|
||||
|
||||
static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
|
||||
{
|
||||
int retval = 0;
|
||||
struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
|
||||
enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
|
||||
u16 sec_bus_status;
|
||||
int retval = 0;
|
||||
u8 pi;
|
||||
u16 sec_bus_reg = readw(php_ctlr->creg + SEC_BUS_CONFIG);
|
||||
u8 pi = readb(php_ctlr->creg + PROG_INTERFACE);
|
||||
u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7);
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
if (!slot->ctrl->hpc_ctlr_handle) {
|
||||
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
|
||||
return -1;
|
||||
if ((pi == 1) && (speed_mode > 4)) {
|
||||
*value = PCI_SPEED_UNKNOWN;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (slot->hp_slot >= php_ctlr->num_slots) {
|
||||
err("%s: Invalid HPC slot number!\n", __FUNCTION__);
|
||||
return -1;
|
||||
switch (speed_mode) {
|
||||
case 0x0:
|
||||
*value = PCI_SPEED_33MHz;
|
||||
break;
|
||||
case 0x1:
|
||||
*value = PCI_SPEED_66MHz;
|
||||
break;
|
||||
case 0x2:
|
||||
*value = PCI_SPEED_66MHz_PCIX;
|
||||
break;
|
||||
case 0x3:
|
||||
*value = PCI_SPEED_100MHz_PCIX;
|
||||
break;
|
||||
case 0x4:
|
||||
*value = PCI_SPEED_133MHz_PCIX;
|
||||
break;
|
||||
case 0x5:
|
||||
*value = PCI_SPEED_66MHz_PCIX_ECC;
|
||||
break;
|
||||
case 0x6:
|
||||
*value = PCI_SPEED_100MHz_PCIX_ECC;
|
||||
break;
|
||||
case 0x7:
|
||||
*value = PCI_SPEED_133MHz_PCIX_ECC;
|
||||
break;
|
||||
case 0x8:
|
||||
*value = PCI_SPEED_66MHz_PCIX_266;
|
||||
break;
|
||||
case 0x9:
|
||||
*value = PCI_SPEED_100MHz_PCIX_266;
|
||||
break;
|
||||
case 0xa:
|
||||
*value = PCI_SPEED_133MHz_PCIX_266;
|
||||
break;
|
||||
case 0xb:
|
||||
*value = PCI_SPEED_66MHz_PCIX_533;
|
||||
break;
|
||||
case 0xc:
|
||||
*value = PCI_SPEED_100MHz_PCIX_533;
|
||||
break;
|
||||
case 0xd:
|
||||
*value = PCI_SPEED_133MHz_PCIX_533;
|
||||
break;
|
||||
default:
|
||||
*value = PCI_SPEED_UNKNOWN;
|
||||
retval = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
pi = readb(php_ctlr->creg + PROG_INTERFACE);
|
||||
sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG);
|
||||
|
||||
if (pi == 2) {
|
||||
switch (sec_bus_status & 0x000f) {
|
||||
case 0:
|
||||
bus_speed = PCI_SPEED_33MHz;
|
||||
break;
|
||||
case 1:
|
||||
bus_speed = PCI_SPEED_66MHz;
|
||||
break;
|
||||
case 2:
|
||||
bus_speed = PCI_SPEED_66MHz_PCIX;
|
||||
break;
|
||||
case 3:
|
||||
bus_speed = PCI_SPEED_100MHz_PCIX;
|
||||
break;
|
||||
case 4:
|
||||
bus_speed = PCI_SPEED_133MHz_PCIX;
|
||||
break;
|
||||
case 5:
|
||||
bus_speed = PCI_SPEED_66MHz_PCIX_ECC;
|
||||
break;
|
||||
case 6:
|
||||
bus_speed = PCI_SPEED_100MHz_PCIX_ECC;
|
||||
break;
|
||||
case 7:
|
||||
bus_speed = PCI_SPEED_133MHz_PCIX_ECC;
|
||||
break;
|
||||
case 8:
|
||||
bus_speed = PCI_SPEED_66MHz_PCIX_266;
|
||||
break;
|
||||
case 9:
|
||||
bus_speed = PCI_SPEED_100MHz_PCIX_266;
|
||||
break;
|
||||
case 0xa:
|
||||
bus_speed = PCI_SPEED_133MHz_PCIX_266;
|
||||
break;
|
||||
case 0xb:
|
||||
bus_speed = PCI_SPEED_66MHz_PCIX_533;
|
||||
break;
|
||||
case 0xc:
|
||||
bus_speed = PCI_SPEED_100MHz_PCIX_533;
|
||||
break;
|
||||
case 0xd:
|
||||
bus_speed = PCI_SPEED_133MHz_PCIX_533;
|
||||
break;
|
||||
case 0xe:
|
||||
case 0xf:
|
||||
default:
|
||||
bus_speed = PCI_SPEED_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* In the case where pi is undefined, default it to 1 */
|
||||
switch (sec_bus_status & 0x0007) {
|
||||
case 0:
|
||||
bus_speed = PCI_SPEED_33MHz;
|
||||
break;
|
||||
case 1:
|
||||
bus_speed = PCI_SPEED_66MHz;
|
||||
break;
|
||||
case 2:
|
||||
bus_speed = PCI_SPEED_66MHz_PCIX;
|
||||
break;
|
||||
case 3:
|
||||
bus_speed = PCI_SPEED_100MHz_PCIX;
|
||||
break;
|
||||
case 4:
|
||||
bus_speed = PCI_SPEED_133MHz_PCIX;
|
||||
break;
|
||||
case 5:
|
||||
bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */
|
||||
break;
|
||||
case 6:
|
||||
bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */
|
||||
break;
|
||||
case 7:
|
||||
bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */
|
||||
break;
|
||||
default:
|
||||
bus_speed = PCI_SPEED_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*value = bus_speed;
|
||||
dbg("Current bus speed = %d\n", bus_speed);
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
@ -1343,7 +1204,6 @@ static struct hpc_ops shpchp_hpc_ops = {
|
||||
.green_led_blink = hpc_set_green_led_blink,
|
||||
|
||||
.release_ctlr = hpc_release_ctlr,
|
||||
.check_cmd_status = hpc_check_cmd_status,
|
||||
};
|
||||
|
||||
inline static int shpc_indirect_creg_read(struct controller *ctrl, int index,
|
||||
@ -1375,15 +1235,13 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
||||
ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
|
||||
|
||||
spin_lock_init(&list_lock);
|
||||
php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
|
||||
php_ctlr = kzalloc(sizeof(*php_ctlr), GFP_KERNEL);
|
||||
|
||||
if (!php_ctlr) { /* allocate controller state data */
|
||||
err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
|
||||
goto abort;
|
||||
}
|
||||
|
||||
memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s));
|
||||
|
||||
php_ctlr->pci_dev = pdev; /* save pci_dev in context */
|
||||
|
||||
if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
|
||||
@ -1454,7 +1312,9 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
||||
}
|
||||
dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
|
||||
|
||||
init_MUTEX(&ctrl->crit_sect);
|
||||
mutex_init(&ctrl->crit_sect);
|
||||
mutex_init(&ctrl->cmd_lock);
|
||||
|
||||
/* Setup wait queue */
|
||||
init_waitqueue_head(&ctrl->queue);
|
||||
|
||||
|
@ -38,7 +38,7 @@ static void program_fw_provided_values(struct pci_dev *dev)
|
||||
{
|
||||
u16 pci_cmd, pci_bctl;
|
||||
struct pci_dev *cdev;
|
||||
struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */
|
||||
struct hotplug_params hpp;
|
||||
|
||||
/* Program hpp values for this device */
|
||||
if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
|
||||
@ -46,7 +46,13 @@ static void program_fw_provided_values(struct pci_dev *dev)
|
||||
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
|
||||
return;
|
||||
|
||||
get_hp_params_from_firmware(dev, &hpp);
|
||||
/* use default values if we can't get them from firmware */
|
||||
if (get_hp_params_from_firmware(dev, &hpp)) {
|
||||
hpp.cache_line_size = 8;
|
||||
hpp.latency_timer = 0x40;
|
||||
hpp.enable_serr = 0;
|
||||
hpp.enable_perr = 0;
|
||||
}
|
||||
|
||||
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size);
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer);
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform
|
||||
*
|
||||
* Copyright (C) 1995,2001 Compaq Computer Corporation
|
||||
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
|
||||
* Copyright (C) 2001 IBM Corp.
|
||||
* Copyright (C) 2003-2004 Intel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include "shpchp.h"
|
||||
|
||||
int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
|
||||
{
|
||||
int offset = devnum - ctrl->slot_device_offset;
|
||||
|
||||
*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
|
||||
*
|
||||
* Copyright (C) 1995,2001 Compaq Computer Corporation
|
||||
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
|
||||
* Copyright (C) 2001 IBM Corp.
|
||||
* Copyright (C) 2003-2004 Intel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "shpchp.h"
|
||||
|
||||
int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
|
||||
{
|
||||
int offset = devnum - ctrl->slot_device_offset;
|
||||
|
||||
dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
|
||||
*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||
{
|
||||
return;
|
||||
}
|
@ -103,9 +103,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
|
||||
switch (entry->msi_attrib.type) {
|
||||
case PCI_CAP_ID_MSI:
|
||||
{
|
||||
int pos;
|
||||
int pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI);
|
||||
|
||||
if (!(pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI)))
|
||||
if (!pos)
|
||||
return;
|
||||
|
||||
pci_read_config_dword(entry->dev, msi_lower_address_reg(pos),
|
||||
@ -347,9 +347,9 @@ static int assign_msi_vector(void)
|
||||
|
||||
static int get_new_vector(void)
|
||||
{
|
||||
int vector;
|
||||
int vector = assign_msi_vector();
|
||||
|
||||
if ((vector = assign_msi_vector()) > 0)
|
||||
if (vector > 0)
|
||||
set_intr_gate(vector, interrupt[vector]);
|
||||
|
||||
return vector;
|
||||
@ -369,7 +369,8 @@ static int msi_init(void)
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = msi_cache_init()) < 0) {
|
||||
status = msi_cache_init();
|
||||
if (status < 0) {
|
||||
pci_msi_enable = 0;
|
||||
printk(KERN_WARNING "PCI: MSI cache init failed\n");
|
||||
return status;
|
||||
@ -523,10 +524,12 @@ static int msi_capability_init(struct pci_dev *dev)
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
||||
pci_read_config_word(dev, msi_control_reg(pos), &control);
|
||||
/* MSI Entry Initialization */
|
||||
if (!(entry = alloc_msi_entry()))
|
||||
entry = alloc_msi_entry();
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
if ((vector = get_msi_vector(dev)) < 0) {
|
||||
vector = get_msi_vector(dev);
|
||||
if (vector < 0) {
|
||||
kmem_cache_free(msi_cachep, entry);
|
||||
return -EBUSY;
|
||||
}
|
||||
@ -597,7 +600,8 @@ static int msix_capability_init(struct pci_dev *dev,
|
||||
struct msg_address address;
|
||||
struct msg_data data;
|
||||
int vector, pos, i, j, nr_entries, temp = 0;
|
||||
u32 phys_addr, table_offset;
|
||||
unsigned long phys_addr;
|
||||
u32 table_offset;
|
||||
u16 control;
|
||||
u8 bir;
|
||||
void __iomem *base;
|
||||
@ -606,11 +610,11 @@ static int msix_capability_init(struct pci_dev *dev,
|
||||
/* Request & Map MSI-X table region */
|
||||
pci_read_config_word(dev, msi_control_reg(pos), &control);
|
||||
nr_entries = multi_msix_capable(control);
|
||||
pci_read_config_dword(dev, msix_table_offset_reg(pos),
|
||||
&table_offset);
|
||||
|
||||
pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset);
|
||||
bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
|
||||
phys_addr = pci_resource_start (dev, bir);
|
||||
phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK);
|
||||
table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
|
||||
phys_addr = pci_resource_start (dev, bir) + table_offset;
|
||||
base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);
|
||||
if (base == NULL)
|
||||
return -ENOMEM;
|
||||
@ -620,7 +624,8 @@ static int msix_capability_init(struct pci_dev *dev,
|
||||
entry = alloc_msi_entry();
|
||||
if (!entry)
|
||||
break;
|
||||
if ((vector = get_msi_vector(dev)) < 0)
|
||||
vector = get_msi_vector(dev);
|
||||
if (vector < 0)
|
||||
break;
|
||||
|
||||
j = entries[i].entry;
|
||||
@ -699,12 +704,17 @@ int pci_enable_msi(struct pci_dev* dev)
|
||||
if (dev->no_msi)
|
||||
return status;
|
||||
|
||||
if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
|
||||
return -EINVAL;
|
||||
|
||||
temp = dev->irq;
|
||||
|
||||
if ((status = msi_init()) < 0)
|
||||
status = msi_init();
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSI)))
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
||||
if (!pos)
|
||||
return -EINVAL;
|
||||
|
||||
pci_read_config_word(dev, msi_control_reg(pos), &control);
|
||||
@ -728,8 +738,8 @@ int pci_enable_msi(struct pci_dev* dev)
|
||||
dev->irq = temp;
|
||||
}
|
||||
/* Check whether driver already requested for MSI-X vectors */
|
||||
if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 &&
|
||||
!msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
|
||||
printk(KERN_INFO "PCI: %s: Can't enable MSI. "
|
||||
"Device already has MSI-X vectors assigned\n",
|
||||
pci_name(dev));
|
||||
@ -755,7 +765,13 @@ void pci_disable_msi(struct pci_dev* dev)
|
||||
u16 control;
|
||||
unsigned long flags;
|
||||
|
||||
if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSI)))
|
||||
if (!pci_msi_enable)
|
||||
return;
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
||||
if (!pos)
|
||||
return;
|
||||
|
||||
pci_read_config_word(dev, msi_control_reg(pos), &control);
|
||||
@ -826,8 +842,10 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign)
|
||||
* Detect last MSI-X vector to be released.
|
||||
* Release the MSI-X memory-mapped table.
|
||||
*/
|
||||
#if 0
|
||||
int pos, nr_entries;
|
||||
u32 phys_addr, table_offset;
|
||||
unsigned long phys_addr;
|
||||
u32 table_offset;
|
||||
u16 control;
|
||||
u8 bir;
|
||||
|
||||
@ -838,9 +856,12 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign)
|
||||
pci_read_config_dword(dev, msix_table_offset_reg(pos),
|
||||
&table_offset);
|
||||
bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
|
||||
phys_addr = pci_resource_start (dev, bir);
|
||||
phys_addr += (u32)(table_offset &
|
||||
~PCI_MSIX_FLAGS_BIRMASK);
|
||||
table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
|
||||
phys_addr = pci_resource_start(dev, bir) + table_offset;
|
||||
/*
|
||||
* FIXME! and what did you want to do with phys_addr?
|
||||
*/
|
||||
#endif
|
||||
iounmap(base);
|
||||
}
|
||||
}
|
||||
@ -924,10 +945,12 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
|
||||
if (!pci_msi_enable || !dev || !entries)
|
||||
return -EINVAL;
|
||||
|
||||
if ((status = msi_init()) < 0)
|
||||
status = msi_init();
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)))
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
if (!pos)
|
||||
return -EINVAL;
|
||||
|
||||
pci_read_config_word(dev, msi_control_reg(pos), &control);
|
||||
@ -1006,7 +1029,13 @@ void pci_disable_msix(struct pci_dev* dev)
|
||||
int pos, temp;
|
||||
u16 control;
|
||||
|
||||
if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)))
|
||||
if (!pci_msi_enable)
|
||||
return;
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
if (!pos)
|
||||
return;
|
||||
|
||||
pci_read_config_word(dev, msi_control_reg(pos), &control);
|
||||
@ -1066,8 +1095,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
|
||||
return;
|
||||
|
||||
temp = dev->irq; /* Save IOAPIC IRQ */
|
||||
if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) > 0 &&
|
||||
!msi_lookup_vector(dev, PCI_CAP_ID_MSI)) {
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
||||
if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) {
|
||||
spin_lock_irqsave(&msi_lock, flags);
|
||||
state = msi_desc[dev->irq]->msi_attrib.state;
|
||||
spin_unlock_irqrestore(&msi_lock, flags);
|
||||
@ -1080,8 +1109,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
|
||||
msi_free_vector(dev, dev->irq, 0);
|
||||
dev->irq = temp; /* Restore IOAPIC IRQ */
|
||||
}
|
||||
if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 &&
|
||||
!msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
|
||||
int vector, head, tail = 0, warning = 0;
|
||||
void __iomem *base = NULL;
|
||||
|
||||
@ -1101,7 +1130,9 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
|
||||
msi_free_vector(dev, vector, 0);
|
||||
if (warning) {
|
||||
/* Force to release the MSI-X memory-mapped table */
|
||||
u32 phys_addr, table_offset;
|
||||
#if 0
|
||||
unsigned long phys_addr;
|
||||
u32 table_offset;
|
||||
u16 control;
|
||||
u8 bir;
|
||||
|
||||
@ -1110,9 +1141,12 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
|
||||
pci_read_config_dword(dev, msix_table_offset_reg(pos),
|
||||
&table_offset);
|
||||
bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
|
||||
phys_addr = pci_resource_start (dev, bir);
|
||||
phys_addr += (u32)(table_offset &
|
||||
~PCI_MSIX_FLAGS_BIRMASK);
|
||||
table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
|
||||
phys_addr = pci_resource_start(dev, bir) + table_offset;
|
||||
/*
|
||||
* FIXME! and what did you want to do with phys_addr?
|
||||
*/
|
||||
#endif
|
||||
iounmap(base);
|
||||
printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
|
||||
"called without free_irq() on all MSI-X vectors\n",
|
||||
@ -1123,6 +1157,11 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
|
||||
}
|
||||
}
|
||||
|
||||
void pci_no_msi(void)
|
||||
{
|
||||
pci_msi_enable = 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pci_enable_msi);
|
||||
EXPORT_SYMBOL(pci_disable_msi);
|
||||
EXPORT_SYMBOL(pci_enable_msix);
|
||||
|
@ -53,11 +53,10 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
|
||||
if (fields < 0)
|
||||
return -EINVAL;
|
||||
|
||||
dynid = kmalloc(sizeof(*dynid), GFP_KERNEL);
|
||||
dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
|
||||
if (!dynid)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(dynid, 0, sizeof(*dynid));
|
||||
INIT_LIST_HEAD(&dynid->node);
|
||||
dynid->id.vendor = vendor;
|
||||
dynid->id.device = device;
|
||||
@ -380,14 +379,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner)
|
||||
/* initialize common driver fields */
|
||||
drv->driver.name = drv->name;
|
||||
drv->driver.bus = &pci_bus_type;
|
||||
/* FIXME, once all of the existing PCI drivers have been fixed to set
|
||||
* the pci shutdown function, this test can go away. */
|
||||
if (!drv->driver.shutdown)
|
||||
drv->driver.shutdown = pci_device_shutdown;
|
||||
else
|
||||
printk(KERN_WARNING "Warning: PCI driver %s has a struct "
|
||||
"device_driver shutdown method, please update!\n",
|
||||
drv->name);
|
||||
drv->driver.owner = owner;
|
||||
drv->driver.kobj.ktype = &pci_driver_kobj_type;
|
||||
|
||||
@ -514,6 +505,7 @@ struct bus_type pci_bus_type = {
|
||||
.probe = pci_device_probe,
|
||||
.remove = pci_device_remove,
|
||||
.suspend = pci_device_suspend,
|
||||
.shutdown = pci_device_shutdown,
|
||||
.resume = pci_device_resume,
|
||||
.dev_attrs = pci_dev_attrs,
|
||||
};
|
||||
|
@ -501,9 +501,8 @@ int pci_create_sysfs_dev_files (struct pci_dev *pdev)
|
||||
if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
|
||||
struct bin_attribute *rom_attr;
|
||||
|
||||
rom_attr = kmalloc(sizeof(*rom_attr), GFP_ATOMIC);
|
||||
rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC);
|
||||
if (rom_attr) {
|
||||
memset(rom_attr, 0x00, sizeof(*rom_attr));
|
||||
pdev->rom_attr = rom_attr;
|
||||
rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
|
||||
rom_attr->attr.name = "rom";
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <asm/dma.h> /* isa_dma_bridge_buggy */
|
||||
#include "pci.h"
|
||||
|
||||
#if 0
|
||||
|
||||
/**
|
||||
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
|
||||
@ -34,7 +33,7 @@ pci_bus_max_busnr(struct pci_bus* bus)
|
||||
struct list_head *tmp;
|
||||
unsigned char max, n;
|
||||
|
||||
max = bus->number;
|
||||
max = bus->subordinate;
|
||||
list_for_each(tmp, &bus->children) {
|
||||
n = pci_bus_max_busnr(pci_bus_b(tmp));
|
||||
if(n > max)
|
||||
@ -42,7 +41,9 @@ pci_bus_max_busnr(struct pci_bus* bus)
|
||||
}
|
||||
return max;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_bus_max_busnr);
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* pci_max_busnr - returns maximum PCI bus number
|
||||
*
|
||||
@ -495,9 +496,8 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
|
||||
int
|
||||
pci_enable_device(struct pci_dev *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
if ((err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1)))
|
||||
int err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
|
||||
if (err)
|
||||
return err;
|
||||
pci_fixup_device(pci_fixup_enable, dev);
|
||||
dev->is_enabled = 1;
|
||||
@ -639,7 +639,7 @@ void pci_release_region(struct pci_dev *pdev, int bar)
|
||||
* Returns 0 on success, or %EBUSY on error. A warning
|
||||
* message is also printed on failure.
|
||||
*/
|
||||
int pci_request_region(struct pci_dev *pdev, int bar, char *res_name)
|
||||
int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
|
||||
{
|
||||
if (pci_resource_len(pdev, bar) == 0)
|
||||
return 0;
|
||||
@ -697,7 +697,7 @@ void pci_release_regions(struct pci_dev *pdev)
|
||||
* Returns 0 on success, or %EBUSY on error. A warning
|
||||
* message is also printed on failure.
|
||||
*/
|
||||
int pci_request_regions(struct pci_dev *pdev, char *res_name)
|
||||
int pci_request_regions(struct pci_dev *pdev, const char *res_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -900,8 +900,12 @@ static int __devinit pci_setup(char *str)
|
||||
if (k)
|
||||
*k++ = 0;
|
||||
if (*str && (str = pcibios_setup(str)) && *str) {
|
||||
/* PCI layer options should be handled here */
|
||||
printk(KERN_ERR "PCI: Unknown option `%s'\n", str);
|
||||
if (!strcmp(str, "nomsi")) {
|
||||
pci_no_msi();
|
||||
} else {
|
||||
printk(KERN_ERR "PCI: Unknown option `%s'\n",
|
||||
str);
|
||||
}
|
||||
}
|
||||
str = k;
|
||||
}
|
||||
|
@ -50,8 +50,10 @@ extern int pci_msi_quirk;
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
void disable_msi_mode(struct pci_dev *dev, int pos, int type);
|
||||
void pci_no_msi(void);
|
||||
#else
|
||||
static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
|
||||
static inline void pci_no_msi(void) { }
|
||||
#endif
|
||||
|
||||
extern int pcie_mch_quirk;
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
struct pcie_port_device_ext {
|
||||
int interrupt_mode; /* [0:INTx | 1:MSI | 2:MSI-X] */
|
||||
unsigned int saved_msi_config_space[5];
|
||||
};
|
||||
|
||||
extern struct bus_type pcie_port_bus_type;
|
||||
|
@ -248,11 +248,10 @@ static struct pcie_device* alloc_pcie_device(struct pci_dev *parent,
|
||||
{
|
||||
struct pcie_device *device;
|
||||
|
||||
device = kmalloc(sizeof(struct pcie_device), GFP_KERNEL);
|
||||
device = kzalloc(sizeof(struct pcie_device), GFP_KERNEL);
|
||||
if (!device)
|
||||
return NULL;
|
||||
|
||||
memset(device, 0, sizeof(struct pcie_device));
|
||||
pcie_device_init(parent, device, port_type, service_type, irq,irq_mode);
|
||||
printk(KERN_DEBUG "Allocate Port Service[%s]\n", device->device.bus_id);
|
||||
return device;
|
||||
|
@ -30,75 +30,16 @@ MODULE_LICENSE("GPL");
|
||||
/* global data */
|
||||
static const char device_name[] = "pcieport-driver";
|
||||
|
||||
static void pci_save_msi_state(struct pci_dev *dev)
|
||||
static int pcie_portdrv_save_config(struct pci_dev *dev)
|
||||
{
|
||||
struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
|
||||
int i = 0, pos;
|
||||
u16 control;
|
||||
|
||||
if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0)
|
||||
return;
|
||||
|
||||
pci_read_config_dword(dev, pos, &p_ext->saved_msi_config_space[i++]);
|
||||
control = p_ext->saved_msi_config_space[0] >> 16;
|
||||
pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO,
|
||||
&p_ext->saved_msi_config_space[i++]);
|
||||
if (control & PCI_MSI_FLAGS_64BIT) {
|
||||
pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
|
||||
&p_ext->saved_msi_config_space[i++]);
|
||||
pci_read_config_dword(dev, pos + PCI_MSI_DATA_64,
|
||||
&p_ext->saved_msi_config_space[i++]);
|
||||
} else
|
||||
pci_read_config_dword(dev, pos + PCI_MSI_DATA_32,
|
||||
&p_ext->saved_msi_config_space[i++]);
|
||||
if (control & PCI_MSI_FLAGS_MASKBIT)
|
||||
pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT,
|
||||
&p_ext->saved_msi_config_space[i++]);
|
||||
}
|
||||
|
||||
static void pci_restore_msi_state(struct pci_dev *dev)
|
||||
{
|
||||
struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
|
||||
int i = 0, pos;
|
||||
u16 control;
|
||||
|
||||
if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0)
|
||||
return;
|
||||
|
||||
control = p_ext->saved_msi_config_space[i++] >> 16;
|
||||
pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
|
||||
pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO,
|
||||
p_ext->saved_msi_config_space[i++]);
|
||||
if (control & PCI_MSI_FLAGS_64BIT) {
|
||||
pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
|
||||
p_ext->saved_msi_config_space[i++]);
|
||||
pci_write_config_dword(dev, pos + PCI_MSI_DATA_64,
|
||||
p_ext->saved_msi_config_space[i++]);
|
||||
} else
|
||||
pci_write_config_dword(dev, pos + PCI_MSI_DATA_32,
|
||||
p_ext->saved_msi_config_space[i++]);
|
||||
if (control & PCI_MSI_FLAGS_MASKBIT)
|
||||
pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT,
|
||||
p_ext->saved_msi_config_space[i++]);
|
||||
}
|
||||
|
||||
static void pcie_portdrv_save_config(struct pci_dev *dev)
|
||||
{
|
||||
struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
|
||||
|
||||
pci_save_state(dev);
|
||||
if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE)
|
||||
pci_save_msi_state(dev);
|
||||
return pci_save_state(dev);
|
||||
}
|
||||
|
||||
static int pcie_portdrv_restore_config(struct pci_dev *dev)
|
||||
{
|
||||
struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
|
||||
int retval;
|
||||
|
||||
pci_restore_state(dev);
|
||||
if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE)
|
||||
pci_restore_msi_state(dev);
|
||||
retval = pci_enable_device(dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
@ -149,7 +90,8 @@ static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state)
|
||||
{
|
||||
int ret = pcie_port_device_suspend(dev, state);
|
||||
|
||||
pcie_portdrv_save_config(dev);
|
||||
if (!ret)
|
||||
ret = pcie_portdrv_save_config(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -33,10 +33,9 @@ LIST_HEAD(pci_devices);
|
||||
*/
|
||||
static void pci_create_legacy_files(struct pci_bus *b)
|
||||
{
|
||||
b->legacy_io = kmalloc(sizeof(struct bin_attribute) * 2,
|
||||
b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2,
|
||||
GFP_ATOMIC);
|
||||
if (b->legacy_io) {
|
||||
memset(b->legacy_io, 0, sizeof(struct bin_attribute) * 2);
|
||||
b->legacy_io->attr.name = "legacy_io";
|
||||
b->legacy_io->size = 0xffff;
|
||||
b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
|
||||
@ -320,9 +319,8 @@ static struct pci_bus * __devinit pci_alloc_bus(void)
|
||||
{
|
||||
struct pci_bus *b;
|
||||
|
||||
b = kmalloc(sizeof(*b), GFP_KERNEL);
|
||||
b = kzalloc(sizeof(*b), GFP_KERNEL);
|
||||
if (b) {
|
||||
memset(b, 0, sizeof(*b));
|
||||
INIT_LIST_HEAD(&b->node);
|
||||
INIT_LIST_HEAD(&b->children);
|
||||
INIT_LIST_HEAD(&b->devices);
|
||||
@ -347,6 +345,7 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
|
||||
child->parent = parent;
|
||||
child->ops = parent->ops;
|
||||
child->sysdata = parent->sysdata;
|
||||
child->bus_flags = parent->bus_flags;
|
||||
child->bridge = get_device(&bridge->dev);
|
||||
|
||||
child->class_dev.class = &pcibus_class;
|
||||
@ -456,7 +455,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
|
||||
* pass and just note the configuration.
|
||||
*/
|
||||
if (pass)
|
||||
return max;
|
||||
goto out;
|
||||
busnr = (buses >> 8) & 0xFF;
|
||||
|
||||
/*
|
||||
@ -466,12 +465,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
|
||||
if (pci_find_bus(pci_domain_nr(bus), busnr)) {
|
||||
printk(KERN_INFO "PCI: Bus %04x:%02x already known\n",
|
||||
pci_domain_nr(bus), busnr);
|
||||
return max;
|
||||
goto out;
|
||||
}
|
||||
|
||||
child = pci_add_new_bus(bus, dev, busnr);
|
||||
if (!child)
|
||||
return max;
|
||||
goto out;
|
||||
child->primary = buses & 0xFF;
|
||||
child->subordinate = (buses >> 16) & 0xFF;
|
||||
child->bridge_ctl = bctl;
|
||||
@ -496,7 +495,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
|
||||
bus ranges. */
|
||||
pci_write_config_dword(dev, PCI_PRIMARY_BUS,
|
||||
buses & ~0xffffff);
|
||||
return max;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Clear errors */
|
||||
@ -505,7 +504,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
|
||||
/* Prevent assigning a bus number that already exists.
|
||||
* This can happen when a bridge is hot-plugged */
|
||||
if (pci_find_bus(pci_domain_nr(bus), max+1))
|
||||
return max;
|
||||
goto out;
|
||||
child = pci_add_new_bus(bus, dev, ++max);
|
||||
buses = (buses & 0xff000000)
|
||||
| ((unsigned int)(child->primary) << 0)
|
||||
@ -537,6 +536,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
|
||||
pci_fixup_parent_subordinate_busnr(child, max);
|
||||
/* Now we can scan all subordinate buses... */
|
||||
max = pci_scan_child_bus(child);
|
||||
/*
|
||||
* now fix it up again since we have found
|
||||
* the real value of max.
|
||||
*/
|
||||
pci_fixup_parent_subordinate_busnr(child, max);
|
||||
} else {
|
||||
/*
|
||||
* For CardBus bridges, we leave 4 bus numbers
|
||||
@ -576,8 +580,6 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
|
||||
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
|
||||
}
|
||||
|
||||
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl);
|
||||
|
||||
sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
|
||||
|
||||
while (bus->parent) {
|
||||
@ -585,17 +587,22 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
|
||||
(child->number > bus->subordinate) ||
|
||||
(child->number < bus->number) ||
|
||||
(child->subordinate < bus->number)) {
|
||||
printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) may be "
|
||||
printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) is "
|
||||
"hidden behind%s bridge #%02x (-#%02x)%s\n",
|
||||
child->number, child->subordinate,
|
||||
bus->self->transparent ? " transparent" : " ",
|
||||
bus->number, bus->subordinate,
|
||||
pcibios_assign_all_busses() ? " " :
|
||||
" (try 'pci=assign-busses')");
|
||||
printk(KERN_WARNING "Please report the result to "
|
||||
"linux-kernel to fix this permanently\n");
|
||||
}
|
||||
bus = bus->parent;
|
||||
}
|
||||
|
||||
out:
|
||||
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl);
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
@ -788,11 +795,10 @@ pci_scan_device(struct pci_bus *bus, int devfn)
|
||||
if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
|
||||
return NULL;
|
||||
|
||||
dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
|
||||
dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
memset(dev, 0, sizeof(struct pci_dev));
|
||||
dev->bus = bus;
|
||||
dev->sysdata = bus->sysdata;
|
||||
dev->dev.parent = bus->bridge;
|
||||
|
@ -458,131 +458,6 @@ int pci_proc_detach_bus(struct pci_bus* bus)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_LEGACY_PROC
|
||||
|
||||
/*
|
||||
* Backward compatible /proc/pci interface.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert some of the configuration space registers of the device at
|
||||
* address (bus,devfn) into a string (possibly several lines each).
|
||||
* The configuration string is stored starting at buf[len]. If the
|
||||
* string would exceed the size of the buffer (SIZE), 0 is returned.
|
||||
*/
|
||||
static int show_dev_config(struct seq_file *m, void *v)
|
||||
{
|
||||
struct pci_dev *dev = v;
|
||||
struct pci_dev *first_dev;
|
||||
struct pci_driver *drv;
|
||||
u32 class_rev;
|
||||
unsigned char latency, min_gnt, max_lat;
|
||||
int reg;
|
||||
|
||||
first_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
if (dev == first_dev)
|
||||
seq_puts(m, "PCI devices found:\n");
|
||||
pci_dev_put(first_dev);
|
||||
|
||||
drv = pci_dev_driver(dev);
|
||||
|
||||
pci_user_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
|
||||
pci_user_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
|
||||
pci_user_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
|
||||
pci_user_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
|
||||
seq_printf(m, " Bus %2d, device %3d, function %2d:\n",
|
||||
dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
|
||||
seq_printf(m, " Class %04x", class_rev >> 16);
|
||||
seq_printf(m, ": PCI device %04x:%04x", dev->vendor, dev->device);
|
||||
seq_printf(m, " (rev %d).\n", class_rev & 0xff);
|
||||
|
||||
if (dev->irq)
|
||||
seq_printf(m, " IRQ %d.\n", dev->irq);
|
||||
|
||||
if (latency || min_gnt || max_lat) {
|
||||
seq_printf(m, " Master Capable. ");
|
||||
if (latency)
|
||||
seq_printf(m, "Latency=%d. ", latency);
|
||||
else
|
||||
seq_puts(m, "No bursts. ");
|
||||
if (min_gnt)
|
||||
seq_printf(m, "Min Gnt=%d.", min_gnt);
|
||||
if (max_lat)
|
||||
seq_printf(m, "Max Lat=%d.", max_lat);
|
||||
seq_putc(m, '\n');
|
||||
}
|
||||
|
||||
for (reg = 0; reg < 6; reg++) {
|
||||
struct resource *res = dev->resource + reg;
|
||||
unsigned long base, end, flags;
|
||||
|
||||
base = res->start;
|
||||
end = res->end;
|
||||
flags = res->flags;
|
||||
if (!end)
|
||||
continue;
|
||||
|
||||
if (flags & PCI_BASE_ADDRESS_SPACE_IO) {
|
||||
seq_printf(m, " I/O at 0x%lx [0x%lx].\n",
|
||||
base, end);
|
||||
} else {
|
||||
const char *pref, *type = "unknown";
|
||||
|
||||
if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH)
|
||||
pref = "P";
|
||||
else
|
||||
pref = "Non-p";
|
||||
switch (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
|
||||
case PCI_BASE_ADDRESS_MEM_TYPE_32:
|
||||
type = "32 bit"; break;
|
||||
case PCI_BASE_ADDRESS_MEM_TYPE_1M:
|
||||
type = "20 bit"; break;
|
||||
case PCI_BASE_ADDRESS_MEM_TYPE_64:
|
||||
type = "64 bit"; break;
|
||||
}
|
||||
seq_printf(m, " %srefetchable %s memory at "
|
||||
"0x%lx [0x%lx].\n", pref, type,
|
||||
base,
|
||||
end);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct seq_operations proc_pci_op = {
|
||||
.start = pci_seq_start,
|
||||
.next = pci_seq_next,
|
||||
.stop = pci_seq_stop,
|
||||
.show = show_dev_config
|
||||
};
|
||||
|
||||
static int proc_pci_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &proc_pci_op);
|
||||
}
|
||||
static struct file_operations proc_pci_operations = {
|
||||
.open = proc_pci_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
static void legacy_proc_init(void)
|
||||
{
|
||||
struct proc_dir_entry * entry = create_proc_entry("pci", 0, NULL);
|
||||
if (entry)
|
||||
entry->proc_fops = &proc_pci_operations;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void legacy_proc_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PCI_LEGACY_PROC */
|
||||
|
||||
static int proc_bus_pci_dev_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &proc_bus_pci_devices_op);
|
||||
@ -606,7 +481,6 @@ static int __init pci_proc_init(void)
|
||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||
pci_proc_attach_device(dev);
|
||||
}
|
||||
legacy_proc_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -575,8 +575,11 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
|
||||
{
|
||||
unsigned char revid, tmp;
|
||||
|
||||
pci_msi_quirk = 1;
|
||||
printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
|
||||
if (dev->subordinate) {
|
||||
printk(KERN_WARNING "PCI: MSI quirk detected. "
|
||||
"PCI_BUS_FLAGS_NO_MSI set for subordinate bus.\n");
|
||||
dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
|
||||
}
|
||||
|
||||
if (nr_ioapics == 0)
|
||||
return;
|
||||
@ -934,6 +937,12 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
|
||||
case 0x12bd: /* HP D530 */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
|
||||
switch (dev->subsystem_device) {
|
||||
case 0x099c: /* HP Compaq nx6110 */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
}
|
||||
} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) {
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB)
|
||||
switch(dev->subsystem_device) {
|
||||
@ -1068,6 +1077,37 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, quirk_sis_96x_compatible );
|
||||
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 );
|
||||
/*
|
||||
* On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller
|
||||
* and MC97 modem controller are disabled when a second PCI soundcard is
|
||||
* present. This patch, tweaking the VT8237 ISA bridge, enables them.
|
||||
* -- bjd
|
||||
*/
|
||||
static void __init asus_hides_ac97_lpc(struct pci_dev *dev)
|
||||
{
|
||||
u8 val;
|
||||
int asus_hides_ac97 = 0;
|
||||
|
||||
if (likely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) {
|
||||
if (dev->device == PCI_DEVICE_ID_VIA_8237)
|
||||
asus_hides_ac97 = 1;
|
||||
}
|
||||
|
||||
if (!asus_hides_ac97)
|
||||
return;
|
||||
|
||||
pci_read_config_byte(dev, 0x50, &val);
|
||||
if (val & 0xc0) {
|
||||
pci_write_config_byte(dev, 0x50, val & (~0xc0));
|
||||
pci_read_config_byte(dev, 0x50, &val);
|
||||
if (val & 0xc0)
|
||||
printk(KERN_INFO "PCI: onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val);
|
||||
else
|
||||
printk(KERN_INFO "PCI: enabled onboard AC97/MC97 devices\n");
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );
|
||||
|
||||
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus );
|
||||
@ -1242,6 +1282,33 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_pc
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_pcie_pxh);
|
||||
|
||||
|
||||
/*
|
||||
* Fixup the cardbus bridges on the IBM Dock II docking station
|
||||
*/
|
||||
static void __devinit quirk_ibm_dock2_cardbus(struct pci_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
* tie the 2 interrupt pins to INTA, and configure the
|
||||
* multifunction routing register to handle this.
|
||||
*/
|
||||
if ((dev->subsystem_vendor == PCI_VENDOR_ID_IBM) &&
|
||||
(dev->subsystem_device == 0x0148)) {
|
||||
printk(KERN_INFO "PCI: Found IBM Dock II Cardbus Bridge "
|
||||
"applying quirk\n");
|
||||
pci_read_config_dword(dev, 0x8c, &val);
|
||||
val = ((val & 0xffffff00) | 0x1002);
|
||||
pci_write_config_dword(dev, 0x8c, val);
|
||||
pci_read_config_dword(dev, 0x80, &val);
|
||||
val = ((val & 0x00ffff00) | 0x2864c077);
|
||||
pci_write_config_dword(dev, 0x80, val);
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420,
|
||||
quirk_ibm_dock2_cardbus);
|
||||
|
||||
static void __devinit quirk_netmos(struct pci_dev *dev)
|
||||
{
|
||||
unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
|
||||
|
@ -246,9 +246,9 @@ pci_get_subsys(unsigned int vendor, unsigned int device,
|
||||
}
|
||||
dev = NULL;
|
||||
exit:
|
||||
pci_dev_put(from);
|
||||
dev = pci_dev_get(dev);
|
||||
spin_unlock(&pci_bus_lock);
|
||||
pci_dev_put(from);
|
||||
return dev;
|
||||
}
|
||||
|
||||
@ -339,9 +339,9 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
|
||||
}
|
||||
dev = NULL;
|
||||
exit:
|
||||
pci_dev_put(from);
|
||||
dev = pci_dev_get(dev);
|
||||
spin_unlock(&pci_bus_lock);
|
||||
pci_dev_put(from);
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
@ -330,6 +330,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver);
|
||||
int acpi_bus_unregister_driver(struct acpi_driver *driver);
|
||||
int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent,
|
||||
acpi_handle handle, int type);
|
||||
int acpi_bus_trim(struct acpi_device *start, int rmdevice);
|
||||
int acpi_bus_start(struct acpi_device *device);
|
||||
|
||||
int acpi_match_ids(struct acpi_device *device, char *ids);
|
||||
|
@ -95,6 +95,11 @@ enum pci_channel_state {
|
||||
pci_channel_io_perm_failure = (__force pci_channel_state_t) 3,
|
||||
};
|
||||
|
||||
typedef unsigned short __bitwise pci_bus_flags_t;
|
||||
enum pci_bus_flags {
|
||||
PCI_BUS_FLAGS_NO_MSI = (pci_bus_flags_t) 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* The pci_dev structure is used to describe PCI devices.
|
||||
*/
|
||||
@ -203,7 +208,7 @@ struct pci_bus {
|
||||
char name[48];
|
||||
|
||||
unsigned short bridge_ctl; /* manage NO_ISA/FBB/et al behaviors */
|
||||
unsigned short pad2;
|
||||
pci_bus_flags_t bus_flags; /* Inherited by child busses */
|
||||
struct device *bridge;
|
||||
struct class_device class_dev;
|
||||
struct bin_attribute *legacy_io; /* legacy I/O for this bus */
|
||||
@ -485,9 +490,9 @@ void pdev_sort_resources(struct pci_dev *, struct resource_list *);
|
||||
void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
|
||||
int (*)(struct pci_dev *, u8, u8));
|
||||
#define HAVE_PCI_REQ_REGIONS 2
|
||||
int pci_request_regions(struct pci_dev *, char *);
|
||||
int pci_request_regions(struct pci_dev *, const char *);
|
||||
void pci_release_regions(struct pci_dev *);
|
||||
int pci_request_region(struct pci_dev *, int, char *);
|
||||
int pci_request_region(struct pci_dev *, int, const char *);
|
||||
void pci_release_region(struct pci_dev *, int);
|
||||
|
||||
/* drivers/pci/bus.c */
|
||||
@ -516,6 +521,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
|
||||
void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
|
||||
void *userdata);
|
||||
int pci_cfg_space_size(struct pci_dev *dev);
|
||||
unsigned char pci_bus_max_busnr(struct pci_bus* bus);
|
||||
|
||||
/* kmem_cache style wrapper around pci_alloc_consistent() */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user