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:
Linus Torvalds 2006-03-23 15:49:57 -08:00
commit a3ea9b584e
64 changed files with 2204 additions and 2570 deletions

View file

@ -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).

View file

@ -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

View file

@ -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";

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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
View 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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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)
{

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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);

View 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);
}
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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) {

View file

@ -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
//-----------------------------------------------------------------------------

View file

@ -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;
}

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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);
}

View file

@ -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

View file

@ -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 */

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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:

View file

@ -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;

View file

@ -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);

View file

@ -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,

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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,
};

View file

@ -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";

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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() */