提交 59ef7a83 编写于 作者: L Linus Torvalds

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

* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (74 commits)
  PCI: make msi_free_irqs() to use msix_mask_irq() instead of open coded write
  PCI: Fix the NIU MSI-X problem in a better way
  PCI ASPM: remove get_root_port_link
  PCI ASPM: cleanup pcie_aspm_sanity_check
  PCI ASPM: remove has_switch field
  PCI ASPM: cleanup calc_Lx_latency
  PCI ASPM: cleanup pcie_aspm_get_cap_device
  PCI ASPM: cleanup clkpm checks
  PCI ASPM: cleanup __pcie_aspm_check_state_one
  PCI ASPM: cleanup initialization
  PCI ASPM: cleanup change input argument of aspm functions
  PCI ASPM: cleanup misc in struct pcie_link_state
  PCI ASPM: cleanup clkpm state in struct pcie_link_state
  PCI ASPM: cleanup latency field in struct pcie_link_state
  PCI ASPM: cleanup aspm state field in struct pcie_link_state
  PCI ASPM: fix typo in struct pcie_link_state
  PCI: drivers/pci/slot.c should depend on CONFIG_SYSFS
  PCI: remove redundant __msi_set_enable()
  PCI PM: consistently use type bool for wake enable variable
  x86/ACPI: Correct maximum allowed _CRS returned resources and warn if exceeded
  ...
