aboutsummaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/hotplug.c119
-rw-r--r--drivers/pci/hotplug/cpci_hotplug.h2
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_core.c427
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_pci.c480
-rw-r--r--drivers/pci/hotplug/pciehp.h1
-rw-r--r--drivers/pci/hotplug/pciehp_core.c2
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c156
-rw-r--r--drivers/pci/hotplug/shpchp_core.c2
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c30
-rw-r--r--drivers/pci/hotplug/shpchprm_acpi.c4
-rw-r--r--drivers/pci/pci-sysfs.c12
-rw-r--r--drivers/pci/pci.h27
-rw-r--r--drivers/pci/pcie/portdrv_bus.c3
-rw-r--r--drivers/pci/quirks.c40
14 files changed, 421 insertions, 884 deletions
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
index 021d0f76bc4..3903f8c559b 100644
--- a/drivers/pci/hotplug.c
+++ b/drivers/pci/hotplug.c
@@ -52,116 +52,17 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
if ((buffer_size - length <= 0) || (i >= num_envp))
return -ENOMEM;
+ envp[i++] = scratch;
+ length += scnprintf (scratch, buffer_size - length,
+ "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n",
+ pdev->vendor, pdev->device,
+ pdev->subsystem_vendor, pdev->subsystem_device,
+ (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
+ (u8)(pdev->class));
+ if ((buffer_size - length <= 0) || (i >= num_envp))
+ return -ENOMEM;
+
envp[i] = NULL;
return 0;
}
-
-static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_parent)
-{
- struct list_head *ln;
- struct pci_dev *dev;
- struct pci_dev_wrapped wrapped_dev;
- int result = 0;
-
- pr_debug("PCI: Scanning bus %04x:%02x\n", pci_domain_nr(wrapped_bus->bus),
- wrapped_bus->bus->number);
-
- if (fn->pre_visit_pci_bus) {
- result = fn->pre_visit_pci_bus(wrapped_bus, wrapped_parent);
- if (result)
- return result;
- }
-
- ln = wrapped_bus->bus->devices.next;
- while (ln != &wrapped_bus->bus->devices) {
- dev = pci_dev_b(ln);
- ln = ln->next;
-
- memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
- wrapped_dev.dev = dev;
-
- result = pci_visit_dev(fn, &wrapped_dev, wrapped_bus);
- if (result)
- return result;
- }
-
- if (fn->post_visit_pci_bus)
- result = fn->post_visit_pci_bus(wrapped_bus, wrapped_parent);
-
- return result;
-}
-
-static int pci_visit_bridge (struct pci_visit * fn,
- struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_parent)
-{
- struct pci_bus *bus;
- struct pci_bus_wrapped wrapped_bus;
- int result = 0;
-
- pr_debug("PCI: Scanning bridge %s\n", pci_name(wrapped_dev->dev));
-
- if (fn->visit_pci_dev) {
- result = fn->visit_pci_dev(wrapped_dev, wrapped_parent);
- if (result)
- return result;
- }
-
- bus = wrapped_dev->dev->subordinate;
- if (bus) {
- memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
- wrapped_bus.bus = bus;
-
- result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev);
- }
- return result;
-}
-
-/**
- * pci_visit_dev - scans the pci buses.
- * @fn: callback functions that are called while visiting
- * @wrapped_dev: the device to scan
- * @wrapped_parent: the bus where @wrapped_dev is connected to
- *
- * Every bus and every function is presented to a custom
- * function that can act upon it.
- */
-int pci_visit_dev(struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_parent)
-{
- struct pci_dev* dev = wrapped_dev ? wrapped_dev->dev : NULL;
- int result = 0;
-
- if (!dev)
- return 0;
-
- if (fn->pre_visit_pci_dev) {
- result = fn->pre_visit_pci_dev(wrapped_dev, wrapped_parent);
- if (result)
- return result;
- }
-
- switch (dev->class >> 8) {
- case PCI_CLASS_BRIDGE_PCI:
- result = pci_visit_bridge(fn, wrapped_dev,
- wrapped_parent);
- if (result)
- return result;
- break;
- default:
- pr_debug("PCI: Scanning device %s\n", pci_name(dev));
- if (fn->visit_pci_dev) {
- result = fn->visit_pci_dev (wrapped_dev,
- wrapped_parent);
- if (result)
- return result;
- }
- }
-
- if (fn->post_visit_pci_dev)
- result = fn->post_visit_pci_dev(wrapped_dev, wrapped_parent);
-
- return result;
-}
-EXPORT_SYMBOL(pci_visit_dev);
diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h
index 3ddd75937a4..d9769b30be9 100644
--- a/drivers/pci/hotplug/cpci_hotplug.h
+++ b/drivers/pci/hotplug/cpci_hotplug.h
@@ -31,7 +31,7 @@
#include <linux/types.h>
#include <linux/pci.h>
-/* PICMG 2.12 R2.0 HS CSR bits: */
+/* PICMG 2.1 R2.0 HS CSR bits: */
#define HS_CSR_INS 0x0080
#define HS_CSR_EXT 0x0040
#define HS_CSR_PI 0x0030
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index ed243605dc7..8132d946c38 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -1,7 +1,7 @@
/*
* CompactPCI Hot Plug Driver
*
- * Copyright (C) 2002 SOMA Networks, Inc.
+ * Copyright (C) 2002,2005 SOMA Networks, Inc.
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2001 IBM Corp.
*
@@ -33,11 +33,11 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
+#include <asm/atomic.h>
#include <linux/delay.h>
#include "pci_hotplug.h"
#include "cpci_hotplug.h"
-#define DRIVER_VERSION "0.2"
#define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>"
#define DRIVER_DESC "CompactPCI Hot Plug Core"
@@ -45,18 +45,19 @@
#define dbg(format, arg...) \
do { \
- if(cpci_debug) \
+ if (cpci_debug) \
printk (KERN_DEBUG "%s: " format "\n", \
MY_NAME , ## arg); \
- } while(0)
+ } while (0)
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
/* local variables */
-static spinlock_t list_lock;
+static DECLARE_RWSEM(list_rwsem);
static LIST_HEAD(slot_list);
static int slots;
+static atomic_t extracting;
int cpci_debug;
static struct cpci_hp_controller *controller;
static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */
@@ -68,6 +69,8 @@ static int disable_slot(struct hotplug_slot *slot);
static int set_attention_status(struct hotplug_slot *slot, u8 value);
static int get_power_status(struct hotplug_slot *slot, u8 * value);
static int get_attention_status(struct hotplug_slot *slot, u8 * value);
+static int get_adapter_status(struct hotplug_slot *slot, u8 * value);
+static int get_latch_status(struct hotplug_slot *slot, u8 * value);
static struct hotplug_slot_ops cpci_hotplug_slot_ops = {
.owner = THIS_MODULE,
@@ -76,6 +79,8 @@ static struct hotplug_slot_ops cpci_hotplug_slot_ops = {
.set_attention_status = set_attention_status,
.get_power_status = get_power_status,
.get_attention_status = get_attention_status,
+ .get_adapter_status = get_adapter_status,
+ .get_latch_status = get_latch_status,
};
static int
@@ -106,10 +111,8 @@ enable_slot(struct hotplug_slot *hotplug_slot)
dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
- if(controller->ops->set_power) {
+ if (controller->ops->set_power)
retval = controller->ops->set_power(slot, 1);
- }
-
return retval;
}
@@ -121,35 +124,41 @@ disable_slot(struct hotplug_slot *hotplug_slot)
dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
+ down_write(&list_rwsem);
+
/* Unconfigure device */
dbg("%s - unconfiguring slot %s",
__FUNCTION__, slot->hotplug_slot->name);
- if((retval = cpci_unconfigure_slot(slot))) {
+ if ((retval = cpci_unconfigure_slot(slot))) {
err("%s - could not unconfigure slot %s",
__FUNCTION__, slot->hotplug_slot->name);
- return retval;
+ goto disable_error;
}
dbg("%s - finished unconfiguring slot %s",
__FUNCTION__, slot->hotplug_slot->name);
/* Clear EXT (by setting it) */
- if(cpci_clear_ext(slot)) {
+ if (cpci_clear_ext(slot)) {
err("%s - could not clear EXT for slot %s",
__FUNCTION__, slot->hotplug_slot->name);
retval = -ENODEV;
+ goto disable_error;
}
cpci_led_on(slot);
- if(controller->ops->set_power) {
- retval = controller->ops->set_power(slot, 0);
- }
+ if (controller->ops->set_power)
+ if ((retval = controller->ops->set_power(slot, 0)))
+ goto disable_error;
- if(update_adapter_status(slot->hotplug_slot, 0)) {
+ if (update_adapter_status(slot->hotplug_slot, 0))
warn("failure to update adapter file");
- }
-
- slot->extracting = 0;
+ if (slot->extracting) {
+ slot->extracting = 0;
+ atomic_dec(&extracting);
+ }
+disable_error:
+ up_write(&list_rwsem);
return retval;
}
@@ -158,9 +167,8 @@ cpci_get_power_status(struct slot *slot)
{
u8 power = 1;
- if(controller->ops->get_power) {
+ if (controller->ops->get_power)
power = controller->ops->get_power(slot);
- }
return power;
}
@@ -188,6 +196,20 @@ set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
return cpci_set_attention_status(hotplug_slot->private, status);
}
+static int
+get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
+{
+ *value = hotplug_slot->info->adapter_status;
+ return 0;
+}
+
+static int
+get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value)
+{
+ *value = hotplug_slot->info->latch_status;
+ return 0;
+}
+
static void release_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
@@ -216,9 +238,8 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
int status = -ENOMEM;
int i;
- if(!(controller && bus)) {
+ if (!(controller && bus))
return -ENODEV;
- }
/*
* Create a structure for each slot, and register that slot
@@ -273,10 +294,10 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
}
/* Add slot to our internal list */
- spin_lock(&list_lock);
+ down_write(&list_rwsem);
list_add(&slot->slot_list, &slot_list);
slots++;
- spin_unlock(&list_lock);
+ up_write(&list_rwsem);
}
return 0;
error_name:
@@ -295,32 +316,30 @@ int
cpci_hp_unregister_bus(struct pci_bus *bus)
{
struct slot *slot;
- struct list_head *tmp;
- struct list_head *next;
- int status;
+ struct slot *tmp;
+ int status = 0;
- spin_lock(&list_lock);
- if(!slots) {
- spin_unlock(&list_lock);
+ down_write(&list_rwsem);
+ if (!slots) {
+ up_write(&list_rwsem);
return -1;
}
- list_for_each_safe(tmp, next, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
- if(slot->bus == bus) {
+ list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) {
+ if (slot->bus == bus) {
+ list_del(&slot->slot_list);
+ slots--;
+
dbg("deregistering slot %s", slot->hotplug_slot->name);
status = pci_hp_deregister(slot->hotplug_slot);
- if(status) {
+ if (status) {
err("pci_hp_deregister failed with error %d",
status);
- return status;
+ break;
}
-
- list_del(&slot->slot_list);
- slots--;
}
}
- spin_unlock(&list_lock);
- return 0;
+ up_write(&list_rwsem);
+ return status;
}
/* This is the interrupt mode interrupt handler */
@@ -330,7 +349,7 @@ cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
dbg("entered cpci_hp_intr");
/* Check to see if it was our interrupt */
- if((controller->irq_flags & SA_SHIRQ) &&
+ if ((controller->irq_flags & SA_SHIRQ) &&
!controller->ops->check_irq(controller->dev_id)) {
dbg("exited cpci_hp_intr, not our interrupt");
return IRQ_NONE;
@@ -347,46 +366,38 @@ cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
}
/*
- * According to PICMG 2.12 R2.0, section 6.3.2, upon
+ * According to PICMG 2.1 R2.0, section 6.3.2, upon
* initialization, the system driver shall clear the
* INS bits of the cold-inserted devices.
*/
static int
-init_slots(void)
+init_slots(int clear_ins)
{
struct slot *slot;
- struct list_head *tmp;
struct pci_dev* dev;
dbg("%s - enter", __FUNCTION__);
- spin_lock(&list_lock);
- if(!slots) {
- spin_unlock(&list_lock);
+ down_read(&list_rwsem);
+ if (!slots) {
+ up_read(&list_rwsem);
return -1;
}
- list_for_each(tmp, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
+ list_for_each_entry(slot, &slot_list, slot_list) {
dbg("%s - looking at slot %s",
__FUNCTION__, slot->hotplug_slot->name);
- if(cpci_check_and_clear_ins(slot)) {
+ if (clear_ins && cpci_check_and_clear_ins(slot))
dbg("%s - cleared INS for slot %s",
__FUNCTION__, slot->hotplug_slot->name);
- dev = pci_find_slot(slot->bus->number, PCI_DEVFN(slot->number, 0));
- if(dev) {
- if(update_adapter_status(slot->hotplug_slot, 1)) {
- warn("failure to update adapter file");
- }
- if(update_latch_status(slot->hotplug_slot, 1)) {
- warn("failure to update latch file");
- }
- slot->dev = dev;
- } else {
- err("%s - no driver attached to device in slot %s",
- __FUNCTION__, slot->hotplug_slot->name);
- }
+ dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0));
+ if (dev) {
+ if (update_adapter_status(slot->hotplug_slot, 1))
+ warn("failure to update adapter file");
+ if (update_latch_status(slot->hotplug_slot, 1))
+ warn("failure to update latch file");
+ slot->dev = dev;
}
}
- spin_unlock(&list_lock);
+ up_read(&list_rwsem);
dbg("%s - exit", __FUNCTION__);
return 0;
}
@@ -395,27 +406,28 @@ static int
check_slots(void)
{
struct slot *slot;
- struct list_head *tmp;
int extracted;
int inserted;
+ u16 hs_csr;
- spin_lock(&list_lock);
- if(!slots) {
- spin_unlock(&list_lock);
+ down_read(&list_rwsem);
+ if (!slots) {
+ up_read(&list_rwsem);
err("no slots registered, shutting down");
return -1;
}
extracted = inserted = 0;
- list_for_each(tmp, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
+ list_for_each_entry(slot, &slot_list, slot_list) {
dbg("%s - looking at slot %s",
__FUNCTION__, slot->hotplug_slot->name);
- if(cpci_check_and_clear_ins(slot)) {
- u16 hs_csr;
-
- /* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */
- if(slot->dev) {
- warn("slot %s already inserted", slot->hotplug_slot->name);
+ if (cpci_check_and_clear_ins(slot)) {
+ /*
+ * Some broken hardware (e.g. PLX 9054AB) asserts
+ * ENUM# twice...
+ */
+ if (slot->dev) {
+ warn("slot %s already inserted",
+ slot->hotplug_slot->name);
inserted++;
continue;
}
@@ -432,7 +444,7 @@ check_slots(void)
/* Configure device */
dbg("%s - configuring slot %s",
__FUNCTION__, slot->hotplug_slot->name);
- if(cpci_configure_slot(slot)) {
+ if (cpci_configure_slot(slot)) {
err("%s - could not configure slot %s",
__FUNCTION__, slot->hotplug_slot->name);
continue;
@@ -445,13 +457,11 @@ check_slots(void)
dbg("%s - slot %s HS_CSR (2) = %04x",
__FUNCTION__, slot->hotplug_slot->name, hs_csr);
- if(update_latch_status(slot->hotplug_slot, 1)) {
+ if (update_latch_status(slot->hotplug_slot, 1))
warn("failure to update latch file");
- }
- if(update_adapter_status(slot->hotplug_slot, 1)) {
+ if (update_adapter_status(slot->hotplug_slot, 1))
warn("failure to update adapter file");
- }
cpci_led_off(slot);
@@ -461,9 +471,7 @@ check_slots(void)
__FUNCTION__, slot->hotplug_slot->name, hs_csr);
inserted++;
- } else if(cpci_check_ext(slot)) {
- u16 hs_csr;
-
+ } else if (cpci_check_ext(slot)) {
/* Process extraction request */
dbg("%s - slot %s extracted",
__FUNCTION__, slot->hotplug_slot->name);
@@ -473,23 +481,40 @@ check_slots(void)
dbg("%s - slot %s HS_CSR = %04x",
__FUNCTION__, slot->hotplug_slot->name, hs_csr);
- if(!slot->extracting) {
- if(update_latch_status(slot->hotplug_slot, 0)) {
+ if (!slot->extracting) {
+ if (update_latch_status(slot->hotplug_slot, 0)) {
warn("failure to update latch file");
}
slot->extracting = 1;
+ atomic_inc(&extracting);
}
extracted++;
+ } else if (slot->extracting) {
+ hs_csr = cpci_get_hs_csr(slot);
+ if (hs_csr == 0xffff) {
+ /*
+ * Hmmm, we're likely hosed at this point, should we
+ * bother trying to tell the driver or not?
+ */
+ err("card in slot %s was improperly removed",
+ slot->hotplug_slot->name);
+ if (update_adapter_status(slot->hotplug_slot, 0))
+ warn("failure to update adapter file");
+ slot->extracting = 0;
+ atomic_dec(&extracting);
+ }
}
}
- spin_unlock(&list_lock);
- if(inserted || extracted) {
+ up_read(&list_rwsem);
+ dbg("inserted=%d, extracted=%d, extracting=%d",
+ inserted, extracted, atomic_read(&extracting));
+ if (inserted || extracted)
return extracted;
- }
- else {
+ else if (!atomic_read(&extracting)) {
err("cannot find ENUM# source, shutting down");
return -1;
}
+ return 0;
}
/* This is the interrupt mode worker thread body */
@@ -497,54 +522,37 @@ static int
event_thread(void *data)
{
int rc;
- struct slot *slot;
- struct list_head *tmp;
lock_kernel();
daemonize("cpci_hp_eventd");
unlock_kernel();
dbg("%s - event thread started", __FUNCTION__);
- while(1) {
+ while (1) {
dbg("event thread sleeping");
down_interruptible(&event_semaphore);
dbg("event thread woken, thread_finished = %d",
thread_finished);
- if(thread_finished || signal_pending(current))
+ if (thread_finished || signal_pending(current))
break;
- while(controller->ops->query_enum()) {
+ do {
rc = check_slots();
- if (rc > 0)
+ if (rc > 0) {
/* Give userspace a chance to handle extraction */
msleep(500);
- else if (rc < 0) {
+ } else if (rc < 0) {
dbg("%s - error checking slots", __FUNCTION__);
thread_finished = 1;
break;
}
- }
- /* Check for someone yanking out a board */
- list_for_each(tmp, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
- if(slot->extracting) {
- /*
- * Hmmm, we're likely hosed at this point, should we
- * bother trying to tell the driver or not?
- */
- err("card in slot %s was improperly removed",
- slot->hotplug_slot->name);
- if(update_adapter_status(slot->hotplug_slot, 0)) {
- warn("failure to update adapter file");
- }
- slot->extracting = 0;
- }
- }
+ } while (atomic_read(&extracting) && !thread_finished);
+ if (thread_finished)
+ break;
/* Re-enable ENUM# interrupt */
dbg("%s - re-enabling irq", __FUNCTION__);
controller->ops->enable_irq();
}
-
dbg("%s - event thread signals exit", __FUNCTION__);
up(&thread_exit);
return 0;
@@ -555,45 +563,27 @@ static int
poll_thread(void *data)
{
int rc;
- struct slot *slot;
- struct list_head *tmp;
lock_kernel();
daemonize("cpci_hp_polld");
unlock_kernel();
- while(1) {
- if(thread_finished || signal_pending(current))
+ while (1) {
+ if (thread_finished || signal_pending(current))
break;
-
- while(controller->ops->query_enum()) {
- rc = check_slots();
- if(rc > 0)
- /* Give userspace a chance to handle extraction */
- msleep(500);
- else if (rc < 0) {
- dbg("%s - error checking slots", __FUNCTION__);
- thread_finished = 1;
- break;
- }
- }
- /* Check for someone yanking out a board */
- list_for_each(tmp, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
- if(slot->extracting) {
- /*
- * Hmmm, we're likely hosed at this point, should we
- * bother trying to tell the driver or not?
- */
- err("card in slot %s was improperly removed",
- slot->hotplug_slot->name);
- if(update_adapter_status(slot->hotplug_slot, 0)) {
- warn("failure to update adapter file");
+ if (controller->ops->query_enum()) {
+ do {
+ rc = check_slots();
+ if (rc > 0) {
+ /* Give userspace a chance to handle extraction */
+ msleep(500);
+ } else if (rc < 0) {
+ dbg("%s - error checking slots", __FUNCTION__);
+ thread_finished = 1;
+ break;
}
- slot->extracting = 0;
- }
+ } while (atomic_read(&extracting) && !thread_finished);
}
-
msleep(100);
}
dbg("poll thread signals exit");
@@ -611,12 +601,11 @@ cpci_start_thread(void)
init_MUTEX_LOCKED(&thread_exit);
thread_finished = 0;
- if(controller->irq) {
+ if (controller->irq)
pid = kernel_thread(event_thread, NULL, 0);
- } else {
+ else
pid = kernel_thread(poll_thread, NULL, 0);
- }
- if(pid < 0) {
+ if (pid < 0) {
err("Can't start up our thread");
return -1;
}
@@ -629,9 +618,8 @@ cpci_stop_thread(void)
{
thread_finished = 1;
dbg("thread finish command given");
- if(controller->irq) {
+ if (controller->irq)
up(&event_semaphore);
- }
dbg("wait for thread to exit");
down(&thread_exit);
}
@@ -641,42 +629,67 @@ cpci_hp_register_controller(struct cpci_hp_controller *new_controller)
{
int status = 0;
- if(!controller) {
- controller = new_controller;
- if(controller->irq) {
- if(request_irq(controller->irq,
- cpci_hp_intr,
- controller->irq_flags,
- MY_NAME, controller->dev_id)) {
- err("Can't get irq %d for the hotplug cPCI controller", controller->irq);
- status = -ENODEV;
- }
- dbg("%s - acquired controller irq %d", __FUNCTION__,
- controller->irq);
+ if (controller)
+ return -1;
+ if (!(new_controller && new_controller->ops))
+ return -EINVAL;
+ if (new_controller->irq) {
+ if (!(new_controller->ops->enable_irq &&
+ new_controller->ops->disable_irq))
+ status = -EINVAL;
+ if (request_irq(new_controller->irq,
+ cpci_hp_intr,
+ new_controller->irq_flags,
+ MY_NAME,
+ new_controller->dev_id)) {
+ err("Can't get irq %d for the hotplug cPCI controller",
+ new_controller->irq);
+ status = -ENODEV;
}
- } else {
- err("cPCI hotplug controller already registered");
- status = -1;
+ dbg("%s - acquired controller irq %d",
+ __FUNCTION__, new_controller->irq);
}
+ if (!status)
+ controller = new_controller;
return status;
}
+static void
+cleanup_slots(void)
+{
+ struct slot *slot;
+ struct slot *tmp;
+
+ /*
+ * Unregister all of our slots with the pci_hotplug subsystem,
+ * and free up all memory that we had allocated.
+ */
+ down_write(&list_rwsem);
+ if (!slots)
+ goto cleanup_null;
+ list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) {
+ list_del(&slot->slot_list);
+ pci_hp_deregister(slot->hotplug_slot);
+ }
+cleanup_null:
+ up_write(&list_rwsem);
+ return;
+}
+
int
cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller)
{
int status = 0;
- if(controller) {
- if(!thread_finished) {
+ if (controller) {
+ if (!thread_finished)
cpci_stop_thread();
- }
- if(controller->irq) {
+ if (controller->irq)
free_irq(controller->irq, controller->dev_id);
- }
controller = NULL;
- } else {
+ cleanup_slots();
+ } else
status = -ENODEV;
- }
return status;
}
@@ -687,32 +700,28 @@ cpci_hp_start(void)
int status;
dbg("%s - enter", __FUNCTION__);
- if(!controller) {
+ if (!controller)
return -ENODEV;
- }
- spin_lock(&list_lock);
- if(!slots) {
- spin_unlock(&list_lock);
+ down_read(&list_rwsem);
+ if (list_empty(&slot_list)) {
+ up_read(&list_rwsem);
return -ENODEV;
}
- spin_unlock(&list_lock);
+ up_read(&list_rwsem);
- if(first) {
- status = init_slots();
- if(status) {
- return status;
- }
+ status = init_slots(first);
+ if (first)
first = 0;
- }
+ if (status)
+ return status;
status = cpci_start_thread();
- if(status) {
+ if (status)
return status;
- }
dbg("%s - thread started", __FUNCTION__);
- if(controller->irq) {
+ if (controller->irq) {
/* Start enum interrupt processing */
dbg("%s - enabling irq", __FUNCTION__);
controller->ops->enable_irq();
@@ -724,11 +733,9 @@ cpci_hp_start(void)
int
cpci_hp_stop(void)
{
- if(!controller) {
+ if (!controller)
return -ENODEV;
- }
-
- if(controller->irq) {
+ if (controller->irq) {
/* Stop enum interrupt processing */
dbg("%s - disabling irq", __FUNCTION__);
controller->ops->disable_irq();
@@ -737,41 +744,10 @@ cpci_hp_stop(void)
return 0;
}
-static void __exit
-cleanup_slots(void)
-{
- struct list_head *tmp;
- struct slot *slot;
-
- /*
- * Unregister all of our slots with the pci_hotplug subsystem,
- * and free up all memory that we had allocated.
- */
- spin_lock(&list_lock);
- if(!slots) {
- goto null_cleanup;
- }
- list_for_each(tmp, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
- list_del(&slot->slot_list);
- pci_hp_deregister(slot->hotplug_slot);
- kfree(slot->hotplug_slot->info);
- kfree(slot->hotplug_slot->name);
- kfree(slot->hotplug_slot);
- kfree(slot);
- }
- null_cleanup:
- spin_unlock(&list_lock);
- return;
-}
-
int __init
cpci_hotplug_init(int debug)
{
- spin_lock_init(&list_lock);
cpci_debug = debug;
-
- info(DRIVER_DESC " version: " DRIVER_VERSION);
return 0;
}
@@ -781,7 +757,8 @@ cpci_hotplug_exit(void)
/*
* Clean everything up.
*/
- cleanup_slots();
+ cpci_hp_stop();
+ cpci_hp_unregister_controller(controller);
}
EXPORT_SYMBOL_GPL(cpci_hp_register_controller);
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index 2e969616f29..c878028ad21 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -1,7 +1,7 @@
/*
* CompactPCI Hot Plug Driver PCI functions
*
- * Copyright (C) 2002 by SOMA Networks, Inc.
+ * Copyright (C) 2002,2005 by SOMA Networks, Inc.
*
* All rights reserved.
*
@@ -32,20 +32,16 @@
#include "pci_hotplug.h"
#include "cpci_hotplug.h"
-#if !defined(MODULE)
#define MY_NAME "cpci_hotplug"
-#else
-#define MY_NAME THIS_MODULE->name
-#endif
extern int cpci_debug;
#define dbg(format, arg...) \
do { \
- if(cpci_debug) \
+ if (cpci_debug) \
printk (KERN_DEBUG "%s: " format "\n", \
MY_NAME , ## arg); \
- } while(0)
+ } while (0)
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
@@ -61,16 +57,15 @@ u8 cpci_get_attention_status(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return 0;
- }
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return 0;
- }
+
return hs_csr & 0x0008 ? 1 : 0;
}
@@ -82,27 +77,22 @@ int cpci_set_attention_status(struct slot* slot, int status)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return 0;
- }
-
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return 0;
- }
- if(status) {
+ if (status)
hs_csr |= HS_CSR_LOO;
- } else {
+ else
hs_csr &= ~HS_CSR_LOO;
- }
- if(pci_bus_write_config_word(slot->bus,
+ if (pci_bus_write_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- hs_csr)) {
+ hs_csr))
return 0;
- }
return 1;
}
@@ -114,51 +104,16 @@ u16 cpci_get_hs_csr(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return 0xFFFF;
- }
-
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return 0xFFFF;
- }
return hs_csr;
}
-#if 0
-u16 cpci_set_hs_csr(struct slot* slot, u16 hs_csr)
-{
- int hs_cap;
- u16 new_hs_csr;
-
- hs_cap = pci_bus_find_capability(slot->bus,
- slot->devfn,
- PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
- return 0xFFFF;
- }
-
- /* Write out the new value */
- if(pci_bus_write_config_word(slot->bus,
- slot->devfn,
- hs_cap + 2,
- hs_csr)) {
- return 0xFFFF;
- }
-
- /* Read back what we just wrote out */
- if(pci_bus_read_config_word(slot->bus,
- slot->devfn,
- hs_cap + 2,
- &new_hs_csr)) {
- return 0xFFFF;
- }
- return new_hs_csr;
-}
-#endif
-
int cpci_check_and_clear_ins(struct slot* slot)
{
int hs_cap;
@@ -168,24 +123,22 @@ int cpci_check_and_clear_ins(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return 0;
- }
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return 0;
- }
- if(hs_csr & HS_CSR_INS) {
+ if (hs_csr & HS_CSR_INS) {
/* Clear INS (by setting it) */
- if(pci_bus_write_config_word(slot->bus,
+ if (pci_bus_write_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- hs_csr)) {
+ hs_csr))
ins = 0;
- }
- ins = 1;
+ else
+ ins = 1;
}
return ins;
}
@@ -199,18 +152,15 @@ int cpci_check_ext(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return 0;
- }
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return 0;
- }
- if(hs_csr & HS_CSR_EXT) {
+ if (hs_csr & HS_CSR_EXT)
ext = 1;
- }
return ext;
}
@@ -222,23 +172,20 @@ int cpci_clear_ext(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return -ENODEV;
- }
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return -ENODEV;
- }
- if(hs_csr & HS_CSR_EXT) {
+ if (hs_csr & HS_CSR_EXT) {
/* Clear EXT (by setting it) */
- if(pci_bus_write_config_word(slot->bus,
+ if (pci_bus_write_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- hs_csr)) {
+ hs_csr))
return -ENODEV;
- }
}
return 0;
}
@@ -251,19 +198,16 @@ int cpci_led_on(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return -ENODEV;
- }
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return -ENODEV;
- }
- if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
- /* Set LOO */
+ if ((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
hs_csr |= HS_CSR_LOO;
- if(pci_bus_write_config_word(slot->bus,
+ if (pci_bus_write_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
hs_csr)) {
@@ -283,19 +227,16 @@ int cpci_led_off(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return -ENODEV;
- }
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return -ENODEV;
- }
- if(hs_csr & HS_CSR_LOO) {
- /* Clear LOO */
+ if (hs_csr & HS_CSR_LOO) {
hs_csr &= ~HS_CSR_LOO;
- if(pci_bus_write_config_word(slot->bus,
+ if (pci_bus_write_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
hs_csr)) {
@@ -312,268 +253,21 @@ int cpci_led_off(struct slot* slot)
* Device configuration functions
*/
-static int cpci_configure_dev(struct pci_bus *bus, struct pci_dev *dev)
-{
- u8 irq_pin;
- int r;
-
- dbg("%s - enter", __FUNCTION__);
-
- /* NOTE: device already setup from prior scan */
-
- /* FIXME: How would we know if we need to enable the expansion ROM? */
- pci_write_config_word(dev, PCI_ROM_ADDRESS, 0x00L);
-
- /* Assign resources */
- dbg("assigning resources for %02x:%02x.%x",
- dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
- for (r = 0; r < 6; r++) {
- struct resource *res = dev->resource + r;
- if(res->flags)
- pci_assign_resource(dev, r);
- }
- dbg("finished assigning resources for %02x:%02x.%x",
- dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-
- /* Does this function have an interrupt at all? */
- dbg("checking for function interrupt");
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
- if(irq_pin) {
- dbg("function uses interrupt pin %d", irq_pin);
- }
-
- /*
- * Need to explicitly set irq field to 0 so that it'll get assigned
- * by the pcibios platform dependent code called by pci_enable_device.
- */
- dev->irq = 0;
-
- dbg("enabling device");
- pci_enable_device(dev); /* XXX check return */
- dbg("now dev->irq = %d", dev->irq);
- if(irq_pin && dev->irq) {
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
- }
-
- /* Can't use pci_insert_device at the moment, do it manually for now */
- pci_proc_attach_device(dev);
- dbg("notifying drivers");
- //pci_announce_device_to_drivers(dev);
- dbg("%s - exit", __FUNCTION__);
- return 0;
-}
-
-static int cpci_configure_bridge(struct pci_bus* bus, struct pci_dev* dev)
-{
- int rc;
- struct pci_bus* child;
- struct resource* r;
- u8 max, n;
- u16 command;
-
- dbg("%s - enter", __FUNCTION__);
-
- /* Do basic bridge initialization */
- rc = pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
- if(rc) {
- printk(KERN_ERR "%s - write of PCI_LATENCY_TIMER failed\n", __FUNCTION__);
- }
- rc = pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x40);
- if(rc) {
- printk(KERN_ERR "%s - write of PCI_SEC_LATENCY_TIMER failed\n", __FUNCTION__);
- }
- rc = pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4);
- if(rc) {
- printk(KERN_ERR "%s - write of PCI_CACHE_LINE_SIZE failed\n", __FUNCTION__);
- }
-
- /*
- * Set parent bridge's subordinate field so that configuration space
- * access will work in pci_scan_bridge and friends.
- */
- max = pci_max_busnr();
- bus->subordinate = max + 1;
- pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, max + 1);
-
- /* Scan behind bridge */
- n = pci_scan_bridge(bus, dev, max, 2);
- child = pci_find_bus(0, max + 1);
- if (!child)
- return -ENODEV;
- pci_proc_attach_bus(child);
-
- /*
- * Update parent bridge's subordinate field if there were more bridges
- * behind the bridge that was scanned.
- */
- if(n > max) {
- bus->subordinate = n;
- pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, n);
- }
-
- /*
- * Update the bridge resources of the bridge to accommodate devices
- * behind it.
- */
- pci_bus_size_bridges(child);
- pci_bus_assign_resources(child);
-
- /* Enable resource mapping via command register */
- command = PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
- r = child->resource[0];
- if(r && r->start) {
- command |= PCI_COMMAND_IO;
- }
- r = child->resource[1];
- if(r && r->start) {
- command |= PCI_COMMAND_MEMORY;
- }
- r = child->resource[2];
- if(r && r->start) {
- command |= PCI_COMMAND_MEMORY;
- }
- rc = pci_write_config_word(dev, PCI_COMMAND, command);
- if(rc) {
- err("Error setting command register");
- return rc;
- }
-
- /* Set bridge control register */
- command = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA;
- rc = pci_write_config_word(dev, PCI_BRIDGE_CONTROL, command);
- if(rc) {
- err("Error setting bridge control register");
- return rc;
- }
- dbg("%s - exit", __FUNCTION__);
- return 0;
-}
-
-static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_bus)
-{
- int rc;
- struct pci_dev *dev = wrapped_dev->dev;
- struct pci_bus *bus = wrapped_bus->bus;
- struct slot* slot;
-
- dbg("%s - enter", __FUNCTION__);
-
- /*
- * We need to fix up the hotplug representation with the Linux
- * representation.
- */
- if(wrapped_dev->data) {
- slot = (struct slot*) wrapped_dev->data;
- slot->dev = dev;
- }
-
- /* If it's a bridge, scan behind it for devices */
- if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- rc = cpci_configure_bridge(bus, dev);
- if(rc)
- return rc;
- }
-
- /* Actually configure device */
- if(dev) {
- rc = cpci_configure_dev(bus, dev);
- if(rc)
- return rc;
- }
- dbg("%s - exit", __FUNCTION__);
- return 0;
-}
-
-static int unconfigure_visit_pci_dev_phase2(struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_bus)
-{
- struct pci_dev *dev = wrapped_dev->dev;
- struct slot* slot;
-
- dbg("%s - enter", __FUNCTION__);
- if(!dev)
- return -ENODEV;
-
- /* Remove the Linux representation */
- if(pci_remove_device_safe(dev)) {
- err("Could not remove device\n");
- return -1;
- }
-
- /*
- * Now remove the hotplug representation.
- */
- if(wrapped_dev->data) {
- slot = (struct slot*) wrapped_dev->data;
- slot->dev = NULL;
- } else {
- dbg("No hotplug representation for %02x:%02x.%x",
- dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
- }
- dbg("%s - exit", __FUNCTION__);
- return 0;
-}
-
-static int unconfigure_visit_pci_bus_phase2(struct pci_bus_wrapped *wrapped_bus,
- struct pci_dev_wrapped *wrapped_dev)
-{
- struct pci_bus *bus = wrapped_bus->bus;
- struct pci_bus *parent = bus->self->bus;
-
- dbg("%s - enter", __FUNCTION__);
-
- /* The cleanup code for proc entries regarding buses should be in the kernel... */
- if(bus->procdir)
- dbg("detach_pci_bus %s", bus->procdir->name);
- pci_proc_detach_bus(bus);
-
- /* The cleanup code should live in the kernel... */
- bus->self->subordinate = NULL;
-
- /* unlink from parent bus */
- list_del(&bus->node);
-
- /* Now, remove */
- if(bus)
- kfree(bus);
-
- /* Update parent's subordinate field */
- if(parent) {
- u8 n = pci_bus_max_busnr(parent);
- if(n < parent->subordinate) {
- parent->subordinate = n;
- pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, n);
- }
- }
- dbg("%s - exit", __FUNCTION__);
- return 0;
-}
-
-static struct pci_visit configure_functions = {
- .visit_pci_dev = configure_visit_pci_dev,
-};
-
-static struct pci_visit unconfigure_functions_phase2 = {
- .post_visit_pci_bus = unconfigure_visit_pci_bus_phase2,
- .post_visit_pci_dev = unconfigure_visit_pci_dev_phase2
-};
-
-
int cpci_configure_slot(struct slot* slot)
{
- int rc = 0;
+ unsigned char busnr;
+ struct pci_bus *child;
dbg("%s - enter", __FUNCTION__);
- if(slot->dev == NULL) {
+ if (slot->dev == NULL) {
dbg("pci_dev null, finding %02x:%02x:%x",
slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn));
- slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
+ slot->dev = pci_get_slot(slot->bus, slot->devfn);
}
/* Still NULL? Well then scan for it! */
- if(slot->dev == NULL) {
+ if (slot->dev == NULL) {
int n;
dbg("pci_dev still null");
@@ -583,79 +277,47 @@ int cpci_configure_slot(struct slot* slot)
*/
n = pci_scan_slot(slot->bus, slot->devfn);
dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n);
- if(n > 0)
+ if (n > 0)
pci_bus_add_devices(slot->bus);
- slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
- if(slot->dev == NULL) {
+ slot->dev = pci_get_slot(slot->bus, slot->devfn);
+ if (slot->dev == NULL) {
err("Could not find PCI device for slot %02x", slot->number);
- return 0;
+ return 1;
}
}
- dbg("slot->dev = %p", slot->dev);
- if(slot->dev) {
- struct pci_dev *dev;
- struct pci_dev_wrapped wrapped_dev;
- struct pci_bus_wrapped wrapped_bus;
- int i;
-
- memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
- memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
-
- for (i = 0; i < 8; i++) {
- dev = pci_find_slot(slot->bus->number,
- PCI_DEVFN(PCI_SLOT(slot->dev->devfn), i));
- if(!dev)
- continue;
- wrapped_dev.dev = dev;
- wrapped_bus.bus = slot->dev->bus;
- if(i)
- wrapped_dev.data = NULL;
- else
- wrapped_dev.data = (void*) slot;
- rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);
- }
+
+ if (slot->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ pci_read_config_byte(slot->dev, PCI_SECONDARY_BUS, &busnr);
+ child = pci_add_new_bus(slot->dev->bus, slot->dev, busnr);
+ pci_do_scan_bus(child);
+ pci_bus_size_bridges(child);
}
- dbg("%s - exit, rc = %d", __FUNCTION__, rc);
- return rc;
+ pci_bus_assign_resources(slot->dev->bus);
+
+ dbg("%s - exit", __FUNCTION__);
+ return 0;
}
int cpci_unconfigure_slot(struct slot* slot)
{
- int rc = 0;
int i;
- struct pci_dev_wrapped wrapped_dev;
- struct pci_bus_wrapped wrapped_bus;
struct pci_dev *dev;
dbg("%s - enter", __FUNCTION__);
-
- if(!slot->dev) {
+ if (!slot->dev) {
err("No device for slot %02x\n", slot->number);
return -ENODEV;
}
- memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
- memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
-
for (i = 0; i < 8; i++) {
- dev = pci_find_slot(slot->bus->number,
+ dev = pci_get_slot(slot->bus,
PCI_DEVFN(PCI_SLOT(slot->devfn), i));
- if(dev) {
- wrapped_dev.dev = dev;
- wrapped_bus.bus = dev->bus;
- if(i)
- wrapped_dev.data = NULL;
- else
- wrapped_dev.data = (void*) slot;
- dbg("%s - unconfigure phase 2", __FUNCTION__);
- rc = pci_visit_dev(&unconfigure_functions_phase2,
- &wrapped_dev,
- &wrapped_bus);
- if(rc)
- break;
+ if (dev) {
+ pci_remove_bus_device(dev);
+ slot->dev = NULL;
}
}
- dbg("%s - exit, rc = %d", __FUNCTION__, rc);
- return rc;
+ dbg("%s - exit", __FUNCTION__);
+ return 0;
}
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index f313121d514..46b294a1241 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -130,6 +130,7 @@ struct controller {
u8 slot_bus; /* Bus where the slots handled by this controller sit */
u8 ctrlcap;
u16 vendor_id;
+ u8 cap_base;
};
struct irq_mapping {
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index ed1fd8d6178..df4915dbc32 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -607,7 +607,7 @@ static int pciehp_resume (struct pcie_device *dev)
static struct pcie_port_service_id port_pci_ids[] = { {
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
- .port_type = PCIE_RC_PORT,
+ .port_type = PCIE_ANY_PORT,
.service_type = PCIE_PORT_SERVICE_HP,
.driver_data = 0,
}, { /* end: all zeroes */ }
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 9e70c4681f7..1cda30bd6e4 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -109,20 +109,20 @@ enum ctrl_offsets {
};
static int pcie_cap_base = 0; /* Base of the PCI Express capability item structure */
-#define PCIE_CAP_ID ( pcie_cap_base + PCIECAPID )
-#define NXT_CAP_PTR ( pcie_cap_base + NXTCAPPTR )
-#define CAP_REG ( pcie_cap_base + CAPREG )
-#define DEV_CAP ( pcie_cap_base + DEVCAP )
-#define DEV_CTRL ( pcie_cap_base + DEVCTRL )
-#define DEV_STATUS ( pcie_cap_base + DEVSTATUS )
-#define LNK_CAP ( pcie_cap_base + LNKCAP )
-#define LNK_CTRL ( pcie_cap_base + LNKCTRL )
-#define LNK_STATUS ( pcie_cap_base + LNKSTATUS )
-#define SLOT_CAP ( pcie_cap_base + SLOTCAP )
-#define SLOT_CTRL ( pcie_cap_base + SLOTCTRL )
-#define SLOT_STATUS ( pcie_cap_base + SLOTSTATUS )
-#define ROOT_CTRL ( pcie_cap_base + ROOTCTRL )
-#define ROOT_STATUS ( pcie_cap_base + ROOTSTATUS )
+#define PCIE_CAP_ID(cb) ( cb + PCIECAPID )
+#define NXT_CAP_PTR(cb) ( cb + NXTCAPPTR )
+#define CAP_REG(cb) ( cb + CAPREG )
+#define DEV_CAP(cb) ( cb + DEVCAP )
+#define DEV_CTRL(cb) ( cb + DEVCTRL )
+#define DEV_STATUS(cb) ( cb + DEVSTATUS )
+#define LNK_CAP(cb) ( cb + LNKCAP )
+#define LNK_CTRL(cb) ( cb + LNKCTRL )
+#define LNK_STATUS(cb) ( cb + LNKSTATUS )
+#define SLOT_CAP(cb) ( cb + SLOTCAP )
+#define SLOT_CTRL(cb) ( cb + SLOTCTRL )
+#define SLOT_STATUS(cb) ( cb + SLOTSTATUS )
+#define ROOT_CTRL(cb) ( cb + ROOTCTRL )
+#define ROOT_STATUS(cb) ( cb + ROOTSTATUS )
#define hp_register_read_word(pdev, reg , value) \
pci_read_config_word(pdev, reg, &value)
@@ -303,7 +303,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
if (retval) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
return retval;
@@ -317,7 +317,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
}
dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd);
- retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, cmd | CMD_CMPL_INTR_ENABLE);
+ retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE);
if (retval) {
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
@@ -342,7 +342,7 @@ static int hpc_check_lnk_status(struct controller *ctrl)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(ctrl->cap_base), lnk_status);
if (retval) {
err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
@@ -376,14 +376,14 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (retval) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
}
- dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL, slot_ctrl);
+ dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
@@ -423,13 +423,13 @@ static int hpc_get_power_status(struct slot * slot, u8 *status)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (retval) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
}
- dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl);
+ dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
@@ -463,7 +463,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
if (retval) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
@@ -490,7 +490,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
if (retval) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
@@ -518,7 +518,7 @@ static int hpc_query_power_fault(struct slot * slot)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
if (retval) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
@@ -549,7 +549,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
err("%s: Invalid HPC slot number!\n", __FUNCTION__);
return -1;
}
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
@@ -574,7 +574,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
slot_cmd = slot_cmd | HP_INTR_ENABLE;
pcie_write_cmd(slot, slot_cmd);
- dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
return rc;
}
@@ -598,7 +598,7 @@ static void hpc_set_green_led_on(struct slot *slot)
return ;
}
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
@@ -611,7 +611,7 @@ static void hpc_set_green_led_on(struct slot *slot)
pcie_write_cmd(slot, slot_cmd);
- dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
return;
}
@@ -633,7 +633,7 @@ static void hpc_set_green_led_off(struct slot *slot)
return ;
}
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
@@ -646,7 +646,7 @@ static void hpc_set_green_led_off(struct slot *slot)
if (!pciehp_poll_mode)
slot_cmd = slot_cmd | HP_INTR_ENABLE;
pcie_write_cmd(slot, slot_cmd);
- dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
return;
}
@@ -669,7 +669,7 @@ static void hpc_set_green_led_blink(struct slot *slot)
return ;
}
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
@@ -683,7 +683,7 @@ static void hpc_set_green_led_blink(struct slot *slot)
slot_cmd = slot_cmd | HP_INTR_ENABLE;
pcie_write_cmd(slot, slot_cmd);
- dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
return;
}
@@ -707,7 +707,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl,
*first_device_num = 0;
*num_ctlr_slots = 1;
- rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap);
+ rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap);
if (rc) {
err("%s : hp_register_read_dword SLOT_CAP failed\n", __FUNCTION__);
@@ -793,13 +793,13 @@ static int hpc_power_on_slot(struct slot * slot)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (retval) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
}
- dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL,
+ dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base),
slot_ctrl);
slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
@@ -813,7 +813,7 @@ static int hpc_power_on_slot(struct slot * slot)
err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
return -1;
}
- dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
DBG_LEAVE_ROUTINE
@@ -842,13 +842,13 @@ static int hpc_power_off_slot(struct slot * slot)
err("%s: Invalid HPC slot number!\n", __FUNCTION__);
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (retval) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
}
- dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL,
+ dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base),
slot_ctrl);
slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
@@ -862,7 +862,7 @@ static int hpc_power_off_slot(struct slot * slot)
err("%s: Write command failed!\n", __FUNCTION__);
return -1;
}
- dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
DBG_LEAVE_ROUTINE
@@ -900,7 +900,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
return IRQ_NONE;
}
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -918,7 +918,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
/* Mask Hot-plug Interrupt Enable */
if (!pciehp_poll_mode) {
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -928,14 +928,14 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
return IRQ_NONE;
}
dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -944,7 +944,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
/* Clear command complete interrupt caused by this write */
temp_word = 0x1f;
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -975,14 +975,14 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
/* Clear all events after serving them */
temp_word = 0x1F;
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
}
/* Unmask Hot-plug Interrupt Enable */
if (!pciehp_poll_mode) {
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -992,14 +992,14 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
return IRQ_NONE;
}
dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -1008,7 +1008,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
/* Clear command complete interrupt caused by this write */
temp_word = 0x1F;
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -1038,7 +1038,7 @@ static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
return -1;
}
- retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap);
+ retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap);
if (retval) {
err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__);
@@ -1079,7 +1079,7 @@ static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value
return -1;
}
- retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap);
+ retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap);
if (retval) {
err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__);
@@ -1141,7 +1141,7 @@ static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status);
if (retval) {
err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
@@ -1182,7 +1182,7 @@ static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status);
if (retval) {
err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
@@ -1292,47 +1292,48 @@ int pcie_init(struct controller * ctrl,
goto abort_free_ctlr;
}
- pcie_cap_base = cap_base;
+ ctrl->cap_base = cap_base;
dbg("%s: pcie_cap_base %x\n", __FUNCTION__, pcie_cap_base);
- rc = hp_register_read_word(pdev, CAP_REG, cap_reg);
+ rc = hp_register_read_word(pdev, CAP_REG(ctrl->cap_base), cap_reg);
if (rc) {
err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG, cap_reg);
+ dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG(ctrl->cap_base), cap_reg);
- if (((cap_reg & SLOT_IMPL) == 0) || ((cap_reg & DEV_PORT_TYPE) != 0x0040)){
+ if (((cap_reg & SLOT_IMPL) == 0) || (((cap_reg & DEV_PORT_TYPE) != 0x0040)
+ && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
dbg("%s : This is not a root port or the port is not connected to a slot\n", __FUNCTION__);
goto abort_free_ctlr;
}
- rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap);
+ rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap);
if (rc) {
err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP, slot_cap);
+ dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP(ctrl->cap_base), slot_cap);
if (!(slot_cap & HP_CAP)) {
dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
goto abort_free_ctlr;
}
/* For debugging purpose */
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status);
+ dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), slot_status);
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), slot_ctrl);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl);
+ dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), slot_ctrl);
if (first) {
spin_lock_init(&hpc_event_lock);
@@ -1372,36 +1373,37 @@ int pcie_init(struct controller * ctrl,
php_ctlr->num_slots = 1;
/* Mask Hot-plug Interrupt Enable */
- rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word);
+ rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
+ dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word);
temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
- rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
+ rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word);
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status);
+ dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base)
+ , slot_status);
temp_word = 0x1F; /* Clear all events */
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word);
+ dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);
if (pciehp_poll_mode) {/* Install interrupt polling code */
/* Install and start the interrupt polling timer */
@@ -1417,12 +1419,12 @@ int pcie_init(struct controller * ctrl,
}
}
- rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word);
+ rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
+ dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word);
dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap);
intr_enable = intr_enable | PRSN_DETECT_ENABLE;
@@ -1446,27 +1448,27 @@ int pcie_init(struct controller * ctrl,
dbg("%s: temp_word %x\n", __FUNCTION__, temp_word);
/* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */
- rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
+ rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word);
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__,
- SLOT_STATUS, slot_status);
+ SLOT_STATUS(ctrl->cap_base), slot_status);
temp_word = 0x1F; /* Clear all events */
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word);
+ dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);
/* Add this HPC instance into the HPC list */
spin_lock(&list_lock);
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index f0c53f850ae..a70a5c5705f 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -95,7 +95,7 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
*/
static void release_slot(struct hotplug_slot *hotplug_slot)
{
- struct slot *slot = (struct slot *)hotplug_slot->private;
+ struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 9f90eb8e6ec..490a9553a06 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -1885,7 +1885,7 @@ int shpchp_enable_slot (struct slot *p_slot)
func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
if (!func) {
dbg("%s: Error! slot NULL\n", __FUNCTION__);
- return 1;
+ return -ENODEV;
}
/* Check to see if (latch closed, card present, power off) */
@@ -1894,19 +1894,19 @@ int shpchp_enable_slot (struct slot *p_slot)
if (rc || !getstatus) {
info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect);
- return 1;
+ return -ENODEV;
}
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (rc || getstatus) {
info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect);
- return 1;
+ return -ENODEV;
}
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (rc || getstatus) {
info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect);
- return 1;
+ return -ENODEV;
}
up(&p_slot->ctrl->crit_sect);
@@ -1914,7 +1914,7 @@ int shpchp_enable_slot (struct slot *p_slot)
func = shpchp_slot_create(p_slot->bus);
if (func == NULL)
- return 1;
+ return -ENOMEM;
func->bus = p_slot->bus;
func->device = p_slot->device;
@@ -1939,7 +1939,7 @@ int shpchp_enable_slot (struct slot *p_slot)
/* Setup slot structure with entry for empty slot */
func = shpchp_slot_create(p_slot->bus);
if (func == NULL)
- return (1); /* Out of memory */
+ return -ENOMEM; /* Out of memory */
func->bus = p_slot->bus;
func->device = p_slot->device;
@@ -1972,7 +1972,7 @@ int shpchp_disable_slot (struct slot *p_slot)
struct pci_func *func;
if (!p_slot->ctrl)
- return 1;
+ return -ENODEV;
pci_bus = p_slot->ctrl->pci_dev->subordinate;
@@ -1983,19 +1983,19 @@ int shpchp_disable_slot (struct slot *p_slot)
if (ret || !getstatus) {
info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect);
- return 1;
+ return -ENODEV;
}
ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (ret || getstatus) {
info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect);
- return 1;
+ return -ENODEV;
}
ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (ret || !getstatus) {
info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect);
- return 1;
+ return -ENODEV;
}
up(&p_slot->ctrl->crit_sect);
@@ -2011,7 +2011,7 @@ int shpchp_disable_slot (struct slot *p_slot)
/* Check the Class Code */
rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
if (rc)
- return rc;
+ return -ENODEV;
if (class_code == PCI_BASE_CLASS_DISPLAY) {
/* Display/Video adapter (not supported) */
@@ -2020,13 +2020,13 @@ int shpchp_disable_slot (struct slot *p_slot)
/* See if it's a bridge */
rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
if (rc)
- return 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 rc;
+ return -ENODEV;
/* If the VGA Enable bit is set, remove isn't supported */
if (BCR & PCI_BRIDGE_CTL_VGA) {
@@ -2042,12 +2042,12 @@ int shpchp_disable_slot (struct slot *p_slot)
if ((func != NULL) && !rc) {
rc = remove_board(func, p_slot->ctrl);
} else if (!rc)
- rc = 1;
+ rc = -ENODEV;
if (p_slot)
update_slot_info(p_slot);
- return(rc);
+ return rc;
}
diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c
index 243a51d88b8..7957cdc72cd 100644
--- a/drivers/pci/hotplug/shpchprm_acpi.c
+++ b/drivers/pci/hotplug/shpchprm_acpi.c
@@ -1626,7 +1626,7 @@ int shpchprm_set_hpp(
pci_bus->number = func->bus;
devfn = PCI_DEVFN(func->device, func->function);
- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
+ ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
if (ab) {
if (ab->_hpp) {
@@ -1681,7 +1681,7 @@ void shpchprm_enable_card(
| 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->bus);
+ ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
if (ab) {
if (ab->_hpp) {
if (ab->_hpp->enable_perr) {
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 8568b207f18..6ca0061137a 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -73,6 +73,17 @@ resource_show(struct device * dev, char * buf)
return (str - buf);
}
+static ssize_t modalias_show(struct device *dev, char *buf)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+
+ return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n",
+ pci_dev->vendor, pci_dev->device,
+ pci_dev->subsystem_vendor, pci_dev->subsystem_device,
+ (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8),
+ (u8)(pci_dev->class));
+}
+
struct device_attribute pci_dev_attrs[] = {
__ATTR_RO(resource),
__ATTR_RO(vendor),
@@ -82,6 +93,7 @@ struct device_attribute pci_dev_attrs[] = {
__ATTR_RO(class),
__ATTR_RO(irq),
__ATTR_RO(local_cpus),
+ __ATTR_RO(modalias),
__ATTR_NULL,
};
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 79cdc16c52c..744da0d4ae5 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -32,33 +32,6 @@ extern unsigned char pci_max_busnr(void);
extern unsigned char pci_bus_max_busnr(struct pci_bus *bus);
extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap);
-struct pci_dev_wrapped {
- struct pci_dev *dev;
- void *data;
-};
-
-struct pci_bus_wrapped {
- struct pci_bus *bus;
- void *data;
-};
-
-struct pci_visit {
- int (* pre_visit_pci_bus) (struct pci_bus_wrapped *,
- struct pci_dev_wrapped *);
- int (* post_visit_pci_bus) (struct pci_bus_wrapped *,
- struct pci_dev_wrapped *);
-
- int (* pre_visit_pci_dev) (struct pci_dev_wrapped *,
- struct pci_bus_wrapped *);
- int (* visit_pci_dev) (struct pci_dev_wrapped *,
- struct pci_bus_wrapped *);
- int (* post_visit_pci_dev) (struct pci_dev_wrapped *,
- struct pci_bus_wrapped *);
-};
-
-extern int pci_visit_dev(struct pci_visit *fn,
- struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_parent);
extern void pci_remove_legacy_files(struct pci_bus *bus);
/* Lock for read/write access to pci device and bus lists */
diff --git a/drivers/pci/pcie/portdrv_bus.c b/drivers/pci/pcie/portdrv_bus.c
index 4037a3e568d..3e84b501e6a 100644
--- a/drivers/pci/pcie/portdrv_bus.c
+++ b/drivers/pci/pcie/portdrv_bus.c
@@ -39,7 +39,8 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
driver->id_table->vendor != pciedev->id.vendor) ||
(driver->id_table->device != PCI_ANY_ID &&
driver->id_table->device != pciedev->id.device) ||
- driver->id_table->port_type != pciedev->id.port_type ||
+ (driver->id_table->port_type != PCIE_ANY_PORT &&
+ driver->id_table->port_type != pciedev->id.port_type) ||
driver->id_table->service_type != pciedev->id.service_type )
return 0;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 026aa04669a..637e9493034 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -18,6 +18,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/acpi.h>
#include "pci.h"
/* Deal with broken BIOS'es that neglect to enable passive release,
@@ -467,9 +468,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC,
* non-x86 architectures (yes Via exists on PPC among other places),
* we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
* interrupts delivered properly.
- *
- * TODO: When we have device-specific interrupt routers,
- * quirk_via_irqpic will go away from quirks.
*/
/*
@@ -494,6 +492,29 @@ static void __devinit quirk_via_acpi(struct pci_dev *d)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi );
+static void quirk_via_irqpic(struct pci_dev *dev)
+{
+ u8 irq, new_irq;
+
+#ifdef CONFIG_X86_IO_APIC
+ if (nr_ioapics && !skip_ioapic_setup)
+ return;
+#endif
+#ifdef CONFIG_ACPI
+ if (acpi_irq_model != ACPI_IRQ_MODEL_PIC)
+ return;
+#endif
+ new_irq = dev->irq & 0xf;
+ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+ if (new_irq != irq) {
+ printk(KERN_INFO "PCI: Via PIC IRQ fixup for %s, from %d to %d\n",
+ pci_name(dev), irq, new_irq);
+ udelay(15); /* unknown if delay really needed */
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
+ }
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irqpic);
+
/*
* PIIX3 USB: We have to disable USB interrupts that are
* hardwired to PIRQD# and may be shared with an
@@ -683,19 +704,6 @@ static void __init quirk_disable_pxb(struct pci_dev *pdev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb );
-/*
- * VIA northbridges care about PCI_INTERRUPT_LINE
- */
-int via_interrupt_line_quirk;
-
-static void __devinit quirk_via_bridge(struct pci_dev *pdev)
-{
- if(pdev->devfn == 0) {
- printk(KERN_INFO "PCI: Via IRQ fixup\n");
- via_interrupt_line_quirk = 1;
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_bridge );
/*
* Serverworks CSB5 IDE does not fully support native mode