summaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/access.c89
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c8
-rw-r--r--drivers/pci/hotplug/cpcihp_generic.c1
-rw-r--r--drivers/pci/hotplug/cpcihp_zt5550.c26
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c24
-rw-r--r--drivers/pci/hotplug/fakephp.c2
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c2
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c2
-rw-r--r--drivers/pci/hotplug/pciehprm_nonacpi.c3
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c3
-rw-r--r--drivers/pci/hotplug/rpaphp.h3
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c5
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c15
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c3
-rw-r--r--drivers/pci/hotplug/shpchp.h124
-rw-r--r--drivers/pci/hotplug/shpchp_core.c111
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c2034
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c175
-rw-r--r--drivers/pci/hotplug/shpchp_pci.c861
-rw-r--r--drivers/pci/hotplug/shpchp_sysfs.c119
-rw-r--r--drivers/pci/hotplug/shpchprm.h55
-rw-r--r--drivers/pci/hotplug/shpchprm_acpi.c1649
-rw-r--r--drivers/pci/hotplug/shpchprm_legacy.c395
-rw-r--r--drivers/pci/hotplug/shpchprm_legacy.h113
-rw-r--r--drivers/pci/hotplug/shpchprm_nonacpi.c391
-rw-r--r--drivers/pci/hotplug/shpchprm_nonacpi.h56
-rw-r--r--drivers/pci/msi.c2
-rw-r--r--drivers/pci/pci-driver.c19
-rw-r--r--drivers/pci/pci-sysfs.c20
-rw-r--r--drivers/pci/pci.c22
-rw-r--r--drivers/pci/pci.h7
-rw-r--r--drivers/pci/pcie/portdrv_core.c6
-rw-r--r--drivers/pci/pcie/portdrv_pci.c1
-rw-r--r--drivers/pci/probe.c1
-rw-r--r--drivers/pci/proc.c28
-rw-r--r--drivers/pci/quirks.c294
-rw-r--r--drivers/pci/rom.c1
-rw-r--r--drivers/pci/syscall.c14
38 files changed, 665 insertions, 6019 deletions
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index 24a76de49f4..2a42add7f56 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -60,3 +60,92 @@ EXPORT_SYMBOL(pci_bus_read_config_dword);
EXPORT_SYMBOL(pci_bus_write_config_byte);
EXPORT_SYMBOL(pci_bus_write_config_word);
EXPORT_SYMBOL(pci_bus_write_config_dword);
+
+static u32 pci_user_cached_config(struct pci_dev *dev, int pos)
+{
+ u32 data;
+
+ data = dev->saved_config_space[pos/sizeof(dev->saved_config_space[0])];
+ data >>= (pos % sizeof(dev->saved_config_space[0])) * 8;
+ return data;
+}
+
+#define PCI_USER_READ_CONFIG(size,type) \
+int pci_user_read_config_##size \
+ (struct pci_dev *dev, int pos, type *val) \
+{ \
+ unsigned long flags; \
+ int ret = 0; \
+ u32 data = -1; \
+ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
+ spin_lock_irqsave(&pci_lock, flags); \
+ if (likely(!dev->block_ucfg_access)) \
+ ret = dev->bus->ops->read(dev->bus, dev->devfn, \
+ pos, sizeof(type), &data); \
+ else if (pos < sizeof(dev->saved_config_space)) \
+ data = pci_user_cached_config(dev, pos); \
+ spin_unlock_irqrestore(&pci_lock, flags); \
+ *val = (type)data; \
+ return ret; \
+}
+
+#define PCI_USER_WRITE_CONFIG(size,type) \
+int pci_user_write_config_##size \
+ (struct pci_dev *dev, int pos, type val) \
+{ \
+ unsigned long flags; \
+ int ret = -EIO; \
+ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
+ spin_lock_irqsave(&pci_lock, flags); \
+ if (likely(!dev->block_ucfg_access)) \
+ ret = dev->bus->ops->write(dev->bus, dev->devfn, \
+ pos, sizeof(type), val); \
+ spin_unlock_irqrestore(&pci_lock, flags); \
+ return ret; \
+}
+
+PCI_USER_READ_CONFIG(byte, u8)
+PCI_USER_READ_CONFIG(word, u16)
+PCI_USER_READ_CONFIG(dword, u32)
+PCI_USER_WRITE_CONFIG(byte, u8)
+PCI_USER_WRITE_CONFIG(word, u16)
+PCI_USER_WRITE_CONFIG(dword, u32)
+
+/**
+ * pci_block_user_cfg_access - Block userspace PCI config reads/writes
+ * @dev: pci device struct
+ *
+ * This function blocks any userspace PCI config accesses from occurring.
+ * When blocked, any writes will be bit bucketed and reads will return the
+ * data saved using pci_save_state for the first 64 bytes of config
+ * space and return 0xff for all other config reads.
+ **/
+void pci_block_user_cfg_access(struct pci_dev *dev)
+{
+ unsigned long flags;
+
+ pci_save_state(dev);
+
+ /* spinlock to synchronize with anyone reading config space now */
+ spin_lock_irqsave(&pci_lock, flags);
+ dev->block_ucfg_access = 1;
+ spin_unlock_irqrestore(&pci_lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_block_user_cfg_access);
+
+/**
+ * pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes
+ * @dev: pci device struct
+ *
+ * This function allows userspace PCI config accesses to resume.
+ **/
+void pci_unblock_user_cfg_access(struct pci_dev *dev)
+{
+ unsigned long flags;
+
+ /* spinlock to synchronize with anyone reading saved config space */
+ spin_lock_irqsave(&pci_lock, flags);
+ dev->block_ucfg_access = 0;
+ spin_unlock_irqrestore(&pci_lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access);
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 424e7de181a..8e21f6ab89a 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -58,6 +58,9 @@ static LIST_HEAD(bridge_list);
static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
static void handle_hotplug_event_func (acpi_handle, u32, void *);
+static void acpiphp_sanitize_bus(struct pci_bus *bus);
+static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus);
+
/*
* initialization & terminatation routines
@@ -796,8 +799,13 @@ static int enable_device(struct acpiphp_slot *slot)
}
}
+ pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
+ acpiphp_sanitize_bus(bus);
+ pci_enable_bridges(bus);
pci_bus_add_devices(bus);
+ acpiphp_set_hpp_values(DEVICE_ACPI_HANDLE(&bus->self->dev), bus);
+ acpiphp_configure_ioapics(DEVICE_ACPI_HANDLE(&bus->self->dev));
/* associate pci_dev to our representation */
list_for_each (l, &slot->funcs) {
diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c
index a62a4345b46..2d4639d6841 100644
--- a/drivers/pci/hotplug/cpcihp_generic.c
+++ b/drivers/pci/hotplug/cpcihp_generic.c
@@ -39,6 +39,7 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
+#include <linux/string.h>
#include "cpci_hotplug.h"
#define DRIVER_VERSION "0.1"
diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
index e9928024be7..f7cb00da38d 100644
--- a/drivers/pci/hotplug/cpcihp_zt5550.c
+++ b/drivers/pci/hotplug/cpcihp_zt5550.c
@@ -36,6 +36,7 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
+#include <linux/signal.h> /* SA_SHIRQ */
#include "cpci_hotplug.h"
#include "cpcihp_zt5550.h"
@@ -78,11 +79,20 @@ static void __iomem *csr_int_mask;
static int zt5550_hc_config(struct pci_dev *pdev)
{
+ int ret;
+
/* Since we know that no boards exist with two HC chips, treat it as an error */
if(hc_dev) {
err("too many host controller devices?");
return -EBUSY;
}
+
+ ret = pci_enable_device(pdev);
+ if(ret) {
+ err("cannot enable %s\n", pci_name(pdev));
+ return ret;
+ }
+
hc_dev = pdev;
dbg("hc_dev = %p", hc_dev);
dbg("pci resource start %lx", pci_resource_start(hc_dev, 1));
@@ -91,7 +101,8 @@ static int zt5550_hc_config(struct pci_dev *pdev)
if(!request_mem_region(pci_resource_start(hc_dev, 1),
pci_resource_len(hc_dev, 1), MY_NAME)) {
err("cannot reserve MMIO region");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto exit_disable_device;
}
hc_registers =
@@ -99,9 +110,8 @@ static int zt5550_hc_config(struct pci_dev *pdev)
if(!hc_registers) {
err("cannot remap MMIO region %lx @ %lx",
pci_resource_len(hc_dev, 1), pci_resource_start(hc_dev, 1));
- release_mem_region(pci_resource_start(hc_dev, 1),
- pci_resource_len(hc_dev, 1));
- return -ENODEV;
+ ret = -ENODEV;
+ goto exit_release_region;
}
csr_hc_index = hc_registers + CSR_HCINDEX;
@@ -124,6 +134,13 @@ static int zt5550_hc_config(struct pci_dev *pdev)
writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask);
dbg("disabled timer0, timer1 and ENUM interrupts");
return 0;
+
+exit_release_region:
+ release_mem_region(pci_resource_start(hc_dev, 1),
+ pci_resource_len(hc_dev, 1));
+exit_disable_device:
+ pci_disable_device(hc_dev);
+ return ret;
}
static int zt5550_hc_cleanup(void)
@@ -134,6 +151,7 @@ static int zt5550_hc_cleanup(void)
iounmap(hc_registers);
release_mem_region(pci_resource_start(hc_dev, 1),
pci_resource_len(hc_dev, 1));
+ pci_disable_device(hc_dev);
return 0;
}
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 8c6d3987d46..9aed8efe6a1 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -794,12 +794,21 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
u32 rc;
struct controller *ctrl;
struct pci_func *func;
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR MY_NAME ": cannot enable PCI device %s (%d)\n",
+ pci_name(pdev), err);
+ return err;
+ }
// Need to read VID early b/c it's used to differentiate CPQ and INTC discovery
rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
err(msg_HPC_non_compaq_or_intel);
- return -ENODEV;
+ rc = -ENODEV;
+ goto err_disable_device;
}
dbg("Vendor ID: %x\n", vendor_id);
@@ -807,7 +816,8 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dbg("revision: %d\n", rev);
if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
err(msg_HPC_rev_error);
- return -ENODEV;
+ rc = -ENODEV;
+ goto err_disable_device;
}
/* Check for the proper subsytem ID's
@@ -820,18 +830,20 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
if (rc) {
err("%s : pci_read_config_word failed\n", __FUNCTION__);
- return rc;
+ goto err_disable_device;
}
dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
err(msg_HPC_non_compaq_or_intel);
- return -ENODEV;
+ rc = -ENODEV;
+ goto err_disable_device;
}
ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
if (!ctrl) {
err("%s : out of memory\n", __FUNCTION__);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto err_disable_device;
}
memset(ctrl, 0, sizeof(struct controller));
@@ -1264,6 +1276,8 @@ err_free_bus:
kfree(ctrl->pci_bus);
err_free_ctrl:
kfree(ctrl);
+err_disable_device:
+ pci_disable_device(pdev);
return rc;
}
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 8e47fa66e25..060d74775d7 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -37,6 +37,8 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "pci_hotplug.h"
#include "../pci.h"
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index 0392e004258..aabf1e70b52 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -1077,7 +1077,7 @@ static int enable_slot(struct hotplug_slot *hs)
if (rc) {
err("Adding this card exceeds the limitations of this bus.\n");
err("(i.e., >1 133MHz cards running on same bus, or "
- ">2 66 PCI cards running on same bus\n.");
+ ">2 66 PCI cards running on same bus.\n");
err("Try hot-adding into another bus\n");
rc = -EINVAL;
goto error_nopower;
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 33b539b34f7..ff17d8e07e9 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -113,7 +113,7 @@ int pciehp_unconfigure_device(struct pci_func* func)
*/
int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
{
-#if defined(CONFIG_X86) && !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
+#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_IO_APIC)
int rc;
u16 temp_word;
struct pci_dev fakedev;
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c
index 3622965f896..33b2c69a082 100644
--- a/drivers/pci/hotplug/pciehprm_nonacpi.c
+++ b/drivers/pci/hotplug/pciehprm_nonacpi.c
@@ -33,10 +33,13 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/slab.h>
+
#include <asm/uaccess.h>
#ifdef CONFIG_IA64
#include <asm/iosapic.h>
#endif
+
#include "pciehp.h"
#include "pciehprm.h"
#include "pciehprm_nonacpi.h"
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index ad1017da865..fcb66b9a0e2 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -16,10 +16,13 @@
*/
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/string.h>
+
#include <asm/pci-bridge.h>
#include <asm/semaphore.h>
#include <asm/rtas.h>
#include <asm/vio.h>
+
#include "../pci.h"
#include "rpaphp.h"
#include "rpadlpar.h"
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 61d94d1e29c..71ea5f9bb28 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -92,9 +92,10 @@ extern struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn);
extern int rpaphp_claim_resource(struct pci_dev *dev, int resource);
extern int rpaphp_enable_pci_slot(struct slot *slot);
extern int register_pci_slot(struct slot *slot);
-extern int rpaphp_unconfig_pci_adapter(struct slot *slot);
extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
+
extern int rpaphp_config_pci_adapter(struct pci_bus *bus);
+extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus);
/* rpaphp_core.c */
extern int rpaphp_add_slot(struct device_node *dn);
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index c830ff0acdc..cf075c34b57 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -426,8 +426,11 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
dbg("DISABLING SLOT %s\n", slot->name);
down(&rpaphp_sem);
- retval = rpaphp_unconfig_pci_adapter(slot);
+ retval = rpaphp_unconfig_pci_adapter(slot->bus);
up(&rpaphp_sem);
+ slot->state = NOT_CONFIGURED;
+ info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
+ slot->name);
exit:
dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
return retval;
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 49e4d10a648..f7c12d7dfcf 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -23,11 +23,13 @@
*
*/
#include <linux/pci.h>
+#include <linux/string.h>
+
#include <asm/pci-bridge.h>
#include <asm/rtas.h>
#include <asm/machdep.h>
-#include "../pci.h" /* for pci_add_new_bus */
+#include "../pci.h" /* for pci_add_new_bus */
#include "rpaphp.h"
static struct pci_bus *find_bus_among_children(struct pci_bus *bus,
@@ -319,20 +321,15 @@ static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
return;
}
-int rpaphp_unconfig_pci_adapter(struct slot *slot)
+int rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
{
struct pci_dev *dev, *tmp;
- int retval = 0;
- list_for_each_entry_safe(dev, tmp, slot->pci_devs, bus_list) {
+ list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
rpaphp_eeh_remove_bus_device(dev);
pci_remove_bus_device(dev);
}
-
- slot->state = NOT_CONFIGURED;
- info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
- slot->name);
- return retval;
+ return 0;
}
static int setup_pci_hotplug_slot_info(struct slot *slot)
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index 0e881549508..daa89ae5712 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -27,6 +27,9 @@
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
#include <asm/rtas.h>
#include "rpaphp.h"
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index b7d1c61d6bb..08ad26a0cae 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -32,8 +32,8 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <asm/semaphore.h>
-#include <asm/io.h>
+#include <linux/sched.h> /* signal_pending(), struct timer_list */
+
#include "pci_hotplug.h"
#if !defined(MODULE)
@@ -52,42 +52,18 @@ extern int shpchp_debug;
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
-struct pci_func {
- struct pci_func *next;
- u8 bus;
- u8 device;
- u8 function;
- u8 is_a_board;
- u16 status;
- u8 configured;
- u8 switch_save;
- u8 presence_save;
- u8 pwr_save;
- u32 base_length[0x06];
- u8 base_type[0x06];
- u16 reserved2;
- u32 config_space[0x20];
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
- struct pci_dev* pci_dev;
-};
-
#define SLOT_MAGIC 0x67267321
struct slot {
u32 magic;
struct slot *next;
u8 bus;
u8 device;
+ u16 status;
u32 number;
u8 is_a_board;
- u8 configured;
u8 state;
- u8 switch_save;
u8 presence_save;
- u32 capabilities;
- u16 reserved2;
+ u8 pwr_save;
struct timer_list task_event;
u8 hp_slot;
struct controller *ctrl;
@@ -96,12 +72,6 @@ struct slot {
struct list_head slot_list;
};
-struct pci_resource {
- struct pci_resource * next;
- u32 base;
- u32 length;
-};
-
struct event_info {
u32 event_type;
u8 hp_slot;
@@ -110,13 +80,9 @@ struct event_info {
struct controller {
struct controller *next;
struct semaphore crit_sect; /* critical section semaphore */
- void * hpc_ctlr_handle; /* HPC controller handle */
+ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
int num_slots; /* Number of slots on ctlr */
int slot_num_inc; /* 1 or -1 */
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
struct pci_dev *pci_dev;
struct pci_bus *pci_bus;
struct event_info event_queue[10];
@@ -124,33 +90,21 @@ struct controller {
struct hpc_ops *hpc_ops;
wait_queue_head_t queue; /* sleep & wake process */
u8 next_event;
- u8 seg;
u8 bus;
u8 device;
u8 function;
- u8 rev;
u8 slot_device_offset;
u8 add_support;
enum pci_bus_speed speed;
u32 first_slot; /* First physical slot number */
u8 slot_bus; /* Bus where the slots handled by this controller sit */
- u8 push_flag;
- u16 ctlrcap;
- u16 vendor_id;
-};
-
-struct irq_mapping {
- u8 barber_pole;
- u8 valid_INT;
- u8 interrupt[4];
};
-struct resource_lists {
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
- struct irq_mapping *irqs;
+struct hotplug_params {
+ u8 cache_line_size;
+ u8 latency_timer;
+ u8 enable_serr;
+ u8 enable_perr;
};
/* Define AMD SHPC ID */
@@ -194,24 +148,16 @@ struct resource_lists {
* error Messages
*/
#define msg_initialization_err "Initialization failure, error=%d\n"
-#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n"
-#define msg_HPC_non_shpc "The PCI hot plug controller is not supported by this driver.\n"
-#define msg_HPC_not_supported "This system is not supported by this version of shpcphd mdoule. Upgrade to a newer version of shpchpd\n"
-#define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
#define msg_button_on "PCI slot #%d - powering on due to button press.\n"
#define msg_button_off "PCI slot #%d - powering off due to button press.\n"
#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n"
-#define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n"
/* sysfs functions for the hotplug controller info */
extern void shpchp_create_ctrl_files (struct controller *ctrl);
/* controller functions */
-extern int shpchprm_find_available_resources(struct controller *ctrl);
extern int shpchp_event_start_thread(void);
extern void shpchp_event_stop_thread(void);
-extern struct pci_func *shpchp_slot_create(unsigned char busnumber);
-extern struct pci_func *shpchp_slot_find(unsigned char bus, unsigned char device, unsigned char index);
extern int shpchp_enable_slot(struct slot *slot);
extern int shpchp_disable_slot(struct slot *slot);
@@ -220,29 +166,20 @@ extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id);
extern u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id);
extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id);
-/* resource functions */
-extern int shpchp_resource_sort_and_combine(struct pci_resource **head);
-
/* pci functions */
-extern int shpchp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
-/*extern int shpchp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/
extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
-extern int shpchp_save_used_resources(struct controller *ctrl, struct pci_func * func, int flag);
-extern int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot);
-extern void shpchp_destroy_board_resources(struct pci_func * func);
-extern int shpchp_return_board_resources(struct pci_func * func, struct resource_lists * resources);
-extern void shpchp_destroy_resource_list(struct resource_lists * resources);
-extern int shpchp_configure_device(struct controller* ctrl, struct pci_func* func);
-extern int shpchp_unconfigure_device(struct pci_func* func);
+extern int shpchp_configure_device(struct slot *p_slot);
+extern int shpchp_unconfigure_device(struct slot *p_slot);
+extern void get_hp_hw_control_from_firmware(struct pci_dev *dev);
+extern void get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp);
+extern int shpchprm_get_physical_slot_number(struct controller *ctrl,
+ u32 *sun, u8 busnum, u8 devnum);
+extern void shpchp_remove_ctrl_files(struct controller *ctrl);
/* Global variables */
extern struct controller *shpchp_ctrl_list;
-extern struct pci_func *shpchp_slot_list[256];
-
-/* These are added to support AMD shpc */
-extern u8 shpchp_nic_irq;
-extern u8 shpchp_disk_irq;
struct ctrl_reg {
volatile u32 base_offset;
@@ -298,7 +235,7 @@ enum ctrl_offsets {
SLOT11 = offsetof(struct ctrl_reg, slot11),
SLOT12 = offsetof(struct ctrl_reg, slot12),
};
-typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id);
+typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id);
struct php_ctlr_state_s {
struct php_ctlr_state_s *pnext;
struct pci_dev *pci_dev;
@@ -359,12 +296,9 @@ static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device)
p_slot = ctrl->slot;
- dbg("p_slot = %p\n", p_slot);
-
while (p_slot && (p_slot->device != device)) {
tmp_slot = p_slot;
p_slot = p_slot->next;
- dbg("In while loop, p_slot = %p\n", p_slot);
}
if (p_slot == NULL) {
err("ERROR: shpchp_find_slot device=0x%x\n", device);
@@ -379,8 +313,6 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
DECLARE_WAITQUEUE(wait, current);
int retval = 0;
- dbg("%s : start\n",__FUNCTION__);
-
add_wait_queue(&ctrl->queue, &wait);
if (!shpchp_poll_mode) {
@@ -394,19 +326,9 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
if (signal_pending(current))
retval = -EINTR;
- dbg("%s : end\n", __FUNCTION__);
return retval;
}
-/* Puts node back in the resource list pointed to by head */
-static inline void return_resource(struct pci_resource **head, struct pci_resource *node)
-{
- if (!node || !head)
- return;
- node->next = *head;
- *head = node;
-}
-
#define SLOT_NAME_SIZE 10
static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
@@ -420,11 +342,7 @@ enum php_ctlr_type {
ACPI
};
-int shpc_init( struct controller *ctrl, struct pci_dev *pdev,
- php_intr_callback_t attention_button_callback,
- php_intr_callback_t switch_change_callback,
- php_intr_callback_t presence_change_callback,
- php_intr_callback_t power_fault_callback);
+int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
int shpc_get_ctlr_slot_config( struct controller *ctrl,
int *num_ctlr_slots,
@@ -437,8 +355,6 @@ struct hpc_ops {
int (*power_on_slot ) (struct slot *slot);
int (*slot_enable ) (struct slot *slot);
int (*slot_disable ) (struct slot *slot);
- int (*enable_all_slots) (struct slot *slot);
- int (*pwr_on_all_slots) (struct slot *slot);
int (*set_bus_speed_mode) (struct slot *slot, enum pci_bus_speed speed);
int (*get_power_status) (struct slot *slot, u8 *status);
int (*get_attention_status) (struct slot *slot, u8 *status);
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 6f7d8a29957..63628e01dd4 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -27,26 +27,18 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
#include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
#include "shpchp.h"
-#include "shpchprm.h"
/* Global variables */
int shpchp_debug;
int shpchp_poll_mode;
int shpchp_poll_time;
struct controller *shpchp_ctrl_list; /* = NULL */
-struct pci_func *shpchp_slot_list[256];
#define DRIVER_VERSION "0.4"
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -113,8 +105,6 @@ static int init_slots(struct controller *ctrl)
u32 slot_number, sun;
int result = -ENOMEM;
- dbg("%s\n",__FUNCTION__);
-
number_of_slots = ctrl->num_slots;
slot_device = ctrl->slot_device_offset;
slot_number = ctrl->first_slot;
@@ -352,6 +342,17 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
return 0;
}
+static int is_shpc_capable(struct pci_dev *dev)
+{
+ if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
+ PCI_DEVICE_ID_AMD_GOLAM_7450))
+ return 1;
+ if (pci_find_capability(dev, PCI_CAP_ID_SHPC))
+ return 1;
+
+ return 0;
+}
+
static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int rc;
@@ -360,6 +361,9 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int first_device_num; /* first PCI device number supported by this SHPC */
int num_ctlr_slots; /* number of slots supported by this SHPC */
+ if (!is_shpc_capable(pdev))
+ return -ENODEV;
+
ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
if (!ctrl) {
err("%s : out of memory\n", __FUNCTION__);
@@ -367,19 +371,12 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
memset(ctrl, 0, sizeof(struct controller));
- dbg("DRV_thread pid = %d\n", current->pid);
-
- rc = shpc_init(ctrl, pdev,
- (php_intr_callback_t) shpchp_handle_attention_button,
- (php_intr_callback_t) shpchp_handle_switch_change,
- (php_intr_callback_t) shpchp_handle_presence_change,
- (php_intr_callback_t) shpchp_handle_power_fault);
+ rc = shpc_init(ctrl, pdev);
if (rc) {
dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME);
goto err_out_free_ctrl;
}
- dbg("%s: controller initialization success\n", __FUNCTION__);
ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
pci_set_drvdata(pdev, ctrl);
@@ -411,23 +408,8 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
first_device_num = ctrl->slot_device_offset;
num_ctlr_slots = ctrl->num_slots;
- /* Store PCI Config Space for all devices on this bus */
- rc = shpchp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
- if (rc) {
- err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
- goto err_out_free_ctrl_bus;
- }
-
- /* Get IO, memory, and IRQ resources for new devices */
- rc = shpchprm_find_available_resources(ctrl);
- ctrl->add_support = !rc;
+ ctrl->add_support = 1;
- if (rc) {
- dbg("shpchprm_find_available_resources = %#x\n", rc);
- err("unable to locate PCI configuration resources for hot plug add.\n");
- goto err_out_free_ctrl_bus;
- }
-
/* Setup the slot information structures */
rc = init_slots(ctrl);
if (rc) {
@@ -477,7 +459,6 @@ err_out_none:
static int shpc_start_thread(void)
{
- int loop;
int retval = 0;
dbg("Initialize + Start the notification/polling mechanism \n");
@@ -488,48 +469,21 @@ static int shpc_start_thread(void)
return retval;
}
- dbg("Initialize slot lists\n");
- /* One slot list for each bus in the system */
- for (loop = 0; loop < 256; loop++) {
- shpchp_slot_list[loop] = NULL;
- }
-
return retval;
}
-static inline void __exit
-free_shpchp_res(struct pci_resource *res)
-{
- struct pci_resource *tres;
-
- while (res) {
- tres = res;
- res = res->next;
- kfree(tres);
- }
-}
-
static void __exit unload_shpchpd(void)
{
- struct pci_func *next;
- struct pci_func *TempSlot;
- int loop;
struct controller *ctrl;
struct controller *tctrl;
ctrl = shpchp_ctrl_list;
while (ctrl) {
+ shpchp_remove_ctrl_files(ctrl);
cleanup_slots(ctrl);
- free_shpchp_res(ctrl->io_head);
- free_shpchp_res(ctrl->mem_head);
- free_shpchp_res(ctrl->p_mem_head);
- free_shpchp_res(ctrl->bus_head);
-
kfree (ctrl->pci_bus);
-
- dbg("%s: calling release_ctlr\n", __FUNCTION__);
ctrl->hpc_ops->release_ctlr(ctrl);
tctrl = ctrl;
@@ -538,20 +492,6 @@ static void __exit unload_shpchpd(void)
kfree(tctrl);
}
- for (loop = 0; loop < 256; loop++) {
- next = shpchp_slot_list[loop];
- while (next != NULL) {
- free_shpchp_res(next->io_head);
- free_shpchp_res(next->mem_head);
- free_shpchp_res(next->p_mem_head);
- free_shpchp_res(next->bus_head);
-
- TempSlot = next;
- next = next->next;
- kfree(TempSlot);
- }
- }
-
/* Stop the notification mechanism */
shpchp_event_stop_thread();
@@ -596,20 +536,14 @@ static int __init shpcd_init(void)
if (retval)
goto error_hpc_init;
- retval = shpchprm_init(PCI);
- if (!retval) {
- retval = pci_register_driver(&shpc_driver);
- dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
- info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
- }
+ retval = pci_register_driver(&shpc_driver);
+ dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
+ info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
error_hpc_init:
if (retval) {
- shpchprm_cleanup();
shpchp_event_stop_thread();
- } else
- shpchprm_print_pirt();
-
+ }
return retval;
}
@@ -618,9 +552,6 @@ static void __exit shpcd_cleanup(void)
dbg("unload_shpchpd()\n");
unload_shpchpd();
- shpchprm_cleanup();
-
- dbg("pci_unregister_driver\n");
pci_unregister_driver(&shpc_driver);
info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 91c9903e621..58619359ad0 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -27,24 +27,14 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
#include <linux/smp_lock.h>
#include <linux/pci.h>
+#include "../pci.h"
#include "shpchp.h"
-#include "shpchprm.h"
-static u32 configure_new_device(struct controller *ctrl, struct pci_func *func,
- u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
-static int configure_new_function( struct controller *ctrl, struct pci_func *func,
- u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
static void interrupt_event_handler(struct controller *ctrl);
static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */
@@ -52,28 +42,22 @@ static struct semaphore event_exit; /* guard ensure thread has exited before ca
static int event_finished;
static unsigned long pushbutton_pending; /* = 0 */
-u8 shpchp_disk_irq;
-u8 shpchp_nic_irq;
-
u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
{
struct controller *ctrl = (struct controller *) inst_id;
struct slot *p_slot;
u8 rc = 0;
u8 getstatus;
- struct pci_func *func;
struct event_info *taskInfo;
/* Attention Button Change */
dbg("shpchp: Attention button interrupt received.\n");
- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
/* This is the structure that tells the worker thread what to do */
taskInfo = &(ctrl->event_queue[ctrl->next_event]);
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
ctrl->next_event = (ctrl->next_event + 1) % 10;
@@ -118,14 +102,11 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
struct slot *p_slot;
u8 rc = 0;
u8 getstatus;
- struct pci_func *func;
struct event_info *taskInfo;
/* Switch Change */
dbg("shpchp: Switch interrupt received.\n");
- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
/* This is the structure that tells the worker thread
* what to do
*/
@@ -135,19 +116,18 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
rc++;
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
dbg("%s: Card present %x Power status %x\n", __FUNCTION__,
- func->presence_save, func->pwr_save);
+ p_slot->presence_save, p_slot->pwr_save);
if (getstatus) {
/*
* Switch opened
*/
info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
- func->switch_save = 0;
taskInfo->event_type = INT_SWITCH_OPEN;
- if (func->pwr_save && func->presence_save) {
+ if (p_slot->pwr_save && p_slot->presence_save) {
taskInfo->event_type = INT_POWER_FAULT;
err("Surprise Removal of card\n");
}
@@ -156,7 +136,6 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
* Switch closed
*/
info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
- func->switch_save = 0x10;
taskInfo->event_type = INT_SWITCH_CLOSE;
}
@@ -172,14 +151,11 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
struct slot *p_slot;
u8 rc = 0;
/*u8 temp_byte;*/
- struct pci_func *func;
struct event_info *taskInfo;
/* Presence Change */
dbg("shpchp: Presence/Notify input change.\n");
- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
/* This is the structure that tells the worker thread
* what to do
*/
@@ -193,8 +169,8 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
/*
* Save the presence state
*/
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
- if (func->presence_save) {
+ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ if (p_slot->presence_save) {
/*
* Card Present
*/
@@ -219,14 +195,11 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
struct controller *ctrl = (struct controller *) inst_id;
struct slot *p_slot;
u8 rc = 0;
- struct pci_func *func;
struct event_info *taskInfo;
/* Power fault */
dbg("shpchp: Power fault interrupt received.\n");
- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
/* This is the structure that tells the worker thread
* what to do
*/
@@ -242,7 +215,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
* Power fault Cleared
*/
info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
- func->status = 0x00;
+ p_slot->status = 0x00;
taskInfo->event_type = INT_POWER_FAULT_CLEAR;
} else {
/*
@@ -251,7 +224,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
taskInfo->event_type = INT_POWER_FAULT;
/* set power fault status for this board */
- func->status = 0xFF;
+ p_slot->status = 0xFF;
info("power fault bit %x set\n", hp_slot);
}
if (rc)
@@ -260,799 +233,13 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
return rc;
}
-
-/*
- * sort_by_size
- *
- * Sorts nodes on the list by their length.
- * Smallest first.
- *
- */
-static int sort_by_size(struct pci_resource **head)
-{
- struct pci_resource *current_res;
- struct pci_resource *next_res;
- int out_of_order = 1;
-
- if (!(*head))
- return(1);
-
- if (!((*head)->next))
- return(0);
-
- while (out_of_order) {
- out_of_order = 0;
-
- /* Special case for swapping list head */
- if (((*head)->next) &&
- ((*head)->length > (*head)->next->length)) {
- out_of_order++;
- current_res = *head;
- *head = (*head)->next;
- current_res->next = (*head)->next;
- (*head)->next = current_res;
- }
-
- current_res = *head;
-
- while (current_res->next && current_res->next->next) {
- if (current_res->next->length > current_res->next->next->length) {
- out_of_order++;
- next_res = current_res->next;
- current_res->next = current_res->next->next;
- current_res = current_res->next;
- next_res->next = current_res->next;
- current_res->next = next_res;
- } else
- current_res = current_res->next;
- }
- } /* End of out_of_order loop */
-
- return(0);
-}
-
-
-/*
- * sort_by_max_size
- *
- * Sorts nodes on the list by their length.
- * Largest first.
- *
- */
-static int sort_by_max_size(struct pci_resource **head)
-{
- struct pci_resource *current_res;
- struct pci_resource *next_res;
- int out_of_order = 1;
-
- if (!(*head))
- return(1);
-
- if (!((*head)->next))
- return(0);
-
- while (out_of_order) {
- out_of_order = 0;
-
- /* Special case for swapping list head */
- if (((*head)->next) &&
- ((*head)->length < (*head)->next->length)) {
- out_of_order++;
- current_res = *head;
- *head = (*head)->next;
- current_res->next = (*head)->next;
- (*head)->next = current_res;
- }
-
- current_res = *head;
-
- while (current_res->next && current_res->next->next) {
- if (current_res->next->length < current_res->next->next->length) {
- out_of_order++;
- next_res = current_res->next;
- current_res->next = current_res->next->next;
- current_res = current_res->next;
- next_res->next = current_res->next;
- current_res->next = next_res;
- } else
- current_res = current_res->next;
- }
- } /* End of out_of_order loop */
-
- return(0);
-}
-
-
-/*
- * do_pre_bridge_resource_split
- *
- * Returns zero or one node of resources that aren't in use
- *
- */
-static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment)
-{
- struct pci_resource *prevnode = NULL;
- struct pci_resource *node;
- struct pci_resource *split_node;
- u32 rc;
- u32 temp_dword;
- dbg("do_pre_bridge_resource_split\n");
-
- if (!(*head) || !(*orig_head))
- return(NULL);
-
- rc = shpchp_resource_sort_and_combine(head);
-
- if (rc)
- return(NULL);
-
- if ((*head)->base != (*orig_head)->base)
- return(NULL);
-
- if ((*head)->length == (*orig_head)->length)
- return(NULL);
-
-
- /* If we got here, there the bridge requires some of the resource, but
- * we may be able to split some off of the front
- */
- node = *head;
-
- if (node->length & (alignment -1)) {
- /* This one isn't an aligned length, so we'll make a new entry
- * and split it up.
- */
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
-
- temp_dword = (node->length | (alignment-1)) + 1 - alignment;
-
- split_node->base = node->base;
- split_node->length = temp_dword;
-
- node->length -= temp_dword;
- node->base += split_node->length;
-
- /* Put it in the list */
- *head = split_node;
- split_node->next = node;
- }
-
- if (node->length < alignment) {
- return(NULL);
- }
-
- /* Now unlink it */
- if (*head == node) {
- *head = node->next;
- node->next = NULL;
- } else {
- prevnode = *head;
- while (prevnode->next != node)
- prevnode = prevnode->next;
-
- prevnode->next = node->next;
- node->next = NULL;
- }
-
- return(node);
-}
-
-
-/*
- * do_bridge_resource_split
- *
- * Returns zero or one node of resources that aren't in use
- *
- */
-static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment)
-{
- struct pci_resource *prevnode = NULL;
- struct pci_resource *node;
- u32 rc;
- u32 temp_dword;
-
- if (!(*head))
- return(NULL);
-
- rc = shpchp_resource_sort_and_combine(head);
-
- if (rc)
- return(NULL);
-
- node = *head;
-
- while (node->next) {
- prevnode = node;
- node = node->next;
- kfree(prevnode);
- }
-
- if (node->length < alignment) {
- kfree(node);
- return(NULL);
- }
-
- if (node->base & (alignment - 1)) {
- /* Short circuit if adjusted size is too small */
- temp_dword = (node->base | (alignment-1)) + 1;
- if ((node->length - (temp_dword - node->base)) < alignment) {
- kfree(node);
- return(NULL);
- }
-
- node->length -= (temp_dword - node->base);
- node->base = temp_dword;
- }
-
- if (node->length & (alignment - 1)) {
- /* There's stuff in use after this node */
- kfree(node);
- return(NULL);
- }
-
- return(node);
-}
-
-
-/*
- * get_io_resource
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length that is not in the
- * ISA aliasing window. If it finds a node larger than "size"
- * it will split it up.
- *
- * size must be a power of two.
- */
-static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size)
-{
- struct pci_resource *prevnode;
- struct pci_resource *node;
- struct pci_resource *split_node = NULL;
- u32 temp_dword;
-
- if (!(*head))
- return(NULL);
-
- if ( shpchp_resource_sort_and_combine(head) )
- return(NULL);
-
- if ( sort_by_size(head) )
- return(NULL);
-
- for (node = *head; node; node = node->next) {
- if (node->length < size)
- continue;
-
- if (node->base & (size - 1)) {
- /* This one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_dword = (node->base | (size-1)) + 1;
-
- /*/ Short circuit if adjusted size is too small */
- if ((node->length - (temp_dword - node->base)) < size)
- continue;
-
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
-
- split_node->base = node->base;
- split_node->length = temp_dword - node->base;
- node->base = temp_dword;
- node->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of non-aligned base */
-
- /* Don't need to check if too small since we already did */
- if (node->length > size) {
- /* This one is longer than we need
- so we'll make a new entry and split it up */
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
-
- split_node->base = node->base + size;
- split_node->length = node->length - size;
- node->length = size;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of too big on top end */
-
- /* For IO make sure it's not in the ISA aliasing space */
- if (node->base & 0x300L)
- continue;
-
- /* If we got here, then it is the right size
- Now take it out of the list */
- if (*head == node) {
- *head = node->next;
- } else {
- prevnode = *head;
- while (prevnode->next != node)
- prevnode = prevnode->next;
-
- prevnode->next = node->next;
- }
- node->next = NULL;
- /* Stop looping */
- break;
- }
-
- return(node);
-}
-
-
-/*
- * get_max_resource
- *
- * Gets the largest node that is at least "size" big from the
- * list pointed to by head. It aligns the node on top and bottom
- * to "size" alignment before returning it.
- * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M
- * This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot.
- */
-static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size)
-{
- struct pci_resource *max;
- struct pci_resource *temp;
- struct pci_resource *split_node;
- u32 temp_dword;
- u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 };
- int i;
-
- if (!(*head))
- return(NULL);
-
- if (shpchp_resource_sort_and_combine(head))
- return(NULL);
-
- if (sort_by_max_size(head))
- return(NULL);
-
- for (max = *head;max; max = max->next) {
-
- /* If not big enough we could probably just bail,
- instead we'll continue to the next. */
- if (max->length < size)
- continue;
-
- if (max->base & (size - 1)) {
- /* This one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_dword = (max->base | (size-1)) + 1;
-
- /* Short circuit if adjusted size is too small */
- if ((max->length - (temp_dword - max->base)) < size)
- continue;
-
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
-
- split_node->base = max->base;
- split_node->length = temp_dword - max->base;
- max->base = temp_dword;
- max->length -= split_node->length;
-
- /* Put it next in the list */
- split_node->next = max->next;
- max->next = split_node;
- }
-
- if ((max->base + max->length) & (size - 1)) {
- /* This one isn't end aligned properly at the top
- so we'll make a new entry and split it up */
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
- temp_dword = ((max->base + max->length) & ~(size - 1));
- split_node->base = temp_dword;
- split_node->length = max->length + max->base
- - split_node->base;
- max->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = max->next;
- max->next = split_node;
- }
-
- /* Make sure it didn't shrink too much when we aligned it */
- if (max->length < size)
- continue;
-
- for ( i = 0; max_size[i] > size; i++) {
- if (max->length > max_size[i]) {
- split_node = kmalloc(sizeof(*split_node),
- GFP_KERNEL);
- if (!split_node)
- break; /* return (NULL); */
- split_node->base = max->base + max_size[i];
- split_node->length = max->length - max_size[i];
- max->length = max_size[i];
- /* Put it next in the list */
- split_node->next = max->next;
- max->next = split_node;
- break;
- }
- }
-
- /* Now take it out of the list */
- temp = (struct pci_resource*) *head;
- if (temp == max) {
- *head = max->next;
- } else {
- while (temp && temp->next != max) {
- temp = temp->next;
- }
-
- temp->next = max->next;
- }
-
- max->next = NULL;
- return(max);
- }
-
- /* If we get here, we couldn't find one */
- return(NULL);
-}
-
-
-/*
- * get_resource
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length. If it finds a node
- * larger than "size" it will split it up.
- *
- * size must be a power of two.
- */
-static struct pci_resource *get_resource (struct pci_resource **head, u32 size)
-{
- struct pci_resource *prevnode;
- struct pci_resource *node;
- struct pci_resource *split_node;
- u32 temp_dword;
-
- if (!(*head))
- return(NULL);
-
- if ( shpchp_resource_sort_and_combine(head) )
- return(NULL);
-
- if ( sort_by_size(head) )
- return(NULL);
-
- for (node = *head; node; node = node->next) {
- dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n",
- __FUNCTION__, size, node, node->base, node->length);
- if (node->length < size)
- continue;
-
- if (node->base & (size - 1)) {
- dbg("%s: not aligned\n", __FUNCTION__);
- /* this one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_dword = (node->base | (size-1)) + 1;
-
- /* Short circuit if adjusted size is too small */
- if ((node->length - (temp_dword - node->base)) < size)
- continue;
-
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
-
- split_node->base = node->base;
- split_node->length = temp_dword - node->base;
- node->base = temp_dword;
- node->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of non-aligned base */
-
- /* Don't need to check if too small since we already did */
- if (node->length > size) {
- dbg("%s: too big\n", __FUNCTION__);
- /* this one is longer than we need
- so we'll make a new entry and split it up */
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
-
- split_node->base = node->base + size;
- split_node->length = node->length - size;
- node->length = size;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of too big on top end */
-
- dbg("%s: got one!!!\n", __FUNCTION__);
- /* If we got here, then it is the right size
- Now take it out of the list */
- if (*head == node) {
- *head = node->next;
- } else {
- prevnode = *head;
- while (prevnode->next != node)
- prevnode = prevnode->next;
-
- prevnode->next = node->next;
- }
- node->next = NULL;
- /* Stop looping */
- break;
- }
- return(node);
-}
-
-
-/*
- * shpchp_resource_sort_and_combine
- *
- * Sorts all of the nodes in the list in ascending order by
- * their base addresses. Also does garbage collection by
- * combining adjacent nodes.
- *
- * returns 0 if success
- */
-int shpchp_resource_sort_and_combine(struct pci_resource **head)
-{
- struct pci_resource *node1;
- struct pci_resource *node2;
- int out_of_order = 1;
-
- dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head);
-
- if (!(*head))
- return(1);
-
- dbg("*head->next = %p\n",(*head)->next);
-
- if (!(*head)->next)
- return(0); /* only one item on the list, already sorted! */
-
- dbg("*head->base = 0x%x\n",(*head)->base);
- dbg("*head->next->base = 0x%x\n",(*head)->next->base);
- while (out_of_order) {
- out_of_order = 0;
-
- /* Special case for swapping list head */
- if (((*head)->next) &&
- ((*head)->base > (*head)->next->base)) {
- node1 = *head;
- (*head) = (*head)->next;
- node1->next = (*head)->next;
- (*head)->next = node1;
- out_of_order++;
- }
-
- node1 = (*head);
-
- while (node1->next && node1->next->next) {
- if (node1->next->base > node1->next->next->base) {
- out_of_order++;
- node2 = node1->next;
- node1->next = node1->next->next;
- node1 = node1->next;
- node2->next = node1->next;
- node1->next = node2;
- } else
- node1 = node1->next;
- }
- } /* End of out_of_order loop */
-
- node1 = *head;
-
- while (node1 && node1->next) {
- if ((node1->base + node1->length) == node1->next->base) {
- /* Combine */
- dbg("8..\n");
- node1->length += node1->next->length;
- node2 = node1->next;
- node1->next = node1->next->next;
- kfree(node2);
- } else
- node1 = node1->next;
- }
-
- return(0);
-}
-
-
-/**
- * shpchp_slot_create - Creates a node and adds it to the proper bus.
- * @busnumber - bus where new node is to be located
- *
- * Returns pointer to the new node or NULL if unsuccessful
- */
-struct pci_func *shpchp_slot_create(u8 busnumber)
-{
- struct pci_func *new_slot;
- struct pci_func *next;
-
- new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);
-
- if (new_slot == NULL) {
- return(new_slot);
- }
-
- memset(new_slot, 0, sizeof(struct pci_func));
-
- new_slot->next = NULL;
- new_slot->configured = 1;
-
- if (shpchp_slot_list[busnumber] == NULL) {
- shpchp_slot_list[busnumber] = new_slot;
- } else {
- next = shpchp_slot_list[busnumber];
- while (next->next != NULL)
- next = next->next;
- next->next = new_slot;
- }
- return(new_slot);
-}
-
-
-/*
- * slot_remove - Removes a node from the linked list of slots.
- * @old_slot: slot to remove
- *
- * Returns 0 if successful, !0 otherwise.
- */
-static int slot_remove(struct pci_func * old_slot)
-{
- struct pci_func *next;
-
- if (old_slot == NULL)
- return(1);
-
- next = shpchp_slot_list[old_slot->bus];
-
- if (next == NULL) {
- return(1);
- }
-
- if (next == old_slot) {
- shpchp_slot_list[old_slot->bus] = old_slot->next;
- shpchp_destroy_board_resources(old_slot);
- kfree(old_slot);
- return(0);
- }
-
- while ((next->next != old_slot) && (next->next != NULL)) {
- next = next->next;
- }
-
- if (next->next == old_slot) {
- next->next = old_slot->next;
- shpchp_destroy_board_resources(old_slot);
- kfree(old_slot);
- return(0);
- } else
- return(2);
-}
-
-
-/**
- * bridge_slot_remove - Removes a node from the linked list of slots.
- * @bridge: bridge to remove
- *
- * Returns 0 if successful, !0 otherwise.
- */
-static int bridge_slot_remove(struct pci_func *bridge)
-{
- u8 subordinateBus, secondaryBus;
- u8 tempBus;
- struct pci_func *next;
-
- if (bridge == NULL)
- return(1);
-
- secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
- subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
-
- for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
- next = shpchp_slot_list[tempBus];
-
- while (!slot_remove(next)) {
- next = shpchp_slot_list[tempBus];
- }
- }
-
- next = shpchp_slot_list[bridge->bus];
-
- if (next == NULL) {
- return(1);
- }
-
- if (next == bridge) {
- shpchp_slot_list[bridge->bus] = bridge->next;
- kfree(bridge);
- return(0);
- }
-
- while ((next->next != bridge) && (next->next != NULL)) {
- next = next->next;
- }
-
- if (next->next == bridge) {
- next->next = bridge->next;
- kfree(bridge);
- return(0);
- } else
- return(2);
-}
-
-
-/**
- * shpchp_slot_find - Looks for a node by bus, and device, multiple functions accessed
- * @bus: bus to find
- * @device: device to find
- * @index: is 0 for first function found, 1 for the second...
- *
- * Returns pointer to the node if successful, %NULL otherwise.
- */
-struct pci_func *shpchp_slot_find(u8 bus, u8 device, u8 index)
-{
- int found = -1;
- struct pci_func *func;
-
- func = shpchp_slot_list[bus];
-
- if ((func == NULL) || ((func->device == device) && (index == 0)))
- return(func);
-
- if (func->device == device)
- found++;
-
- while (func->next != NULL) {
- func = func->next;
-
- if (func->device == device)
- found++;
-
- if (found == index)
- return(func);
- }
-
- return(NULL);
-}
-
-static int is_bridge(struct pci_func * func)
-{
- /* Check the header type */
- if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
- return 1;
- else
- return 0;
-}
-
-
/* The following routines constitute the bulk of the
hotplug controller logic
*/
-static u32 change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum pci_bus_speed speed)
+static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
+ enum pci_bus_speed speed)
{
- u32 rc = 0;
+ int rc = 0;
dbg("%s: change to speed %d\n", __FUNCTION__, speed);
down(&ctrl->crit_sect);
@@ -1074,10 +261,11 @@ static u32 change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum p
return rc;
}
-static u32 fix_bus_speed(struct controller *ctrl, struct slot *pslot, u8 flag,
-enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp)
+static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
+ u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp,
+ enum pci_bus_speed msp)
{
- u32 rc = 0;
+ int rc = 0;
if (flag != 0) { /* Other slots on the same bus are occupied */
if ( asp < bsp ) {
@@ -1116,23 +304,20 @@ enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp)
* Configures board
*
*/
-static u32 board_added(struct pci_func * func, struct controller * ctrl)
+static int board_added(struct slot *p_slot)
{
u8 hp_slot;
u8 slots_not_empty = 0;
- int index;
- u32 temp_register = 0xFFFFFFFF;
- u32 retval, rc = 0;
- struct pci_func *new_func = NULL;
- struct slot *p_slot;
- struct resource_lists res_lists;
+ int rc = 0;
enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed;
u8 pi, mode;
+ struct controller *ctrl = p_slot->ctrl;
- p_slot = shpchp_find_slot(ctrl, func->device);
- hp_slot = func->device - ctrl->slot_device_offset;
+ hp_slot = p_slot->device - ctrl->slot_device_offset;
- dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
+ dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n",
+ __FUNCTION__, p_slot->device,
+ ctrl->slot_device_offset, hp_slot);
/* Wait for exclusive access to hardware */
down(&ctrl->crit_sect);
@@ -1320,143 +505,68 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
up(&ctrl->crit_sect);
/* Wait for ~1 second */
- dbg("%s: before long_delay\n", __FUNCTION__);
wait_for_ctrl_irq (ctrl);
- dbg("%s: after long_delay\n", __FUNCTION__);
- dbg("%s: func status = %x\n", __FUNCTION__, func->status);
+ dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
/* Check for a power fault */
- if (func->status == 0xFF) {
+ if (p_slot->status == 0xFF) {
/* power fault occurred, but it was benign */
- temp_register = 0xFFFFFFFF;
- dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
+ dbg("%s: power fault\n", __FUNCTION__);
rc = POWER_FAILURE;
- func->status = 0;
- } else {
- /* Get vendor/device ID u32 */
- rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function),
- PCI_VENDOR_ID, &temp_register);
- dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc);
- dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register);
-
- if (rc != 0) {
- /* Something's wrong here */
- temp_register = 0xFFFFFFFF;
- dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register);
- }
- /* Preset return code. It will be changed later if things go okay. */
- rc = NO_ADAPTER_PRESENT;
+ p_slot->status = 0;
+ goto err_exit;
}
- /* All F's is an empty slot or an invalid board */
- if (temp_register != 0xFFFFFFFF) { /* Check for a board in the slot */
- res_lists.io_head = ctrl->io_head;
- res_lists.mem_head = ctrl->mem_head;
- res_lists.p_mem_head = ctrl->p_mem_head;
- res_lists.bus_head = ctrl->bus_head;
- res_lists.irqs = NULL;
-
- rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0);
- dbg("%s: back from configure_new_device\n", __FUNCTION__);
-
- ctrl->io_head = res_lists.io_head;
- ctrl->mem_head = res_lists.mem_head;
- ctrl->p_mem_head = res_lists.p_mem_head;
- ctrl->bus_head = res_lists.bus_head;
-
- shpchp_resource_sort_and_combine(&(ctrl->mem_head));
- shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
- shpchp_resource_sort_and_combine(&(ctrl->io_head));
- shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
- if (rc) {
- /* Wait for exclusive access to hardware */
- down(&ctrl->crit_sect);
-
- /* turn off slot, turn on Amber LED, turn off Green LED */
- retval = p_slot->hpc_ops->slot_disable(p_slot);
- if (retval) {
- err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
- /* Done with exclusive hardware access */
- up(&ctrl->crit_sect);
- return retval;
- }
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
-
- retval = p_slot->hpc_ops->check_cmd_status(ctrl);
- if (retval) {
- err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, retval);
- /* Done with exclusive hardware access */
- up(&ctrl->crit_sect);
- return retval;
- }
-
- /* Done with exclusive hardware access */
- up(&ctrl->crit_sect);
+ if (shpchp_configure_device(p_slot)) {
+ err("Cannot add device at 0x%x:0x%x\n", p_slot->bus,
+ p_slot->device);
+ goto err_exit;
+ }
- return(rc);
- }
- shpchp_save_slot_config(ctrl, func);
+ p_slot->status = 0;
+ p_slot->is_a_board = 0x01;
+ p_slot->pwr_save = 1;
- func->status = 0;
- func->switch_save = 0x10;
- func->is_a_board = 0x01;
- func->pwr_save = 1;
+ /* Wait for exclusive access to hardware */
+ down(&ctrl->crit_sect);
- /* Next, we will instantiate the linux pci_dev structures
- * (with appropriate driver notification, if already present)
- */
- index = 0;
- do {
- new_func = shpchp_slot_find(ctrl->slot_bus, func->device, index++);
- if (new_func && !new_func->pci_dev) {
- dbg("%s:call pci_hp_configure_dev\n", __FUNCTION__);
- shpchp_configure_device(ctrl, new_func);
- }
- } while (new_func);
+ p_slot->hpc_ops->green_led_on(p_slot);
- /* Wait for exclusive access to hardware */
- down(&ctrl->crit_sect);
+ /* Wait for the command to complete */
+ wait_for_ctrl_irq (ctrl);
- p_slot->hpc_ops->green_led_on(p_slot);
+ /* Done with exclusive hardware access */
+ up(&ctrl->crit_sect);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
+ return 0;
+err_exit:
+ /* Wait for exclusive access to hardware */
+ down(&ctrl->crit_sect);
+ /* turn off slot, turn on Amber LED, turn off Green LED */
+ rc = p_slot->hpc_ops->slot_disable(p_slot);
+ if (rc) {
+ err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
+ return rc;
+ }
+ /* Wait for the command to complete */
+ wait_for_ctrl_irq (ctrl);
- } else {
- /* Wait for exclusive access to hardware */
- down(&ctrl->crit_sect);
-
- /* turn off slot, turn on Amber LED, turn off Green LED */
- rc = p_slot->hpc_ops->slot_disable(p_slot);
- if (rc) {
- err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
- /* Done with exclusive hardware access */
- up(&ctrl->crit_sect);
- return rc;
- }
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
-
- rc = p_slot->hpc_ops->check_cmd_status(ctrl);
- if (rc) {
- err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
- /* Done with exclusive hardware access */
- up(&ctrl->crit_sect);
- return rc;
- }
-
+ rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+ if (rc) {
+ err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
-
- return(rc);
+ return rc;
}
- return 0;
+
+ /* Done with exclusive hardware access */
+ up(&ctrl->crit_sect);
+
+ return(rc);
}
@@ -1464,55 +574,23 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
* remove_board - Turns off slot and LED's
*
*/
-static u32 remove_board(struct pci_func *func, struct controller *ctrl)
+static int remove_board(struct slot *p_slot)
{
- int index;
- u8 skip = 0;
- u8 device;
+ struct controller *ctrl = p_slot->ctrl;
u8 hp_slot;
- u32 rc;
- struct resource_lists res_lists;
- struct pci_func *temp_func;
- struct slot *p_slot;
-
- if (func == NULL)
- return(1);
+ int rc;
- if (shpchp_unconfigure_device(func))
+ if (shpchp_unconfigure_device(p_slot))
return(1);
- device = func->device;
-
- hp_slot = func->device - ctrl->slot_device_offset;
+ hp_slot = p_slot->device - ctrl->slot_device_offset;
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
- if ((ctrl->add_support) &&
- !(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) {
- /* Here we check to see if we've saved any of the board's
- * resources already. If so, we'll skip the attempt to
- * determine what's being used.
- */
- index = 0;
-
- temp_func = func;
-
- while ((temp_func = shpchp_slot_find(temp_func->bus, temp_func->device, index++))) {
- if (temp_func->bus_head || temp_func->mem_head
- || temp_func->p_mem_head || temp_func->io_head) {
- skip = 1;
- break;
- }
- }
-
- if (!skip)
- rc = shpchp_save_used_resources(ctrl, func, DISABLE_CARD);
- }
/* Change status to shutdown */
- if (func->is_a_board)
- func->status = 0x01;
- func->configured = 0;
+ if (p_slot->is_a_board)
+ p_slot->status = 0x01;
/* Wait for exclusive access to hardware */
down(&ctrl->crit_sect);
@@ -1549,55 +627,8 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
- if (ctrl->add_support) {
- while (func) {
- res_lists.io_head = ctrl->io_head;
- res_lists.mem_head = ctrl->mem_head;
- res_lists.p_mem_head = ctrl->p_mem_head;
- res_lists.bus_head = ctrl->bus_head;
-
- dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n", func->bus,
- func->device, func->function);
-
- shpchp_return_board_resources(func, &res_lists);
-
- ctrl->io_head = res_lists.io_head;
- ctrl->mem_head = res_lists.mem_head;
- ctrl->p_mem_head = res_lists.p_mem_head;
- ctrl->bus_head = res_lists.bus_head;
-
- shpchp_resource_sort_and_combine(&(ctrl->mem_head));
- shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
- shpchp_resource_sort_and_combine(&(ctrl->io_head));
- shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
- if (is_bridge(func)) {
- dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus,
- func->device, func->function);
- bridge_slot_remove(func);
- } else
- dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus,
- func->device, func->function);
- slot_remove(func);
-
- func = shpchp_slot_find(ctrl->slot_bus, device, 0);
- }
-
- /* Setup slot structure with entry for empty slot */
- func = shpchp_slot_create(ctrl->slot_bus);
-
- if (func == NULL) {
- return(1);
- }
-
- func->bus = ctrl->slot_bus;
- func->device = device;
- func->function = 0;
- func->configured = 0;
- func->switch_save = 0x10;
- func->pwr_save = 0;
- func->is_a_board = 0;
- }
+ p_slot->pwr_save = 0;
+ p_slot->is_a_board = 0;
return 0;
}
@@ -1633,13 +664,11 @@ static void shpchp_pushbutton_thread (unsigned long slot)
p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (getstatus) {
p_slot->state = POWEROFF_STATE;
- dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
shpchp_disable_slot(p_slot);
p_slot->state = STATIC_STATE;
} else {
p_slot->state = POWERON_STATE;
- dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
if (shpchp_enable_slot(p_slot)) {
/* Wait for exclusive access to hardware */
@@ -1701,7 +730,6 @@ int shpchp_event_start_thread (void)
err ("Can't start up our event thread\n");
return -1;
}
- dbg("Our event thread pid = %d\n", pid);
return 0;
}
@@ -1709,9 +737,7 @@ int shpchp_event_start_thread (void)
void shpchp_event_stop_thread (void)
{
event_finished = 1;
- dbg("event_thread finish command given\n");
up(&event_semaphore);
- dbg("wait for event_thread to exit\n");
down(&event_exit);
}
@@ -1739,12 +765,10 @@ static void interrupt_event_handler(struct controller *ctrl)
{
int loop = 0;
int change = 1;
- struct pci_func *func;
u8 hp_slot;
u8 getstatus;
struct slot *p_slot;
- dbg("%s:\n", __FUNCTION__);
while (change) {
change = 0;
@@ -1754,12 +778,8 @@ static void interrupt_event_handler(struct controller *ctrl)
ctrl->event_queue[loop].event_type);
hp_slot = ctrl->event_queue[loop].hp_slot;
- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
- dbg("%s: hp_slot %d, func %p, p_slot %p\n", __FUNCTION__, hp_slot, func, p_slot);
-
if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
dbg("%s: button cancel\n", __FUNCTION__);
del_timer(&p_slot->task_event);
@@ -1880,13 +900,6 @@ int shpchp_enable_slot (struct slot *p_slot)
{
u8 getstatus = 0;
int rc;
- struct pci_func *func;
-
- func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
- if (!func) {
- dbg("%s: Error! slot NULL\n", __FUNCTION__);
- return -ENODEV;
- }
/* Check to see if (latch closed, card present, power off) */
down(&p_slot->ctrl->crit_sect);
@@ -1910,72 +923,34 @@ int shpchp_enable_slot (struct slot *p_slot)
}
up(&p_slot->ctrl->crit_sect);
- slot_remove(func);
-
- func = shpchp_slot_create(p_slot->bus);
- if (func == NULL)
- return -ENOMEM;
-
- func->bus = p_slot->bus;
- func->device = p_slot->device;
- func->function = 0;
- func->configured = 0;
- func->is_a_board = 1;
+ p_slot->is_a_board = 1;
/* We have to save the presence info for these slots */
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
- p_slot->hpc_ops->get_power_status(p_slot, &(func->pwr_save));
- dbg("%s: func->pwr_save %x\n", __FUNCTION__, func->pwr_save);
+ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save));
+ dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save);
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
- func->switch_save = !getstatus? 0x10:0;
- rc = board_added(func, p_slot->ctrl);
+ rc = board_added(p_slot);
if (rc) {
- if (is_bridge(func))
- bridge_slot_remove(func);
- else
- slot_remove(func);
-
- /* Setup slot structure with entry for empty slot */
- func = shpchp_slot_create(p_slot->bus);
- if (func == NULL)
- return -ENOMEM; /* Out of memory */
-
- func->bus = p_slot->bus;
- func->device = p_slot->device;
- func->function = 0;
- func->configured = 0;
- func->is_a_board = 1;
-
- /* We have to save the presence info for these slots */
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+ p_slot->hpc_ops->get_adapter_status(p_slot,
+ &(p_slot->presence_save));
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
- func->switch_save = !getstatus? 0x10:0;
}
- if (p_slot)
- update_slot_info(p_slot);
-
+ update_slot_info(p_slot);
return rc;
}
int shpchp_disable_slot (struct slot *p_slot)
{
- u8 class_code, header_type, BCR;
- u8 index = 0;
u8 getstatus = 0;
- u32 rc = 0;
int ret = 0;
- unsigned int devfn;
- struct pci_bus *pci_bus;
- struct pci_func *func;
if (!p_slot->ctrl)
return -ENODEV;
- pci_bus = p_slot->ctrl->pci_dev->subordinate;
-
/* Check to see if (latch closed, card present, power on) */
down(&p_slot->ctrl->crit_sect);
@@ -1999,849 +974,8 @@ int shpchp_disable_slot (struct slot *p_slot)
}
up(&p_slot->ctrl->crit_sect);
- func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
-
- /* Make sure there are no video controllers here
- * for all func of p_slot
- */
- while (func && !rc) {
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- /* Check the Class Code */
- rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
- if (rc)
- return -ENODEV;
-
- if (class_code == PCI_BASE_CLASS_DISPLAY) {
- /* Display/Video adapter (not supported) */
- rc = REMOVE_NOT_SUPPORTED;
- } else {
- /* See if it's a bridge */
- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
- if (rc)
- return -ENODEV;
-
- /* If it's a bridge, check the VGA Enable bit */
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
- if (rc)
- return -ENODEV;
-
- /* If the VGA Enable bit is set, remove isn't supported */
- if (BCR & PCI_BRIDGE_CTL_VGA) {
- rc = REMOVE_NOT_SUPPORTED;
- }
- }
- }
-
- func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
- }
-
- func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
- if ((func != NULL) && !rc) {
- rc = remove_board(func, p_slot->ctrl);
- } else if (!rc)
- rc = -ENODEV;
-
- if (p_slot)
- update_slot_info(p_slot);
-
- return rc;
-}
-
-
-/**
- * configure_new_device - Configures the PCI header information of one board.
- *
- * @ctrl: pointer to controller structure
- * @func: pointer to function structure
- * @behind_bridge: 1 if this is a recursive call, 0 if not
- * @resources: pointer to set of resource lists
- *
- * Returns 0 if success
- *
- */
-static u32 configure_new_device (struct controller * ctrl, struct pci_func * func,
- u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev)
-{
- u8 temp_byte, function, max_functions, stop_it;
- int rc;
- u32 ID;
- struct pci_func *new_slot;
- struct pci_bus lpci_bus, *pci_bus;
- int index;
-
- new_slot = func;
-
- dbg("%s\n", __FUNCTION__);
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
-
- /* Check for Multi-function device */
- rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
- if (rc) {
- dbg("%s: rc = %d\n", __FUNCTION__, rc);
- return rc;
- }
-
- if (temp_byte & 0x80) /* Multi-function device */
- max_functions = 8;
- else
- max_functions = 1;
-
- function = 0;
-
- do {
- rc = configure_new_function(ctrl, new_slot, behind_bridge, resources, bridge_bus, bridge_dev);
-
- if (rc) {
- dbg("configure_new_function failed %d\n",rc);
- index = 0;
-
- while (new_slot) {
- new_slot = shpchp_slot_find(new_slot->bus, new_slot->device, index++);
-
- if (new_slot)
- shpchp_return_board_resources(new_slot, resources);
- }
-
- return(rc);
- }
-
- function++;
-
- stop_it = 0;
-
- /* The following loop skips to the next present function
- * and creates a board structure
- */
-
- while ((function < max_functions) && (!stop_it)) {
- pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
-
- if (ID == 0xFFFFFFFF) { /* There's nothing there. */
- function++;
- } else { /* There's something there */
- /* Setup slot structure. */
- new_slot = shpchp_slot_create(func->bus);
-
- if (new_slot == NULL) {
- /* Out of memory */
- return(1);
- }
-
- new_slot->bus = func->bus;
- new_slot->device = func->device;
- new_slot->function = function;
- new_slot->is_a_board = 1;
- new_slot->status = 0;
-
- stop_it++;
- }
- }
-
- } while (function < max_functions);
- dbg("returning from configure_new_device\n");
-
- return 0;
-}
-
-
-/*
- * Configuration logic that involves the hotplug data structures and
- * their bookkeeping
- */
-
-
-/**
- * configure_new_function - Configures the PCI header information of one device
- *
- * @ctrl: pointer to controller structure
- * @func: pointer to function structure
- * @behind_bridge: 1 if this is a recursive call, 0 if not
- * @resources: pointer to set of resource lists
- *
- * Calls itself recursively for bridged devices.
- * Returns 0 if success
- *
- */
-static int configure_new_function (struct controller * ctrl, struct pci_func * func,
- u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev)
-{
- int cloop;
- u8 temp_byte;
- u8 device;
- u8 class_code;
- u16 temp_word;
- u32 rc;
- u32 temp_register;
- u32 base;
- u32 ID;
- unsigned int devfn;
- struct pci_resource *mem_node;
- struct pci_resource *p_mem_node;
- struct pci_resource *io_node;
- struct pci_resource *bus_node;
- struct pci_resource *hold_mem_node;
- struct pci_resource *hold_p_mem_node;
- struct pci_resource *hold_IO_node;
- struct pci_resource *hold_bus_node;
- struct irq_mapping irqs;
- struct pci_func *new_slot;
- struct pci_bus lpci_bus, *pci_bus;
- struct resource_lists temp_resources;
-#if defined(CONFIG_X86_64)
- u8 IRQ=0;
-#endif
-
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- /* Check for Bridge */
- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte);
- if (rc)
- return rc;
-
- if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
- /* set Primary bus */
- dbg("set Primary bus = 0x%x\n", func->bus);
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
- if (rc)
- return rc;
-
- /* find range of busses to use */
- bus_node = get_max_resource(&resources->bus_head, 1L);
-
- /* If we don't have any busses to allocate, we can't continue */
- if (!bus_node) {
- err("Got NO bus resource to use\n");
- return -ENOMEM;
- }
- dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length);
-
- /* set Secondary bus */
- temp_byte = (u8)bus_node->base;
- dbg("set Secondary bus = 0x%x\n", temp_byte);
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte);
- if (rc)
- return rc;
-
- /* set subordinate bus */
- temp_byte = (u8)(bus_node->base + bus_node->length - 1);
- dbg("set subordinate bus = 0x%x\n", temp_byte);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
- if (rc)
- return rc;
-
- /* Set HP parameters (Cache Line Size, Latency Timer) */
- rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
- if (rc)
- return rc;
-
- /* Setup the IO, memory, and prefetchable windows */
-
- io_node = get_max_resource(&(resources->io_head), 0x1000L);
- if (io_node) {
- dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next);
- }
-
- mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
- if (mem_node) {
- dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next);
- }
-
- if (resources->p_mem_head)
- p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L);
- else {
- /*
- * In some platform implementation, MEM and PMEM are not
- * distinguished, and hence ACPI _CRS has only MEM entries
- * for both MEM and PMEM.
- */
- dbg("using MEM for PMEM\n");
- p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
- }
- if (p_mem_node) {
- dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next);
- }
-
- /* set up the IRQ info */
- if (!resources->irqs) {
- irqs.barber_pole = 0;
- irqs.interrupt[0] = 0;
- irqs.interrupt[1] = 0;
- irqs.interrupt[2] = 0;
- irqs.interrupt[3] = 0;
- irqs.valid_INT = 0;
- } else {
- irqs.barber_pole = resources->irqs->barber_pole;
- irqs.interrupt[0] = resources->irqs->interrupt[0];
- irqs.interrupt[1] = resources->irqs->interrupt[1];
- irqs.interrupt[2] = resources->irqs->interrupt[2];
- irqs.interrupt[3] = resources->irqs->interrupt[3];
- irqs.valid_INT = resources->irqs->valid_INT;
- }
-
- /* set up resource lists that are now aligned on top and bottom
- * for anything behind the bridge.
- */
- temp_resources.bus_head = bus_node;
- temp_resources.io_head = io_node;
- temp_resources.mem_head = mem_node;
- temp_resources.p_mem_head = p_mem_node;
- temp_resources.irqs = &irqs;
-
- /* Make copies of the nodes we are going to pass down so that
- * if there is a problem,we can just use these to free resources
- */
- hold_bus_node = kmalloc(sizeof(*hold_bus_node), GFP_KERNEL);
- hold_IO_node = kmalloc(sizeof(*hold_IO_node), GFP_KERNEL);
- hold_mem_node = kmalloc(sizeof(*hold_mem_node), GFP_KERNEL);
- hold_p_mem_node = kmalloc(sizeof(*hold_p_mem_node), GFP_KERNEL);
-
- if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {
- kfree(hold_bus_node);
- kfree(hold_IO_node);
- kfree(hold_mem_node);
- kfree(hold_p_mem_node);
-
- return 1;
- }
-
- memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));
-
- bus_node->base += 1;
- bus_node->length -= 1;
- bus_node->next = NULL;
-
- /* If we have IO resources copy them and fill in the bridge's
- * IO range registers
- */
- if (io_node) {
- memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
- io_node->next = NULL;
-
- /* set IO base and Limit registers */
- RES_CHECK(io_node->base, 8);
- temp_byte = (u8)(io_node->base >> 8);
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);
-
- RES_CHECK(io_node->base + io_node->length - 1, 8);
- temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8);
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
- } else {
- kfree(hold_IO_node);
- hold_IO_node = NULL;
- }
-
- /* If we have memory resources copy them and fill in the bridge's
- * memory range registers. Otherwise, fill in the range
- * registers with values that disable them.
- */
- if (mem_node) {
- memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
- mem_node->next = NULL;
-
- /* set Mem base and Limit registers */
- RES_CHECK(mem_node->base, 16);
- temp_word = (u32)(mem_node->base >> 16);
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
- RES_CHECK(mem_node->base + mem_node->length - 1, 16);
- temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16);
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
- } else {
- temp_word = 0xFFFF;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
- temp_word = 0x0000;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
- kfree(hold_mem_node);
- hold_mem_node = NULL;
- }
-
- /* If we have prefetchable memory resources copy them and
- * fill in the bridge's memory range registers. Otherwise,
- * fill in the range registers with values that disable them.
- */
- if (p_mem_node) {
- memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
- p_mem_node->next = NULL;
-
- /* set Pre Mem base and Limit registers */
- RES_CHECK(p_mem_node->base, 16);
- temp_word = (u32)(p_mem_node->base >> 16);
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
- RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16);
- temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16);
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
- } else {
- temp_word = 0xFFFF;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
- temp_word = 0x0000;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
- kfree(hold_p_mem_node);
- hold_p_mem_node = NULL;
- }
-
- /* Adjust this to compensate for extra adjustment in first loop */
- irqs.barber_pole--;
-
- rc = 0;
-
- /* Here we actually find the devices and configure them */
- for (device = 0; (device <= 0x1F) && !rc; device++) {
- irqs.barber_pole = (irqs.barber_pole + 1) & 0x03;
-
- ID = 0xFFFFFFFF;
- pci_bus->number = hold_bus_node->base;
- pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
- PCI_VENDOR_ID, &ID);
- pci_bus->number = func->bus;
-
- if (ID != 0xFFFFFFFF) { /* device Present */
- /* Setup slot structure. */
- new_slot = shpchp_slot_create(hold_bus_node->base);
-
- if (new_slot == NULL) {
- /* Out of memory */
- rc = -ENOMEM;
- continue;
- }
-
- new_slot->bus = hold_bus_node->base;
- new_slot->device = device;
- new_slot->function = 0;
- new_slot->is_a_board = 1;
- new_slot->status = 0;
-
- rc = configure_new_device(ctrl, new_slot, 1, &temp_resources, func->bus, func->device);
- dbg("configure_new_device rc=0x%x\n",rc);
- } /* End of IF (device in slot?) */
- } /* End of FOR loop */
-
- if (rc) {
- shpchp_destroy_resource_list(&temp_resources);
-
- return_resource(&(resources->bus_head), hold_bus_node);
- return_resource(&(resources->io_head), hold_IO_node);
- return_resource(&(resources->mem_head), hold_mem_node);
- return_resource(&(resources->p_mem_head), hold_p_mem_node);
- return(rc);
- }
-
- /* save the interrupt routing information */
- if (resources->irqs) {
- resources->irqs->interrupt[0] = irqs.interrupt[0];
- resources->irqs->interrupt[1] = irqs.interrupt[1];
- resources->irqs->interrupt[2] = irqs.interrupt[2];
- resources->irqs->interrupt[3] = irqs.interrupt[3];
- resources->irqs->valid_INT = irqs.valid_INT;
- } else if (!behind_bridge) {
- /* We need to hook up the interrupts here */
- for (cloop = 0; cloop < 4; cloop++) {
- if (irqs.valid_INT & (0x01 << cloop)) {
- rc = shpchp_set_irq(func->bus, func->device,
- 0x0A + cloop, irqs.interrupt[cloop]);
- if (rc) {
- shpchp_destroy_resource_list (&temp_resources);
- return_resource(&(resources->bus_head), hold_bus_node);
- return_resource(&(resources->io_head), hold_IO_node);
- return_resource(&(resources->mem_head), hold_mem_node);
- return_resource(&(resources->p_mem_head), hold_p_mem_node);
- return rc;
- }
- }
- } /* end of for loop */
- }
-
- /* Return unused bus resources
- * First use the temporary node to store information for the board
- */
- if (hold_bus_node && bus_node && temp_resources.bus_head) {
- hold_bus_node->length = bus_node->base - hold_bus_node->base;
-
- hold_bus_node->next = func->bus_head;
- func->bus_head = hold_bus_node;
-
- temp_byte = (u8)(temp_resources.bus_head->base - 1);
-
- /* set subordinate bus */
- dbg("re-set subordinate bus = 0x%x\n", temp_byte);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
-
- if (temp_resources.bus_head->length == 0) {
- kfree(temp_resources.bus_head);
- temp_resources.bus_head = NULL;
- } else {
- dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n",
- func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length);
- return_resource(&(resources->bus_head), temp_resources.bus_head);
- }
- }
-
- /* If we have IO space available and there is some left,
- * return the unused portion
- */
- if (hold_IO_node && temp_resources.io_head) {
- io_node = do_pre_bridge_resource_split(&(temp_resources.io_head),
- &hold_IO_node, 0x1000);
-
- /* Check if we were able to split something off */
- if (io_node) {
- hold_IO_node->base = io_node->base + io_node->length;
-
- RES_CHECK(hold_IO_node->base, 8);
- temp_byte = (u8)((hold_IO_node->base) >> 8);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
-
- return_resource(&(resources->io_head), io_node);
- }
-
- io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000);
-
- /* Check if we were able to split something off */
- if (io_node) {
- /* First use the temporary node to store information for the board */
- hold_IO_node->length = io_node->base - hold_IO_node->base;
-
- /* If we used any, add it to the board's list */
- if (hold_IO_node->length) {
- hold_IO_node->next = func->io_head;
- func->io_head = hold_IO_node;
-
- RES_CHECK(io_node->base - 1, 8);
- temp_byte = (u8)((io_node->base - 1) >> 8);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-
- return_resource(&(resources->io_head), io_node);
- } else {
- /* it doesn't need any IO */
- temp_byte = 0x00;
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-
- return_resource(&(resources->io_head), io_node);
- kfree(hold_IO_node);
- }
- } else {
- /* it used most of the range */
- hold_IO_node->next = func->io_head;
- func->io_head = hold_IO_node;
- }
- } else if (hold_IO_node) {
- /* it used the whole range */
- hold_IO_node->next = func->io_head;
- func->io_head = hold_IO_node;
- }
-
- /* If we have memory space available and there is some left,
- * return the unused portion
- */
- if (hold_mem_node && temp_resources.mem_head) {
- mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L);
-
- /* Check if we were able to split something off */
- if (mem_node) {
- hold_mem_node->base = mem_node->base + mem_node->length;
-
- RES_CHECK(hold_mem_node->base, 16);
- temp_word = (u32)((hold_mem_node->base) >> 16);
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
- return_resource(&(resources->mem_head), mem_node);
- }
-
- mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L);
-
- /* Check if we were able to split something off */
- if (mem_node) {
- /* First use the temporary node to store information for the board */
- hold_mem_node->length = mem_node->base - hold_mem_node->base;
-
- if (hold_mem_node->length) {
- hold_mem_node->next = func->mem_head;
- func->mem_head = hold_mem_node;
-
- /* configure end address */
- RES_CHECK(mem_node->base - 1, 16);
- temp_word = (u32)((mem_node->base - 1) >> 16);
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
- /* Return unused resources to the pool */
- return_resource(&(resources->mem_head), mem_node);
- } else {
- /* it doesn't need any Mem */
- temp_word = 0x0000;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
- return_resource(&(resources->mem_head), mem_node);
- kfree(hold_mem_node);
- }
- } else {
- /* it used most of the range */
- hold_mem_node->next = func->mem_head;
- func->mem_head = hold_mem_node;
- }
- } else if (hold_mem_node) {
- /* it used the whole range */
- hold_mem_node->next = func->mem_head;
- func->mem_head = hold_mem_node;
- }
-
- /* If we have prefetchable memory space available and there is some
- * left at the end, return the unused portion
- */
- if (hold_p_mem_node && temp_resources.p_mem_head) {
- p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
- &hold_p_mem_node, 0x100000L);
-
- /* Check if we were able to split something off */
- if (p_mem_node) {
- hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;
-
- RES_CHECK(hold_p_mem_node->base, 16);
- temp_word = (u32)((hold_p_mem_node->base) >> 16);
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
- return_resource(&(resources->p_mem_head), p_mem_node);
- }
-
- p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L);
-
- /* Check if we were able to split something off */
- if (p_mem_node) {
- /* First use the temporary node to store information for the board */
- hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base;
-
- /* If we used any, add it to the board's list */
- if (hold_p_mem_node->length) {
- hold_p_mem_node->next = func->p_mem_head;
- func->p_mem_head = hold_p_mem_node;
-
- RES_CHECK(p_mem_node->base - 1, 16);
- temp_word = (u32)((p_mem_node->base - 1) >> 16);
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
- return_resource(&(resources->p_mem_head), p_mem_node);
- } else {
- /* it doesn't need any PMem */
- temp_word = 0x0000;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
- return_resource(&(resources->p_mem_head), p_mem_node);
- kfree(hold_p_mem_node);
- }
- } else {
- /* it used the most of the range */
- hold_p_mem_node->next = func->p_mem_head;
- func->p_mem_head = hold_p_mem_node;
- }
- } else if (hold_p_mem_node) {
- /* it used the whole range */
- hold_p_mem_node->next = func->p_mem_head;
- func->p_mem_head = hold_p_mem_node;
- }
-
- /* We should be configuring an IRQ and the bridge's base address
- * registers if it needs them. Although we have never seen such
- * a device
- */
-
- shpchprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
-
- dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
- } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
- /* Standard device */
- u64 base64;
- rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
-
- if (class_code == PCI_BASE_CLASS_DISPLAY)
- return (DEVICE_TYPE_NOT_SUPPORTED);
-
- /* Figure out IO and memory needs */
- for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
- temp_register = 0xFFFFFFFF;
-
- rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
- rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
- dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register, func->bus, func->device,
- func->function);
-
- if (!temp_register)
- continue;
-
- base64 = 0L;
- if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) {
- /* Map IO */
-
- /* set base = amount of IO space */
- base = temp_register & 0xFFFFFFFC;
- base = ~base + 1;
-
- dbg("NEED IO length(0x%x)\n", base);
- io_node = get_io_resource(&(resources->io_head),(ulong)base);
-
- /* allocate the resource to the board */
- if (io_node) {
- dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length);
- base = (u32)io_node->base;
- io_node->next = func->io_head;
- func->io_head = io_node;
- } else {
- err("Got NO IO resource(length=0x%x)\n", base);
- return -ENOMEM;
- }
- } else { /* map MEM */
- int prefetchable = 1;
- struct pci_resource **res_node = &func->p_mem_head;
- char *res_type_str = "PMEM";
- u32 temp_register2;
-
- if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) {
- prefetchable = 0;
- res_node = &func->mem_head;
- res_type_str++;
- }
-
- base = temp_register & 0xFFFFFFF0;
- base = ~base + 1;
-
- switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
- case PCI_BASE_ADDRESS_MEM_TYPE_32:
- dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base);
-
- if (prefetchable && resources->p_mem_head)
- mem_node=get_resource(&(resources->p_mem_head), (ulong)base);
- else {
- if (prefetchable)
- dbg("using MEM for PMEM\n");
- mem_node=get_resource(&(resources->mem_head), (ulong)base);
- }
-
- /* allocate the resource to the board */
- if (mem_node) {
- base = (u32)mem_node->base;
- mem_node->next = *res_node;
- *res_node = mem_node;
- dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base,
- mem_node->length);
- } else {
- err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base);
- return -ENOMEM;
- }
- break;
- case PCI_BASE_ADDRESS_MEM_TYPE_64:
- rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
- dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2,
- temp_register, base);
-
- if (prefetchable && resources->p_mem_head)
- mem_node = get_resource(&(resources->p_mem_head), (ulong)base);
- else {
- if (prefetchable)
- dbg("using MEM for PMEM\n");
- mem_node = get_resource(&(resources->mem_head), (ulong)base);
- }
-
- /* allocate the resource to the board */
- if (mem_node) {
- base64 = mem_node->base;
- mem_node->next = *res_node;
- *res_node = mem_node;
- dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32),
- (u32)base64, mem_node->length);
- } else {
- err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base);
- return -ENOMEM;
- }
- break;
- default:
- dbg("reserved BAR type=0x%x\n", temp_register);
- break;
- }
-
- }
-
- if (base64) {
- rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
- cloop += 4;
- base64 >>= 32;
-
- if (base64) {
- dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64);
- base64 = 0x0L;
- }
-
- rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
- } else {
- rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base);
- }
- } /* End of base register loop */
-
-#if defined(CONFIG_X86_64)
- /* Figure out which interrupt pin this function uses */
- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte);
-
- /* If this function needs an interrupt and we are behind a bridge
- and the pin is tied to something that's alread mapped,
- set this one the same
- */
- if (temp_byte && resources->irqs &&
- (resources->irqs->valid_INT &
- (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) {
- /* We have to share with something already set up */
- IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03];
- } else {
- /* Program IRQ based on card type */
- rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
-
- if (class_code == PCI_BASE_CLASS_STORAGE) {
- IRQ = shpchp_disk_irq;
- } else {
- IRQ = shpchp_nic_irq;
- }
- }
-
- /* IRQ Line */
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ);
-
- if (!behind_bridge) {
- rc = shpchp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ);
- if (rc)
- return(1);
- } else {
- /* TBD - this code may also belong in the other clause of this If statement */
- resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ;
- resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03;
- }
-#endif
- /* Disable ROM base Address */
- rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00);
-
- /* Set HP parameters (Cache Line Size, Latency Timer) */
- rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
- if (rc)
- return rc;
-
- shpchprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL);
-
- dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
- } /* End of Not-A-Bridge else */
- else {
- /* It's some strange type of PCI adapter (Cardbus?) */
- return(DEVICE_TYPE_NOT_SUPPORTED);
- }
-
- func->configured = 1;
-
- return 0;
+ ret = remove_board(p_slot);
+ update_slot_info(p_slot);
+ return ret;
}
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 8d98410bf1c..40905a6c809 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -27,17 +27,10 @@
*
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
#include <linux/pci.h>
-#include <asm/system.h>
#include "shpchp.h"
#ifdef DEBUG
@@ -282,7 +275,7 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds)
static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u16 cmd_status;
int retval = 0;
u16 temp_word;
@@ -320,7 +313,6 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
* command.
*/
writew(temp_word, php_ctlr->creg + CMD);
- dbg("%s: temp_word written %x\n", __FUNCTION__, temp_word);
DBG_LEAVE_ROUTINE
return retval;
@@ -328,7 +320,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
static int hpc_check_cmd_status(struct controller *ctrl)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
u16 cmd_status;
int retval = 0;
@@ -368,7 +360,7 @@ static int hpc_check_cmd_status(struct controller *ctrl)
static int hpc_get_attention_status(struct slot *slot, u8 *status)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u32 slot_reg;
u16 slot_status;
u8 atten_led_state;
@@ -408,7 +400,7 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
static int hpc_get_power_status(struct slot * slot, u8 *status)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u32 slot_reg;
u16 slot_status;
u8 slot_state;
@@ -450,7 +442,7 @@ static int hpc_get_power_status(struct slot * slot, u8 *status)
static int hpc_get_latch_status(struct slot *slot, u8 *status)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u32 slot_reg;
u16 slot_status;
@@ -473,7 +465,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
static int hpc_get_adapter_status(struct slot *slot, u8 *status)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u32 slot_reg;
u16 slot_status;
u8 card_state;
@@ -496,7 +488,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
DBG_ENTER_ROUTINE
@@ -513,7 +505,7 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u32 slot_reg;
u16 slot_status, sec_bus_status;
u8 m66_cap, pcix_cap, pi;
@@ -594,7 +586,7 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u16 sec_bus_status;
u8 pi;
int retval = 0;
@@ -623,7 +615,7 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
static int hpc_query_power_fault(struct slot * slot)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u32 slot_reg;
u16 slot_status;
u8 pwr_fault_state, status;
@@ -647,7 +639,7 @@ static int hpc_query_power_fault(struct slot * slot)
static int hpc_set_attention_status(struct slot *slot, u8 value)
{
- struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd = 0;
int rc = 0;
@@ -683,7 +675,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
static void hpc_set_green_led_on(struct slot *slot)
{
- struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd;
if (!slot->ctrl->hpc_ctlr_handle) {
@@ -705,7 +697,7 @@ static void hpc_set_green_led_on(struct slot *slot)
static void hpc_set_green_led_off(struct slot *slot)
{
- struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd;
if (!slot->ctrl->hpc_ctlr_handle) {
@@ -727,7 +719,7 @@ static void hpc_set_green_led_off(struct slot *slot)
static void hpc_set_green_led_blink(struct slot *slot)
{
- struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd;
if (!slot->ctrl->hpc_ctlr_handle) {
@@ -754,7 +746,7 @@ int shpc_get_ctlr_slot_config(struct controller *ctrl,
int *updown, /* physical_slot_num increament: 1 or -1 */
int *flags)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
DBG_ENTER_ROUTINE
@@ -776,7 +768,7 @@ int shpc_get_ctlr_slot_config(struct controller *ctrl,
static void hpc_release_ctlr(struct controller *ctrl)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
struct php_ctlr_state_s *p, *p_prev;
DBG_ENTER_ROUTINE
@@ -796,10 +788,8 @@ static void hpc_release_ctlr(struct controller *ctrl)
}
}
if (php_ctlr->pci_dev) {
- dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__);
iounmap(php_ctlr->creg);
release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0));
- dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__);
php_ctlr->pci_dev = NULL;
}
@@ -828,7 +818,7 @@ DBG_LEAVE_ROUTINE
static int hpc_power_on_slot(struct slot * slot)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd;
int retval = 0;
@@ -859,7 +849,7 @@ static int hpc_power_on_slot(struct slot * slot)
static int hpc_slot_enable(struct slot * slot)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd;
int retval = 0;
@@ -890,7 +880,7 @@ static int hpc_slot_enable(struct slot * slot)
static int hpc_slot_disable(struct slot * slot)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd;
int retval = 0;
@@ -920,51 +910,12 @@ static int hpc_slot_disable(struct slot * slot)
return retval;
}
-static int hpc_enable_all_slots( struct slot *slot )
-{
- int retval = 0;
-
- DBG_ENTER_ROUTINE
-
- if (!slot->ctrl->hpc_ctlr_handle) {
- err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
- return -1;
- }
-
- retval = shpc_write_cmd(slot, 0, SET_ENABLE_ALL);
- if (retval) {
- err("%s: Write command failed!\n", __FUNCTION__);
- return -1;
- }
-
- DBG_LEAVE_ROUTINE
-
- return retval;
-}
-
-static int hpc_pwr_on_all_slots(struct slot *slot)
-{
- int retval = 0;
-
- DBG_ENTER_ROUTINE
-
- retval = shpc_write_cmd(slot, 0, SET_PWR_ON_ALL);
-
- if (retval) {
- err("%s: Write command failed!\n", __FUNCTION__);
- return -1;
- }
-
- DBG_LEAVE_ROUTINE
- return retval;
-}
-
static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
{
u8 slot_cmd;
u8 pi;
int retval = 0;
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
DBG_ENTER_ROUTINE
@@ -1089,18 +1040,13 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
if (!intr_loc)
return IRQ_NONE;
- dbg("%s: shpc_isr proceeds\n", __FUNCTION__);
dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc);
if(!shpchp_poll_mode) {
/* Mask Global Interrupt Mask - see implementation note on p. 139 */
/* of SHPC spec rev 1.0*/
temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
- dbg("%s: Before masking global interrupt, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
temp_dword |= 0x00000001;
- dbg("%s: After masking global interrupt, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
intr_loc2 = readl(php_ctlr->creg + INTR_LOC);
@@ -1114,11 +1060,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
* Detect bit in Controller SERR-INT register
*/
temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
- dbg("%s: Before clearing CCIP, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
temp_dword &= 0xfffeffff;
- dbg("%s: After clearing CCIP, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
wake_up_interruptible(&ctrl->queue);
}
@@ -1126,11 +1068,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
if ((intr_loc = (intr_loc >> 1)) == 0) {
/* Unmask Global Interrupt Mask */
temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
- dbg("%s: 1-Before unmasking global interrupt, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
temp_dword &= 0xfffffffe;
- dbg("%s: 1-After unmasking global interrupt, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
return IRQ_NONE;
@@ -1140,11 +1078,9 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
/* To find out which slot has interrupt pending */
if ((intr_loc >> hp_slot) & 0x01) {
temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot));
- dbg("%s: Slot %x with intr, temp_dword = %x\n",
- __FUNCTION__, hp_slot, temp_dword);
+ dbg("%s: Slot %x with intr, slot register = %x\n",
+ __FUNCTION__, hp_slot, temp_dword);
temp_byte = (temp_dword >> 16) & 0xFF;
- dbg("%s: Slot with intr, temp_byte = %x\n",
- __FUNCTION__, temp_byte);
if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08))
schedule_flag += php_ctlr->switch_change_callback(
hp_slot, php_ctlr->callback_instance_id);
@@ -1160,8 +1096,6 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
/* Clear all slot events */
temp_dword = 0xe01f3fff;
- dbg("%s: Clearing slot events, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot));
intr_loc2 = readl(php_ctlr->creg + INTR_LOC);
@@ -1171,11 +1105,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
if (!shpchp_poll_mode) {
/* Unmask Global Interrupt Mask */
temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
- dbg("%s: 2-Before unmasking global interrupt, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
temp_dword &= 0xfffffffe;
- dbg("%s: 2-After unmasking global interrupt, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
}
@@ -1184,7 +1114,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
int retval = 0;
u8 pi;
@@ -1253,7 +1183,7 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
u16 sec_bus_status;
int retval = 0;
@@ -1367,8 +1297,6 @@ static struct hpc_ops shpchp_hpc_ops = {
.power_on_slot = hpc_power_on_slot,
.slot_enable = hpc_slot_enable,
.slot_disable = hpc_slot_disable,
- .enable_all_slots = hpc_enable_all_slots,
- .pwr_on_all_slots = hpc_pwr_on_all_slots,
.set_bus_speed_mode = hpc_set_bus_speed_mode,
.set_attention_status = hpc_set_attention_status,
.get_power_status = hpc_get_power_status,
@@ -1391,12 +1319,7 @@ static struct hpc_ops shpchp_hpc_ops = {
.check_cmd_status = hpc_check_cmd_status,
};
-int shpc_init(struct controller * ctrl,
- struct pci_dev * pdev,
- php_intr_callback_t attention_button_callback,
- php_intr_callback_t switch_change_callback,
- php_intr_callback_t presence_change_callback,
- php_intr_callback_t power_fault_callback)
+int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
{
struct php_ctlr_state_s *php_ctlr, *p;
void *instance_id = ctrl;
@@ -1405,7 +1328,6 @@ int shpc_init(struct controller * ctrl,
static int first = 1;
u32 shpc_cap_offset, shpc_base_offset;
u32 tempdword, slot_reg;
- u16 vendor_id, device_id;
u8 i;
DBG_ENTER_ROUTINE
@@ -1422,21 +1344,8 @@ int shpc_init(struct controller * ctrl,
php_ctlr->pci_dev = pdev; /* save pci_dev in context */
- rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
- dbg("%s: Vendor ID: %x\n",__FUNCTION__, vendor_id);
- if (rc) {
- err("%s: unable to read PCI configuration data\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- rc = pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
- dbg("%s: Device ID: %x\n",__FUNCTION__, device_id);
- if (rc) {
- err("%s: unable to read PCI configuration data\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- if ((vendor_id == PCI_VENDOR_ID_AMD) || (device_id == PCI_DEVICE_ID_AMD_GOLAM_7450)) {
+ if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
+ PCI_DEVICE_ID_AMD_GOLAM_7450)) {
shpc_base_offset = 0; /* amd shpc driver doesn't use this; assume 0 */
} else {
if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) {
@@ -1469,7 +1378,8 @@ int shpc_init(struct controller * ctrl,
err("%s : pci_read_config_dword failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: offset %d: tempdword %x\n", __FUNCTION__,i, tempdword);
+ dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
+ tempdword);
}
}
@@ -1478,13 +1388,6 @@ int shpc_init(struct controller * ctrl,
first = 0;
}
- dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, PCI_SLOT(pdev->devfn),
- PCI_FUNC(pdev->devfn), pdev->irq);
- for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
- if (pci_resource_len(pdev, rc) > 0)
- dbg("pci resource[%d] start=0x%lx(len=0x%lx), shpc_base_offset %x\n", rc,
- pci_resource_start(pdev, rc), pci_resource_len(pdev, rc), shpc_base_offset);
-
info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor,
pdev->subsystem_device);
@@ -1504,7 +1407,6 @@ int shpc_init(struct controller * ctrl,
goto abort_free_ctlr;
}
dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
- dbg("%s: physical addr %p\n", __FUNCTION__, (void*)pci_resource_start(pdev, 0));
init_MUTEX(&ctrl->crit_sect);
/* Setup wait queue */
@@ -1512,13 +1414,10 @@ int shpc_init(struct controller * ctrl,
/* Find the IRQ */
php_ctlr->irq = pdev->irq;
- dbg("HPC interrupt = %d\n", php_ctlr->irq);
-
- /* Save interrupt callback info */
- php_ctlr->attention_button_callback = attention_button_callback;
- php_ctlr->switch_change_callback = switch_change_callback;
- php_ctlr->presence_change_callback = presence_change_callback;
- php_ctlr->power_fault_callback = power_fault_callback;
+ php_ctlr->attention_button_callback = shpchp_handle_attention_button,
+ php_ctlr->switch_change_callback = shpchp_handle_switch_change;
+ php_ctlr->presence_change_callback = shpchp_handle_presence_change;
+ php_ctlr->power_fault_callback = shpchp_handle_power_fault;
php_ctlr->callback_instance_id = instance_id;
/* Return PCI Controller Info */
@@ -1556,7 +1455,6 @@ int shpc_init(struct controller * ctrl,
if (rc) {
info("Can't get msi for the hotplug controller\n");
info("Use INTx for the hotplug controller\n");
- dbg("%s: rc = %x\n", __FUNCTION__, rc);
} else
php_ctlr->irq = pdev->irq;
@@ -1566,9 +1464,11 @@ int shpc_init(struct controller * ctrl,
err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
goto abort_free_ctlr;
}
- /* Execute OSHP method here */
}
- dbg("%s: Before adding HPC to HPC list\n", __FUNCTION__);
+ dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __FUNCTION__,
+ pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn), pdev->irq);
+ get_hp_hw_control_from_firmware(pdev);
/* Add this HPC instance into the HPC list */
spin_lock(&list_lock);
@@ -1607,7 +1507,6 @@ int shpc_init(struct controller * ctrl,
dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
}
- dbg("%s: Leaving shpc_init\n", __FUNCTION__);
DBG_LEAVE_ROUTINE
return 0;
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index d867099114e..b8e95acea3b 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -27,784 +27,151 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/proc_fs.h>
#include <linux/pci.h>
#include "../pci.h"
#include "shpchp.h"
-#ifndef CONFIG_IA64
-#include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */
-#endif
-int shpchp_configure_device (struct controller* ctrl, struct pci_func* func)
+void program_fw_provided_values(struct pci_dev *dev)
{
- unsigned char bus;
- struct pci_bus *child;
- int num;
-
- if (func->pci_dev == NULL)
- func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
-
- /* Still NULL ? Well then scan for it ! */
- if (func->pci_dev == NULL) {
- num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function));
- if (num) {
- dbg("%s: subordiante %p number %x\n", __FUNCTION__, ctrl->pci_dev->subordinate,
- ctrl->pci_dev->subordinate->number);
- pci_bus_add_devices(ctrl->pci_dev->subordinate);
- }
-
- func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
- if (func->pci_dev == NULL) {
- dbg("ERROR: pci_dev still null\n");
- return 0;
+ u16 pci_cmd, pci_bctl;
+ struct pci_dev *cdev;
+ struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */
+
+ /* Program hpp values for this device */
+ if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
+ (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
+ (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
+ return;
+
+ get_hp_params_from_firmware(dev, &hpp);
+
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer);
+ pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+ if (hpp.enable_serr)
+ pci_cmd |= PCI_COMMAND_SERR;
+ else
+ pci_cmd &= ~PCI_COMMAND_SERR;
+ if (hpp.enable_perr)
+ pci_cmd |= PCI_COMMAND_PARITY;
+ else
+ pci_cmd &= ~PCI_COMMAND_PARITY;
+ pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+
+ /* Program bridge control value and child devices */
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+ pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
+ hpp.latency_timer);
+ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
+ if (hpp.enable_serr)
+ pci_bctl |= PCI_BRIDGE_CTL_SERR;
+ else
+ pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
+ if (hpp.enable_perr)
+ pci_bctl |= PCI_BRIDGE_CTL_PARITY;
+ else
+ pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
+ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
+ if (dev->subordinate) {
+ list_for_each_entry(cdev, &dev->subordinate->devices,
+ bus_list)
+ program_fw_provided_values(cdev);
}
}
-
- if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
- child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
- pci_do_scan_bus(child);
-
- }
-
- return 0;
}
-
-int shpchp_unconfigure_device(struct pci_func* func)
+int shpchp_configure_device(struct slot *p_slot)
{
- int rc = 0;
- int j;
-
- dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus,
- func->device, func->function);
-
- for (j=0; j<8 ; j++) {
- struct pci_dev* temp = pci_find_slot(func->bus,
- (func->device << 3) | j);
- if (temp) {
- pci_remove_bus_device(temp);
- }
+ struct pci_dev *dev;
+ struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+ int num, fn;
+
+ dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
+ if (dev) {
+ err("Device %s already exists at %x:%x, cannot hot-add\n",
+ pci_name(dev), p_slot->bus, p_slot->device);
+ return -EINVAL;
}
- return rc;
-}
-
-/*
- * shpchp_set_irq
- *
- * @bus_num: bus number of PCI device
- * @dev_num: device number of PCI device
- * @slot: pointer to u8 where slot number will be returned
- */
-int shpchp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
-{
-#if defined(CONFIG_X86) && !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
- int rc;
- u16 temp_word;
- struct pci_dev fakedev;
- struct pci_bus fakebus;
- fakedev.devfn = dev_num << 3;
- fakedev.bus = &fakebus;
- fakebus.number = bus_num;
- dbg("%s: dev %d, bus %d, pin %d, num %d\n",
- __FUNCTION__, dev_num, bus_num, int_pin, irq_num);
- rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
- dbg("%s: rc %d\n", __FUNCTION__, rc);
- if (!rc)
- return !rc;
-
- /* set the Edge Level Control Register (ELCR) */
- temp_word = inb(0x4d0);
- temp_word |= inb(0x4d1) << 8;
-
- temp_word |= 0x01 << irq_num;
-
- /* This should only be for x86 as it sets the Edge Level Control Register */
- outb((u8) (temp_word & 0xFF), 0x4d0);
- outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
-#endif
- return 0;
-}
-
-/* More PCI configuration routines; this time centered around hotplug controller */
-
-
-/*
- * shpchp_save_config
- *
- * Reads configuration for all slots in a PCI bus and saves info.
- *
- * Note: For non-hot plug busses, the slot # saved is the device #
- *
- * returns 0 if success
- */
-int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
-{
- int rc;
- u8 class_code;
- u8 header_type;
- u32 ID;
- u8 secondary_bus;
- struct pci_func *new_slot;
- int sub_bus;
- int FirstSupported;
- int LastSupported;
- int max_functions;
- int function;
- u8 DevError;
- int device = 0;
- int cloop = 0;
- int stop_it;
- int index;
- int is_hot_plug = num_ctlr_slots || first_device_num;
- struct pci_bus lpci_bus, *pci_bus;
-
- dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
- num_ctlr_slots, first_device_num);
-
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
-
- dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
- num_ctlr_slots, first_device_num);
-
- /* Decide which slots are supported */
- if (is_hot_plug) {
- /*********************************
- * is_hot_plug is the slot mask
- *********************************/
- FirstSupported = first_device_num;
- LastSupported = FirstSupported + num_ctlr_slots - 1;
- } else {
- FirstSupported = 0;
- LastSupported = 0x1F;
+ num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
+ if (num == 0) {
+ err("No new device found\n");
+ return -ENODEV;
}
- dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported,
- LastSupported);
-
- /* Save PCI configuration space for all devices in supported slots */
- pci_bus->number = busnumber;
- for (device = FirstSupported; device <= LastSupported; device++) {
- ID = 0xFFFFFFFF;
- rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
- PCI_VENDOR_ID, &ID);
-
- if (ID != 0xFFFFFFFF) { /* device in slot */
- rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
- 0x0B, &class_code);
- if (rc)
- return rc;
-
- rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
- PCI_HEADER_TYPE, &header_type);
- if (rc)
- return rc;
-
- dbg("class_code = %x, header_type = %x\n", class_code, header_type);
-
- /* If multi-function device, set max_functions to 8 */
- if (header_type & 0x80)
- max_functions = 8;
- else
- max_functions = 1;
-
- function = 0;
-
- do {
- DevError = 0;
-
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */
- /* Recurse the subordinate bus
- * get the subordinate bus number
- */
- rc = pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(device, function),
- PCI_SECONDARY_BUS, &secondary_bus);
- if (rc) {
- return rc;
- } else {
- sub_bus = (int) secondary_bus;
-
- /* Save secondary bus cfg spc with this recursive call. */
- rc = shpchp_save_config(ctrl, sub_bus, 0, 0);
- if (rc)
- return rc;
- }
- }
-
- index = 0;
- new_slot = shpchp_slot_find(busnumber, device, index++);
-
- dbg("new_slot = %p\n", new_slot);
-
- while (new_slot && (new_slot->function != (u8) function)) {
- new_slot = shpchp_slot_find(busnumber, device, index++);
- dbg("new_slot = %p\n", new_slot);
- }
- if (!new_slot) {
- /* Setup slot structure. */
- new_slot = shpchp_slot_create(busnumber);
- dbg("new_slot = %p\n", new_slot);
-
- if (new_slot == NULL)
- return(1);
- }
-
- new_slot->bus = (u8) busnumber;
- new_slot->device = (u8) device;
- new_slot->function = (u8) function;
- new_slot->is_a_board = 1;
- new_slot->switch_save = 0x10;
- new_slot->pwr_save = 1;
- /* In case of unsupported board */
- new_slot->status = DevError;
- new_slot->pci_dev = pci_find_slot(new_slot->bus,
- (new_slot->device << 3) | new_slot->function);
- dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
-
- for (cloop = 0; cloop < 0x20; cloop++) {
- rc = pci_bus_read_config_dword(pci_bus,
- PCI_DEVFN(device, function),
- cloop << 2,
- (u32 *) &(new_slot->config_space [cloop]));
- /* dbg("new_slot->config_space[%x] = %x\n",
- cloop, new_slot->config_space[cloop]); */
- if (rc)
- return rc;
- }
-
- function++;
-
- stop_it = 0;
-
- /* this loop skips to the next present function
- * reading in Class Code and Header type.
- */
-
- while ((function < max_functions)&&(!stop_it)) {
- rc = pci_bus_read_config_dword(pci_bus,
- PCI_DEVFN(device, function),
- PCI_VENDOR_ID, &ID);
-
- if (ID == 0xFFFFFFFF) { /* nothing there. */
- function++;
- dbg("Nothing there\n");
- } else { /* Something there */
- rc = pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(device, function),
- 0x0B, &class_code);
- if (rc)
- return rc;
-
- rc = pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(device, function),
- PCI_HEADER_TYPE, &header_type);
- if (rc)
- return rc;
-
- dbg("class_code = %x, header_type = %x\n",
- class_code, header_type);
- stop_it++;
- }
- }
-
- } while (function < max_functions);
- /* End of IF (device in slot?) */
- } else if (is_hot_plug) {
- /* Setup slot structure with entry for empty slot */
- new_slot = shpchp_slot_create(busnumber);
-
- if (new_slot == NULL) {
- return(1);
- }
- dbg("new_slot = %p\n", new_slot);
-
- new_slot->bus = (u8) busnumber;
- new_slot->device = (u8) device;
- new_slot->function = 0;
- new_slot->is_a_board = 0;
- new_slot->presence_save = 0;
- new_slot->switch_save = 0;
+ for (fn = 0; fn < 8; fn++) {
+ if (!(dev = pci_find_slot(p_slot->bus,
+ PCI_DEVFN(p_slot->device, fn))))
+ continue;
+ if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+ err("Cannot hot-add display device %s\n",
+ pci_name(dev));
+ continue;
}
- } /* End of FOR loop */
-
- return(0);
-}
-
-
-/*
- * shpchp_save_slot_config
- *
- * Saves configuration info for all PCI devices in a given slot
- * including subordinate busses.
- *
- * returns 0 if success
- */
-int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot)
-{
- int rc;
- u8 class_code;
- u8 header_type;
- u32 ID;
- u8 secondary_bus;
- int sub_bus;
- int max_functions;
- int function;
- int cloop = 0;
- int stop_it;
- struct pci_bus lpci_bus, *pci_bus;
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = new_slot->bus;
-
- ID = 0xFFFFFFFF;
-
- pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0),
- PCI_VENDOR_ID, &ID);
-
- if (ID != 0xFFFFFFFF) { /* device in slot */
- pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
- 0x0B, &class_code);
-
- pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
- PCI_HEADER_TYPE, &header_type);
-
- if (header_type & 0x80) /* Multi-function device */
- max_functions = 8;
- else
- max_functions = 1;
-
- function = 0;
-
- do {
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
- /* Recurse the subordinate bus */
- pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- PCI_SECONDARY_BUS, &secondary_bus);
-
- sub_bus = (int) secondary_bus;
-
- /* Save the config headers for the secondary bus. */
- rc = shpchp_save_config(ctrl, sub_bus, 0, 0);
-
- if (rc)
- return rc;
-
- } /* End of IF */
-
- new_slot->status = 0;
-
- for (cloop = 0; cloop < 0x20; cloop++) {
- pci_bus_read_config_dword(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- cloop << 2,
- (u32 *) &(new_slot->config_space [cloop]));
+ if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
+ (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
+ /* Find an unused bus number for the new bridge */
+ struct pci_bus *child;
+ unsigned char busnr, start = parent->secondary;
+ unsigned char end = parent->subordinate;
+ for (busnr = start; busnr <= end; busnr++) {
+ if (!pci_find_bus(pci_domain_nr(parent),
+ busnr))
+ break;
}
-
- function++;
-
- stop_it = 0;
-
- /* this loop skips to the next present function
- * reading in the Class Code and the Header type.
- */
-
- while ((function < max_functions) && (!stop_it)) {
- pci_bus_read_config_dword(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- PCI_VENDOR_ID, &ID);
-
- if (ID == 0xFFFFFFFF) { /* nothing there. */
- function++;
- } else { /* Something there */
- pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- 0x0B, &class_code);
-
- pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- PCI_HEADER_TYPE, &header_type);
-
- stop_it++;
- }
+ if (busnr >= end) {
+ err("No free bus for hot-added bridge\n");
+ continue;
}
-
- } while (function < max_functions);
- } /* End of IF (device in slot?) */
- else {
- return 2;
+ child = pci_add_new_bus(parent, dev, busnr);
+ if (!child) {
+ err("Cannot add new bus for %s\n",
+ pci_name(dev));
+ continue;
+ }
+ child->subordinate = pci_do_scan_bus(child);
+ pci_bus_size_bridges(child);
+ }
+ program_fw_provided_values(dev);
}
+ pci_bus_assign_resources(parent);
+ pci_bus_add_devices(parent);
+ pci_enable_bridges(parent);
return 0;
}
-
-/*
- * shpchp_save_used_resources
- *
- * Stores used resource information for existing boards. this is
- * for boards that were in the system when this driver was loaded.
- * this function is for hot plug ADD
- *
- * returns 0 if success
- * if disable == 1(DISABLE_CARD),
- * it loops for all functions of the slot and disables them.
- * else, it just get resources of the function and return.
- */
-int shpchp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable)
+int shpchp_unconfigure_device(struct slot *p_slot)
{
- u8 cloop;
- u8 header_type;
- u8 secondary_bus;
- u8 temp_byte;
- u16 command;
- u16 save_command;
- u16 w_base, w_length;
- u32 temp_register;
- u32 save_base;
- u32 base, length;
- u64 base64 = 0;
- int index = 0;
- unsigned int devfn;
- struct pci_resource *mem_node = NULL;
- struct pci_resource *p_mem_node = NULL;
- struct pci_resource *t_mem_node;
- struct pci_resource *io_node;
- struct pci_resource *bus_node;
- struct pci_bus lpci_bus, *pci_bus;
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
-
- if (disable)
- func = shpchp_slot_find(func->bus, func->device, index++);
-
- while ((func != NULL) && func->is_a_board) {
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- /* Save the command register */
- pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);
+ int rc = 0;
+ int j;
+ u8 bctl = 0;
+
+ dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device);
- if (disable) {
- /* disable card */
- command = 0x00;
- pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+ for (j=0; j<8 ; j++) {
+ struct pci_dev* temp = pci_find_slot(p_slot->bus,
+ (p_slot->device << 3) | j);
+ if (!temp)
+ continue;
+ if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+ err("Cannot remove display device %s\n",
+ pci_name(temp));
+ continue;
}
-
- /* Check for Bridge */
- pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
- dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n",
- func->bus, func->device, save_command);
- if (disable) {
- /* Clear Bridge Control Register */
- command = 0x00;
- pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+ if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+ if (bctl & PCI_BRIDGE_CTL_VGA) {
+ err("Cannot remove display device %s\n",
+ pci_name(temp));
+ continue;
}
-
- pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
- pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
-
- bus_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!bus_node)
- return -ENOMEM;
-
- bus_node->base = (ulong)secondary_bus;
- bus_node->length = (ulong)(temp_byte - secondary_bus + 1);
-
- bus_node->next = func->bus_head;
- func->bus_head = bus_node;
-
- /* Save IO base and Limit registers */
- pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte);
- base = temp_byte;
- pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
- length = temp_byte;
-
- if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
- io_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!io_node)
- return -ENOMEM;
-
- io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
- io_node->length = (ulong)(length - base + 0x10) << 8;
-
- io_node->next = func->io_head;
- func->io_head = io_node;
- }
-
- /* Save memory base and Limit registers */
- pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
- pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
-
- if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
- mem_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!mem_node)
- return -ENOMEM;
-
- mem_node->base = (ulong)w_base << 16;
- mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
-
- mem_node->next = func->mem_head;
- func->mem_head = mem_node;
- }
- /* Save prefetchable memory base and Limit registers */
- pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
- pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
-
- if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
- p_mem_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!p_mem_node)
- return -ENOMEM;
-
- p_mem_node->base = (ulong)w_base << 16;
- p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
-
- p_mem_node->next = func->p_mem_head;
- func->p_mem_head = p_mem_node;
- }
- } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
- dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n",
- func->bus, func->device, save_command);
-
- /* Figure out IO and memory base lengths */
- for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
- pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
-
- temp_register = 0xFFFFFFFF;
- pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
- pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
-
- if (!disable)
- pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base);
-
- if (!temp_register)
- continue;
-
- base = temp_register;
-
- if ((base & PCI_BASE_ADDRESS_SPACE_IO) &&
- (!disable || (save_command & PCI_COMMAND_IO))) {
- /* IO base */
- /* set temp_register = amount of IO space requested */
- base = base & 0xFFFFFFFCL;
- base = (~base) + 1;
-
- io_node = kmalloc(sizeof (struct pci_resource),
- GFP_KERNEL);
- if (!io_node)
- return -ENOMEM;
-
- io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
- io_node->length = (ulong)base;
- dbg("sur adapter: IO bar=0x%x(length=0x%x)\n",
- io_node->base, io_node->length);
-
- io_node->next = func->io_head;
- func->io_head = io_node;
- } else { /* map Memory */
- int prefetchable = 1;
- /* struct pci_resources **res_node; */
- char *res_type_str = "PMEM";
- u32 temp_register2;
-
- t_mem_node = kmalloc(sizeof (struct pci_resource),
- GFP_KERNEL);
- if (!t_mem_node)
- return -ENOMEM;
-
- if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
- (!disable || (save_command & PCI_COMMAND_MEMORY))) {
- prefetchable = 0;
- mem_node = t_mem_node;
- res_type_str++;
- } else
- p_mem_node = t_mem_node;
-
- base = base & 0xFFFFFFF0L;
- base = (~base) + 1;
-
- switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
- case PCI_BASE_ADDRESS_MEM_TYPE_32:
- if (prefetchable) {
- p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
- p_mem_node->length = (ulong)base;
- dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
- res_type_str,
- p_mem_node->base,
- p_mem_node->length);
-
- p_mem_node->next = func->p_mem_head;
- func->p_mem_head = p_mem_node;
- } else {
- mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
- mem_node->length = (ulong)base;
- dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
- res_type_str,
- mem_node->base,
- mem_node->length);
-
- mem_node->next = func->mem_head;
- func->mem_head = mem_node;
- }
- break;
- case PCI_BASE_ADDRESS_MEM_TYPE_64:
- pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
- base64 = temp_register2;
- base64 = (base64 << 32) | save_base;
-
- if (temp_register2) {
- dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n",
- res_type_str, temp_register2, (u32)base64);
- base64 &= 0x00000000FFFFFFFFL;
- }
-
- if (prefetchable) {
- p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
- p_mem_node->length = base;
- dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
- res_type_str,
- p_mem_node->base,
- p_mem_node->length);
-
- p_mem_node->next = func->p_mem_head;
- func->p_mem_head = p_mem_node;
- } else {
- mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
- mem_node->length = base;
- dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
- res_type_str,
- mem_node->base,
- mem_node->length);
-
- mem_node->next = func->mem_head;
- func->mem_head = mem_node;
- }
- cloop += 4;
- break;
- default:
- dbg("asur: reserved BAR type=0x%x\n",
- temp_register);
- break;
- }
- }
- } /* End of base register loop */
- } else { /* Some other unknown header type */
- dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n",
- func->bus, func->device);
}
-
- /* find the next device in this slot */
- if (!disable)
- break;
- func = shpchp_slot_find(func->bus, func->device, index++);
+ pci_remove_bus_device(temp);
}
-
- return 0;
-}
-
-/**
- * kfree_resource_list: release memory of all list members
- * @res: resource list to free
- */
-static inline void
-return_resource_list(struct pci_resource **func, struct pci_resource **res)
-{
- struct pci_resource *node;
- struct pci_resource *t_node;
-
- node = *func;
- *func = NULL;
- while (node) {
- t_node = node->next;
- return_resource(res, node);
- node = t_node;
- }
-}
-
-/*
- * shpchp_return_board_resources
- *
- * this routine returns all resources allocated to a board to
- * the available pool.
- *
- * returns 0 if success
- */
-int shpchp_return_board_resources(struct pci_func * func,
- struct resource_lists * resources)
-{
- int rc;
- dbg("%s\n", __FUNCTION__);
-
- if (!func)
- return 1;
-
- return_resource_list(&(func->io_head),&(resources->io_head));
- return_resource_list(&(func->mem_head),&(resources->mem_head));
- return_resource_list(&(func->p_mem_head),&(resources->p_mem_head));
- return_resource_list(&(func->bus_head),&(resources->bus_head));
-
- rc = shpchp_resource_sort_and_combine(&(resources->mem_head));
- rc |= shpchp_resource_sort_and_combine(&(resources->p_mem_head));
- rc |= shpchp_resource_sort_and_combine(&(resources->io_head));
- rc |= shpchp_resource_sort_and_combine(&(resources->bus_head));
-
return rc;
}
-/**
- * kfree_resource_list: release memory of all list members
- * @res: resource list to free
- */
-static inline void
-kfree_resource_list(struct pci_resource **r)
-{
- struct pci_resource *res, *tres;
-
- res = *r;
- *r = NULL;
-
- while (res) {
- tres = res;
- res = res->next;
- kfree(tres);
- }
-}
-
-/**
- * shpchp_destroy_resource_list: put node back in the resource list
- * @resources: list to put nodes back
- */
-void shpchp_destroy_resource_list(struct resource_lists *resources)
-{
- kfree_resource_list(&(resources->io_head));
- kfree_resource_list(&(resources->mem_head));
- kfree_resource_list(&(resources->p_mem_head));
- kfree_resource_list(&(resources->bus_head));
-}
-
-/**
- * shpchp_destroy_board_resources: put node back in the resource list
- * @resources: list to put nodes back
- */
-void shpchp_destroy_board_resources(struct pci_func * func)
-{
- kfree_resource_list(&(func->io_head));
- kfree_resource_list(&(func->mem_head));
- kfree_resource_list(&(func->p_mem_head));
- kfree_resource_list(&(func->bus_head));
-}
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c
index c9445ebda5c..f5cfbf2c047 100644
--- a/drivers/pci/hotplug/shpchp_sysfs.c
+++ b/drivers/pci/hotplug/shpchp_sysfs.c
@@ -26,12 +26,9 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/workqueue.h>
#include <linux/pci.h>
#include "shpchp.h"
@@ -40,104 +37,60 @@
static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
{
- struct pci_dev *pci_dev;
- struct controller *ctrl;
+ struct pci_dev *pdev;
char * out = buf;
- int index;
- struct pci_resource *res;
+ int index, busnr;
+ struct resource *res;
+ struct pci_bus *bus;
- pci_dev = container_of (dev, struct pci_dev, dev);
- ctrl = pci_get_drvdata(pci_dev);
+ pdev = container_of (dev, struct pci_dev, dev);
+ bus = pdev->subordinate;
out += sprintf(buf, "Free resources: memory\n");
- index = 11;
- res = ctrl->mem_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
+ for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
+ res = bus->resource[index];
+ if (res && (res->flags & IORESOURCE_MEM) &&
+ !(res->flags & IORESOURCE_PREFETCH)) {
+ out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
+ res->start, (res->end - res->start));
+ }
}
out += sprintf(out, "Free resources: prefetchable memory\n");
- index = 11;
- res = ctrl->p_mem_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
+ for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
+ res = bus->resource[index];
+ if (res && (res->flags & IORESOURCE_MEM) &&
+ (res->flags & IORESOURCE_PREFETCH)) {
+ out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
+ res->start, (res->end - res->start));
+ }
}
out += sprintf(out, "Free resources: IO\n");
- index = 11;
- res = ctrl->io_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
+ for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
+ res = bus->resource[index];
+ if (res && (res->flags & IORESOURCE_IO)) {
+ out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
+ res->start, (res->end - res->start));
+ }
}
out += sprintf(out, "Free resources: bus numbers\n");
- index = 11;
- res = ctrl->bus_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
+ for (busnr = bus->secondary; busnr <= bus->subordinate; busnr++) {
+ if (!pci_find_bus(pci_domain_nr(bus), busnr))
+ break;
}
+ if (busnr < bus->subordinate)
+ out += sprintf(out, "start = %8.8x, length = %8.8x\n",
+ busnr, (bus->subordinate - busnr));
return out - buf;
}
static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
-static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf)
+void shpchp_create_ctrl_files (struct controller *ctrl)
{
- struct pci_dev *pci_dev;
- struct controller *ctrl;
- char * out = buf;
- int index;
- struct pci_resource *res;
- struct pci_func *new_slot;
- struct slot *slot;
-
- pci_dev = container_of (dev, struct pci_dev, dev);
- ctrl = pci_get_drvdata(pci_dev);
-
- slot=ctrl->slot;
-
- while (slot) {
- new_slot = shpchp_slot_find(slot->bus, slot->device, 0);
- if (!new_slot)
- break;
- out += sprintf(out, "assigned resources: memory\n");
- index = 11;
- res = new_slot->mem_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
- }
- out += sprintf(out, "assigned resources: prefetchable memory\n");
- index = 11;
- res = new_slot->p_mem_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
- }
- out += sprintf(out, "assigned resources: IO\n");
- index = 11;
- res = new_slot->io_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
- }
- out += sprintf(out, "assigned resources: bus numbers\n");
- index = 11;
- res = new_slot->bus_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
- }
- slot=slot->next;
- }
-
- return out - buf;
+ device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
}
-static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
-void shpchp_create_ctrl_files (struct controller *ctrl)
+void shpchp_remove_ctrl_files(struct controller *ctrl)
{
- device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
- device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev);
+ device_remove_file(&ctrl->pci_dev->dev, &dev_attr_ctrl);
}
diff --git a/drivers/pci/hotplug/shpchprm.h b/drivers/pci/hotplug/shpchprm.h
deleted file mode 100644
index 057b192ce58..00000000000
--- a/drivers/pci/hotplug/shpchprm.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SHPCHPRM : SHPCHP Resource Manager for ACPI/non-ACPI platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
- *
- */
-
-#ifndef _SHPCHPRM_H_
-#define _SHPCHPRM_H_
-
-#ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
-#include "shpchprm_legacy.h"
-#else
-#include "shpchprm_nonacpi.h"
-#endif
-
-int shpchprm_init(enum php_ctlr_type ct);
-void shpchprm_cleanup(void);
-int shpchprm_print_pirt(void);
-int shpchprm_find_available_resources(struct controller *ctrl);
-int shpchprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
-void shpchprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum);
-
-#ifdef DEBUG
-#define RES_CHECK(this, bits) \
- { if (((this) & (bits - 1))) \
- printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); }
-#else
-#define RES_CHECK(this, bits)
-#endif
-
-#endif /* _SHPCHPRM_H_ */
diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c
index d37b31658ed..17145e52223 100644
--- a/drivers/pci/hotplug/shpchprm_acpi.c
+++ b/drivers/pci/hotplug/shpchprm_acpi.c
@@ -24,91 +24,19 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include <linux/efi.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
#include <acpi/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/actypes.h>
#include "shpchp.h"
-#include "shpchprm.h"
-
-#define PCI_MAX_BUS 0x100
-#define ACPI_STA_DEVICE_PRESENT 0x01
#define METHOD_NAME__SUN "_SUN"
#define METHOD_NAME__HPP "_HPP"
#define METHOD_NAME_OSHP "OSHP"
-#define PHP_RES_BUS 0xA0
-#define PHP_RES_IO 0xA1
-#define PHP_RES_MEM 0xA2
-#define PHP_RES_PMEM 0xA3
-
-#define BRIDGE_TYPE_P2P 0x00
-#define BRIDGE_TYPE_HOST 0x01
-
-/* this should go to drivers/acpi/include/ */
-struct acpi__hpp {
- u8 cache_line_size;
- u8 latency_timer;
- u8 enable_serr;
- u8 enable_perr;
-};
-
-struct acpi_php_slot {
- struct acpi_php_slot *next;
- struct acpi_bridge *bridge;
- acpi_handle handle;
- int seg;
- int bus;
- int dev;
- int fun;
- u32 sun;
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
- void *slot_ops; /* _STA, _EJx, etc */
- struct slot *slot;
-}; /* per func */
-
-struct acpi_bridge {
- struct acpi_bridge *parent;
- struct acpi_bridge *next;
- struct acpi_bridge *child;
- acpi_handle handle;
- int seg;
- int pbus; /* pdev->bus->number */
- int pdevice; /* PCI_SLOT(pdev->devfn) */
- int pfunction; /* PCI_DEVFN(pdev->devfn) */
- int bus; /* pdev->subordinate->number */
- struct acpi__hpp *_hpp;
- struct acpi_php_slot *slots;
- struct pci_resource *tmem_head; /* total from crs */
- struct pci_resource *tp_mem_head; /* total from crs */
- struct pci_resource *tio_head; /* total from crs */
- struct pci_resource *tbus_head; /* total from crs */
- struct pci_resource *mem_head; /* available */
- struct pci_resource *p_mem_head; /* available */
- struct pci_resource *io_head; /* available */
- struct pci_resource *bus_head; /* available */
- int scanned;
- int type;
-};
-
-static struct acpi_bridge *acpi_bridges_head;
-
static u8 * acpi_path_name( acpi_handle handle)
{
acpi_status status;
@@ -124,82 +52,43 @@ static u8 * acpi_path_name( acpi_handle handle)
return path_name;
}
-static void acpi_get__hpp ( struct acpi_bridge *ab);
-static void acpi_run_oshp ( struct acpi_bridge *ab);
-
-static int acpi_add_slot_to_php_slots(
- struct acpi_bridge *ab,
- int bus_num,
- acpi_handle handle,
- u32 adr,
- u32 sun
- )
-{
- struct acpi_php_slot *aps;
- static long samesun = -1;
-
- aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL);
- if (!aps) {
- err ("acpi_shpchprm: alloc for aps fail\n");
- return -1;
- }
- memset(aps, 0, sizeof(struct acpi_php_slot));
-
- aps->handle = handle;
- aps->bus = bus_num;
- aps->dev = (adr >> 16) & 0xffff;
- aps->fun = adr & 0xffff;
- aps->sun = sun;
-
- aps->next = ab->slots; /* cling to the bridge */
- aps->bridge = ab;
- ab->slots = aps;
-
- ab->scanned += 1;
- if (!ab->_hpp)
- acpi_get__hpp(ab);
-
- acpi_run_oshp(ab);
-
- if (sun != samesun) {
- info("acpi_shpchprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", aps->sun, ab->seg,
- aps->bus, aps->dev, aps->fun);
- samesun = sun;
- }
- return 0;
-}
-
-static void acpi_get__hpp ( struct acpi_bridge *ab)
+static acpi_status
+acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
{
acpi_status status;
u8 nui[4];
struct acpi_buffer ret_buf = { 0, NULL};
union acpi_object *ext_obj, *package;
- u8 *path_name = acpi_path_name(ab->handle);
+ u8 *path_name = acpi_path_name(handle);
int i, len = 0;
/* get _hpp */
- status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+ status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
switch (status) {
case AE_BUFFER_OVERFLOW:
ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
if (!ret_buf.pointer) {
- err ("acpi_shpchprm:%s alloc for _HPP fail\n", path_name);
- return;
+ err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
+ path_name);
+ return AE_NO_MEMORY;
}
- status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+ status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
+ NULL, &ret_buf);
if (ACPI_SUCCESS(status))
break;
default:
if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s _HPP fail=0x%x\n", path_name, status);
- return;
+ dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
+ path_name, status);
+ return status;
}
}
ext_obj = (union acpi_object *) ret_buf.pointer;
if (ext_obj->type != ACPI_TYPE_PACKAGE) {
- err ("acpi_shpchprm:%s _HPP obj not a package\n", path_name);
+ err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
+ path_name);
+ status = AE_ERROR;
goto free_and_return;
}
@@ -212,1353 +101,41 @@ static void acpi_get__hpp ( struct acpi_bridge *ab)
nui[i] = (u8)ext_obj->integer.value;
break;
default:
- err ("acpi_shpchprm:%s _HPP obj type incorrect\n", path_name);
+ err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
+ path_name);
+ status = AE_ERROR;
goto free_and_return;
}
}
- ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL);
- if (!ab->_hpp) {
- err ("acpi_shpchprm:%s alloc for _HPP failed\n", path_name);
- goto free_and_return;
- }
- memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
+ hpp->cache_line_size = nui[0];
+ hpp->latency_timer = nui[1];
+ hpp->enable_serr = nui[2];
+ hpp->enable_perr = nui[3];
- ab->_hpp->cache_line_size = nui[0];
- ab->_hpp->latency_timer = nui[1];
- ab->_hpp->enable_serr = nui[2];
- ab->_hpp->enable_perr = nui[3];
-
- dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
- dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer);
- dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr);
- dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr);
+ dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
+ dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
+ dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
+ dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
free_and_return:
kfree(ret_buf.pointer);
-}
-
-static void acpi_run_oshp ( struct acpi_bridge *ab)
-{
- acpi_status status;
- u8 *path_name = acpi_path_name(ab->handle);
-
- /* run OSHP */
- status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL);
- if (ACPI_FAILURE(status)) {
- err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
- } else
- dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
- return;
-}
-
-static acpi_status acpi_evaluate_crs(
- acpi_handle handle,
- struct acpi_resource **retbuf
- )
-{
- acpi_status status;
- struct acpi_buffer crsbuf;
- u8 *path_name = acpi_path_name(handle);
-
- crsbuf.length = 0;
- crsbuf.pointer = NULL;
-
- status = acpi_get_current_resources (handle, &crsbuf);
-
- switch (status) {
- case AE_BUFFER_OVERFLOW:
- break; /* found */
- case AE_NOT_FOUND:
- dbg("acpi_shpchprm:%s _CRS not found\n", path_name);
- return status;
- default:
- err ("acpi_shpchprm:%s _CRS fail=0x%x\n", path_name, status);
- return status;
- }
-
- crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL);
- if (!crsbuf.pointer) {
- err ("acpi_shpchprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name);
- return AE_NO_MEMORY;
- }
-
- status = acpi_get_current_resources (handle, &crsbuf);
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm: %s _CRS fail=0x%x.\n", path_name, status);
- kfree(crsbuf.pointer);
- return status;
- }
-
- *retbuf = crsbuf.pointer;
-
- return status;
-}
-
-static void free_pci_resource ( struct pci_resource *aprh)
-{
- struct pci_resource *res, *next;
-
- for (res = aprh; res; res = next) {
- next = res->next;
- kfree(res);
- }
-}
-
-static void print_pci_resource ( struct pci_resource *aprh)
-{
- struct pci_resource *res;
-
- for (res = aprh; res; res = res->next)
- dbg(" base= 0x%x length= 0x%x\n", res->base, res->length);
-}
-
-static void print_slot_resources( struct acpi_php_slot *aps)
-{
- if (aps->bus_head) {
- dbg(" BUS Resources:\n");
- print_pci_resource (aps->bus_head);
- }
-
- if (aps->io_head) {
- dbg(" IO Resources:\n");
- print_pci_resource (aps->io_head);
- }
-
- if (aps->mem_head) {
- dbg(" MEM Resources:\n");
- print_pci_resource (aps->mem_head);
- }
-
- if (aps->p_mem_head) {
- dbg(" PMEM Resources:\n");
- print_pci_resource (aps->p_mem_head);
- }
-}
-
-static void print_pci_resources( struct acpi_bridge *ab)
-{
- if (ab->tbus_head) {
- dbg(" Total BUS Resources:\n");
- print_pci_resource (ab->tbus_head);
- }
- if (ab->bus_head) {
- dbg(" BUS Resources:\n");
- print_pci_resource (ab->bus_head);
- }
-
- if (ab->tio_head) {
- dbg(" Total IO Resources:\n");
- print_pci_resource (ab->tio_head);
- }
- if (ab->io_head) {
- dbg(" IO Resources:\n");
- print_pci_resource (ab->io_head);
- }
-
- if (ab->tmem_head) {
- dbg(" Total MEM Resources:\n");
- print_pci_resource (ab->tmem_head);
- }
- if (ab->mem_head) {
- dbg(" MEM Resources:\n");
- print_pci_resource (ab->mem_head);
- }
-
- if (ab->tp_mem_head) {
- dbg(" Total PMEM Resources:\n");
- print_pci_resource (ab->tp_mem_head);
- }
- if (ab->p_mem_head) {
- dbg(" PMEM Resources:\n");
- print_pci_resource (ab->p_mem_head);
- }
- if (ab->_hpp) {
- dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
- dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer);
- dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr);
- dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr);
- }
-}
-
-static int shpchprm_delete_resource(
- struct pci_resource **aprh,
- ulong base,
- ulong size)
-{
- struct pci_resource *res;
- struct pci_resource *prevnode;
- struct pci_resource *split_node;
- ulong tbase;
-
- shpchp_resource_sort_and_combine(aprh);
-
- for (res = *aprh; res; res = res->next) {
- if (res->base > base)
- continue;
-
- if ((res->base + res->length) < (base + size))
- continue;
-
- if (res->base < base) {
- tbase = base;
-
- if ((res->length - (tbase - res->base)) < size)
- continue;
-
- split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base;
- split_node->length = tbase - res->base;
- res->base = tbase;
- res->length -= split_node->length;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (res->length >= size) {
- split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base + size;
- split_node->length = res->length - size;
- res->length = size;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (*aprh == res) {
- *aprh = res->next;
- } else {
- prevnode = *aprh;
- while (prevnode->next != res)
- prevnode = prevnode->next;
-
- prevnode->next = res->next;
- }
- res->next = NULL;
- kfree(res);
- break;
- }
-
- return 0;
-}
-
-static int shpchprm_delete_resources(
- struct pci_resource **aprh,
- struct pci_resource *this
- )
-{
- struct pci_resource *res;
-
- for (res = this; res; res = res->next)
- shpchprm_delete_resource(aprh, res->base, res->length);
-
- return 0;
-}
-
-static int shpchprm_add_resource(
- struct pci_resource **aprh,
- ulong base,
- ulong size)
-{
- struct pci_resource *res;
-
- for (res = *aprh; res; res = res->next) {
- if ((res->base + res->length) == base) {
- res->length += size;
- size = 0L;
- break;
- }
- if (res->next == *aprh)
- break;
- }
-
- if (size) {
- res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!res) {
- err ("acpi_shpchprm: alloc for res fail\n");
- return -ENOMEM;
- }
- memset(res, 0, sizeof (struct pci_resource));
-
- res->base = base;
- res->length = size;
- res->next = *aprh;
- *aprh = res;
- }
-
- return 0;
-}
-
-static int shpchprm_add_resources(
- struct pci_resource **aprh,
- struct pci_resource *this
- )
-{
- struct pci_resource *res;
- int rc = 0;
-
- for (res = this; res && !rc; res = res->next)
- rc = shpchprm_add_resource(aprh, res->base, res->length);
-
- return rc;
-}
-
-static void acpi_parse_io (
- struct acpi_bridge *ab,
- union acpi_resource_data *data
- )
-{
- struct acpi_resource_io *dataio;
- dataio = (struct acpi_resource_io *) data;
-
- dbg("Io Resource\n");
- dbg(" %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10);
- dbg(" Range minimum base: %08X\n", dataio->min_base_address);
- dbg(" Range maximum base: %08X\n", dataio->max_base_address);
- dbg(" Alignment: %08X\n", dataio->alignment);
- dbg(" Range Length: %08X\n", dataio->range_length);
-}
-
-static void acpi_parse_fixed_io (
- struct acpi_bridge *ab,
- union acpi_resource_data *data
- )
-{
- struct acpi_resource_fixed_io *datafio;
- datafio = (struct acpi_resource_fixed_io *) data;
-
- dbg("Fixed Io Resource\n");
- dbg(" Range base address: %08X", datafio->base_address);
- dbg(" Range length: %08X", datafio->range_length);
-}
-
-static void acpi_parse_address16_32 (
- struct acpi_bridge *ab,
- union acpi_resource_data *data,
- acpi_resource_type id
- )
-{
- /*
- * acpi_resource_address16 == acpi_resource_address32
- * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data;
- */
- struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data;
- struct pci_resource **aprh, **tprh;
-
- if (id == ACPI_RSTYPE_ADDRESS16)
- dbg("acpi_shpchprm:16-Bit Address Space Resource\n");
- else
- dbg("acpi_shpchprm:32-Bit Address Space Resource\n");
-
- switch (data32->resource_type) {
- case ACPI_MEMORY_RANGE:
- dbg(" Resource Type: Memory Range\n");
- aprh = &ab->mem_head;
- tprh = &ab->tmem_head;
-
- switch (data32->attribute.memory.cache_attribute) {
- case ACPI_NON_CACHEABLE_MEMORY:
- dbg(" Type Specific: Noncacheable memory\n");
- break;
- case ACPI_CACHABLE_MEMORY:
- dbg(" Type Specific: Cacheable memory\n");
- break;
- case ACPI_WRITE_COMBINING_MEMORY:
- dbg(" Type Specific: Write-combining memory\n");
- break;
- case ACPI_PREFETCHABLE_MEMORY:
- aprh = &ab->p_mem_head;
- dbg(" Type Specific: Prefetchable memory\n");
- break;
- default:
- dbg(" Type Specific: Invalid cache attribute\n");
- break;
- }
-
- dbg(" Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only");
- break;
-
- case ACPI_IO_RANGE:
- dbg(" Resource Type: I/O Range\n");
- aprh = &ab->io_head;
- tprh = &ab->tio_head;
-
- switch (data32->attribute.io.range_attribute) {
- case ACPI_NON_ISA_ONLY_RANGES:
- dbg(" Type Specific: Non-ISA Io Addresses\n");
- break;
- case ACPI_ISA_ONLY_RANGES:
- dbg(" Type Specific: ISA Io Addresses\n");
- break;
- case ACPI_ENTIRE_RANGE:
- dbg(" Type Specific: ISA and non-ISA Io Addresses\n");
- break;
- default:
- dbg(" Type Specific: Invalid range attribute\n");
- break;
- }
- break;
-
- case ACPI_BUS_NUMBER_RANGE:
- dbg(" Resource Type: Bus Number Range(fixed)\n");
- /* fixup to be compatible with the rest of php driver */
- data32->min_address_range++;
- data32->address_length--;
- aprh = &ab->bus_head;
- tprh = &ab->tbus_head;
- break;
- default:
- dbg(" Resource Type: Invalid resource type. Exiting.\n");
- return;
- }
-
- dbg(" Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer");
- dbg(" %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive");
- dbg(" Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not");
- dbg(" Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not");
- dbg(" Granularity: %08X\n", data32->granularity);
- dbg(" Address range min: %08X\n", data32->min_address_range);
- dbg(" Address range max: %08X\n", data32->max_address_range);
- dbg(" Address translation offset: %08X\n", data32->address_translation_offset);
- dbg(" Address Length: %08X\n", data32->address_length);
-
- if (0xFF != data32->resource_source.index) {
- dbg(" Resource Source Index: %X\n", data32->resource_source.index);
- /* dbg(" Resource Source: %s\n", data32->resource_source.string_ptr); */
- }
-
- shpchprm_add_resource(aprh, data32->min_address_range, data32->address_length);
-}
-
-static acpi_status acpi_parse_crs(
- struct acpi_bridge *ab,
- struct acpi_resource *crsbuf
- )
-{
- acpi_status status = AE_OK;
- struct acpi_resource *resource = crsbuf;
- u8 count = 0;
- u8 done = 0;
-
- while (!done) {
- dbg("acpi_shpchprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++);
- switch (resource->id) {
- case ACPI_RSTYPE_IRQ:
- dbg("Irq -------- Resource\n");
- break;
- case ACPI_RSTYPE_DMA:
- dbg("DMA -------- Resource\n");
- break;
- case ACPI_RSTYPE_START_DPF:
- dbg("Start DPF -------- Resource\n");
- break;
- case ACPI_RSTYPE_END_DPF:
- dbg("End DPF -------- Resource\n");
- break;
- case ACPI_RSTYPE_IO:
- acpi_parse_io (ab, &resource->data);
- break;
- case ACPI_RSTYPE_FIXED_IO:
- acpi_parse_fixed_io (ab, &resource->data);
- break;
- case ACPI_RSTYPE_VENDOR:
- dbg("Vendor -------- Resource\n");
- break;
- case ACPI_RSTYPE_END_TAG:
- dbg("End_tag -------- Resource\n");
- done = 1;
- break;
- case ACPI_RSTYPE_MEM24:
- dbg("Mem24 -------- Resource\n");
- break;
- case ACPI_RSTYPE_MEM32:
- dbg("Mem32 -------- Resource\n");
- break;
- case ACPI_RSTYPE_FIXED_MEM32:
- dbg("Fixed Mem32 -------- Resource\n");
- break;
- case ACPI_RSTYPE_ADDRESS16:
- acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16);
- break;
- case ACPI_RSTYPE_ADDRESS32:
- acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32);
- break;
- case ACPI_RSTYPE_ADDRESS64:
- info("Address64 -------- Resource unparsed\n");
- break;
- case ACPI_RSTYPE_EXT_IRQ:
- dbg("Ext Irq -------- Resource\n");
- break;
- default:
- dbg("Invalid -------- resource type 0x%x\n", resource->id);
- break;
- }
-
- resource = (struct acpi_resource *) ((char *)resource + resource->length);
- }
-
return status;
}
-static acpi_status acpi_get_crs( struct acpi_bridge *ab)
+static void acpi_run_oshp(acpi_handle handle)
{
acpi_status status;
- struct acpi_resource *crsbuf;
-
- status = acpi_evaluate_crs(ab->handle, &crsbuf);
- if (ACPI_SUCCESS(status)) {
- status = acpi_parse_crs(ab, crsbuf);
- kfree(crsbuf);
-
- shpchp_resource_sort_and_combine(&ab->bus_head);
- shpchp_resource_sort_and_combine(&ab->io_head);
- shpchp_resource_sort_and_combine(&ab->mem_head);
- shpchp_resource_sort_and_combine(&ab->p_mem_head);
-
- shpchprm_add_resources (&ab->tbus_head, ab->bus_head);
- shpchprm_add_resources (&ab->tio_head, ab->io_head);
- shpchprm_add_resources (&ab->tmem_head, ab->mem_head);
- shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
- }
-
- return status;
-}
-
-/* find acpi_bridge downword from ab. */
-static struct acpi_bridge *
-find_acpi_bridge_by_bus(
- struct acpi_bridge *ab,
- int seg,
- int bus /* pdev->subordinate->number */
- )
-{
- struct acpi_bridge *lab = NULL;
-
- if (!ab)
- return NULL;
-
- if ((ab->bus == bus) && (ab->seg == seg))
- return ab;
-
- if (ab->child)
- lab = find_acpi_bridge_by_bus(ab->child, seg, bus);
-
- if (!lab)
- if (ab->next)
- lab = find_acpi_bridge_by_bus(ab->next, seg, bus);
-
- return lab;
-}
-
-/*
- * Build a device tree of ACPI PCI Bridges
- */
-static void shpchprm_acpi_register_a_bridge (
- struct acpi_bridge **head,
- struct acpi_bridge *pab, /* parent bridge to which child bridge is added */
- struct acpi_bridge *cab /* child bridge to add */
- )
-{
- struct acpi_bridge *lpab;
- struct acpi_bridge *lcab;
-
- lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus);
- if (!lpab) {
- if (!(pab->type & BRIDGE_TYPE_HOST))
- warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus);
- pab->next = *head;
- *head = pab;
- lpab = pab;
- }
-
- if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab))
- return;
-
- lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus);
- if (lcab) {
- if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus))
- err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus);
- return;
- } else
- lcab = cab;
-
- lcab->parent = lpab;
- lcab->next = lpab->child;
- lpab->child = lcab;
-}
-
-static acpi_status shpchprm_acpi_build_php_slots_callback(
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval
- )
-{
- ulong bus_num;
- ulong seg_num;
- ulong sun, adr;
- ulong padr = 0;
- acpi_handle phandle = NULL;
- struct acpi_bridge *pab = (struct acpi_bridge *)context;
- struct acpi_bridge *lab;
- acpi_status status;
u8 *path_name = acpi_path_name(handle);
- /* get _SUN */
- status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun);
- switch(status) {
- case AE_NOT_FOUND:
- return AE_OK;
- default:
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s _SUN fail=0x%x\n", path_name, status);
- return status;
- }
- }
-
- /* get _ADR. _ADR must exist if _SUN exists */
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
- return status;
- }
-
- dbg("acpi_shpchprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr);
-
- status = acpi_get_parent(handle, &phandle);
+ /* run OSHP */
+ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s get_parent fail=0x%x\n", path_name, status);
- return (status);
- }
-
- bus_num = pab->bus;
- seg_num = pab->seg;
-
- if (pab->bus == bus_num) {
- lab = pab;
+ err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
+ status);
} else {
- dbg("WARN: pab is not parent\n");
- lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num);
- if (!lab) {
- dbg("acpi_shpchprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
- lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL);
- if (!lab) {
- err("acpi_shpchprm: alloc for ab fail\n");
- return AE_NO_MEMORY;
- }
- memset(lab, 0, sizeof(struct acpi_bridge));
-
- lab->handle = phandle;
- lab->pbus = pab->bus;
- lab->pdevice = (int)(padr >> 16) & 0xffff;
- lab->pfunction = (int)(padr & 0xffff);
- lab->bus = (int)bus_num;
- lab->scanned = 0;
- lab->type = BRIDGE_TYPE_P2P;
-
- shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab);
- } else
- dbg("acpi_shpchprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
+ dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
}
-
- acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun);
- return (status);
-}
-
-static int shpchprm_acpi_build_php_slots(
- struct acpi_bridge *ab,
- u32 depth
- )
-{
- acpi_status status;
- u8 *path_name = acpi_path_name(ab->handle);
-
- /* Walk down this pci bridge to get _SUNs if any behind P2P */
- status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
- ab->handle,
- depth,
- shpchprm_acpi_build_php_slots_callback,
- ab,
- NULL );
- if (ACPI_FAILURE(status)) {
- dbg("acpi_shpchprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status);
- return -1;
- }
-
- return 0;
-}
-
-static void build_a_bridge(
- struct acpi_bridge *pab,
- struct acpi_bridge *ab
- )
-{
- u8 *path_name = acpi_path_name(ab->handle);
-
- shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab);
-
- switch (ab->type) {
- case BRIDGE_TYPE_HOST:
- dbg("acpi_shpchprm: Registered PCI HOST Bridge(%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
- ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
- break;
- case BRIDGE_TYPE_P2P:
- dbg("acpi_shpchprm: Registered PCI P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
- ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
- break;
- };
-
- /* build any immediate PHP slots under this pci bridge */
- shpchprm_acpi_build_php_slots(ab, 1);
-}
-
-static struct acpi_bridge * add_p2p_bridge(
- acpi_handle handle,
- struct acpi_bridge *pab, /* parent */
- ulong adr
- )
-{
- struct acpi_bridge *ab;
- struct pci_dev *pdev;
- ulong devnum, funcnum;
- u8 *path_name = acpi_path_name(handle);
-
- ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
- if (!ab) {
- err("acpi_shpchprm: alloc for ab fail\n");
- return NULL;
- }
- memset(ab, 0, sizeof(struct acpi_bridge));
-
- devnum = (adr >> 16) & 0xffff;
- funcnum = adr & 0xffff;
-
- pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
- if (!pdev || !pdev->subordinate) {
- err("acpi_shpchprm:%s is not a P2P Bridge\n", path_name);
- kfree(ab);
- return NULL;
- }
-
- ab->handle = handle;
- ab->seg = pab->seg;
- ab->pbus = pab->bus; /* or pdev->bus->number */
- ab->pdevice = devnum; /* or PCI_SLOT(pdev->devfn) */
- ab->pfunction = funcnum; /* or PCI_FUNC(pdev->devfn) */
- ab->bus = pdev->subordinate->number;
- ab->scanned = 0;
- ab->type = BRIDGE_TYPE_P2P;
-
- dbg("acpi_shpchprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n",
- pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
- pab->bus, (u32)devnum, (u32)funcnum, path_name);
-
- build_a_bridge(pab, ab);
-
- return ab;
-}
-
-static acpi_status scan_p2p_bridge(
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval
- )
-{
- struct acpi_bridge *pab = (struct acpi_bridge *)context;
- struct acpi_bridge *ab;
- acpi_status status;
- ulong adr = 0;
- u8 *path_name = acpi_path_name(handle);
- ulong devnum, funcnum;
- struct pci_dev *pdev;
-
- /* get device, function */
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
- if (ACPI_FAILURE(status)) {
- if (status != AE_NOT_FOUND)
- err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
- return AE_OK;
- }
-
- devnum = (adr >> 16) & 0xffff;
- funcnum = adr & 0xffff;
-
- pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
- if (!pdev)
- return AE_OK;
- if (!pdev->subordinate)
- return AE_OK;
-
- ab = add_p2p_bridge(handle, pab, adr);
- if (ab) {
- status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
- handle,
- (u32)1,
- scan_p2p_bridge,
- ab,
- NULL);
- if (ACPI_FAILURE(status))
- dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
- }
-
- return AE_OK;
-}
-
-static struct acpi_bridge * add_host_bridge(
- acpi_handle handle,
- ulong segnum,
- ulong busnum
- )
-{
- ulong adr = 0;
- acpi_status status;
- struct acpi_bridge *ab;
- u8 *path_name = acpi_path_name(handle);
-
- /* get device, function: host br adr is always 0000 though. */
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
- return NULL;
- }
- dbg("acpi_shpchprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, (u32)busnum,
- (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name);
-
- ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
- if (!ab) {
- err("acpi_shpchprm: alloc for ab fail\n");
- return NULL;
- }
- memset(ab, 0, sizeof(struct acpi_bridge));
-
- ab->handle = handle;
- ab->seg = (int)segnum;
- ab->bus = ab->pbus = (int)busnum;
- ab->pdevice = (int)(adr >> 16) & 0xffff;
- ab->pfunction = (int)(adr & 0xffff);
- ab->scanned = 0;
- ab->type = BRIDGE_TYPE_HOST;
-
- /* get root pci bridge's current resources */
- status = acpi_get_crs(ab);
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s evaluate _CRS fail=0x%x\n", path_name, status);
- kfree(ab);
- return NULL;
- }
- build_a_bridge(ab, ab);
-
- return ab;
-}
-
-static acpi_status acpi_scan_from_root_pci_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval
- )
-{
- ulong segnum = 0;
- ulong busnum = 0;
- acpi_status status;
- struct acpi_bridge *ab;
- u8 *path_name = acpi_path_name(handle);
-
- /* get bus number of this pci root bridge */
- status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum);
- if (ACPI_FAILURE(status)) {
- if (status != AE_NOT_FOUND) {
- err("acpi_shpchprm:%s evaluate _SEG fail=0x%x\n", path_name, status);
- return status;
- }
- segnum = 0;
- }
-
- /* get bus number of this pci root bridge */
- status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum);
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s evaluate _BBN fail=0x%x\n", path_name, status);
- return (status);
- }
-
- ab = add_host_bridge(handle, segnum, busnum);
- if (ab) {
- status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
- handle,
- 1,
- scan_p2p_bridge,
- ab,
- NULL);
- if (ACPI_FAILURE(status))
- dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
- }
-
- return AE_OK;
-}
-
-static int shpchprm_acpi_scan_pci (void)
-{
- acpi_status status;
-
- /*
- * TBD: traverse LDM device tree with the help of
- * unified ACPI augmented for php device population.
- */
- status = acpi_get_devices ( PCI_ROOT_HID_STRING,
- acpi_scan_from_root_pci_callback,
- NULL,
- NULL );
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:get_device PCI ROOT HID fail=0x%x\n", status);
- return -1;
- }
-
- return 0;
-}
-
-int shpchprm_init(enum php_ctlr_type ctlr_type)
-{
- int rc;
-
- if (ctlr_type != PCI)
- return -ENODEV;
-
- dbg("shpchprm ACPI init <enter>\n");
- acpi_bridges_head = NULL;
-
- /* construct PCI bus:device tree of acpi_handles */
- rc = shpchprm_acpi_scan_pci();
- if (rc)
- return rc;
-
- dbg("shpchprm ACPI init %s\n", (rc)?"fail":"success");
- return rc;
-}
-
-static void free_a_slot(struct acpi_php_slot *aps)
-{
- dbg(" free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun);
-
- free_pci_resource (aps->io_head);
- free_pci_resource (aps->bus_head);
- free_pci_resource (aps->mem_head);
- free_pci_resource (aps->p_mem_head);
-
- kfree(aps);
-}
-
-static void free_a_bridge( struct acpi_bridge *ab)
-{
- struct acpi_php_slot *aps, *next;
-
- switch (ab->type) {
- case BRIDGE_TYPE_HOST:
- dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
- ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
- break;
- case BRIDGE_TYPE_P2P:
- dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
- ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
- break;
- };
-
- /* free slots first */
- for (aps = ab->slots; aps; aps = next) {
- next = aps->next;
- free_a_slot(aps);
- }
-
- free_pci_resource (ab->io_head);
- free_pci_resource (ab->tio_head);
- free_pci_resource (ab->bus_head);
- free_pci_resource (ab->tbus_head);
- free_pci_resource (ab->mem_head);
- free_pci_resource (ab->tmem_head);
- free_pci_resource (ab->p_mem_head);
- free_pci_resource (ab->tp_mem_head);
-
- kfree(ab);
-}
-
-static void shpchprm_free_bridges ( struct acpi_bridge *ab)
-{
- if (!ab)
- return;
-
- if (ab->child)
- shpchprm_free_bridges (ab->child);
-
- if (ab->next)
- shpchprm_free_bridges (ab->next);
-
- free_a_bridge(ab);
-}
-
-void shpchprm_cleanup(void)
-{
- shpchprm_free_bridges (acpi_bridges_head);
-}
-
-static int get_number_of_slots (
- struct acpi_bridge *ab,
- int selfonly
- )
-{
- struct acpi_php_slot *aps;
- int prev_slot = -1;
- int slot_num = 0;
-
- for ( aps = ab->slots; aps; aps = aps->next)
- if (aps->dev != prev_slot) {
- prev_slot = aps->dev;
- slot_num++;
- }
-
- if (ab->child)
- slot_num += get_number_of_slots (ab->child, 0);
-
- if (selfonly)
- return slot_num;
-
- if (ab->next)
- slot_num += get_number_of_slots (ab->next, 0);
-
- return slot_num;
-}
-
-static int print_acpi_resources (struct acpi_bridge *ab)
-{
- struct acpi_php_slot *aps;
- int i;
-
- switch (ab->type) {
- case BRIDGE_TYPE_HOST:
- dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle));
- break;
- case BRIDGE_TYPE_P2P:
- dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle));
- break;
- };
-
- print_pci_resources (ab);
-
- for ( i = -1, aps = ab->slots; aps; aps = aps->next) {
- if (aps->dev == i)
- continue;
- dbg(" Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
- print_slot_resources(aps);
- i = aps->dev;
- }
-
- if (ab->child)
- print_acpi_resources (ab->child);
-
- if (ab->next)
- print_acpi_resources (ab->next);
-
- return 0;
-}
-
-int shpchprm_print_pirt(void)
-{
- dbg("SHPCHPRM ACPI Slots\n");
- if (acpi_bridges_head)
- print_acpi_resources (acpi_bridges_head);
- return 0;
-}
-
-static struct acpi_php_slot * get_acpi_slot (
- struct acpi_bridge *ab,
- u32 sun
- )
-{
- struct acpi_php_slot *aps = NULL;
-
- for ( aps = ab->slots; aps; aps = aps->next)
- if (aps->sun == sun)
- return aps;
-
- if (!aps && ab->child) {
- aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun);
- if (aps)
- return aps;
- }
-
- if (!aps && ab->next) {
- aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun);
- if (aps)
- return aps;
- }
-
- return aps;
-
-}
-
-#if 0
-static void * shpchprm_get_slot(struct slot *slot)
-{
- struct acpi_bridge *ab = acpi_bridges_head;
- struct acpi_php_slot *aps = get_acpi_slot (ab, slot->number);
-
- aps->slot = slot;
-
- dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
-
- return (void *)aps;
-}
-#endif
-
-static void shpchprm_dump_func_res( struct pci_func *fun)
-{
- struct pci_func *func = fun;
-
- if (func->bus_head) {
- dbg(": BUS Resources:\n");
- print_pci_resource (func->bus_head);
- }
- if (func->io_head) {
- dbg(": IO Resources:\n");
- print_pci_resource (func->io_head);
- }
- if (func->mem_head) {
- dbg(": MEM Resources:\n");
- print_pci_resource (func->mem_head);
- }
- if (func->p_mem_head) {
- dbg(": PMEM Resources:\n");
- print_pci_resource (func->p_mem_head);
- }
-}
-
-static void shpchprm_dump_ctrl_res( struct controller *ctlr)
-{
- struct controller *ctrl = ctlr;
-
- if (ctrl->bus_head) {
- dbg(": BUS Resources:\n");
- print_pci_resource (ctrl->bus_head);
- }
- if (ctrl->io_head) {
- dbg(": IO Resources:\n");
- print_pci_resource (ctrl->io_head);
- }
- if (ctrl->mem_head) {
- dbg(": MEM Resources:\n");
- print_pci_resource (ctrl->mem_head);
- }
- if (ctrl->p_mem_head) {
- dbg(": PMEM Resources:\n");
- print_pci_resource (ctrl->p_mem_head);
- }
-}
-
-static int shpchprm_get_used_resources (
- struct controller *ctrl,
- struct pci_func *func
- )
-{
- return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);
-}
-
-static int configure_existing_function(
- struct controller *ctrl,
- struct pci_func *func
- )
-{
- int rc;
-
- /* see how much resources the func has used. */
- rc = shpchprm_get_used_resources (ctrl, func);
-
- if (!rc) {
- /* subtract the resources used by the func from ctrl resources */
- rc = shpchprm_delete_resources (&ctrl->bus_head, func->bus_head);
- rc |= shpchprm_delete_resources (&ctrl->io_head, func->io_head);
- rc |= shpchprm_delete_resources (&ctrl->mem_head, func->mem_head);
- rc |= shpchprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
- if (rc)
- warn("aCEF: cannot del used resources\n");
- } else
- err("aCEF: cannot get used resources\n");
-
- return rc;
-}
-
-static int bind_pci_resources_to_slots ( struct controller *ctrl)
-{
- struct pci_func *func, new_func;
- int busn = ctrl->slot_bus;
- int devn, funn;
- u32 vid;
-
- for (devn = 0; devn < 32; devn++) {
- for (funn = 0; funn < 8; funn++) {
- /*
- if (devn == ctrl->device && funn == ctrl->function)
- continue;
- */
- /* find out if this entry is for an occupied slot */
- vid = 0xFFFFFFFF;
- pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
-
- if (vid != 0xFFFFFFFF) {
- func = shpchp_slot_find(busn, devn, funn);
- if (!func) {
- memset(&new_func, 0, sizeof(struct pci_func));
- new_func.bus = busn;
- new_func.device = devn;
- new_func.function = funn;
- new_func.is_a_board = 1;
- configure_existing_function(ctrl, &new_func);
- shpchprm_dump_func_res(&new_func);
- } else {
- configure_existing_function(ctrl, func);
- shpchprm_dump_func_res(func);
- }
- dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
- }
- }
- }
-
- return 0;
-}
-
-static int bind_pci_resources(
- struct controller *ctrl,
- struct acpi_bridge *ab
- )
-{
- int status = 0;
-
- if (ab->bus_head) {
- dbg("bapr: BUS Resources add on PCI 0x%x\n", ab->bus);
- status = shpchprm_add_resources (&ctrl->bus_head, ab->bus_head);
- if (shpchprm_delete_resources (&ab->bus_head, ctrl->bus_head))
- warn("bapr: cannot sub BUS Resource on PCI 0x%x\n", ab->bus);
- if (status) {
- err("bapr: BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
- return status;
- }
- } else
- info("bapr: No BUS Resource on PCI 0x%x.\n", ab->bus);
-
- if (ab->io_head) {
- dbg("bapr: IO Resources add on PCI 0x%x\n", ab->bus);
- status = shpchprm_add_resources (&ctrl->io_head, ab->io_head);
- if (shpchprm_delete_resources (&ab->io_head, ctrl->io_head))
- warn("bapr: cannot sub IO Resource on PCI 0x%x\n", ab->bus);
- if (status) {
- err("bapr: IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
- return status;
- }
- } else
- info("bapr: No IO Resource on PCI 0x%x.\n", ab->bus);
-
- if (ab->mem_head) {
- dbg("bapr: MEM Resources add on PCI 0x%x\n", ab->bus);
- status = shpchprm_add_resources (&ctrl->mem_head, ab->mem_head);
- if (shpchprm_delete_resources (&ab->mem_head, ctrl->mem_head))
- warn("bapr: cannot sub MEM Resource on PCI 0x%x\n", ab->bus);
- if (status) {
- err("bapr: MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
- return status;
- }
- } else
- info("bapr: No MEM Resource on PCI 0x%x.\n", ab->bus);
-
- if (ab->p_mem_head) {
- dbg("bapr: PMEM Resources add on PCI 0x%x\n", ab->bus);
- status = shpchprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head);
- if (shpchprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head))
- warn("bapr: cannot sub PMEM Resource on PCI 0x%x\n", ab->bus);
- if (status) {
- err("bapr: PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
- return status;
- }
- } else
- info("bapr: No PMEM Resource on PCI 0x%x.\n", ab->bus);
-
- return status;
-}
-
-static int no_pci_resources( struct acpi_bridge *ab)
-{
- return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head);
-}
-
-static int find_pci_bridge_resources (
- struct controller *ctrl,
- struct acpi_bridge *ab
- )
-{
- int rc = 0;
- struct pci_func func;
-
- memset(&func, 0, sizeof(struct pci_func));
-
- func.bus = ab->pbus;
- func.device = ab->pdevice;
- func.function = ab->pfunction;
- func.is_a_board = 1;
-
- /* Get used resources for this PCI bridge */
- rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD);
-
- ab->io_head = func.io_head;
- ab->mem_head = func.mem_head;
- ab->p_mem_head = func.p_mem_head;
- ab->bus_head = func.bus_head;
- if (ab->bus_head)
- shpchprm_delete_resource(&ab->bus_head, ctrl->bus, 1);
-
- return rc;
-}
-
-static int get_pci_resources_from_bridge(
- struct controller *ctrl,
- struct acpi_bridge *ab
- )
-{
- int rc = 0;
-
- dbg("grfb: Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus);
-
- rc = find_pci_bridge_resources (ctrl, ab);
-
- shpchp_resource_sort_and_combine(&ab->bus_head);
- shpchp_resource_sort_and_combine(&ab->io_head);
- shpchp_resource_sort_and_combine(&ab->mem_head);
- shpchp_resource_sort_and_combine(&ab->p_mem_head);
-
- shpchprm_add_resources (&ab->tbus_head, ab->bus_head);
- shpchprm_add_resources (&ab->tio_head, ab->io_head);
- shpchprm_add_resources (&ab->tmem_head, ab->mem_head);
- shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
-
- return rc;
-}
-
-static int get_pci_resources(
- struct controller *ctrl,
- struct acpi_bridge *ab
- )
-{
- int rc = 0;
-
- if (no_pci_resources(ab)) {
- dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus);
- rc = get_pci_resources_from_bridge(ctrl, ab);
- }
-
- return rc;
}
int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
@@ -1570,144 +147,40 @@ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn
return 0;
}
-/*
- * Get resources for this ctrl.
- * 1. get total resources from ACPI _CRS or bridge (this ctrl)
- * 2. find used resources of existing adapters
- * 3. subtract used resources from total resources
- */
-int shpchprm_find_available_resources( struct controller *ctrl)
+void get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
- int rc = 0;
- struct acpi_bridge *ab;
-
- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number);
- if (!ab) {
- err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number);
- return -1;
- }
- if (no_pci_resources(ab)) {
- rc = get_pci_resources(ctrl, ab);
- if (rc) {
- err("pfar:cannot get pci resources of PCI 0x%x.\n",ctrl->pci_dev->subordinate->number);
- return -1;
- }
- }
-
- rc = bind_pci_resources(ctrl, ab);
- dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
- shpchprm_dump_ctrl_res(ctrl);
-
- bind_pci_resources_to_slots (ctrl);
-
- dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
- shpchprm_dump_ctrl_res(ctrl);
-
- return rc;
-}
-
-int shpchprm_set_hpp(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type
- )
-{
- struct acpi_bridge *ab;
- struct pci_bus lpci_bus, *pci_bus;
- int rc = 0;
- unsigned int devfn;
- u8 cls= 0x08; /* default cache line size */
- u8 lt = 0x40; /* default latency timer */
- u8 ep = 0;
- u8 es = 0;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
-
- if (ab) {
- if (ab->_hpp) {
- lt = (u8)ab->_hpp->latency_timer;
- cls = (u8)ab->_hpp->cache_line_size;
- ep = (u8)ab->_hpp->enable_perr;
- es = (u8)ab->_hpp->enable_serr;
- } else
- dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
- } else
- dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
-
-
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- /* set subordinate Latency Timer */
- rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt);
- }
-
- /* set base Latency Timer */
- rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt);
- dbg(" set latency timer =0x%02x: %x\n", lt, rc);
-
- rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls);
- dbg(" set cache_line_size=0x%02x: %x\n", cls, rc);
-
- return rc;
+ /*
+ * OSHP is an optional ACPI firmware control method. If present,
+ * we need to run it to inform BIOS that we will control SHPC
+ * hardware from now on.
+ */
+ acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
+ if (!handle)
+ return;
+ acpi_run_oshp(handle);
}
-void shpchprm_enable_card(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
+void get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
{
- u16 command, cmd, bcommand, bcmd;
- struct pci_bus lpci_bus, *pci_bus;
- struct acpi_bridge *ab;
- unsigned int devfn;
- int rc;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
-
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
- }
+ acpi_status status = AE_NOT_FOUND;
+ struct pci_dev *pdev = dev;
- cmd = command = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
- | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
- bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA;
-
- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
- if (ab) {
- if (ab->_hpp) {
- if (ab->_hpp->enable_perr) {
- command |= PCI_COMMAND_PARITY;
- bcommand |= PCI_BRIDGE_CTL_PARITY;
- } else {
- command &= ~PCI_COMMAND_PARITY;
- bcommand &= ~PCI_BRIDGE_CTL_PARITY;
- }
- if (ab->_hpp->enable_serr) {
- command |= PCI_COMMAND_SERR;
- bcommand |= PCI_BRIDGE_CTL_SERR;
- } else {
- command &= ~PCI_COMMAND_SERR;
- bcommand &= ~PCI_BRIDGE_CTL_SERR;
- }
- } else
- dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
- } else
- dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
-
- if (command != cmd) {
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
- }
- if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) {
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
+ /*
+ * _HPP settings apply to all child buses, until another _HPP is
+ * encountered. If we don't find an _HPP for the input pci dev,
+ * look for it in the parent device scope since that would apply to
+ * this pci dev. If we don't find any _HPP, use hardcoded defaults
+ */
+ while (pdev && (ACPI_FAILURE(status))) {
+ acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
+ if (!handle)
+ break;
+ status = acpi_run_hpp(handle, hpp);
+ if (!(pdev->bus->parent))
+ break;
+ /* Check if a parent object supports _HPP */
+ pdev = pdev->bus->parent->self;
}
}
diff --git a/drivers/pci/hotplug/shpchprm_legacy.c b/drivers/pci/hotplug/shpchprm_legacy.c
index ba6c549c9b9..ed6c1254bf6 100644
--- a/drivers/pci/hotplug/shpchprm_legacy.c
+++ b/drivers/pci/hotplug/shpchprm_legacy.c
@@ -27,33 +27,11 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
#include "shpchp.h"
-#include "shpchprm.h"
-#include "shpchprm_legacy.h"
-
-static void __iomem *shpchp_rom_start;
-static u16 unused_IRQ;
-
-void shpchprm_cleanup(void)
-{
- if (shpchp_rom_start)
- iounmap(shpchp_rom_start);
-}
-
-int shpchprm_print_pirt(void)
-{
- return 0;
-}
int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
{
@@ -63,377 +41,14 @@ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn
return 0;
}
-/* Find the Hot Plug Resource Table in the specified region of memory */
-static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iomem *end)
+void get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
{
- void __iomem *fp;
- void __iomem *endp;
- u8 temp1, temp2, temp3, temp4;
- int status = 0;
-
- endp = (end - sizeof(struct hrt) + 1);
-
- for (fp = begin; fp <= endp; fp += 16) {
- temp1 = readb(fp + SIG0);
- temp2 = readb(fp + SIG1);
- temp3 = readb(fp + SIG2);
- temp4 = readb(fp + SIG3);
- if (temp1 == '$' && temp2 == 'H' && temp3 == 'R' && temp4 == 'T') {
- status = 1;
- break;
- }
- }
-
- if (!status)
- fp = NULL;
-
- dbg("Discovered Hotplug Resource Table at %p\n", fp);
- return fp;
+ return;
}
-/*
- * shpchprm_find_available_resources
- *
- * Finds available memory, IO, and IRQ resources for programming
- * devices which may be added to the system
- * this function is for hot plug ADD!
- *
- * returns 0 if success
- */
-int shpchprm_find_available_resources(struct controller *ctrl)
+void get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
- u8 populated_slot;
- u8 bridged_slot;
- void __iomem *one_slot;
- struct pci_func *func = NULL;
- int i = 10, index = 0;
- u32 temp_dword, rc;
- ulong temp_ulong;
- struct pci_resource *mem_node;
- struct pci_resource *p_mem_node;
- struct pci_resource *io_node;
- struct pci_resource *bus_node;
- void __iomem *rom_resource_table;
- struct pci_bus lpci_bus, *pci_bus;
- u8 cfgspc_irq, temp;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- rom_resource_table = detect_HRT_floating_pointer(shpchp_rom_start, shpchp_rom_start + 0xffff);
- dbg("rom_resource_table = %p\n", rom_resource_table);
- if (rom_resource_table == NULL)
- return -ENODEV;
-
- /* Sum all resources and setup resource maps */
- unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
- dbg("unused_IRQ = %x\n", unused_IRQ);
-
- temp = 0;
- while (unused_IRQ) {
- if (unused_IRQ & 1) {
- shpchp_disk_irq = temp;
- break;
- }
- unused_IRQ = unused_IRQ >> 1;
- temp++;
- }
-
- dbg("shpchp_disk_irq= %d\n", shpchp_disk_irq);
- unused_IRQ = unused_IRQ >> 1;
- temp++;
-
- while (unused_IRQ) {
- if (unused_IRQ & 1) {
- shpchp_nic_irq = temp;
- break;
- }
- unused_IRQ = unused_IRQ >> 1;
- temp++;
- }
-
- dbg("shpchp_nic_irq= %d\n", shpchp_nic_irq);
- unused_IRQ = readl(rom_resource_table + PCIIRQ);
-
- temp = 0;
-
- pci_read_config_byte(ctrl->pci_dev, PCI_INTERRUPT_LINE, &cfgspc_irq);
-
- if (!shpchp_nic_irq) {
- shpchp_nic_irq = cfgspc_irq;
- }
-
- if (!shpchp_disk_irq) {
- shpchp_disk_irq = cfgspc_irq;
- }
-
- dbg("shpchp_disk_irq, shpchp_nic_irq= %d, %d\n", shpchp_disk_irq, shpchp_nic_irq);
-
- one_slot = rom_resource_table + sizeof(struct hrt);
-
- i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
- dbg("number_of_entries = %d\n", i);
-
- if (!readb(one_slot + SECONDARY_BUS))
- return (1);
-
- dbg("dev|IO base|length|MEMbase|length|PM base|length|PB SB MB\n");
-
- while (i && readb(one_slot + SECONDARY_BUS)) {
- u8 dev_func = readb(one_slot + DEV_FUNC);
- u8 primary_bus = readb(one_slot + PRIMARY_BUS);
- u8 secondary_bus = readb(one_slot + SECONDARY_BUS);
- u8 max_bus = readb(one_slot + MAX_BUS);
- u16 io_base = readw(one_slot + IO_BASE);
- u16 io_length = readw(one_slot + IO_LENGTH);
- u16 mem_base = readw(one_slot + MEM_BASE);
- u16 mem_length = readw(one_slot + MEM_LENGTH);
- u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE);
- u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH);
-
- dbg("%2.2x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x |%2.2x %2.2x %2.2x\n",
- dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
- primary_bus, secondary_bus, max_bus);
-
- /* If this entry isn't for our controller's bus, ignore it */
- if (primary_bus != ctrl->slot_bus) {
- i--;
- one_slot += sizeof(struct slot_rt);
- continue;
- }
- /* find out if this entry is for an occupied slot */
- temp_dword = 0xFFFFFFFF;
- pci_bus->number = primary_bus;
- pci_bus_read_config_dword(pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
-
- dbg("temp_D_word = %x\n", temp_dword);
-
- if (temp_dword != 0xFFFFFFFF) {
- index = 0;
- func = shpchp_slot_find(primary_bus, dev_func >> 3, 0);
-
- while (func && (func->function != (dev_func & 0x07))) {
- dbg("func = %p b:d:f(%x:%x:%x)\n", func, primary_bus, dev_func >> 3, index);
- func = shpchp_slot_find(primary_bus, dev_func >> 3, index++);
- }
-
- /* If we can't find a match, skip this table entry */
- if (!func) {
- i--;
- one_slot += sizeof(struct slot_rt);
- continue;
- }
- /* this may not work and shouldn't be used */
- if (secondary_bus != primary_bus)
- bridged_slot = 1;
- else
- bridged_slot = 0;
-
- populated_slot = 1;
- } else {
- populated_slot = 0;
- bridged_slot = 0;
- }
- dbg("slot populated =%s \n", populated_slot?"yes":"no");
-
- /* If we've got a valid IO base, use it */
-
- temp_ulong = io_base + io_length;
-
- if ((io_base) && (temp_ulong <= 0x10000)) {
- io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!io_node)
- return -ENOMEM;
-
- io_node->base = (ulong)io_base;
- io_node->length = (ulong)io_length;
- dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length);
-
- if (!populated_slot) {
- io_node->next = ctrl->io_head;
- ctrl->io_head = io_node;
- } else {
- io_node->next = func->io_head;
- func->io_head = io_node;
- }
- }
-
- /* If we've got a valid memory base, use it */
- temp_ulong = mem_base + mem_length;
- if ((mem_base) && (temp_ulong <= 0x10000)) {
- mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!mem_node)
- return -ENOMEM;
-
- mem_node->base = (ulong)mem_base << 16;
- mem_node->length = (ulong)(mem_length << 16);
- dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length);
-
- if (!populated_slot) {
- mem_node->next = ctrl->mem_head;
- ctrl->mem_head = mem_node;
- } else {
- mem_node->next = func->mem_head;
- func->mem_head = mem_node;
- }
- }
-
- /*
- * If we've got a valid prefetchable memory base, and
- * the base + length isn't greater than 0xFFFF
- */
- temp_ulong = pre_mem_base + pre_mem_length;
- if ((pre_mem_base) && (temp_ulong <= 0x10000)) {
- p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!p_mem_node)
- return -ENOMEM;
-
- p_mem_node->base = (ulong)pre_mem_base << 16;
- p_mem_node->length = (ulong)pre_mem_length << 16;
- dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length);
-
- if (!populated_slot) {
- p_mem_node->next = ctrl->p_mem_head;
- ctrl->p_mem_head = p_mem_node;
- } else {
- p_mem_node->next = func->p_mem_head;
- func->p_mem_head = p_mem_node;
- }
- }
-
- /*
- * If we've got a valid bus number, use it
- * The second condition is to ignore bus numbers on
- * populated slots that don't have PCI-PCI bridges
- */
- if (secondary_bus && (secondary_bus != primary_bus)) {
- bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!bus_node)
- return -ENOMEM;
-
- bus_node->base = (ulong)secondary_bus;
- bus_node->length = (ulong)(max_bus - secondary_bus + 1);
- dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length);
-
- if (!populated_slot) {
- bus_node->next = ctrl->bus_head;
- ctrl->bus_head = bus_node;
- } else {
- bus_node->next = func->bus_head;
- func->bus_head = bus_node;
- }
- }
-
- i--;
- one_slot += sizeof(struct slot_rt);
- }
-
- /* If all of the following fail, we don't have any resources for hot plug add */
- rc = 1;
- rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head));
- rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
- rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head));
- rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
- return (rc);
+ return;
}
-int shpchprm_set_hpp(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
-{
- u32 rc;
- u8 temp_byte;
- struct pci_bus lpci_bus, *pci_bus;
- unsigned int devfn;
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- temp_byte = 0x40; /* hard coded value for LT */
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- /* set subordinate Latency Timer */
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
- if (rc) {
- dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus,
- func->device, func->function);
- return rc;
- }
- }
-
- /* set base Latency Timer */
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
- if (rc) {
- dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
- return rc;
- }
-
- /* set Cache Line size */
- temp_byte = 0x08; /* hard coded value for CLS */
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
- if (rc) {
- dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
- }
-
- /* set enable_perr */
- /* set enable_serr */
-
- return rc;
-}
-
-void shpchprm_enable_card(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
-{
- u16 command, bcommand;
- struct pci_bus lpci_bus, *pci_bus;
- unsigned int devfn;
- int rc;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
- command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
- | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
- | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
-
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
- bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
- | PCI_BRIDGE_CTL_NO_ISA;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
- }
-}
-
-static int legacy_shpchprm_init_pci(void)
-{
- shpchp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
- if (!shpchp_rom_start) {
- err("Could not ioremap memory region for ROM\n");
- return -EIO;
- }
-
- return 0;
-}
-
-int shpchprm_init(enum php_ctlr_type ctrl_type)
-{
- int retval;
-
- switch (ctrl_type) {
- case PCI:
- retval = legacy_shpchprm_init_pci();
- break;
- default:
- retval = -ENODEV;
- break;
- }
-
- return retval;
-}
diff --git a/drivers/pci/hotplug/shpchprm_legacy.h b/drivers/pci/hotplug/shpchprm_legacy.h
deleted file mode 100644
index 21bda74ddfa..00000000000
--- a/drivers/pci/hotplug/shpchprm_legacy.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform using HRT
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
- *
- */
-
-#ifndef _SHPCHPRM_LEGACY_H_
-#define _SHPCHPRM_LEGACY_H_
-
-#define ROM_PHY_ADDR 0x0F0000
-#define ROM_PHY_LEN 0x00FFFF
-
-struct slot_rt {
- u8 dev_func;
- u8 primary_bus;
- u8 secondary_bus;
- u8 max_bus;
- u16 io_base;
- u16 io_length;
- u16 mem_base;
- u16 mem_length;
- u16 pre_mem_base;
- u16 pre_mem_length;
-} __attribute__ ((packed));
-
-/* offsets to the hotplug slot resource table registers based on the above structure layout */
-enum slot_rt_offsets {
- DEV_FUNC = offsetof(struct slot_rt, dev_func),
- PRIMARY_BUS = offsetof(struct slot_rt, primary_bus),
- SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus),
- MAX_BUS = offsetof(struct slot_rt, max_bus),
- IO_BASE = offsetof(struct slot_rt, io_base),
- IO_LENGTH = offsetof(struct slot_rt, io_length),
- MEM_BASE = offsetof(struct slot_rt, mem_base),
- MEM_LENGTH = offsetof(struct slot_rt, mem_length),
- PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base),
- PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length),
-};
-
-struct hrt {
- char sig0;
- char sig1;
- char sig2;
- char sig3;
- u16 unused_IRQ;
- u16 PCIIRQ;
- u8 number_of_entries;
- u8 revision;
- u16 reserved1;
- u32 reserved2;
-} __attribute__ ((packed));
-
-/* offsets to the hotplug resource table registers based on the above structure layout */
-enum hrt_offsets {
- SIG0 = offsetof(struct hrt, sig0),
- SIG1 = offsetof(struct hrt, sig1),
- SIG2 = offsetof(struct hrt, sig2),
- SIG3 = offsetof(struct hrt, sig3),
- UNUSED_IRQ = offsetof(struct hrt, unused_IRQ),
- PCIIRQ = offsetof(struct hrt, PCIIRQ),
- NUMBER_OF_ENTRIES = offsetof(struct hrt, number_of_entries),
- REVISION = offsetof(struct hrt, revision),
- HRT_RESERVED1 = offsetof(struct hrt, reserved1),
- HRT_RESERVED2 = offsetof(struct hrt, reserved2),
-};
-
-struct irq_info {
- u8 bus, devfn; /* bus, device and function */
- struct {
- u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
- u16 bitmap; /* Available IRQs */
- } __attribute__ ((packed)) irq[4];
- u8 slot; /* slot number, 0=onboard */
- u8 rfu;
-} __attribute__ ((packed));
-
-struct irq_routing_table {
- u32 signature; /* PIRQ_SIGNATURE should be here */
- u16 version; /* PIRQ_VERSION */
- u16 size; /* Table size in bytes */
- u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
- u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
- u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
- u32 miniport_data; /* Crap */
- u8 rfu[11];
- u8 checksum; /* Modulo 256 checksum must give zero */
- struct irq_info slots[0];
-} __attribute__ ((packed));
-
-#endif /* _SHPCHPRM_LEGACY_H_ */
diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.c b/drivers/pci/hotplug/shpchprm_nonacpi.c
index 5f75ef7f3df..c6b40998eeb 100644
--- a/drivers/pci/hotplug/shpchprm_nonacpi.c
+++ b/drivers/pci/hotplug/shpchprm_nonacpi.c
@@ -32,24 +32,9 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
-#include "shpchp.h"
-#include "shpchprm.h"
-#include "shpchprm_nonacpi.h"
+#include <linux/slab.h>
-void shpchprm_cleanup(void)
-{
- return;
-}
-
-int shpchprm_print_pirt(void)
-{
- return 0;
-}
+#include "shpchp.h"
int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
{
@@ -60,375 +45,13 @@ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn
return 0;
}
-static void print_pci_resource ( struct pci_resource *aprh)
-{
- struct pci_resource *res;
-
- for (res = aprh; res; res = res->next)
- dbg(" base= 0x%x length= 0x%x\n", res->base, res->length);
-}
-
-
-static void phprm_dump_func_res( struct pci_func *fun)
-{
- struct pci_func *func = fun;
-
- if (func->bus_head) {
- dbg(": BUS Resources:\n");
- print_pci_resource (func->bus_head);
- }
- if (func->io_head) {
- dbg(": IO Resources:\n");
- print_pci_resource (func->io_head);
- }
- if (func->mem_head) {
- dbg(": MEM Resources:\n");
- print_pci_resource (func->mem_head);
- }
- if (func->p_mem_head) {
- dbg(": PMEM Resources:\n");
- print_pci_resource (func->p_mem_head);
- }
-}
-
-static int phprm_get_used_resources (
- struct controller *ctrl,
- struct pci_func *func
- )
-{
- return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);
-}
-
-static int phprm_delete_resource(
- struct pci_resource **aprh,
- ulong base,
- ulong size)
-{
- struct pci_resource *res;
- struct pci_resource *prevnode;
- struct pci_resource *split_node;
- ulong tbase;
-
- shpchp_resource_sort_and_combine(aprh);
-
- for (res = *aprh; res; res = res->next) {
- if (res->base > base)
- continue;
-
- if ((res->base + res->length) < (base + size))
- continue;
-
- if (res->base < base) {
- tbase = base;
-
- if ((res->length - (tbase - res->base)) < size)
- continue;
-
- split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base;
- split_node->length = tbase - res->base;
- res->base = tbase;
- res->length -= split_node->length;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (res->length >= size) {
- split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base + size;
- split_node->length = res->length - size;
- res->length = size;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (*aprh == res) {
- *aprh = res->next;
- } else {
- prevnode = *aprh;
- while (prevnode->next != res)
- prevnode = prevnode->next;
-
- prevnode->next = res->next;
- }
- res->next = NULL;
- kfree(res);
- break;
- }
-
- return 0;
-}
-
-
-static int phprm_delete_resources(
- struct pci_resource **aprh,
- struct pci_resource *this
- )
-{
- struct pci_resource *res;
-
- for (res = this; res; res = res->next)
- phprm_delete_resource(aprh, res->base, res->length);
-
- return 0;
-}
-
-
-static int configure_existing_function(
- struct controller *ctrl,
- struct pci_func *func
- )
-{
- int rc;
-
- /* see how much resources the func has used. */
- rc = phprm_get_used_resources (ctrl, func);
-
- if (!rc) {
- /* subtract the resources used by the func from ctrl resources */
- rc = phprm_delete_resources (&ctrl->bus_head, func->bus_head);
- rc |= phprm_delete_resources (&ctrl->io_head, func->io_head);
- rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head);
- rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
- if (rc)
- warn("aCEF: cannot del used resources\n");
- } else
- err("aCEF: cannot get used resources\n");
-
- return rc;
-}
-
-static int bind_pci_resources_to_slots ( struct controller *ctrl)
-{
- struct pci_func *func, new_func;
- int busn = ctrl->slot_bus;
- int devn, funn;
- u32 vid;
-
- for (devn = 0; devn < 32; devn++) {
- for (funn = 0; funn < 8; funn++) {
- /*
- if (devn == ctrl->device && funn == ctrl->function)
- continue;
- */
- /* find out if this entry is for an occupied slot */
- vid = 0xFFFFFFFF;
-
- pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
-
- if (vid != 0xFFFFFFFF) {
- func = shpchp_slot_find(busn, devn, funn);
- if (!func) {
- memset(&new_func, 0, sizeof(struct pci_func));
- new_func.bus = busn;
- new_func.device = devn;
- new_func.function = funn;
- new_func.is_a_board = 1;
- configure_existing_function(ctrl, &new_func);
- phprm_dump_func_res(&new_func);
- } else {
- configure_existing_function(ctrl, func);
- phprm_dump_func_res(func);
- }
- dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
- }
- }
- }
-
- return 0;
-}
-
-static void phprm_dump_ctrl_res( struct controller *ctlr)
-{
- struct controller *ctrl = ctlr;
-
- if (ctrl->bus_head) {
- dbg(": BUS Resources:\n");
- print_pci_resource (ctrl->bus_head);
- }
- if (ctrl->io_head) {
- dbg(": IO Resources:\n");
- print_pci_resource (ctrl->io_head);
- }
- if (ctrl->mem_head) {
- dbg(": MEM Resources:\n");
- print_pci_resource (ctrl->mem_head);
- }
- if (ctrl->p_mem_head) {
- dbg(": PMEM Resources:\n");
- print_pci_resource (ctrl->p_mem_head);
- }
-}
-
-/*
- * phprm_find_available_resources
- *
- * Finds available memory, IO, and IRQ resources for programming
- * devices which may be added to the system
- * this function is for hot plug ADD!
- *
- * returns 0 if success
- */
-int shpchprm_find_available_resources(struct controller *ctrl)
-{
- struct pci_func func;
- u32 rc;
-
- memset(&func, 0, sizeof(struct pci_func));
-
- func.bus = ctrl->bus;
- func.device = ctrl->device;
- func.function = ctrl->function;
- func.is_a_board = 1;
-
- /* Get resources for this PCI bridge */
- rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD);
- dbg("%s: shpchp_save_used_resources rc = %d\n", __FUNCTION__, rc);
-
- if (func.mem_head)
- func.mem_head->next = ctrl->mem_head;
- ctrl->mem_head = func.mem_head;
-
- if (func.p_mem_head)
- func.p_mem_head->next = ctrl->p_mem_head;
- ctrl->p_mem_head = func.p_mem_head;
-
- if (func.io_head)
- func.io_head->next = ctrl->io_head;
- ctrl->io_head = func.io_head;
-
- if(func.bus_head)
- func.bus_head->next = ctrl->bus_head;
- ctrl->bus_head = func.bus_head;
- if (ctrl->bus_head)
- phprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1);
-
- dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
- phprm_dump_ctrl_res(ctrl);
- bind_pci_resources_to_slots (ctrl);
-
- dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
- phprm_dump_ctrl_res(ctrl);
-
-
- /* If all of the following fail, we don't have any resources for hot plug add */
- rc = 1;
- rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head));
- rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
- rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head));
- rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
- return (rc);
-}
-
-int shpchprm_set_hpp(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
+void get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
{
- u32 rc;
- u8 temp_byte;
- struct pci_bus lpci_bus, *pci_bus;
- unsigned int devfn;
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- temp_byte = 0x40; /* hard coded value for LT */
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- /* set subordinate Latency Timer */
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
-
- if (rc) {
- dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus,
- func->device, func->function);
- return rc;
- }
- }
-
- /* set base Latency Timer */
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
-
- if (rc) {
- dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
- return rc;
- }
-
- /* set Cache Line size */
- temp_byte = 0x08; /* hard coded value for CLS */
-
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
-
- if (rc) {
- dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
- }
-
- /* set enable_perr */
- /* set enable_serr */
-
- return rc;
-}
-
-void shpchprm_enable_card(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
-{
- u16 command, bcommand;
- struct pci_bus lpci_bus, *pci_bus;
- unsigned int devfn;
- int rc;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
-
- command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
- | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
- | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
-
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
-
- bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
- | PCI_BRIDGE_CTL_NO_ISA;
-
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
- }
-}
-
-static int legacy_shpchprm_init_pci(void)
-{
- return 0;
+ return;
}
-int shpchprm_init(enum php_ctlr_type ctrl_type)
+void get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
- int retval;
-
- switch (ctrl_type) {
- case PCI:
- retval = legacy_shpchprm_init_pci();
- break;
- default:
- retval = -ENODEV;
- break;
- }
-
- return retval;
+ return;
}
diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.h b/drivers/pci/hotplug/shpchprm_nonacpi.h
deleted file mode 100644
index cddaaa5ee1b..00000000000
--- a/drivers/pci/hotplug/shpchprm_nonacpi.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
- *
- */
-
-#ifndef _SHPCHPRM_NONACPI_H_
-#define _SHPCHPRM_NONACPI_H_
-
-struct irq_info {
- u8 bus, devfn; /* bus, device and function */
- struct {
- u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
- u16 bitmap; /* Available IRQs */
- } __attribute__ ((packed)) irq[4];
- u8 slot; /* slot number, 0=onboard */
- u8 rfu;
-} __attribute__ ((packed));
-
-struct irq_routing_table {
- u32 signature; /* PIRQ_SIGNATURE should be here */
- u16 version; /* PIRQ_VERSION */
- u16 size; /* Table size in bytes */
- u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
- u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
- u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
- u32 miniport_data; /* Crap */
- u8 rfu[11];
- u8 checksum; /* Modulo 256 checksum must give zero */
- struct irq_info slots[0];
-} __attribute__ ((packed));
-
-#endif /* _SHPCHPRM_NONACPI_H_ */
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index ee8677bda95..a2033552423 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -575,6 +575,8 @@ static int msi_capability_init(struct pci_dev *dev)
/**
* msix_capability_init - configure device's MSI-X capability
* @dev: pointer to the pci_dev data structure of MSI-X device function
+ * @entries: pointer to an array of struct msix_entry entries
+ * @nvec: number of @entries
*
* Setup the MSI-X capability structure of device function with a
* single MSI-X vector. A return of zero indicates the successful setup of
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 0d0d533894e..ae986e590b4 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -8,6 +8,8 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/mempolicy.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "pci.h"
/*
@@ -26,7 +28,10 @@ struct pci_dynid {
#ifdef CONFIG_HOTPLUG
/**
- * store_new_id
+ * store_new_id - add a new PCI device ID to this driver and re-probe devices
+ * @driver: target device driver
+ * @buf: buffer for scanning device ID data
+ * @count: input size
*
* Adds a new dynamic pci device ID to this driver,
* and causes the driver to probe for all devices again.
@@ -194,8 +199,10 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
/**
* __pci_device_probe()
+ * @drv: driver to call to check if it wants the PCI device
+ * @pci_dev: PCI device being probed
*
- * returns 0 on success, else error.
+ * returns 0 on success, else error.
* side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
*/
static int
@@ -377,6 +384,10 @@ int pci_register_driver(struct pci_driver *drv)
* the pci shutdown function, this test can go away. */
if (!drv->driver.shutdown)
drv->driver.shutdown = pci_device_shutdown;
+ else
+ printk(KERN_WARNING "Warning: PCI driver %s has a struct "
+ "device_driver shutdown method, please update!\n",
+ drv->name);
drv->driver.owner = drv->owner;
drv->driver.kobj.ktype = &pci_driver_kobj_type;
@@ -436,11 +447,11 @@ pci_dev_driver(const struct pci_dev *dev)
/**
* pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
- * @ids: array of PCI device id structures to search in
* @dev: the PCI device structure to match against
+ * @drv: the device driver to search for matching PCI device id structures
*
* Used by a driver to check whether a PCI device present in the
- * system is in its list of supported devices.Returns the matching
+ * system is in its list of supported devices. Returns the matching
* pci_device_id structure or %NULL if there is no match.
*/
static int pci_bus_match(struct device *dev, struct device_driver *drv)
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 2898830c496..965a5934623 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -130,7 +130,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
if ((off & 1) && size) {
u8 val;
- pci_read_config_byte(dev, off, &val);
+ pci_user_read_config_byte(dev, off, &val);
data[off - init_off] = val;
off++;
size--;
@@ -138,7 +138,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
if ((off & 3) && size > 2) {
u16 val;
- pci_read_config_word(dev, off, &val);
+ pci_user_read_config_word(dev, off, &val);
data[off - init_off] = val & 0xff;
data[off - init_off + 1] = (val >> 8) & 0xff;
off += 2;
@@ -147,7 +147,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
while (size > 3) {
u32 val;
- pci_read_config_dword(dev, off, &val);
+ pci_user_read_config_dword(dev, off, &val);
data[off - init_off] = val & 0xff;
data[off - init_off + 1] = (val >> 8) & 0xff;
data[off - init_off + 2] = (val >> 16) & 0xff;
@@ -158,7 +158,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
if (size >= 2) {
u16 val;
- pci_read_config_word(dev, off, &val);
+ pci_user_read_config_word(dev, off, &val);
data[off - init_off] = val & 0xff;
data[off - init_off + 1] = (val >> 8) & 0xff;
off += 2;
@@ -167,7 +167,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
if (size > 0) {
u8 val;
- pci_read_config_byte(dev, off, &val);
+ pci_user_read_config_byte(dev, off, &val);
data[off - init_off] = val;
off++;
--size;
@@ -192,7 +192,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
}
if ((off & 1) && size) {
- pci_write_config_byte(dev, off, data[off - init_off]);
+ pci_user_write_config_byte(dev, off, data[off - init_off]);
off++;
size--;
}
@@ -200,7 +200,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
if ((off & 3) && size > 2) {
u16 val = data[off - init_off];
val |= (u16) data[off - init_off + 1] << 8;
- pci_write_config_word(dev, off, val);
+ pci_user_write_config_word(dev, off, val);
off += 2;
size -= 2;
}
@@ -210,7 +210,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
val |= (u32) data[off - init_off + 1] << 8;
val |= (u32) data[off - init_off + 2] << 16;
val |= (u32) data[off - init_off + 3] << 24;
- pci_write_config_dword(dev, off, val);
+ pci_user_write_config_dword(dev, off, val);
off += 4;
size -= 4;
}
@@ -218,13 +218,13 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
if (size >= 2) {
u16 val = data[off - init_off];
val |= (u16) data[off - init_off + 1] << 8;
- pci_write_config_word(dev, off, val);
+ pci_user_write_config_word(dev, off, val);
off += 2;
size -= 2;
}
if (size) {
- pci_write_config_byte(dev, off, data[off - init_off]);
+ pci_user_write_config_byte(dev, off, data[off - init_off]);
off++;
--size;
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 259d247b755..e74d7584304 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -15,6 +15,7 @@
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/string.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
@@ -252,6 +253,8 @@ pci_restore_bars(struct pci_dev *dev)
pci_update_resource(dev, &dev->resource[i], i);
}
+int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
+
/**
* pci_set_power_state - Set the power state of a PCI device
* @dev: PCI device to be suspended
@@ -266,7 +269,6 @@ pci_restore_bars(struct pci_dev *dev)
* -EIO if device does not support PCI PM.
* 0 if we can successfully change the power state.
*/
-int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
int
pci_set_power_state(struct pci_dev *dev, pci_power_t state)
{
@@ -314,19 +316,19 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
* sets PowerState to 0.
*/
switch (dev->current_state) {
+ case PCI_D0:
+ case PCI_D1:
+ case PCI_D2:
+ pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+ pmcsr |= state;
+ break;
case PCI_UNKNOWN: /* Boot-up */
if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
&& !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
need_restore = 1;
/* Fall-through: force to D0 */
- case PCI_D3hot:
- case PCI_D3cold:
- case PCI_POWER_ERROR:
- pmcsr = 0;
- break;
default:
- pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
- pmcsr |= state;
+ pmcsr = 0;
break;
}
@@ -808,8 +810,8 @@ pci_clear_mwi(struct pci_dev *dev)
/**
* pci_intx - enables/disables PCI INTx for device dev
- * @dev: the PCI device to operate on
- * @enable: boolean
+ * @pdev: the PCI device to operate on
+ * @enable: boolean: whether to enable or disable PCI INTx
*
* Enables/disables PCI INTx for device dev
*/
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index d3f3dd42240..6527b36c9a6 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -15,6 +15,13 @@ extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);
+extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
+extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
+extern int pci_user_read_config_dword(struct pci_dev *dev, int where, u32 *val);
+extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val);
+extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val);
+extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
+
/* PCI /proc functions */
#ifdef CONFIG_PROC_FS
extern int pci_proc_attach_device(struct pci_dev *dev);
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 393e0cee91a..467a4ceccf1 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -11,6 +11,8 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/pm.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include <linux/pcieport_if.h>
#include "portdrv.h"
@@ -61,7 +63,7 @@ static int pcie_port_remove_service(struct device *dev)
static void pcie_port_shutdown_service(struct device *dev) {}
-static int pcie_port_suspend_service(struct device *dev, pm_message_t state, u32 level)
+static int pcie_port_suspend_service(struct device *dev, pm_message_t state)
{
struct pcie_device *pciedev;
struct pcie_port_service_driver *driver;
@@ -76,7 +78,7 @@ static int pcie_port_suspend_service(struct device *dev, pm_message_t state, u32
return 0;
}
-static int pcie_port_resume_service(struct device *dev, u32 level)
+static int pcie_port_resume_service(struct device *dev)
{
struct pcie_device *pciedev;
struct pcie_port_service_driver *driver;
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 3c565ce7f77..02260141dc8 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -12,6 +12,7 @@
#include <linux/errno.h>
#include <linux/pm.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/pcieport_if.h>
#include "portdrv.h"
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 005786416bb..fce2cb2112d 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -669,6 +669,7 @@ static void pci_release_dev(struct device *dev)
/**
* pci_cfg_space_size - get the configuration space size of the PCI device.
+ * @dev: PCI device
*
* Regular PCI devices have 256 bytes, but PCI-X 2 and PCI Express devices
* have 4096 bytes. Even if the device is capable, that doesn't mean we can
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 9613f666c11..9eb465727fc 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -80,7 +80,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if ((pos & 1) && cnt) {
unsigned char val;
- pci_read_config_byte(dev, pos, &val);
+ pci_user_read_config_byte(dev, pos, &val);
__put_user(val, buf);
buf++;
pos++;
@@ -89,7 +89,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if ((pos & 3) && cnt > 2) {
unsigned short val;
- pci_read_config_word(dev, pos, &val);
+ pci_user_read_config_word(dev, pos, &val);
__put_user(cpu_to_le16(val), (unsigned short __user *) buf);
buf += 2;
pos += 2;
@@ -98,7 +98,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
while (cnt >= 4) {
unsigned int val;
- pci_read_config_dword(dev, pos, &val);
+ pci_user_read_config_dword(dev, pos, &val);
__put_user(cpu_to_le32(val), (unsigned int __user *) buf);
buf += 4;
pos += 4;
@@ -107,7 +107,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if (cnt >= 2) {
unsigned short val;
- pci_read_config_word(dev, pos, &val);
+ pci_user_read_config_word(dev, pos, &val);
__put_user(cpu_to_le16(val), (unsigned short __user *) buf);
buf += 2;
pos += 2;
@@ -116,7 +116,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if (cnt) {
unsigned char val;
- pci_read_config_byte(dev, pos, &val);
+ pci_user_read_config_byte(dev, pos, &val);
__put_user(val, buf);
buf++;
pos++;
@@ -151,7 +151,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if ((pos & 1) && cnt) {
unsigned char val;
__get_user(val, buf);
- pci_write_config_byte(dev, pos, val);
+ pci_user_write_config_byte(dev, pos, val);
buf++;
pos++;
cnt--;
@@ -160,7 +160,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if ((pos & 3) && cnt > 2) {
unsigned short val;
__get_user(val, (unsigned short __user *) buf);
- pci_write_config_word(dev, pos, le16_to_cpu(val));
+ pci_user_write_config_word(dev, pos, le16_to_cpu(val));
buf += 2;
pos += 2;
cnt -= 2;
@@ -169,7 +169,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
while (cnt >= 4) {
unsigned int val;
__get_user(val, (unsigned int __user *) buf);
- pci_write_config_dword(dev, pos, le32_to_cpu(val));
+ pci_user_write_config_dword(dev, pos, le32_to_cpu(val));
buf += 4;
pos += 4;
cnt -= 4;
@@ -178,7 +178,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if (cnt >= 2) {
unsigned short val;
__get_user(val, (unsigned short __user *) buf);
- pci_write_config_word(dev, pos, le16_to_cpu(val));
+ pci_user_write_config_word(dev, pos, le16_to_cpu(val));
buf += 2;
pos += 2;
cnt -= 2;
@@ -187,7 +187,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if (cnt) {
unsigned char val;
__get_user(val, buf);
- pci_write_config_byte(dev, pos, val);
+ pci_user_write_config_byte(dev, pos, val);
buf++;
pos++;
cnt--;
@@ -484,10 +484,10 @@ static int show_dev_config(struct seq_file *m, void *v)
drv = pci_dev_driver(dev);
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
- pci_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
- pci_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
+ pci_user_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ pci_user_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
+ pci_user_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
+ pci_user_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
seq_printf(m, " Bus %2d, device %3d, function %2d:\n",
dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
seq_printf(m, " Class %04x", class_rev >> 16);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7992bc8cc6a..5627ce1d2b3 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -7,6 +7,9 @@
*
* Copyright (c) 1999 Martin Mares <mj@ucw.cz>
*
+ * Init/reset quirks for USB host controllers should be in the
+ * USB quirks file, where their drivers can access reuse it.
+ *
* The bridge optimization stuff has been removed. If you really
* have a silly BIOS which is unable to set your host bridge right,
* use the PowerTweak utility (see http://powertweak.sourceforge.net).
@@ -353,7 +356,7 @@ static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int
/*
* PIIX4 ACPI: Two IO regions pointed to by longwords at
* 0x40 (64 bytes of ACPI registers)
- * 0x90 (32 bytes of SMB registers)
+ * 0x90 (16 bytes of SMB registers)
* and a few strange programmable PIIX4 device resources.
*/
static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
@@ -363,7 +366,7 @@ static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
pci_read_config_dword(dev, 0x40, &region);
quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI");
pci_read_config_dword(dev, 0x90, &region);
- quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB");
+ quirk_io_region(dev, region, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB");
/* Device resource A has enables for some of the other ones */
pci_read_config_dword(dev, 0x5c, &res_a);
@@ -414,6 +417,18 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12,
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, quirk_ich4_lpc_acpi );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, quirk_ich4_lpc_acpi );
+static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev)
+{
+ u32 region;
+
+ pci_read_config_dword(dev, 0x40, &region);
+ quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO");
+
+ pci_read_config_dword(dev, 0x48, &region);
+ quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi );
+
/*
* VIA ACPI: One IO region pointed to by longword at
* 0x48 or 0x20 (256 bytes of ACPI registers)
@@ -633,28 +648,6 @@ static void quirk_via_irq(struct pci_dev *dev)
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
/*
- * PIIX3 USB: We have to disable USB interrupts that are
- * hardwired to PIRQD# and may be shared with an
- * external device.
- *
- * Legacy Support Register (LEGSUP):
- * bit13: USB PIRQ Enable (USBPIRQDEN),
- * bit4: Trap/SMI On IRQ Enable (USBSMIEN).
- *
- * We mask out all r/wc bits, too.
- */
-static void __devinit quirk_piix3_usb(struct pci_dev *dev)
-{
- u16 legsup;
-
- pci_read_config_word(dev, 0xc0, &legsup);
- legsup &= 0x50ef;
- pci_write_config_word(dev, 0xc0, legsup);
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_2, quirk_piix3_usb );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_2, quirk_piix3_usb );
-
-/*
* VIA VT82C598 has its device ID settable and many BIOSes
* set it to the ID of VT82C597 for backward compatibility.
* We need to switch it off to be able to recognize the real
@@ -922,6 +915,12 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
case 0x186a: /* M6Ne notebook */
asus_hides_smbus = 1;
}
+ if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
+ switch (dev->subsystem_device) {
+ case 0x1882: /* M6V notebook */
+ asus_hides_smbus = 1;
+ }
+ }
} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_HP)) {
if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
switch(dev->subsystem_device) {
@@ -932,6 +931,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)
switch (dev->subsystem_device) {
case 0x12bc: /* HP D330L */
+ case 0x12bd: /* HP D530 */
asus_hides_smbus = 1;
}
} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) {
@@ -966,6 +966,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB, asus
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, asus_hides_smbus_hostbridge );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge );
static void __init asus_hides_smbus_lpc(struct pci_dev *dev)
{
@@ -990,6 +991,23 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, as
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
+static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
+{
+ u32 val, rcba;
+ void __iomem *base;
+
+ if (likely(!asus_hides_smbus))
+ return;
+ pci_read_config_dword(dev, 0xF0, &rcba);
+ base = ioremap_nocache(rcba & 0xFFFFC000, 0x4000); /* use bits 31:14, 16 kB aligned */
+ if (base == NULL) return;
+ val=readl(base + 0x3418); /* read the Function Disable register, dword mode only */
+ writel(val & 0xFFFFFFF7, base + 0x3418); /* enable the SMBus device */
+ iounmap(base);
+ printk(KERN_INFO "PCI: Enabled ICH6/i801 SMBus device\n");
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
+
/*
* SiS 96x south bridge: BIOS typically hides SMBus device...
*/
@@ -1002,234 +1020,6 @@ static void __init quirk_sis_96x_smbus(struct pci_dev *dev)
pci_read_config_byte(dev, 0x77, &val);
}
-
-#define UHCI_USBLEGSUP 0xc0 /* legacy support */
-#define UHCI_USBCMD 0 /* command register */
-#define UHCI_USBSTS 2 /* status register */
-#define UHCI_USBINTR 4 /* interrupt register */
-#define UHCI_USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */
-#define UHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */
-#define UHCI_USBCMD_GRESET (1 << 2) /* Global reset */
-#define UHCI_USBCMD_CONFIGURE (1 << 6) /* config semaphore */
-#define UHCI_USBSTS_HALTED (1 << 5) /* HCHalted bit */
-
-#define OHCI_CONTROL 0x04
-#define OHCI_CMDSTATUS 0x08
-#define OHCI_INTRSTATUS 0x0c
-#define OHCI_INTRENABLE 0x10
-#define OHCI_INTRDISABLE 0x14
-#define OHCI_OCR (1 << 3) /* ownership change request */
-#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
-#define OHCI_INTR_OC (1 << 30) /* ownership change */
-
-#define EHCI_HCC_PARAMS 0x08 /* extended capabilities */
-#define EHCI_USBCMD 0 /* command register */
-#define EHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */
-#define EHCI_USBSTS 4 /* status register */
-#define EHCI_USBSTS_HALTED (1 << 12) /* HCHalted bit */
-#define EHCI_USBINTR 8 /* interrupt register */
-#define EHCI_USBLEGSUP 0 /* legacy support register */
-#define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */
-#define EHCI_USBLEGSUP_OS (1 << 24) /* OS semaphore */
-#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */
-#define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */
-
-int usb_early_handoff __devinitdata = 0;
-static int __init usb_handoff_early(char *str)
-{
- usb_early_handoff = 1;
- return 0;
-}
-__setup("usb-handoff", usb_handoff_early);
-
-static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
-{
- unsigned long base = 0;
- int wait_time, delta;
- u16 val, sts;
- int i;
-
- for (i = 0; i < PCI_ROM_RESOURCE; i++)
- if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
- base = pci_resource_start(pdev, i);
- break;
- }
-
- if (!base)
- return;
-
- /*
- * stop controller
- */
- sts = inw(base + UHCI_USBSTS);
- val = inw(base + UHCI_USBCMD);
- val &= ~(u16)(UHCI_USBCMD_RUN | UHCI_USBCMD_CONFIGURE);
- outw(val, base + UHCI_USBCMD);
-
- /*
- * wait while it stops if it was running
- */
- if ((sts & UHCI_USBSTS_HALTED) == 0)
- {
- wait_time = 1000;
- delta = 100;
-
- do {
- outw(0x1f, base + UHCI_USBSTS);
- udelay(delta);
- wait_time -= delta;
- val = inw(base + UHCI_USBSTS);
- if (val & UHCI_USBSTS_HALTED)
- break;
- } while (wait_time > 0);
- }
-
- /*
- * disable interrupts & legacy support
- */
- outw(0, base + UHCI_USBINTR);
- outw(0x1f, base + UHCI_USBSTS);
- pci_read_config_word(pdev, UHCI_USBLEGSUP, &val);
- if (val & 0xbf)
- pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_DEFAULT);
-
-}
-
-static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
-{
- void __iomem *base;
- int wait_time;
-
- base = ioremap_nocache(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- if (base == NULL) return;
-
- if (readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
- wait_time = 500; /* 0.5 seconds */
- writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
- writel(OHCI_OCR, base + OHCI_CMDSTATUS);
- while (wait_time > 0 &&
- readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
- wait_time -= 10;
- msleep(10);
- }
- }
-
- /*
- * disable interrupts
- */
- writel(~(u32)0, base + OHCI_INTRDISABLE);
- writel(~(u32)0, base + OHCI_INTRSTATUS);
-
- iounmap(base);
-}
-
-static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
-{
- int wait_time, delta;
- void __iomem *base, *op_reg_base;
- u32 hcc_params, val, temp;
- u8 cap_length;
-
- base = ioremap_nocache(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- if (base == NULL) return;
-
- cap_length = readb(base);
- op_reg_base = base + cap_length;
- hcc_params = readl(base + EHCI_HCC_PARAMS);
- hcc_params = (hcc_params >> 8) & 0xff;
- if (hcc_params) {
- pci_read_config_dword(pdev,
- hcc_params + EHCI_USBLEGSUP,
- &val);
- if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
- /*
- * Ok, BIOS is in smm mode, try to hand off...
- */
- pci_read_config_dword(pdev,
- hcc_params + EHCI_USBLEGCTLSTS,
- &temp);
- pci_write_config_dword(pdev,
- hcc_params + EHCI_USBLEGCTLSTS,
- temp | EHCI_USBLEGCTLSTS_SOOE);
- val |= EHCI_USBLEGSUP_OS;
- pci_write_config_dword(pdev,
- hcc_params + EHCI_USBLEGSUP,
- val);
-
- wait_time = 500;
- do {
- msleep(10);
- wait_time -= 10;
- pci_read_config_dword(pdev,
- hcc_params + EHCI_USBLEGSUP,
- &val);
- } while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
- if (!wait_time) {
- /*
- * well, possibly buggy BIOS...
- */
- printk(KERN_WARNING "EHCI early BIOS handoff "
- "failed (BIOS bug ?)\n");
- pci_write_config_dword(pdev,
- hcc_params + EHCI_USBLEGSUP,
- EHCI_USBLEGSUP_OS);
- pci_write_config_dword(pdev,
- hcc_params + EHCI_USBLEGCTLSTS,
- 0);
- }
- }
- }
-
- /*
- * halt EHCI & disable its interrupts in any case
- */
- val = readl(op_reg_base + EHCI_USBSTS);
- if ((val & EHCI_USBSTS_HALTED) == 0) {
- val = readl(op_reg_base + EHCI_USBCMD);
- val &= ~EHCI_USBCMD_RUN;
- writel(val, op_reg_base + EHCI_USBCMD);
-
- wait_time = 2000;
- delta = 100;
- do {
- writel(0x3f, op_reg_base + EHCI_USBSTS);
- udelay(delta);
- wait_time -= delta;
- val = readl(op_reg_base + EHCI_USBSTS);
- if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
- break;
- }
- } while (wait_time > 0);
- }
- writel(0, op_reg_base + EHCI_USBINTR);
- writel(0x3f, op_reg_base + EHCI_USBSTS);
-
- iounmap(base);
-
- return;
-}
-
-
-
-static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
-{
- if (!usb_early_handoff)
- return;
-
- if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x00)) { /* UHCI */
- quirk_usb_handoff_uhci(pdev);
- } else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10)) { /* OHCI */
- quirk_usb_handoff_ohci(pdev);
- } else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x20)) { /* EHCI */
- quirk_usb_disable_ehci(pdev);
- }
-
- return;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
-
/*
* ... This is further complicated by the fact that some SiS96x south
* bridges pretend to be 85C503/5513 instead. In that case see if we
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index 49bd2170231..598a115cd00 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -9,6 +9,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
+#include <linux/slab.h>
#include "pci.h"
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index c071790cc98..87fafc08cb9 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -13,7 +13,7 @@
#include <linux/smp_lock.h>
#include <linux/syscalls.h>
#include <asm/uaccess.h>
-
+#include "pci.h"
asmlinkage long
sys_pciconfig_read(unsigned long bus, unsigned long dfn,
@@ -38,13 +38,13 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
lock_kernel();
switch (len) {
case 1:
- cfg_ret = pci_read_config_byte(dev, off, &byte);
+ cfg_ret = pci_user_read_config_byte(dev, off, &byte);
break;
case 2:
- cfg_ret = pci_read_config_word(dev, off, &word);
+ cfg_ret = pci_user_read_config_word(dev, off, &word);
break;
case 4:
- cfg_ret = pci_read_config_dword(dev, off, &dword);
+ cfg_ret = pci_user_read_config_dword(dev, off, &dword);
break;
default:
err = -EINVAL;
@@ -112,7 +112,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
err = get_user(byte, (u8 __user *)buf);
if (err)
break;
- err = pci_write_config_byte(dev, off, byte);
+ err = pci_user_write_config_byte(dev, off, byte);
if (err != PCIBIOS_SUCCESSFUL)
err = -EIO;
break;
@@ -121,7 +121,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
err = get_user(word, (u16 __user *)buf);
if (err)
break;
- err = pci_write_config_word(dev, off, word);
+ err = pci_user_write_config_word(dev, off, word);
if (err != PCIBIOS_SUCCESSFUL)
err = -EIO;
break;
@@ -130,7 +130,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
err = get_user(dword, (u32 __user *)buf);
if (err)
break;
- err = pci_write_config_dword(dev, off, dword);
+ err = pci_user_write_config_dword(dev, off, dword);
if (err != PCIBIOS_SUCCESSFUL)
err = -EIO;
break;