...@@ -122,3 +122,10 @@ Description: ...@@ -122,3 +122,10 @@ Description:
This symbolic link appears when a device is a Virtual Function. This symbolic link appears when a device is a Virtual Function.
The symbolic link points to the PCI device sysfs entry of the The symbolic link points to the PCI device sysfs entry of the
Physical Function this device associates with. Physical Function this device associates with.
What: /sys/bus/pci/slots/.../module
Date: June 2009
Contact: linux-pci@vger.kernel.org
Description:
This symbolic link points to the PCI hotplug controller driver
module that manages the hotplug slot.
...@@ -61,6 +61,10 @@ be initiated although firmwares have no _OSC support. To enable the ...@@ -61,6 +61,10 @@ be initiated although firmwares have no _OSC support. To enable the
walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
when booting kernel. Note that forceload=n by default. when booting kernel. Note that forceload=n by default.
nosourceid, another parameter of type bool, can be used when broken
hardware (mostly chipsets) has root ports that cannot obtain the reporting
source ID. nosourceid=n by default.
2.3 AER error output 2.3 AER error output
When a PCI-E AER error is captured, an error message will be outputed to When a PCI-E AER error is captured, an error message will be outputed to
console. If it's a correctable error, it is outputed as a warning. console. If it's a correctable error, it is outputed as a warning.
...@@ -246,3 +250,24 @@ with the PCI Express AER Root driver? ...@@ -246,3 +250,24 @@ with the PCI Express AER Root driver?
A: It could call the helper functions to enable AER in devices and A: It could call the helper functions to enable AER in devices and
cleanup uncorrectable status register. Pls. refer to section 3.3. cleanup uncorrectable status register. Pls. refer to section 3.3.
4. Software error injection
Debugging PCIE AER error recovery code is quite difficult because it
is hard to trigger real hardware errors. Software based error
injection can be used to fake various kinds of PCIE errors.
First you should enable PCIE AER software error injection in kernel
configuration, that is, following item should be in your .config.
CONFIG_PCIEAER_INJECT=y or CONFIG_PCIEAER_INJECT=m
After reboot with new kernel or insert the module, a device file named
/dev/aer_inject should be created.
Then, you need a user space tool named aer-inject, which can be gotten
from:
http://www.kernel.org/pub/linux/utils/pci/aer-inject/
More information about aer-inject can be found in the document comes
with its source code.
...@@ -1776,6 +1776,9 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1776,6 +1776,9 @@ and is between 256 and 4096 characters. It is defined in the file
root domains (aka PCI segments, in ACPI-speak). root domains (aka PCI segments, in ACPI-speak).
nommconf [X86] Disable use of MMCONFIG for PCI nommconf [X86] Disable use of MMCONFIG for PCI
Configuration Configuration
check_enable_amd_mmconf [X86] check for and enable
properly configured MMIO access to PCI
config space on AMD family 10h CPU
nomsi [MSI] If the PCI_MSI kernel config parameter is nomsi [MSI] If the PCI_MSI kernel config parameter is
enabled, this kernel boot option can be used to enabled, this kernel boot option can be used to
disable the use of MSI interrupts system-wide. disable the use of MSI interrupts system-wide.
...@@ -1828,7 +1831,7 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1828,7 +1831,7 @@ and is between 256 and 4096 characters. It is defined in the file
IRQ routing is enabled. IRQ routing is enabled.
noacpi [X86] Do not use ACPI for IRQ routing noacpi [X86] Do not use ACPI for IRQ routing
or for PCI scanning. or for PCI scanning.
use_crs [X86] Use _CRS for PCI resource nocrs [X86] Don't use _CRS for PCI resource
allocation. allocation.
routeirq Do IRQ routing for all PCI devices. routeirq Do IRQ routing for all PCI devices.
This is normally done in pci_enable_device(), This is normally done in pci_enable_device(),
...@@ -1865,6 +1868,12 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1865,6 +1868,12 @@ and is between 256 and 4096 characters. It is defined in the file
PAGE_SIZE is used as alignment. PAGE_SIZE is used as alignment.
PCI-PCI bridge can be specified, if resource PCI-PCI bridge can be specified, if resource
windows need to be expanded. windows need to be expanded.
ecrc= Enable/disable PCIe ECRC (transaction layer
end-to-end CRC checking).
bios: Use BIOS/firmware settings. This is the
the default.
off: Turn ECRC off
on: Turn ECRC on.
pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power
Management. Management.
......
...@@ -122,7 +122,7 @@ static void eeh_enable_irq(struct pci_dev *dev) ...@@ -122,7 +122,7 @@ static void eeh_enable_irq(struct pci_dev *dev)
* passed back in "userdata". * passed back in "userdata".
*/ */
static void eeh_report_error(struct pci_dev *dev, void *userdata) static int eeh_report_error(struct pci_dev *dev, void *userdata)
{ {
enum pci_ers_result rc, *res = userdata; enum pci_ers_result rc, *res = userdata;
struct pci_driver *driver = dev->driver; struct pci_driver *driver = dev->driver;
...@@ -130,19 +130,21 @@ static void eeh_report_error(struct pci_dev *dev, void *userdata) ...@@ -130,19 +130,21 @@ static void eeh_report_error(struct pci_dev *dev, void *userdata)
dev->error_state = pci_channel_io_frozen; dev->error_state = pci_channel_io_frozen;
if (!driver) if (!driver)
return; return 0;
eeh_disable_irq(dev); eeh_disable_irq(dev);
if (!driver->err_handler || if (!driver->err_handler ||
!driver->err_handler->error_detected) !driver->err_handler->error_detected)
return; return 0;
rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen); rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen);
/* A driver that needs a reset trumps all others */ /* A driver that needs a reset trumps all others */
if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
if (*res == PCI_ERS_RESULT_NONE) *res = rc; if (*res == PCI_ERS_RESULT_NONE) *res = rc;
return 0;
} }
/** /**
...@@ -153,7 +155,7 @@ static void eeh_report_error(struct pci_dev *dev, void *userdata) ...@@ -153,7 +155,7 @@ static void eeh_report_error(struct pci_dev *dev, void *userdata)
* Cumulative response passed back in "userdata". * Cumulative response passed back in "userdata".
*/ */
static void eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
{ {
enum pci_ers_result rc, *res = userdata; enum pci_ers_result rc, *res = userdata;
struct pci_driver *driver = dev->driver; struct pci_driver *driver = dev->driver;
...@@ -161,26 +163,28 @@ static void eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) ...@@ -161,26 +163,28 @@ static void eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
if (!driver || if (!driver ||
!driver->err_handler || !driver->err_handler ||
!driver->err_handler->mmio_enabled) !driver->err_handler->mmio_enabled)
return; return 0;
rc = driver->err_handler->mmio_enabled (dev); rc = driver->err_handler->mmio_enabled (dev);
/* A driver that needs a reset trumps all others */ /* A driver that needs a reset trumps all others */
if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
if (*res == PCI_ERS_RESULT_NONE) *res = rc; if (*res == PCI_ERS_RESULT_NONE) *res = rc;
return 0;
} }
/** /**
* eeh_report_reset - tell device that slot has been reset * eeh_report_reset - tell device that slot has been reset
*/ */
static void eeh_report_reset(struct pci_dev *dev, void *userdata) static int eeh_report_reset(struct pci_dev *dev, void *userdata)
{ {
enum pci_ers_result rc, *res = userdata; enum pci_ers_result rc, *res = userdata;
struct pci_driver *driver = dev->driver; struct pci_driver *driver = dev->driver;
if (!driver) if (!driver)
return; return 0;
dev->error_state = pci_channel_io_normal; dev->error_state = pci_channel_io_normal;
...@@ -188,35 +192,39 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata) ...@@ -188,35 +192,39 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata)
if (!driver->err_handler || if (!driver->err_handler ||
!driver->err_handler->slot_reset) !driver->err_handler->slot_reset)
return; return 0;
rc = driver->err_handler->slot_reset(dev); rc = driver->err_handler->slot_reset(dev);
if ((*res == PCI_ERS_RESULT_NONE) || if ((*res == PCI_ERS_RESULT_NONE) ||
(*res == PCI_ERS_RESULT_RECOVERED)) *res = rc; (*res == PCI_ERS_RESULT_RECOVERED)) *res = rc;
if (*res == PCI_ERS_RESULT_DISCONNECT && if (*res == PCI_ERS_RESULT_DISCONNECT &&
rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
return 0;
} }
/** /**
* eeh_report_resume - tell device to resume normal operations * eeh_report_resume - tell device to resume normal operations
*/ */
static void eeh_report_resume(struct pci_dev *dev, void *userdata) static int eeh_report_resume(struct pci_dev *dev, void *userdata)
{ {
struct pci_driver *driver = dev->driver; struct pci_driver *driver = dev->driver;
dev->error_state = pci_channel_io_normal; dev->error_state = pci_channel_io_normal;
if (!driver) if (!driver)
return; return 0;
eeh_enable_irq(dev); eeh_enable_irq(dev);
if (!driver->err_handler || if (!driver->err_handler ||
!driver->err_handler->resume) !driver->err_handler->resume)
return; return 0;
driver->err_handler->resume(dev); driver->err_handler->resume(dev);
return 0;
} }
/** /**
...@@ -226,22 +234,24 @@ static void eeh_report_resume(struct pci_dev *dev, void *userdata) ...@@ -226,22 +234,24 @@ static void eeh_report_resume(struct pci_dev *dev, void *userdata)
* dead, and that no further recovery attempts will be made on it. * dead, and that no further recovery attempts will be made on it.
*/ */
static void eeh_report_failure(struct pci_dev *dev, void *userdata) static int eeh_report_failure(struct pci_dev *dev, void *userdata)
{ {
struct pci_driver *driver = dev->driver; struct pci_driver *driver = dev->driver;
dev->error_state = pci_channel_io_perm_failure; dev->error_state = pci_channel_io_perm_failure;
if (!driver) if (!driver)
return; return 0;
eeh_disable_irq(dev); eeh_disable_irq(dev);
if (!driver->err_handler || if (!driver->err_handler ||
!driver->err_handler->error_detected) !driver->err_handler->error_detected)
return; return 0;
driver->err_handler->error_detected(dev, pci_channel_io_perm_failure); driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
return 0;
} }
/* ------------------------------------------------------- */ /* ------------------------------------------------------- */
......
...@@ -130,6 +130,7 @@ extern void pci_iommu_alloc(void); ...@@ -130,6 +130,7 @@ extern void pci_iommu_alloc(void);
/* generic pci stuff */ /* generic pci stuff */
#include <asm-generic/pci.h> #include <asm-generic/pci.h>
#define PCIBIOS_MAX_MEM_32 0xffffffff
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
/* Returns the node based on pci bus */ /* Returns the node based on pci bus */
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#define PCI_BIOS_IRQ_SCAN 0x2000 #define PCI_BIOS_IRQ_SCAN 0x2000
#define PCI_ASSIGN_ALL_BUSSES 0x4000 #define PCI_ASSIGN_ALL_BUSSES 0x4000
#define PCI_CAN_SKIP_ISA_ALIGN 0x8000 #define PCI_CAN_SKIP_ISA_ALIGN 0x8000
#define PCI_USE__CRS 0x10000 #define PCI_NO_ROOT_CRS 0x10000
#define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000 #define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000
#define PCI_HAS_IO_ECS 0x40000 #define PCI_HAS_IO_ECS 0x40000
#define PCI_NOASSIGN_ROMS 0x80000 #define PCI_NOASSIGN_ROMS 0x80000
......
...@@ -38,15 +38,26 @@ count_resource(struct acpi_resource *acpi_res, void *data) ...@@ -38,15 +38,26 @@ count_resource(struct acpi_resource *acpi_res, void *data)
struct acpi_resource_address64 addr; struct acpi_resource_address64 addr;
acpi_status status; acpi_status status;
if (info->res_num >= PCI_BUS_NUM_RESOURCES)
return AE_OK;
status = resource_to_addr(acpi_res, &addr); status = resource_to_addr(acpi_res, &addr);
if (ACPI_SUCCESS(status)) if (ACPI_SUCCESS(status))
info->res_num++; info->res_num++;
return AE_OK; return AE_OK;
} }
static int
bus_has_transparent_bridge(struct pci_bus *bus)
{
struct pci_dev *dev;
list_for_each_entry(dev, &bus->devices, bus_list) {
u16 class = dev->class >> 8;
if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent)
return true;
}
return false;
}
static acpi_status static acpi_status
setup_resource(struct acpi_resource *acpi_res, void *data) setup_resource(struct acpi_resource *acpi_res, void *data)
{ {
...@@ -56,9 +67,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data) ...@@ -56,9 +67,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
acpi_status status; acpi_status status;
unsigned long flags; unsigned long flags;
struct resource *root; struct resource *root;
int max_root_bus_resources = PCI_BUS_NUM_RESOURCES;
if (info->res_num >= PCI_BUS_NUM_RESOURCES)
return AE_OK;
status = resource_to_addr(acpi_res, &addr); status = resource_to_addr(acpi_res, &addr);
if (!ACPI_SUCCESS(status)) if (!ACPI_SUCCESS(status))
...@@ -82,6 +91,18 @@ setup_resource(struct acpi_resource *acpi_res, void *data) ...@@ -82,6 +91,18 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
res->end = res->start + addr.address_length - 1; res->end = res->start + addr.address_length - 1;
res->child = NULL; res->child = NULL;
if (bus_has_transparent_bridge(info->bus))
max_root_bus_resources -= 3;
if (info->res_num >= max_root_bus_resources) {
printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx "
"from %s for %s due to _CRS returning more than "
"%d resource descriptors\n", (unsigned long) res->start,
(unsigned long) res->end, root->name, info->name,
max_root_bus_resources);
info->res_num++;
return AE_OK;
}
if (insert_resource(root, res)) { if (insert_resource(root, res)) {
printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx " printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
"from %s for %s\n", (unsigned long) res->start, "from %s for %s\n", (unsigned long) res->start,
...@@ -217,7 +238,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do ...@@ -217,7 +238,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
#endif #endif
} }
if (bus && (pci_probe & PCI_USE__CRS)) if (bus && !(pci_probe & PCI_NO_ROOT_CRS))
get_current_resources(device, busnum, domain, bus); get_current_resources(device, busnum, domain, bus);
return bus; return bus;
} }
......
...@@ -101,7 +101,7 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b) ...@@ -101,7 +101,7 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b)
struct pci_root_info *info; struct pci_root_info *info;
/* don't go for it if _CRS is used */ /* don't go for it if _CRS is used */
if (pci_probe & PCI_USE__CRS) if (!(pci_probe & PCI_NO_ROOT_CRS))
return; return;
/* if only one root bus, don't need to anything */ /* if only one root bus, don't need to anything */
......
...@@ -515,8 +515,8 @@ char * __devinit pcibios_setup(char *str) ...@@ -515,8 +515,8 @@ char * __devinit pcibios_setup(char *str)
} else if (!strcmp(str, "assign-busses")) { } else if (!strcmp(str, "assign-busses")) {
pci_probe |= PCI_ASSIGN_ALL_BUSSES; pci_probe |= PCI_ASSIGN_ALL_BUSSES;
return NULL; return NULL;
} else if (!strcmp(str, "use_crs")) { } else if (!strcmp(str, "nocrs")) {
pci_probe |= PCI_USE__CRS; pci_probe |= PCI_NO_ROOT_CRS;
return NULL; return NULL;
} else if (!strcmp(str, "earlydump")) { } else if (!strcmp(str, "earlydump")) {
pci_early_dump_regs = 1; pci_early_dump_regs = 1;
......
...@@ -266,6 +266,7 @@ config ACPI_DEBUG_FUNC_TRACE ...@@ -266,6 +266,7 @@ config ACPI_DEBUG_FUNC_TRACE
config ACPI_PCI_SLOT config ACPI_PCI_SLOT
tristate "PCI slot detection driver" tristate "PCI slot detection driver"
depends on SYSFS
default n default n
help help
This driver creates entries in /sys/bus/pci/slots/ for all PCI This driver creates entries in /sys/bus/pci/slots/ for all PCI
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
# Makefile for the PCI bus specific drivers. # Makefile for the PCI bus specific drivers.
# #
obj-y += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \ obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
irq.o irq.o
obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_SYSFS) += slot.o
# Build PCI Express stuff if needed # Build PCI Express stuff if needed
obj-$(CONFIG_PCIEPORTBUS) += pcie/ obj-$(CONFIG_PCIEPORTBUS) += pcie/
......
...@@ -66,6 +66,25 @@ EXPORT_SYMBOL(pci_bus_write_config_byte); ...@@ -66,6 +66,25 @@ EXPORT_SYMBOL(pci_bus_write_config_byte);
EXPORT_SYMBOL(pci_bus_write_config_word); EXPORT_SYMBOL(pci_bus_write_config_word);
EXPORT_SYMBOL(pci_bus_write_config_dword); EXPORT_SYMBOL(pci_bus_write_config_dword);
/**
* pci_bus_set_ops - Set raw operations of pci bus
* @bus: pci bus struct
* @ops: new raw operations
*
* Return previous raw operations
*/
struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops)
{
struct pci_ops *old_ops;
unsigned long flags;
spin_lock_irqsave(&pci_lock, flags);
old_ops = bus->ops;
bus->ops = ops;
spin_unlock_irqrestore(&pci_lock, flags);
return old_ops;
}
EXPORT_SYMBOL(pci_bus_set_ops);
/** /**
* pci_read_vpd - Read one entry from Vital Product Data * pci_read_vpd - Read one entry from Vital Product Data
......
...@@ -41,9 +41,14 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, ...@@ -41,9 +41,14 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
void *alignf_data) void *alignf_data)
{ {
int i, ret = -ENOMEM; int i, ret = -ENOMEM;
resource_size_t max = -1;
type_mask |= IORESOURCE_IO | IORESOURCE_MEM; type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
/* don't allocate too high if the pref mem doesn't support 64bit*/
if (!(res->flags & IORESOURCE_MEM_64))
max = PCIBIOS_MAX_MEM_32;
for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
struct resource *r = bus->resource[i]; struct resource *r = bus->resource[i];
if (!r) if (!r)
...@@ -62,7 +67,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, ...@@ -62,7 +67,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
/* Ok, try it out.. */ /* Ok, try it out.. */
ret = allocate_resource(r, res, size, ret = allocate_resource(r, res, size,
r->start ? : min, r->start ? : min,
-1, align, max, align,
alignf, alignf_data); alignf, alignf_data);
if (ret == 0) if (ret == 0)
break; break;
...@@ -201,13 +206,18 @@ void pci_enable_bridges(struct pci_bus *bus) ...@@ -201,13 +206,18 @@ void pci_enable_bridges(struct pci_bus *bus)
* Walk the given bus, including any bridged devices * Walk the given bus, including any bridged devices
* on buses under this bus. Call the provided callback * on buses under this bus. Call the provided callback
* on each device found. * on each device found.
*
* We check the return of @cb each time. If it returns anything
* other than 0, we break out.
*
*/ */
void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
void *userdata) void *userdata)
{ {
struct pci_dev *dev; struct pci_dev *dev;
struct pci_bus *bus; struct pci_bus *bus;
struct list_head *next; struct list_head *next;
int retval;
bus = top; bus = top;
down_read(&pci_bus_sem); down_read(&pci_bus_sem);
...@@ -231,8 +241,10 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), ...@@ -231,8 +241,10 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
/* Run device routines with the device locked */ /* Run device routines with the device locked */
down(&dev->dev.sem); down(&dev->dev.sem);
cb(dev, userdata); retval = cb(dev, userdata);
up(&dev->dev.sem); up(&dev->dev.sem);
if (retval)
break;
} }
up_read(&pci_bus_sem); up_read(&pci_bus_sem);
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
menuconfig HOTPLUG_PCI menuconfig HOTPLUG_PCI
tristate "Support for PCI Hotplug" tristate "Support for PCI Hotplug"
depends on PCI && HOTPLUG depends on PCI && HOTPLUG && SYSFS
---help--- ---help---
Say Y here if you have a motherboard with a PCI Hotplug controller. Say Y here if you have a motherboard with a PCI Hotplug controller.
This allows you to add and remove PCI cards while the machine is This allows you to add and remove PCI cards while the machine is
...@@ -41,7 +41,7 @@ config HOTPLUG_PCI_FAKE ...@@ -41,7 +41,7 @@ config HOTPLUG_PCI_FAKE
config HOTPLUG_PCI_COMPAQ config HOTPLUG_PCI_COMPAQ
tristate "Compaq PCI Hotplug driver" tristate "Compaq PCI Hotplug driver"
depends on X86 && PCI_BIOS && PCI_LEGACY depends on X86 && PCI_BIOS
help help
Say Y here if you have a motherboard with a Compaq PCI Hotplug Say Y here if you have a motherboard with a Compaq PCI Hotplug
controller. controller.
......
...@@ -77,7 +77,6 @@ static int get_latch_status (struct hotplug_slot *slot, u8 *value); ...@@ -77,7 +77,6 @@ static int get_latch_status (struct hotplug_slot *slot, u8 *value);
static int get_adapter_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
static struct hotplug_slot_ops acpi_hotplug_slot_ops = { static struct hotplug_slot_ops acpi_hotplug_slot_ops = {
.owner = THIS_MODULE,
.enable_slot = enable_slot, .enable_slot = enable_slot,
.disable_slot = disable_slot, .disable_slot = disable_slot,
.set_attention_status = set_attention_status, .set_attention_status = set_attention_status,
......
...@@ -72,7 +72,6 @@ static int get_adapter_status(struct hotplug_slot *slot, u8 * value); ...@@ -72,7 +72,6 @@ static int get_adapter_status(struct hotplug_slot *slot, u8 * value);
static int get_latch_status(struct hotplug_slot *slot, u8 * value); static int get_latch_status(struct hotplug_slot *slot, u8 * value);
static struct hotplug_slot_ops cpci_hotplug_slot_ops = { static struct hotplug_slot_ops cpci_hotplug_slot_ops = {
.owner = THIS_MODULE,
.enable_slot = enable_slot, .enable_slot = enable_slot,
.disable_slot = disable_slot, .disable_slot = disable_slot,
.set_attention_status = set_attention_status, .set_attention_status = set_attention_status,
......
...@@ -150,25 +150,25 @@ struct ctrl_reg { /* offset */ ...@@ -150,25 +150,25 @@ struct ctrl_reg { /* offset */
/* offsets to the controller registers based on the above structure layout */ /* offsets to the controller registers based on the above structure layout */
enum ctrl_offsets { enum ctrl_offsets {
SLOT_RST = offsetof(struct ctrl_reg, slot_RST), SLOT_RST = offsetof(struct ctrl_reg, slot_RST),
SLOT_ENABLE = offsetof(struct ctrl_reg, slot_enable), SLOT_ENABLE = offsetof(struct ctrl_reg, slot_enable),
MISC = offsetof(struct ctrl_reg, misc), MISC = offsetof(struct ctrl_reg, misc),
LED_CONTROL = offsetof(struct ctrl_reg, led_control), LED_CONTROL = offsetof(struct ctrl_reg, led_control),
INT_INPUT_CLEAR = offsetof(struct ctrl_reg, int_input_clear), INT_INPUT_CLEAR = offsetof(struct ctrl_reg, int_input_clear),
INT_MASK = offsetof(struct ctrl_reg, int_mask), INT_MASK = offsetof(struct ctrl_reg, int_mask),
CTRL_RESERVED0 = offsetof(struct ctrl_reg, reserved0), CTRL_RESERVED0 = offsetof(struct ctrl_reg, reserved0),
CTRL_RESERVED1 = offsetof(struct ctrl_reg, reserved1), CTRL_RESERVED1 = offsetof(struct ctrl_reg, reserved1),
CTRL_RESERVED2 = offsetof(struct ctrl_reg, reserved1), CTRL_RESERVED2 = offsetof(struct ctrl_reg, reserved1),
GEN_OUTPUT_AB = offsetof(struct ctrl_reg, gen_output_AB), GEN_OUTPUT_AB = offsetof(struct ctrl_reg, gen_output_AB),
NON_INT_INPUT = offsetof(struct ctrl_reg, non_int_input), NON_INT_INPUT = offsetof(struct ctrl_reg, non_int_input),
CTRL_RESERVED3 = offsetof(struct ctrl_reg, reserved3), CTRL_RESERVED3 = offsetof(struct ctrl_reg, reserved3),
CTRL_RESERVED4 = offsetof(struct ctrl_reg, reserved4), CTRL_RESERVED4 = offsetof(struct ctrl_reg, reserved4),
CTRL_RESERVED5 = offsetof(struct ctrl_reg, reserved5), CTRL_RESERVED5 = offsetof(struct ctrl_reg, reserved5),
CTRL_RESERVED6 = offsetof(struct ctrl_reg, reserved6), CTRL_RESERVED6 = offsetof(struct ctrl_reg, reserved6),
CTRL_RESERVED7 = offsetof(struct ctrl_reg, reserved7), CTRL_RESERVED7 = offsetof(struct ctrl_reg, reserved7),
CTRL_RESERVED8 = offsetof(struct ctrl_reg, reserved8), CTRL_RESERVED8 = offsetof(struct ctrl_reg, reserved8),
SLOT_MASK = offsetof(struct ctrl_reg, slot_mask), SLOT_MASK = offsetof(struct ctrl_reg, slot_mask),
CTRL_RESERVED9 = offsetof(struct ctrl_reg, reserved9), CTRL_RESERVED9 = offsetof(struct ctrl_reg, reserved9),
CTRL_RESERVED10 = offsetof(struct ctrl_reg, reserved10), CTRL_RESERVED10 = offsetof(struct ctrl_reg, reserved10),
CTRL_RESERVED11 = offsetof(struct ctrl_reg, reserved11), CTRL_RESERVED11 = offsetof(struct ctrl_reg, reserved11),
SLOT_SERR = offsetof(struct ctrl_reg, slot_SERR), SLOT_SERR = offsetof(struct ctrl_reg, slot_SERR),
...@@ -190,7 +190,9 @@ struct hrt { ...@@ -190,7 +190,9 @@ struct hrt {
u32 reserved2; u32 reserved2;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* offsets to the hotplug resource table registers based on the above structure layout */ /* offsets to the hotplug resource table registers based on the above
* structure layout
*/
enum hrt_offsets { enum hrt_offsets {
SIG0 = offsetof(struct hrt, sig0), SIG0 = offsetof(struct hrt, sig0),
SIG1 = offsetof(struct hrt, sig1), SIG1 = offsetof(struct hrt, sig1),
...@@ -217,18 +219,20 @@ struct slot_rt { ...@@ -217,18 +219,20 @@ struct slot_rt {
u16 pre_mem_length; u16 pre_mem_length;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* offsets to the hotplug slot resource table registers based on the above structure layout */ /* offsets to the hotplug slot resource table registers based on the above
* structure layout
*/
enum slot_rt_offsets { enum slot_rt_offsets {
DEV_FUNC = offsetof(struct slot_rt, dev_func), DEV_FUNC = offsetof(struct slot_rt, dev_func),
PRIMARY_BUS = offsetof(struct slot_rt, primary_bus), PRIMARY_BUS = offsetof(struct slot_rt, primary_bus),
SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus), SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus),
MAX_BUS = offsetof(struct slot_rt, max_bus), MAX_BUS = offsetof(struct slot_rt, max_bus),
IO_BASE = offsetof(struct slot_rt, io_base), IO_BASE = offsetof(struct slot_rt, io_base),
IO_LENGTH = offsetof(struct slot_rt, io_length), IO_LENGTH = offsetof(struct slot_rt, io_length),
MEM_BASE = offsetof(struct slot_rt, mem_base), MEM_BASE = offsetof(struct slot_rt, mem_base),
MEM_LENGTH = offsetof(struct slot_rt, mem_length), MEM_LENGTH = offsetof(struct slot_rt, mem_length),
PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base), PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base),
PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length), PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length),
}; };
struct pci_func { struct pci_func {
...@@ -286,8 +290,8 @@ struct event_info { ...@@ -286,8 +290,8 @@ struct event_info {
struct controller { struct controller {
struct controller *next; struct controller *next;
u32 ctrl_int_comp; u32 ctrl_int_comp;
struct mutex crit_sect; /* critical section mutex */ struct mutex crit_sect; /* critical section mutex */
void __iomem *hpc_reg; /* cookie for our pci controller location */ void __iomem *hpc_reg; /* cookie for our pci controller location */
struct pci_resource *mem_head; struct pci_resource *mem_head;
struct pci_resource *p_mem_head; struct pci_resource *p_mem_head;
struct pci_resource *io_head; struct pci_resource *io_head;
...@@ -299,7 +303,7 @@ struct controller { ...@@ -299,7 +303,7 @@ struct controller {
u8 next_event; u8 next_event;
u8 interrupt; u8 interrupt;
u8 cfgspc_irq; u8 cfgspc_irq;
u8 bus; /* bus number for the pci hotplug controller */ u8 bus; /* bus number for the pci hotplug controller */
u8 rev; u8 rev;
u8 slot_device_offset; u8 slot_device_offset;
u8 first_slot; u8 first_slot;
...@@ -401,46 +405,57 @@ struct resource_lists { ...@@ -401,46 +405,57 @@ struct resource_lists {
/* debugfs functions for the hotplug controller info */ /* debugfs functions for the hotplug controller info */
extern void cpqhp_initialize_debugfs (void); extern void cpqhp_initialize_debugfs(void);
extern void cpqhp_shutdown_debugfs (void); extern void cpqhp_shutdown_debugfs(void);
extern void cpqhp_create_debugfs_files (struct controller *ctrl); extern void cpqhp_create_debugfs_files(struct controller *ctrl);
extern void cpqhp_remove_debugfs_files (struct controller *ctrl); extern void cpqhp_remove_debugfs_files(struct controller *ctrl);
/* controller functions */ /* controller functions */
extern void cpqhp_pushbutton_thread (unsigned long event_pointer); extern void cpqhp_pushbutton_thread(unsigned long event_pointer);
extern irqreturn_t cpqhp_ctrl_intr (int IRQ, void *data); extern irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data);
extern int cpqhp_find_available_resources (struct controller *ctrl, void __iomem *rom_start); extern int cpqhp_find_available_resources(struct controller *ctrl,
extern int cpqhp_event_start_thread (void); void __iomem *rom_start);
extern void cpqhp_event_stop_thread (void); extern int cpqhp_event_start_thread(void);
extern struct pci_func *cpqhp_slot_create (unsigned char busnumber); extern void cpqhp_event_stop_thread(void);
extern struct pci_func *cpqhp_slot_find (unsigned char bus, unsigned char device, unsigned char index); extern struct pci_func *cpqhp_slot_create(unsigned char busnumber);
extern int cpqhp_process_SI (struct controller *ctrl, struct pci_func *func); extern struct pci_func *cpqhp_slot_find(unsigned char bus, unsigned char device,
extern int cpqhp_process_SS (struct controller *ctrl, struct pci_func *func); unsigned char index);
extern int cpqhp_hardware_test (struct controller *ctrl, int test_num); extern int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func);
extern int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func);
extern int cpqhp_hardware_test(struct controller *ctrl, int test_num);
/* resource functions */ /* resource functions */
extern int cpqhp_resource_sort_and_combine (struct pci_resource **head); extern int cpqhp_resource_sort_and_combine (struct pci_resource **head);
/* pci functions */ /* pci functions */
extern int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); extern int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
extern int cpqhp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot); extern int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num,
extern int cpqhp_save_config (struct controller *ctrl, int busnumber, int is_hot_plug); u8 slot);
extern int cpqhp_save_base_addr_length (struct controller *ctrl, struct pci_func * func); extern int cpqhp_save_config(struct controller *ctrl, int busnumber,
extern int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func); int is_hot_plug);
extern int cpqhp_configure_board (struct controller *ctrl, struct pci_func * func); extern int cpqhp_save_base_addr_length(struct controller *ctrl,
extern int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot); struct pci_func *func);
extern int cpqhp_valid_replace (struct controller *ctrl, struct pci_func * func); extern int cpqhp_save_used_resources(struct controller *ctrl,
extern void cpqhp_destroy_board_resources (struct pci_func * func); struct pci_func *func);
extern int cpqhp_return_board_resources (struct pci_func * func, struct resource_lists * resources); extern int cpqhp_configure_board(struct controller *ctrl,
extern void cpqhp_destroy_resource_list (struct resource_lists * resources); struct pci_func *func);
extern int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func); extern int cpqhp_save_slot_config(struct controller *ctrl,
extern int cpqhp_unconfigure_device (struct pci_func* func); struct pci_func *new_slot);
extern int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func);
extern void cpqhp_destroy_board_resources(struct pci_func *func);
extern int cpqhp_return_board_resources (struct pci_func *func,
struct resource_lists *resources);
extern void cpqhp_destroy_resource_list(struct resource_lists *resources);
extern int cpqhp_configure_device(struct controller *ctrl,
struct pci_func *func);
extern int cpqhp_unconfigure_device(struct pci_func *func);
/* Global variables */ /* Global variables */
extern int cpqhp_debug; extern int cpqhp_debug;
extern int cpqhp_legacy_mode; extern int cpqhp_legacy_mode;
extern struct controller *cpqhp_ctrl_list; extern struct controller *cpqhp_ctrl_list;
extern struct pci_func *cpqhp_slot_list[256]; extern struct pci_func *cpqhp_slot_list[256];
extern struct irq_routing_table *cpqhp_routing_table;
/* these can be gotten rid of, but for debugging they are purty */ /* these can be gotten rid of, but for debugging they are purty */
extern u8 cpqhp_nic_irq; extern u8 cpqhp_nic_irq;
...@@ -449,7 +464,7 @@ extern u8 cpqhp_disk_irq; ...@@ -449,7 +464,7 @@ extern u8 cpqhp_disk_irq;
/* inline functions */ /* inline functions */
static inline char *slot_name(struct slot *slot) static inline const char *slot_name(struct slot *slot)
{ {
return hotplug_slot_name(slot->hotplug_slot); return hotplug_slot_name(slot->hotplug_slot);
} }
...@@ -458,9 +473,9 @@ static inline char *slot_name(struct slot *slot) ...@@ -458,9 +473,9 @@ static inline char *slot_name(struct slot *slot)
* return_resource * return_resource
* *
* Puts node back in the resource list pointed to by head * Puts node back in the resource list pointed to by head
*
*/ */
static inline void return_resource(struct pci_resource **head, struct pci_resource *node) static inline void return_resource(struct pci_resource **head,
struct pci_resource *node)
{ {
if (!node || !head) if (!node || !head)
return; return;
...@@ -471,7 +486,7 @@ static inline void return_resource(struct pci_resource **head, struct pci_resour ...@@ -471,7 +486,7 @@ static inline void return_resource(struct pci_resource **head, struct pci_resour
static inline void set_SOGO(struct controller *ctrl) static inline void set_SOGO(struct controller *ctrl)
{ {
u16 misc; u16 misc;
misc = readw(ctrl->hpc_reg + MISC); misc = readw(ctrl->hpc_reg + MISC);
misc = (misc | 0x0001) & 0xFFFB; misc = (misc | 0x0001) & 0xFFFB;
writew(misc, ctrl->hpc_reg + MISC); writew(misc, ctrl->hpc_reg + MISC);
...@@ -481,7 +496,7 @@ static inline void set_SOGO(struct controller *ctrl) ...@@ -481,7 +496,7 @@ static inline void set_SOGO(struct controller *ctrl)
static inline void amber_LED_on(struct controller *ctrl, u8 slot) static inline void amber_LED_on(struct controller *ctrl, u8 slot)
{ {
u32 led_control; u32 led_control;
led_control = readl(ctrl->hpc_reg + LED_CONTROL); led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control |= (0x01010000L << slot); led_control |= (0x01010000L << slot);
writel(led_control, ctrl->hpc_reg + LED_CONTROL); writel(led_control, ctrl->hpc_reg + LED_CONTROL);
...@@ -491,7 +506,7 @@ static inline void amber_LED_on(struct controller *ctrl, u8 slot) ...@@ -491,7 +506,7 @@ static inline void amber_LED_on(struct controller *ctrl, u8 slot)
static inline void amber_LED_off(struct controller *ctrl, u8 slot) static inline void amber_LED_off(struct controller *ctrl, u8 slot)
{ {
u32 led_control; u32 led_control;
led_control = readl(ctrl->hpc_reg + LED_CONTROL); led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control &= ~(0x01010000L << slot); led_control &= ~(0x01010000L << slot);
writel(led_control, ctrl->hpc_reg + LED_CONTROL); writel(led_control, ctrl->hpc_reg + LED_CONTROL);
...@@ -504,7 +519,7 @@ static inline int read_amber_LED(struct controller *ctrl, u8 slot) ...@@ -504,7 +519,7 @@ static inline int read_amber_LED(struct controller *ctrl, u8 slot)
led_control = readl(ctrl->hpc_reg + LED_CONTROL); led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control &= (0x01010000L << slot); led_control &= (0x01010000L << slot);
return led_control ? 1 : 0; return led_control ? 1 : 0;
} }
...@@ -512,7 +527,7 @@ static inline int read_amber_LED(struct controller *ctrl, u8 slot) ...@@ -512,7 +527,7 @@ static inline int read_amber_LED(struct controller *ctrl, u8 slot)
static inline void green_LED_on(struct controller *ctrl, u8 slot) static inline void green_LED_on(struct controller *ctrl, u8 slot)
{ {
u32 led_control; u32 led_control;
led_control = readl(ctrl->hpc_reg + LED_CONTROL); led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control |= 0x0101L << slot; led_control |= 0x0101L << slot;
writel(led_control, ctrl->hpc_reg + LED_CONTROL); writel(led_control, ctrl->hpc_reg + LED_CONTROL);
...@@ -521,7 +536,7 @@ static inline void green_LED_on(struct controller *ctrl, u8 slot) ...@@ -521,7 +536,7 @@ static inline void green_LED_on(struct controller *ctrl, u8 slot)
static inline void green_LED_off(struct controller *ctrl, u8 slot) static inline void green_LED_off(struct controller *ctrl, u8 slot)
{ {
u32 led_control; u32 led_control;
led_control = readl(ctrl->hpc_reg + LED_CONTROL); led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control &= ~(0x0101L << slot); led_control &= ~(0x0101L << slot);
writel(led_control, ctrl->hpc_reg + LED_CONTROL); writel(led_control, ctrl->hpc_reg + LED_CONTROL);
...@@ -531,7 +546,7 @@ static inline void green_LED_off(struct controller *ctrl, u8 slot) ...@@ -531,7 +546,7 @@ static inline void green_LED_off(struct controller *ctrl, u8 slot)
static inline void green_LED_blink(struct controller *ctrl, u8 slot) static inline void green_LED_blink(struct controller *ctrl, u8 slot)
{ {
u32 led_control; u32 led_control;
led_control = readl(ctrl->hpc_reg + LED_CONTROL); led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control &= ~(0x0101L << slot); led_control &= ~(0x0101L << slot);
led_control |= (0x0001L << slot); led_control |= (0x0001L << slot);
...@@ -575,22 +590,21 @@ static inline u8 read_slot_enable(struct controller *ctrl) ...@@ -575,22 +590,21 @@ static inline u8 read_slot_enable(struct controller *ctrl)
} }
/* /**
* get_controller_speed - find the current frequency/mode of controller. * get_controller_speed - find the current frequency/mode of controller.
* *
* @ctrl: controller to get frequency/mode for. * @ctrl: controller to get frequency/mode for.
* *
* Returns controller speed. * Returns controller speed.
*
*/ */
static inline u8 get_controller_speed(struct controller *ctrl) static inline u8 get_controller_speed(struct controller *ctrl)
{ {
u8 curr_freq; u8 curr_freq;
u16 misc; u16 misc;
if (ctrl->pcix_support) { if (ctrl->pcix_support) {
curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ); curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ);
if ((curr_freq & 0xB0) == 0xB0) if ((curr_freq & 0xB0) == 0xB0)
return PCI_SPEED_133MHz_PCIX; return PCI_SPEED_133MHz_PCIX;
if ((curr_freq & 0xA0) == 0xA0) if ((curr_freq & 0xA0) == 0xA0)
return PCI_SPEED_100MHz_PCIX; return PCI_SPEED_100MHz_PCIX;
...@@ -602,19 +616,18 @@ static inline u8 get_controller_speed(struct controller *ctrl) ...@@ -602,19 +616,18 @@ static inline u8 get_controller_speed(struct controller *ctrl)
return PCI_SPEED_33MHz; return PCI_SPEED_33MHz;
} }
misc = readw(ctrl->hpc_reg + MISC); misc = readw(ctrl->hpc_reg + MISC);
return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
} }
/*
/**
* get_adapter_speed - find the max supported frequency/mode of adapter. * get_adapter_speed - find the max supported frequency/mode of adapter.
* *
* @ctrl: hotplug controller. * @ctrl: hotplug controller.
* @hp_slot: hotplug slot where adapter is installed. * @hp_slot: hotplug slot where adapter is installed.
* *
* Returns adapter speed. * Returns adapter speed.
*
*/ */
static inline u8 get_adapter_speed(struct controller *ctrl, u8 hp_slot) static inline u8 get_adapter_speed(struct controller *ctrl, u8 hp_slot)
{ {
...@@ -672,7 +685,8 @@ static inline int get_slot_enabled(struct controller *ctrl, struct slot *slot) ...@@ -672,7 +685,8 @@ static inline int get_slot_enabled(struct controller *ctrl, struct slot *slot)
} }
static inline int cpq_get_latch_status(struct controller *ctrl, struct slot *slot) static inline int cpq_get_latch_status(struct controller *ctrl,
struct slot *slot)
{ {
u32 status; u32 status;
u8 hp_slot; u8 hp_slot;
...@@ -687,7 +701,8 @@ static inline int cpq_get_latch_status(struct controller *ctrl, struct slot *slo ...@@ -687,7 +701,8 @@ static inline int cpq_get_latch_status(struct controller *ctrl, struct slot *slo
} }
static inline int get_presence_status(struct controller *ctrl, struct slot *slot) static inline int get_presence_status(struct controller *ctrl,
struct slot *slot)
{ {
int presence_save = 0; int presence_save = 0;
u8 hp_slot; u8 hp_slot;
...@@ -696,7 +711,8 @@ static inline int get_presence_status(struct controller *ctrl, struct slot *slot ...@@ -696,7 +711,8 @@ static inline int get_presence_status(struct controller *ctrl, struct slot *slot
hp_slot = slot->device - ctrl->slot_device_offset; hp_slot = slot->device - ctrl->slot_device_offset;
tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
presence_save = (int) ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> hp_slot) & 0x02; presence_save = (int) ((((~tempdword) >> 23) | ((~tempdword) >> 15))
>> hp_slot) & 0x02;
return presence_save; return presence_save;
} }
...@@ -718,5 +734,12 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl) ...@@ -718,5 +734,12 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl)
return retval; return retval;
} }
#endif #include <asm/pci_x86.h>
static inline int cpqhp_routing_table_length(void)
{
BUG_ON(cpqhp_routing_table == NULL);
return ((cpqhp_routing_table->size - sizeof(struct irq_routing_table)) /
sizeof(struct irq_info));
}
#endif
此差异已折叠。
此差异已折叠。
...@@ -94,12 +94,13 @@ static u8 evbuffer[1024]; ...@@ -94,12 +94,13 @@ static u8 evbuffer[1024];
static void __iomem *compaq_int15_entry_point; static void __iomem *compaq_int15_entry_point;
static spinlock_t int15_lock; /* lock for ordering int15_bios_call() */ /* lock for ordering int15_bios_call() */
static spinlock_t int15_lock;
/* This is a series of function that deals with /* This is a series of function that deals with
setting & getting the hotplug resource table in some environment variable. * setting & getting the hotplug resource table in some environment variable.
*/ */
/* /*
* We really shouldn't be doing this unless there is a _very_ good reason to!!! * We really shouldn't be doing this unless there is a _very_ good reason to!!!
...@@ -113,7 +114,7 @@ static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail) ...@@ -113,7 +114,7 @@ static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail)
if ((*used + 1) > *avail) if ((*used + 1) > *avail)
return(1); return(1);
*((u8*)*p_buffer) = value; *((u8*)*p_buffer) = value;
tByte = (u8**)p_buffer; tByte = (u8**)p_buffer;
(*tByte)++; (*tByte)++;
...@@ -170,10 +171,10 @@ static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size) ...@@ -170,10 +171,10 @@ static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
unsigned long flags; unsigned long flags;
int op = operation; int op = operation;
int ret_val; int ret_val;
if (!compaq_int15_entry_point) if (!compaq_int15_entry_point)
return -ENODEV; return -ENODEV;
spin_lock_irqsave(&int15_lock, flags); spin_lock_irqsave(&int15_lock, flags);
__asm__ ( __asm__ (
"xorl %%ebx,%%ebx\n" \ "xorl %%ebx,%%ebx\n" \
...@@ -187,7 +188,7 @@ static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size) ...@@ -187,7 +188,7 @@ static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
"D" (buffer), "m" (compaq_int15_entry_point) "D" (buffer), "m" (compaq_int15_entry_point)
: "%ebx", "%edx"); : "%ebx", "%edx");
spin_unlock_irqrestore(&int15_lock, flags); spin_unlock_irqrestore(&int15_lock, flags);
return((ret_val & 0xFF00) >> 8); return((ret_val & 0xFF00) >> 8);
} }
...@@ -210,14 +211,16 @@ static int load_HRT (void __iomem *rom_start) ...@@ -210,14 +211,16 @@ static int load_HRT (void __iomem *rom_start)
available = 1024; available = 1024;
// Now load the EV /* Now load the EV */
temp_dword = available; temp_dword = available;
rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword); rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword);
evbuffer_length = temp_dword; evbuffer_length = temp_dword;
// We're maintaining the resource lists so write FF to invalidate old info /* We're maintaining the resource lists so write FF to invalidate old
* info
*/
temp_dword = 1; temp_dword = 1;
rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword); rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword);
...@@ -263,13 +266,13 @@ static u32 store_HRT (void __iomem *rom_start) ...@@ -263,13 +266,13 @@ static u32 store_HRT (void __iomem *rom_start)
p_EV_header = (struct ev_hrt_header *) pFill; p_EV_header = (struct ev_hrt_header *) pFill;
ctrl = cpqhp_ctrl_list; ctrl = cpqhp_ctrl_list;
// The revision of this structure /* The revision of this structure */
rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available); rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
// The number of controllers /* The number of controllers */
rc = add_byte( &pFill, 1, &usedbytes, &available); rc = add_byte( &pFill, 1, &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
...@@ -279,27 +282,27 @@ static u32 store_HRT (void __iomem *rom_start) ...@@ -279,27 +282,27 @@ static u32 store_HRT (void __iomem *rom_start)
numCtrl++; numCtrl++;
// The bus number /* The bus number */
rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available); rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
// The device Number /* The device Number */
rc = add_byte( &pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available); rc = add_byte( &pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
// The function Number /* The function Number */
rc = add_byte( &pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available); rc = add_byte( &pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
// Skip the number of available entries /* Skip the number of available entries */
rc = add_dword( &pFill, 0, &usedbytes, &available); rc = add_dword( &pFill, 0, &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
// Figure out memory Available /* Figure out memory Available */
resNode = ctrl->mem_head; resNode = ctrl->mem_head;
...@@ -308,12 +311,12 @@ static u32 store_HRT (void __iomem *rom_start) ...@@ -308,12 +311,12 @@ static u32 store_HRT (void __iomem *rom_start)
while (resNode) { while (resNode) {
loop ++; loop ++;
// base /* base */
rc = add_dword( &pFill, resNode->base, &usedbytes, &available); rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
// length /* length */
rc = add_dword( &pFill, resNode->length, &usedbytes, &available); rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
...@@ -321,10 +324,10 @@ static u32 store_HRT (void __iomem *rom_start) ...@@ -321,10 +324,10 @@ static u32 store_HRT (void __iomem *rom_start)
resNode = resNode->next; resNode = resNode->next;
} }
// Fill in the number of entries /* Fill in the number of entries */
p_ev_ctrl->mem_avail = loop; p_ev_ctrl->mem_avail = loop;
// Figure out prefetchable memory Available /* Figure out prefetchable memory Available */
resNode = ctrl->p_mem_head; resNode = ctrl->p_mem_head;
...@@ -333,12 +336,12 @@ static u32 store_HRT (void __iomem *rom_start) ...@@ -333,12 +336,12 @@ static u32 store_HRT (void __iomem *rom_start)
while (resNode) { while (resNode) {
loop ++; loop ++;
// base /* base */
rc = add_dword( &pFill, resNode->base, &usedbytes, &available); rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
// length /* length */
rc = add_dword( &pFill, resNode->length, &usedbytes, &available); rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
...@@ -346,10 +349,10 @@ static u32 store_HRT (void __iomem *rom_start) ...@@ -346,10 +349,10 @@ static u32 store_HRT (void __iomem *rom_start)
resNode = resNode->next; resNode = resNode->next;
} }
// Fill in the number of entries /* Fill in the number of entries */
p_ev_ctrl->p_mem_avail = loop; p_ev_ctrl->p_mem_avail = loop;
// Figure out IO Available /* Figure out IO Available */
resNode = ctrl->io_head; resNode = ctrl->io_head;
...@@ -358,12 +361,12 @@ static u32 store_HRT (void __iomem *rom_start) ...@@ -358,12 +361,12 @@ static u32 store_HRT (void __iomem *rom_start)
while (resNode) { while (resNode) {
loop ++; loop ++;
// base /* base */
rc = add_dword( &pFill, resNode->base, &usedbytes, &available); rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
// length /* length */
rc = add_dword( &pFill, resNode->length, &usedbytes, &available); rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
...@@ -371,10 +374,10 @@ static u32 store_HRT (void __iomem *rom_start) ...@@ -371,10 +374,10 @@ static u32 store_HRT (void __iomem *rom_start)
resNode = resNode->next; resNode = resNode->next;
} }
// Fill in the number of entries /* Fill in the number of entries */
p_ev_ctrl->io_avail = loop; p_ev_ctrl->io_avail = loop;
// Figure out bus Available /* Figure out bus Available */
resNode = ctrl->bus_head; resNode = ctrl->bus_head;
...@@ -383,12 +386,12 @@ static u32 store_HRT (void __iomem *rom_start) ...@@ -383,12 +386,12 @@ static u32 store_HRT (void __iomem *rom_start)
while (resNode) { while (resNode) {
loop ++; loop ++;
// base /* base */
rc = add_dword( &pFill, resNode->base, &usedbytes, &available); rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
// length /* length */
rc = add_dword( &pFill, resNode->length, &usedbytes, &available); rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
if (rc) if (rc)
return(rc); return(rc);
...@@ -396,15 +399,15 @@ static u32 store_HRT (void __iomem *rom_start) ...@@ -396,15 +399,15 @@ static u32 store_HRT (void __iomem *rom_start)
resNode = resNode->next; resNode = resNode->next;
} }
// Fill in the number of entries /* Fill in the number of entries */
p_ev_ctrl->bus_avail = loop; p_ev_ctrl->bus_avail = loop;
ctrl = ctrl->next; ctrl = ctrl->next;
} }
p_EV_header->num_of_ctrl = numCtrl; p_EV_header->num_of_ctrl = numCtrl;
// Now store the EV /* Now store the EV */
temp_dword = usedbytes; temp_dword = usedbytes;
...@@ -449,20 +452,21 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) ...@@ -449,20 +452,21 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
struct ev_hrt_header *p_EV_header; struct ev_hrt_header *p_EV_header;
if (!evbuffer_init) { if (!evbuffer_init) {
// Read the resource list information in from NVRAM /* Read the resource list information in from NVRAM */
if (load_HRT(rom_start)) if (load_HRT(rom_start))
memset (evbuffer, 0, 1024); memset (evbuffer, 0, 1024);
evbuffer_init = 1; evbuffer_init = 1;
} }
// If we saved information in NVRAM, use it now /* If we saved information in NVRAM, use it now */
p_EV_header = (struct ev_hrt_header *) evbuffer; p_EV_header = (struct ev_hrt_header *) evbuffer;
// The following code is for systems where version 1.0 of this /* The following code is for systems where version 1.0 of this
// driver has been loaded, but doesn't support the hardware. * driver has been loaded, but doesn't support the hardware.
// In that case, the driver would incorrectly store something * In that case, the driver would incorrectly store something
// in NVRAM. * in NVRAM.
*/
if ((p_EV_header->Version == 2) || if ((p_EV_header->Version == 2) ||
((p_EV_header->Version == 1) && !ctrl->push_flag)) { ((p_EV_header->Version == 1) && !ctrl->push_flag)) {
p_byte = &(p_EV_header->next); p_byte = &(p_EV_header->next);
...@@ -479,7 +483,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) ...@@ -479,7 +483,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
function = p_ev_ctrl->function; function = p_ev_ctrl->function;
while ((bus != ctrl->bus) || while ((bus != ctrl->bus) ||
(device != PCI_SLOT(ctrl->pci_dev->devfn)) || (device != PCI_SLOT(ctrl->pci_dev->devfn)) ||
(function != PCI_FUNC(ctrl->pci_dev->devfn))) { (function != PCI_FUNC(ctrl->pci_dev->devfn))) {
nummem = p_ev_ctrl->mem_avail; nummem = p_ev_ctrl->mem_avail;
numpmem = p_ev_ctrl->p_mem_avail; numpmem = p_ev_ctrl->p_mem_avail;
...@@ -491,7 +495,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) ...@@ -491,7 +495,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length))
return 2; return 2;
// Skip forward to the next entry /* Skip forward to the next entry */
p_byte += (nummem + numpmem + numio + numbus) * 8; p_byte += (nummem + numpmem + numio + numbus) * 8;
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) if (p_byte > ((u8*)p_EV_header + evbuffer_length))
...@@ -629,8 +633,9 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) ...@@ -629,8 +633,9 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
ctrl->bus_head = bus_node; ctrl->bus_head = bus_node;
} }
// If all of the following fail, we don't have any resources for /* If all of the following fail, we don't have any resources for
// hot plug add * hot plug add
*/
rc = 1; rc = 1;
rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head)); rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head)); rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
...@@ -640,14 +645,14 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) ...@@ -640,14 +645,14 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
if (rc) if (rc)
return(rc); return(rc);
} else { } else {
if ((evbuffer[0] != 0) && (!ctrl->push_flag)) if ((evbuffer[0] != 0) && (!ctrl->push_flag))
return 1; return 1;
} }
return 0; return 0;
} }
int compaq_nvram_store (void __iomem *rom_start) int compaq_nvram_store (void __iomem *rom_start)
{ {
int rc = 1; int rc = 1;
......
此差异已折叠。
...@@ -1318,7 +1318,6 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) ...@@ -1318,7 +1318,6 @@ int ibmphp_do_disable_slot(struct slot *slot_cur)
} }
struct hotplug_slot_ops ibmphp_hotplug_slot_ops = { struct hotplug_slot_ops ibmphp_hotplug_slot_ops = {
.owner = THIS_MODULE,
.set_attention_status = set_attention_status, .set_attention_status = set_attention_status,
.enable_slot = enable_slot, .enable_slot = enable_slot,
.disable_slot = ibmphp_disable_slot, .disable_slot = ibmphp_disable_slot,
...@@ -1421,3 +1420,4 @@ static void __exit ibmphp_exit(void) ...@@ -1421,3 +1420,4 @@ static void __exit ibmphp_exit(void)
} }
module_init(ibmphp_init); module_init(ibmphp_init);
module_exit(ibmphp_exit);
...@@ -347,125 +347,129 @@ static struct pci_slot_attribute hotplug_slot_attr_test = { ...@@ -347,125 +347,129 @@ static struct pci_slot_attribute hotplug_slot_attr_test = {
.store = test_write_file .store = test_write_file
}; };
static int has_power_file(struct pci_slot *pci_slot) static bool has_power_file(struct pci_slot *pci_slot)
{ {
struct hotplug_slot *slot = pci_slot->hotplug; struct hotplug_slot *slot = pci_slot->hotplug;
if ((!slot) || (!slot->ops)) if ((!slot) || (!slot->ops))
return -ENODEV; return false;
if ((slot->ops->enable_slot) || if ((slot->ops->enable_slot) ||
(slot->ops->disable_slot) || (slot->ops->disable_slot) ||
(slot->ops->get_power_status)) (slot->ops->get_power_status))
return 0; return true;
return -ENOENT; return false;
} }
static int has_attention_file(struct pci_slot *pci_slot) static bool has_attention_file(struct pci_slot *pci_slot)
{ {
struct hotplug_slot *slot = pci_slot->hotplug; struct hotplug_slot *slot = pci_slot->hotplug;
if ((!slot) || (!slot->ops)) if ((!slot) || (!slot->ops))
return -ENODEV; return false;
if ((slot->ops->set_attention_status) || if ((slot->ops->set_attention_status) ||
(slot->ops->get_attention_status)) (slot->ops->get_attention_status))
return 0; return true;
return -ENOENT; return false;
} }
static int has_latch_file(struct pci_slot *pci_slot) static bool has_latch_file(struct pci_slot *pci_slot)
{ {
struct hotplug_slot *slot = pci_slot->hotplug; struct hotplug_slot *slot = pci_slot->hotplug;
if ((!slot) || (!slot->ops)) if ((!slot) || (!slot->ops))
return -ENODEV; return false;
if (slot->ops->get_latch_status) if (slot->ops->get_latch_status)
return 0; return true;
return -ENOENT; return false;
} }
static int has_adapter_file(struct pci_slot *pci_slot) static bool has_adapter_file(struct pci_slot *pci_slot)
{ {
struct hotplug_slot *slot = pci_slot->hotplug; struct hotplug_slot *slot = pci_slot->hotplug;
if ((!slot) || (!slot->ops)) if ((!slot) || (!slot->ops))
return -ENODEV; return false;
if (slot->ops->get_adapter_status) if (slot->ops->get_adapter_status)
return 0; return true;
return -ENOENT; return false;
} }
static int has_max_bus_speed_file(struct pci_slot *pci_slot) static bool has_max_bus_speed_file(struct pci_slot *pci_slot)
{ {
struct hotplug_slot *slot = pci_slot->hotplug; struct hotplug_slot *slot = pci_slot->hotplug;
if ((!slot) || (!slot->ops)) if ((!slot) || (!slot->ops))
return -ENODEV; return false;
if (slot->ops->get_max_bus_speed) if (slot->ops->get_max_bus_speed)
return 0; return true;
return -ENOENT; return false;
} }
static int has_cur_bus_speed_file(struct pci_slot *pci_slot) static bool has_cur_bus_speed_file(struct pci_slot *pci_slot)
{ {
struct hotplug_slot *slot = pci_slot->hotplug; struct hotplug_slot *slot = pci_slot->hotplug;
if ((!slot) || (!slot->ops)) if ((!slot) || (!slot->ops))
return -ENODEV; return false;
if (slot->ops->get_cur_bus_speed) if (slot->ops->get_cur_bus_speed)
return 0; return true;
return -ENOENT; return false;
} }
static int has_test_file(struct pci_slot *pci_slot) static bool has_test_file(struct pci_slot *pci_slot)
{ {
struct hotplug_slot *slot = pci_slot->hotplug; struct hotplug_slot *slot = pci_slot->hotplug;
if ((!slot) || (!slot->ops)) if ((!slot) || (!slot->ops))
return -ENODEV; return false;
if (slot->ops->hardware_test) if (slot->ops->hardware_test)
return 0; return true;
return -ENOENT; return false;
} }
static int fs_add_slot(struct pci_slot *slot) static int fs_add_slot(struct pci_slot *slot)
{ {
int retval = 0; int retval = 0;
if (has_power_file(slot) == 0) { /* Create symbolic link to the hotplug driver module */
retval = sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr); pci_hp_create_module_link(slot);
if (has_power_file(slot)) {
retval = sysfs_create_file(&slot->kobj,
&hotplug_slot_attr_power.attr);
if (retval) if (retval)
goto exit_power; goto exit_power;
} }
if (has_attention_file(slot) == 0) { if (has_attention_file(slot)) {
retval = sysfs_create_file(&slot->kobj, retval = sysfs_create_file(&slot->kobj,
&hotplug_slot_attr_attention.attr); &hotplug_slot_attr_attention.attr);
if (retval) if (retval)
goto exit_attention; goto exit_attention;
} }
if (has_latch_file(slot) == 0) { if (has_latch_file(slot)) {
retval = sysfs_create_file(&slot->kobj, retval = sysfs_create_file(&slot->kobj,
&hotplug_slot_attr_latch.attr); &hotplug_slot_attr_latch.attr);
if (retval) if (retval)
goto exit_latch; goto exit_latch;
} }
if (has_adapter_file(slot) == 0) { if (has_adapter_file(slot)) {
retval = sysfs_create_file(&slot->kobj, retval = sysfs_create_file(&slot->kobj,
&hotplug_slot_attr_presence.attr); &hotplug_slot_attr_presence.attr);
if (retval) if (retval)
goto exit_adapter; goto exit_adapter;
} }
if (has_max_bus_speed_file(slot) == 0) { if (has_max_bus_speed_file(slot)) {
retval = sysfs_create_file(&slot->kobj, retval = sysfs_create_file(&slot->kobj,
&hotplug_slot_attr_max_bus_speed.attr); &hotplug_slot_attr_max_bus_speed.attr);
if (retval) if (retval)
goto exit_max_speed; goto exit_max_speed;
} }
if (has_cur_bus_speed_file(slot) == 0) { if (has_cur_bus_speed_file(slot)) {
retval = sysfs_create_file(&slot->kobj, retval = sysfs_create_file(&slot->kobj,
&hotplug_slot_attr_cur_bus_speed.attr); &hotplug_slot_attr_cur_bus_speed.attr);
if (retval) if (retval)
goto exit_cur_speed; goto exit_cur_speed;
} }
if (has_test_file(slot) == 0) { if (has_test_file(slot)) {
retval = sysfs_create_file(&slot->kobj, retval = sysfs_create_file(&slot->kobj,
&hotplug_slot_attr_test.attr); &hotplug_slot_attr_test.attr);
if (retval) if (retval)
...@@ -475,55 +479,61 @@ static int fs_add_slot(struct pci_slot *slot) ...@@ -475,55 +479,61 @@ static int fs_add_slot(struct pci_slot *slot)
goto exit; goto exit;
exit_test: exit_test:
if (has_cur_bus_speed_file(slot) == 0) if (has_cur_bus_speed_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr); sysfs_remove_file(&slot->kobj,
&hotplug_slot_attr_cur_bus_speed.attr);
exit_cur_speed: exit_cur_speed:
if (has_max_bus_speed_file(slot) == 0) if (has_max_bus_speed_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); sysfs_remove_file(&slot->kobj,
&hotplug_slot_attr_max_bus_speed.attr);
exit_max_speed: exit_max_speed:
if (has_adapter_file(slot) == 0) if (has_adapter_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr); sysfs_remove_file(&slot->kobj,
&hotplug_slot_attr_presence.attr);
exit_adapter: exit_adapter:
if (has_latch_file(slot) == 0) if (has_latch_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr); sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
exit_latch: exit_latch:
if (has_attention_file(slot) == 0) if (has_attention_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_attention.attr); sysfs_remove_file(&slot->kobj,
&hotplug_slot_attr_attention.attr);
exit_attention: exit_attention:
if (has_power_file(slot) == 0) if (has_power_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr); sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
exit_power: exit_power:
pci_hp_remove_module_link(slot);
exit: exit:
return retval; return retval;
} }
static void fs_remove_slot(struct pci_slot *slot) static void fs_remove_slot(struct pci_slot *slot)
{ {
if (has_power_file(slot) == 0) if (has_power_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr); sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
if (has_attention_file(slot) == 0) if (has_attention_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_attention.attr); sysfs_remove_file(&slot->kobj,
&hotplug_slot_attr_attention.attr);
if (has_latch_file(slot) == 0) if (has_latch_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr); sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
if (has_adapter_file(slot) == 0) if (has_adapter_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr); sysfs_remove_file(&slot->kobj,
&hotplug_slot_attr_presence.attr);
if (has_max_bus_speed_file(slot) == 0) if (has_max_bus_speed_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); sysfs_remove_file(&slot->kobj,
&hotplug_slot_attr_max_bus_speed.attr);
if (has_cur_bus_speed_file(slot) == 0) if (has_cur_bus_speed_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr); sysfs_remove_file(&slot->kobj,
&hotplug_slot_attr_cur_bus_speed.attr);
if (has_test_file(slot) == 0) if (has_test_file(slot))
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr); sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr);
pci_hp_remove_module_link(slot);
} }
static struct hotplug_slot *get_slot_from_name (const char *name) static struct hotplug_slot *get_slot_from_name (const char *name)
...@@ -540,10 +550,10 @@ static struct hotplug_slot *get_slot_from_name (const char *name) ...@@ -540,10 +550,10 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
} }
/** /**
* pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem * __pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem
* @bus: bus this slot is on * @bus: bus this slot is on
* @slot: pointer to the &struct hotplug_slot to register * @slot: pointer to the &struct hotplug_slot to register
* @slot_nr: slot number * @devnr: device number
* @name: name registered with kobject core * @name: name registered with kobject core
* *
* Registers a hotplug slot with the pci hotplug subsystem, which will allow * Registers a hotplug slot with the pci hotplug subsystem, which will allow
...@@ -551,8 +561,9 @@ static struct hotplug_slot *get_slot_from_name (const char *name) ...@@ -551,8 +561,9 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
* *
* Returns 0 if successful, anything else for an error. * Returns 0 if successful, anything else for an error.
*/ */
int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr, int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus,
const char *name) int devnr, const char *name,
struct module *owner, const char *mod_name)
{ {
int result; int result;
struct pci_slot *pci_slot; struct pci_slot *pci_slot;
...@@ -567,14 +578,16 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr, ...@@ -567,14 +578,16 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr,
return -EINVAL; return -EINVAL;
} }
mutex_lock(&pci_hp_mutex); slot->ops->owner = owner;
slot->ops->mod_name = mod_name;
mutex_lock(&pci_hp_mutex);
/* /*
* No problems if we call this interface from both ACPI_PCI_SLOT * No problems if we call this interface from both ACPI_PCI_SLOT
* driver and call it here again. If we've already created the * driver and call it here again. If we've already created the
* pci_slot, the interface will simply bump the refcount. * pci_slot, the interface will simply bump the refcount.
*/ */
pci_slot = pci_create_slot(bus, slot_nr, name, slot); pci_slot = pci_create_slot(bus, devnr, name, slot);
if (IS_ERR(pci_slot)) { if (IS_ERR(pci_slot)) {
result = PTR_ERR(pci_slot); result = PTR_ERR(pci_slot);
goto out; goto out;
...@@ -684,6 +697,6 @@ MODULE_LICENSE("GPL"); ...@@ -684,6 +697,6 @@ MODULE_LICENSE("GPL");
module_param(debug, bool, 0644); module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
EXPORT_SYMBOL_GPL(pci_hp_register); EXPORT_SYMBOL_GPL(__pci_hp_register);
EXPORT_SYMBOL_GPL(pci_hp_deregister); EXPORT_SYMBOL_GPL(pci_hp_deregister);
EXPORT_SYMBOL_GPL(pci_hp_change_slot_info); EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
...@@ -81,7 +81,6 @@ struct slot { ...@@ -81,7 +81,6 @@ struct slot {
struct hpc_ops *hpc_ops; struct hpc_ops *hpc_ops;
struct hotplug_slot *hotplug_slot; struct hotplug_slot *hotplug_slot;
struct list_head slot_list; struct list_head slot_list;
unsigned long last_emi_toggle;
struct delayed_work work; /* work for button event */ struct delayed_work work; /* work for button event */
struct mutex lock; struct mutex lock;
}; };
...@@ -203,8 +202,6 @@ struct hpc_ops { ...@@ -203,8 +202,6 @@ struct hpc_ops {
int (*set_attention_status)(struct slot *slot, u8 status); int (*set_attention_status)(struct slot *slot, u8 status);
int (*get_latch_status)(struct slot *slot, u8 *status); int (*get_latch_status)(struct slot *slot, u8 *status);
int (*get_adapter_status)(struct slot *slot, u8 *status); int (*get_adapter_status)(struct slot *slot, u8 *status);
int (*get_emi_status)(struct slot *slot, u8 *status);
int (*toggle_emi)(struct slot *slot);
int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
int (*get_max_lnk_width)(struct slot *slot, enum pcie_link_width *val); int (*get_max_lnk_width)(struct slot *slot, enum pcie_link_width *val);
......
...@@ -73,7 +73,6 @@ static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *val ...@@ -73,7 +73,6 @@ static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *val
static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
.owner = THIS_MODULE,
.set_attention_status = set_attention_status, .set_attention_status = set_attention_status,
.enable_slot = enable_slot, .enable_slot = enable_slot,
.disable_slot = disable_slot, .disable_slot = disable_slot,
...@@ -85,99 +84,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { ...@@ -85,99 +84,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
.get_cur_bus_speed = get_cur_bus_speed, .get_cur_bus_speed = get_cur_bus_speed,
}; };
/*
* Check the status of the Electro Mechanical Interlock (EMI)
*/
static int get_lock_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
return (slot->hpc_ops->get_emi_status(slot, value));
}
/*
* sysfs interface for the Electro Mechanical Interlock (EMI)
* 1 == locked, 0 == unlocked
*/
static ssize_t lock_read_file(struct hotplug_slot *slot, char *buf)
{
int retval;
u8 value;
retval = get_lock_status(slot, &value);
if (retval)
goto lock_read_exit;
retval = sprintf (buf, "%d\n", value);
lock_read_exit:
return retval;
}
/*
* Change the status of the Electro Mechanical Interlock (EMI)
* This is a toggle - in addition there must be at least 1 second
* in between toggles.
*/
static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status)
{
struct slot *slot = hotplug_slot->private;
int retval;
u8 value;
mutex_lock(&slot->ctrl->crit_sect);
/* has it been >1 sec since our last toggle? */
if ((get_seconds() - slot->last_emi_toggle) < 1) {
mutex_unlock(&slot->ctrl->crit_sect);
return -EINVAL;
}
/* see what our current state is */
retval = get_lock_status(hotplug_slot, &value);
if (retval || (value == status))
goto set_lock_exit;
slot->hpc_ops->toggle_emi(slot);
set_lock_exit:
mutex_unlock(&slot->ctrl->crit_sect);
return 0;
}
/*
* sysfs interface which allows the user to toggle the Electro Mechanical
* Interlock. Valid values are either 0 or 1. 0 == unlock, 1 == lock
*/
static ssize_t lock_write_file(struct hotplug_slot *hotplug_slot,
const char *buf, size_t count)
{
struct slot *slot = hotplug_slot->private;
unsigned long llock;
u8 lock;
int retval = 0;
llock = simple_strtoul(buf, NULL, 10);
lock = (u8)(llock & 0xff);
switch (lock) {
case 0:
case 1:
retval = set_lock_status(hotplug_slot, lock);
break;
default:
ctrl_err(slot->ctrl, "%d is an invalid lock value\n",
lock);
retval = -EINVAL;
}
if (retval)
return retval;
return count;
}
static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
.attr = {.name = "lock", .mode = S_IFREG | S_IRUGO | S_IWUSR},
.show = lock_read_file,
.store = lock_write_file
};
/** /**
* release_slot - free up the memory used by a slot * release_slot - free up the memory used by a slot
* @hotplug_slot: slot to free * @hotplug_slot: slot to free
...@@ -236,17 +142,6 @@ static int init_slots(struct controller *ctrl) ...@@ -236,17 +142,6 @@ static int init_slots(struct controller *ctrl)
get_attention_status(hotplug_slot, &info->attention_status); get_attention_status(hotplug_slot, &info->attention_status);
get_latch_status(hotplug_slot, &info->latch_status); get_latch_status(hotplug_slot, &info->latch_status);
get_adapter_status(hotplug_slot, &info->adapter_status); get_adapter_status(hotplug_slot, &info->adapter_status);
/* create additional sysfs entries */
if (EMI(ctrl)) {
retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
&hotplug_slot_attr_lock.attr);
if (retval) {
pci_hp_deregister(hotplug_slot);
ctrl_err(ctrl, "Cannot create additional sysfs "
"entries\n");
goto error_info;
}
}
} }
return 0; return 0;
...@@ -261,13 +156,8 @@ static int init_slots(struct controller *ctrl) ...@@ -261,13 +156,8 @@ static int init_slots(struct controller *ctrl)
static void cleanup_slots(struct controller *ctrl) static void cleanup_slots(struct controller *ctrl)
{ {
struct slot *slot; struct slot *slot;
list_for_each_entry(slot, &ctrl->slot_list, slot_list)
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
if (EMI(ctrl))
sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
&hotplug_slot_attr_lock.attr);
pci_hp_deregister(slot->hotplug_slot); pci_hp_deregister(slot->hotplug_slot);
}
} }
/* /*
......
...@@ -422,35 +422,6 @@ static int hpc_query_power_fault(struct slot *slot) ...@@ -422,35 +422,6 @@ static int hpc_query_power_fault(struct slot *slot)
return !!(slot_status & PCI_EXP_SLTSTA_PFD); return !!(slot_status & PCI_EXP_SLTSTA_PFD);
} }
static int hpc_get_emi_status(struct slot *slot, u8 *status)
{
struct controller *ctrl = slot->ctrl;
u16 slot_status;
int retval;
retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
if (retval) {
ctrl_err(ctrl, "Cannot check EMI status\n");
return retval;
}
*status = !!(slot_status & PCI_EXP_SLTSTA_EIS);
return retval;
}
static int hpc_toggle_emi(struct slot *slot)
{
u16 slot_cmd;
u16 cmd_mask;
int rc;
slot_cmd = PCI_EXP_SLTCTL_EIC;
cmd_mask = PCI_EXP_SLTCTL_EIC;
rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask);
slot->last_emi_toggle = get_seconds();
return rc;
}
static int hpc_set_attention_status(struct slot *slot, u8 value) static int hpc_set_attention_status(struct slot *slot, u8 value)
{ {
struct controller *ctrl = slot->ctrl; struct controller *ctrl = slot->ctrl;
...@@ -874,8 +845,6 @@ static struct hpc_ops pciehp_hpc_ops = { ...@@ -874,8 +845,6 @@ static struct hpc_ops pciehp_hpc_ops = {
.get_attention_status = hpc_get_attention_status, .get_attention_status = hpc_get_attention_status,
.get_latch_status = hpc_get_latch_status, .get_latch_status = hpc_get_latch_status,
.get_adapter_status = hpc_get_adapter_status, .get_adapter_status = hpc_get_adapter_status,
.get_emi_status = hpc_get_emi_status,
.toggle_emi = hpc_toggle_emi,
.get_max_bus_speed = hpc_get_max_lnk_speed, .get_max_bus_speed = hpc_get_max_lnk_speed,
.get_cur_bus_speed = hpc_get_cur_lnk_speed, .get_cur_bus_speed = hpc_get_cur_lnk_speed,
......
...@@ -82,7 +82,6 @@ static int get_latch_status (struct hotplug_slot *slot, u8 *value); ...@@ -82,7 +82,6 @@ static int get_latch_status (struct hotplug_slot *slot, u8 *value);
static int get_adapter_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
static struct hotplug_slot_ops skel_hotplug_slot_ops = { static struct hotplug_slot_ops skel_hotplug_slot_ops = {
.owner = THIS_MODULE,
.enable_slot = enable_slot, .enable_slot = enable_slot,
.disable_slot = disable_slot, .disable_slot = disable_slot,
.set_attention_status = set_attention_status, .set_attention_status = set_attention_status,
......
...@@ -423,7 +423,6 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) ...@@ -423,7 +423,6 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
} }
struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
.owner = THIS_MODULE,
.enable_slot = enable_slot, .enable_slot = enable_slot,
.disable_slot = disable_slot, .disable_slot = disable_slot,
.set_attention_status = set_attention_status, .set_attention_status = set_attention_status,
......
...@@ -83,7 +83,6 @@ static int disable_slot(struct hotplug_slot *slot); ...@@ -83,7 +83,6 @@ static int disable_slot(struct hotplug_slot *slot);
static inline int get_power_status(struct hotplug_slot *slot, u8 *value); static inline int get_power_status(struct hotplug_slot *slot, u8 *value);
static struct hotplug_slot_ops sn_hotplug_slot_ops = { static struct hotplug_slot_ops sn_hotplug_slot_ops = {
.owner = THIS_MODULE,
.enable_slot = enable_slot, .enable_slot = enable_slot,
.disable_slot = disable_slot, .disable_slot = disable_slot,
.get_power_status = get_power_status, .get_power_status = get_power_status,
......
...@@ -69,7 +69,6 @@ static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *val ...@@ -69,7 +69,6 @@ static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *val
static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
.owner = THIS_MODULE,
.set_attention_status = set_attention_status, .set_attention_status = set_attention_status,
.enable_slot = enable_slot, .enable_slot = enable_slot,
.disable_slot = disable_slot, .disable_slot = disable_slot,
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册