Commit 59ef7a83 authored by Linus Torvalds's avatar Linus Torvalds

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

* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (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
  ...
parents 5165aece 2af5066f
...@@ -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,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -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;
......
This diff is collapsed.
...@@ -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,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment