diff options
| author | <jgarzik@pretzel.yyz.us> | 2005-06-04 00:40:40 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-06-04 00:40:40 -0400 |
| commit | ae20ea8525a80a863f70d332cf47b71bd9f54c1f (patch) | |
| tree | 9d3cedeb65db521a8436b545bd91641549a18d24 /drivers/pci | |
| parent | f497ba735fc9ff4e35a19641143708b3be1c7061 (diff) | |
| parent | 8be3de3fd8469154a2b3e18a4712032dac5b4a53 (diff) | |
Automatic merge of /spare/repo/linux-2.6/.git branch HEAD
Diffstat (limited to 'drivers/pci')
| -rw-r--r-- | drivers/pci/hotplug.c | 119 | ||||
| -rw-r--r-- | drivers/pci/hotplug/cpci_hotplug.h | 2 | ||||
| -rw-r--r-- | drivers/pci/hotplug/cpci_hotplug_core.c | 427 | ||||
| -rw-r--r-- | drivers/pci/hotplug/cpci_hotplug_pci.c | 480 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp.h | 1 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 2 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 156 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp_core.c | 2 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp_ctrl.c | 30 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchprm_acpi.c | 4 | ||||
| -rw-r--r-- | drivers/pci/pci-sysfs.c | 12 | ||||
| -rw-r--r-- | drivers/pci/pci.h | 27 | ||||
| -rw-r--r-- | drivers/pci/pcie/portdrv_bus.c | 3 | ||||
| -rw-r--r-- | drivers/pci/quirks.c | 40 |
14 files changed, 421 insertions, 884 deletions
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c index 021d0f76bc4c..3903f8c559b6 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, | |||
| 52 | if ((buffer_size - length <= 0) || (i >= num_envp)) | 52 | if ((buffer_size - length <= 0) || (i >= num_envp)) |
| 53 | return -ENOMEM; | 53 | return -ENOMEM; |
| 54 | 54 | ||
| 55 | envp[i++] = scratch; | ||
| 56 | length += scnprintf (scratch, buffer_size - length, | ||
| 57 | "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n", | ||
| 58 | pdev->vendor, pdev->device, | ||
| 59 | pdev->subsystem_vendor, pdev->subsystem_device, | ||
| 60 | (u8)(pdev->class >> 16), (u8)(pdev->class >> 8), | ||
| 61 | (u8)(pdev->class)); | ||
| 62 | if ((buffer_size - length <= 0) || (i >= num_envp)) | ||
| 63 | return -ENOMEM; | ||
| 64 | |||
| 55 | envp[i] = NULL; | 65 | envp[i] = NULL; |
| 56 | 66 | ||
| 57 | return 0; | 67 | return 0; |
| 58 | } | 68 | } |
| 59 | |||
| 60 | static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_parent) | ||
| 61 | { | ||
| 62 | struct list_head *ln; | ||
| 63 | struct pci_dev *dev; | ||
| 64 | struct pci_dev_wrapped wrapped_dev; | ||
| 65 | int result = 0; | ||
| 66 | |||
| 67 | pr_debug("PCI: Scanning bus %04x:%02x\n", pci_domain_nr(wrapped_bus->bus), | ||
| 68 | wrapped_bus->bus->number); | ||
| 69 | |||
| 70 | if (fn->pre_visit_pci_bus) { | ||
| 71 | result = fn->pre_visit_pci_bus(wrapped_bus, wrapped_parent); | ||
| 72 | if (result) | ||
| 73 | return result; | ||
| 74 | } | ||
| 75 | |||
| 76 | ln = wrapped_bus->bus->devices.next; | ||
| 77 | while (ln != &wrapped_bus->bus->devices) { | ||
| 78 | dev = pci_dev_b(ln); | ||
| 79 | ln = ln->next; | ||
| 80 | |||
| 81 | memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped)); | ||
| 82 | wrapped_dev.dev = dev; | ||
| 83 | |||
| 84 | result = pci_visit_dev(fn, &wrapped_dev, wrapped_bus); | ||
| 85 | if (result) | ||
| 86 | return result; | ||
| 87 | } | ||
| 88 | |||
| 89 | if (fn->post_visit_pci_bus) | ||
| 90 | result = fn->post_visit_pci_bus(wrapped_bus, wrapped_parent); | ||
| 91 | |||
| 92 | return result; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int pci_visit_bridge (struct pci_visit * fn, | ||
| 96 | struct pci_dev_wrapped *wrapped_dev, | ||
| 97 | struct pci_bus_wrapped *wrapped_parent) | ||
| 98 | { | ||
| 99 | struct pci_bus *bus; | ||
| 100 | struct pci_bus_wrapped wrapped_bus; | ||
| 101 | int result = 0; | ||
| 102 | |||
| 103 | pr_debug("PCI: Scanning bridge %s\n", pci_name(wrapped_dev->dev)); | ||
| 104 | |||
| 105 | if (fn->visit_pci_dev) { | ||
| 106 | result = fn->visit_pci_dev(wrapped_dev, wrapped_parent); | ||
| 107 | if (result) | ||
| 108 | return result; | ||
| 109 | } | ||
| 110 | |||
| 111 | bus = wrapped_dev->dev->subordinate; | ||
| 112 | if (bus) { | ||
| 113 | memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped)); | ||
| 114 | wrapped_bus.bus = bus; | ||
| 115 | |||
| 116 | result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev); | ||
| 117 | } | ||
| 118 | return result; | ||
| 119 | } | ||
| 120 | |||
| 121 | /** | ||
| 122 | * pci_visit_dev - scans the pci buses. | ||
| 123 | * @fn: callback functions that are called while visiting | ||
| 124 | * @wrapped_dev: the device to scan | ||
| 125 | * @wrapped_parent: the bus where @wrapped_dev is connected to | ||
| 126 | * | ||
| 127 | * Every bus and every function is presented to a custom | ||
| 128 | * function that can act upon it. | ||
| 129 | */ | ||
| 130 | int pci_visit_dev(struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev, | ||
| 131 | struct pci_bus_wrapped *wrapped_parent) | ||
| 132 | { | ||
| 133 | struct pci_dev* dev = wrapped_dev ? wrapped_dev->dev : NULL; | ||
| 134 | int result = 0; | ||
| 135 | |||
| 136 | if (!dev) | ||
| 137 | return 0; | ||
| 138 | |||
| 139 | if (fn->pre_visit_pci_dev) { | ||
| 140 | result = fn->pre_visit_pci_dev(wrapped_dev, wrapped_parent); | ||
| 141 | if (result) | ||
| 142 | return result; | ||
| 143 | } | ||
| 144 | |||
| 145 | switch (dev->class >> 8) { | ||
| 146 | case PCI_CLASS_BRIDGE_PCI: | ||
| 147 | result = pci_visit_bridge(fn, wrapped_dev, | ||
| 148 | wrapped_parent); | ||
| 149 | if (result) | ||
| 150 | return result; | ||
| 151 | break; | ||
| 152 | default: | ||
| 153 | pr_debug("PCI: Scanning device %s\n", pci_name(dev)); | ||
| 154 | if (fn->visit_pci_dev) { | ||
| 155 | result = fn->visit_pci_dev (wrapped_dev, | ||
| 156 | wrapped_parent); | ||
| 157 | if (result) | ||
| 158 | return result; | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | if (fn->post_visit_pci_dev) | ||
| 163 | result = fn->post_visit_pci_dev(wrapped_dev, wrapped_parent); | ||
| 164 | |||
| 165 | return result; | ||
| 166 | } | ||
| 167 | EXPORT_SYMBOL(pci_visit_dev); | ||
diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h index 3ddd75937a40..d9769b30be9a 100644 --- a/drivers/pci/hotplug/cpci_hotplug.h +++ b/drivers/pci/hotplug/cpci_hotplug.h | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
| 32 | #include <linux/pci.h> | 32 | #include <linux/pci.h> |
| 33 | 33 | ||
| 34 | /* PICMG 2.12 R2.0 HS CSR bits: */ | 34 | /* PICMG 2.1 R2.0 HS CSR bits: */ |
| 35 | #define HS_CSR_INS 0x0080 | 35 | #define HS_CSR_INS 0x0080 |
| 36 | #define HS_CSR_EXT 0x0040 | 36 | #define HS_CSR_EXT 0x0040 |
| 37 | #define HS_CSR_PI 0x0030 | 37 | #define HS_CSR_PI 0x0030 |
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index ed243605dc7b..8132d946c384 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * CompactPCI Hot Plug Driver | 2 | * CompactPCI Hot Plug Driver |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2002 SOMA Networks, Inc. | 4 | * Copyright (C) 2002,2005 SOMA Networks, Inc. |
| 5 | * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) | 5 | * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) |
| 6 | * Copyright (C) 2001 IBM Corp. | 6 | * Copyright (C) 2001 IBM Corp. |
| 7 | * | 7 | * |
| @@ -33,11 +33,11 @@ | |||
| 33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
| 34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
| 35 | #include <linux/smp_lock.h> | 35 | #include <linux/smp_lock.h> |
| 36 | #include <asm/atomic.h> | ||
| 36 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
| 37 | #include "pci_hotplug.h" | 38 | #include "pci_hotplug.h" |
| 38 | #include "cpci_hotplug.h" | 39 | #include "cpci_hotplug.h" |
| 39 | 40 | ||
| 40 | #define DRIVER_VERSION "0.2" | ||
| 41 | #define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>" | 41 | #define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>" |
| 42 | #define DRIVER_DESC "CompactPCI Hot Plug Core" | 42 | #define DRIVER_DESC "CompactPCI Hot Plug Core" |
| 43 | 43 | ||
| @@ -45,18 +45,19 @@ | |||
| 45 | 45 | ||
| 46 | #define dbg(format, arg...) \ | 46 | #define dbg(format, arg...) \ |
| 47 | do { \ | 47 | do { \ |
| 48 | if(cpci_debug) \ | 48 | if (cpci_debug) \ |
| 49 | printk (KERN_DEBUG "%s: " format "\n", \ | 49 | printk (KERN_DEBUG "%s: " format "\n", \ |
| 50 | MY_NAME , ## arg); \ | 50 | MY_NAME , ## arg); \ |
| 51 | } while(0) | 51 | } while (0) |
| 52 | #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) | 52 | #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) |
| 53 | #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) | 53 | #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) |
| 54 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) | 54 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) |
| 55 | 55 | ||
| 56 | /* local variables */ | 56 | /* local variables */ |
| 57 | static spinlock_t list_lock; | 57 | static DECLARE_RWSEM(list_rwsem); |
| 58 | static LIST_HEAD(slot_list); | 58 | static LIST_HEAD(slot_list); |
| 59 | static int slots; | 59 | static int slots; |
| 60 | static atomic_t extracting; | ||
| 60 | int cpci_debug; | 61 | int cpci_debug; |
| 61 | static struct cpci_hp_controller *controller; | 62 | static struct cpci_hp_controller *controller; |
| 62 | static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ | 63 | 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); | |||
| 68 | static int set_attention_status(struct hotplug_slot *slot, u8 value); | 69 | static int set_attention_status(struct hotplug_slot *slot, u8 value); |
| 69 | static int get_power_status(struct hotplug_slot *slot, u8 * value); | 70 | static int get_power_status(struct hotplug_slot *slot, u8 * value); |
| 70 | static int get_attention_status(struct hotplug_slot *slot, u8 * value); | 71 | static int get_attention_status(struct hotplug_slot *slot, u8 * value); |
| 72 | static int get_adapter_status(struct hotplug_slot *slot, u8 * value); | ||
| 73 | static int get_latch_status(struct hotplug_slot *slot, u8 * value); | ||
| 71 | 74 | ||
| 72 | static struct hotplug_slot_ops cpci_hotplug_slot_ops = { | 75 | static struct hotplug_slot_ops cpci_hotplug_slot_ops = { |
| 73 | .owner = THIS_MODULE, | 76 | .owner = THIS_MODULE, |
| @@ -76,6 +79,8 @@ static struct hotplug_slot_ops cpci_hotplug_slot_ops = { | |||
| 76 | .set_attention_status = set_attention_status, | 79 | .set_attention_status = set_attention_status, |
| 77 | .get_power_status = get_power_status, | 80 | .get_power_status = get_power_status, |
| 78 | .get_attention_status = get_attention_status, | 81 | .get_attention_status = get_attention_status, |
| 82 | .get_adapter_status = get_adapter_status, | ||
| 83 | .get_latch_status = get_latch_status, | ||
| 79 | }; | 84 | }; |
| 80 | 85 | ||
| 81 | static int | 86 | static int |
| @@ -106,10 +111,8 @@ enable_slot(struct hotplug_slot *hotplug_slot) | |||
| 106 | 111 | ||
| 107 | dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); | 112 | dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); |
| 108 | 113 | ||
| 109 | if(controller->ops->set_power) { | 114 | if (controller->ops->set_power) |
| 110 | retval = controller->ops->set_power(slot, 1); | 115 | retval = controller->ops->set_power(slot, 1); |
| 111 | } | ||
| 112 | |||
| 113 | return retval; | 116 | return retval; |
| 114 | } | 117 | } |
| 115 | 118 | ||
| @@ -121,35 +124,41 @@ disable_slot(struct hotplug_slot *hotplug_slot) | |||
| 121 | 124 | ||
| 122 | dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); | 125 | dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); |
| 123 | 126 | ||
| 127 | down_write(&list_rwsem); | ||
| 128 | |||
| 124 | /* Unconfigure device */ | 129 | /* Unconfigure device */ |
| 125 | dbg("%s - unconfiguring slot %s", | 130 | dbg("%s - unconfiguring slot %s", |
| 126 | __FUNCTION__, slot->hotplug_slot->name); | 131 | __FUNCTION__, slot->hotplug_slot->name); |
| 127 | if((retval = cpci_unconfigure_slot(slot))) { | 132 | if ((retval = cpci_unconfigure_slot(slot))) { |
| 128 | err("%s - could not unconfigure slot %s", | 133 | err("%s - could not unconfigure slot %s", |
| 129 | __FUNCTION__, slot->hotplug_slot->name); | 134 | __FUNCTION__, slot->hotplug_slot->name); |
| 130 | return retval; | 135 | goto disable_error; |
| 131 | } | 136 | } |
| 132 | dbg("%s - finished unconfiguring slot %s", | 137 | dbg("%s - finished unconfiguring slot %s", |
| 133 | __FUNCTION__, slot->hotplug_slot->name); | 138 | __FUNCTION__, slot->hotplug_slot->name); |
| 134 | 139 | ||
| 135 | /* Clear EXT (by setting it) */ | 140 | /* Clear EXT (by setting it) */ |
| 136 | if(cpci_clear_ext(slot)) { | 141 | if (cpci_clear_ext(slot)) { |
| 137 | err("%s - could not clear EXT for slot %s", | 142 | err("%s - could not clear EXT for slot %s", |
| 138 | __FUNCTION__, slot->hotplug_slot->name); | 143 | __FUNCTION__, slot->hotplug_slot->name); |
| 139 | retval = -ENODEV; | 144 | retval = -ENODEV; |
| 145 | goto disable_error; | ||
| 140 | } | 146 | } |
| 141 | cpci_led_on(slot); | 147 | cpci_led_on(slot); |
| 142 | 148 | ||
| 143 | if(controller->ops->set_power) { | 149 | if (controller->ops->set_power) |
| 144 | retval = controller->ops->set_power(slot, 0); | 150 | if ((retval = controller->ops->set_power(slot, 0))) |
| 145 | } | 151 | goto disable_error; |
| 146 | 152 | ||
| 147 | if(update_adapter_status(slot->hotplug_slot, 0)) { | 153 | if (update_adapter_status(slot->hotplug_slot, 0)) |
| 148 | warn("failure to update adapter file"); | 154 | warn("failure to update adapter file"); |
| 149 | } | ||
| 150 | |||
| 151 | slot->extracting = 0; | ||
| 152 | 155 | ||
| 156 | if (slot->extracting) { | ||
| 157 | slot->extracting = 0; | ||
| 158 | atomic_dec(&extracting); | ||
| 159 | } | ||
| 160 | disable_error: | ||
| 161 | up_write(&list_rwsem); | ||
| 153 | return retval; | 162 | return retval; |
| 154 | } | 163 | } |
| 155 | 164 | ||
| @@ -158,9 +167,8 @@ cpci_get_power_status(struct slot *slot) | |||
| 158 | { | 167 | { |
| 159 | u8 power = 1; | 168 | u8 power = 1; |
| 160 | 169 | ||
| 161 | if(controller->ops->get_power) { | 170 | if (controller->ops->get_power) |
| 162 | power = controller->ops->get_power(slot); | 171 | power = controller->ops->get_power(slot); |
| 163 | } | ||
| 164 | return power; | 172 | return power; |
| 165 | } | 173 | } |
| 166 | 174 | ||
| @@ -188,6 +196,20 @@ set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) | |||
| 188 | return cpci_set_attention_status(hotplug_slot->private, status); | 196 | return cpci_set_attention_status(hotplug_slot->private, status); |
| 189 | } | 197 | } |
| 190 | 198 | ||
| 199 | static int | ||
| 200 | get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) | ||
| 201 | { | ||
| 202 | *value = hotplug_slot->info->adapter_status; | ||
| 203 | return 0; | ||
| 204 | } | ||
| 205 | |||
| 206 | static int | ||
| 207 | get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value) | ||
| 208 | { | ||
| 209 | *value = hotplug_slot->info->latch_status; | ||
| 210 | return 0; | ||
| 211 | } | ||
| 212 | |||
| 191 | static void release_slot(struct hotplug_slot *hotplug_slot) | 213 | static void release_slot(struct hotplug_slot *hotplug_slot) |
| 192 | { | 214 | { |
| 193 | struct slot *slot = hotplug_slot->private; | 215 | struct slot *slot = hotplug_slot->private; |
| @@ -216,9 +238,8 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) | |||
| 216 | int status = -ENOMEM; | 238 | int status = -ENOMEM; |
| 217 | int i; | 239 | int i; |
| 218 | 240 | ||
| 219 | if(!(controller && bus)) { | 241 | if (!(controller && bus)) |
| 220 | return -ENODEV; | 242 | return -ENODEV; |
| 221 | } | ||
| 222 | 243 | ||
| 223 | /* | 244 | /* |
| 224 | * Create a structure for each slot, and register that slot | 245 | * 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) | |||
| 273 | } | 294 | } |
| 274 | 295 | ||
| 275 | /* Add slot to our internal list */ | 296 | /* Add slot to our internal list */ |
| 276 | spin_lock(&list_lock); | 297 | down_write(&list_rwsem); |
| 277 | list_add(&slot->slot_list, &slot_list); | 298 | list_add(&slot->slot_list, &slot_list); |
| 278 | slots++; | 299 | slots++; |
| 279 | spin_unlock(&list_lock); | 300 | up_write(&list_rwsem); |
| 280 | } | 301 | } |
| 281 | return 0; | 302 | return 0; |
| 282 | error_name: | 303 | error_name: |
| @@ -295,32 +316,30 @@ int | |||
| 295 | cpci_hp_unregister_bus(struct pci_bus *bus) | 316 | cpci_hp_unregister_bus(struct pci_bus *bus) |
| 296 | { | 317 | { |
| 297 | struct slot *slot; | 318 | struct slot *slot; |
| 298 | struct list_head *tmp; | 319 | struct slot *tmp; |
| 299 | struct list_head *next; | 320 | int status = 0; |
| 300 | int status; | ||
| 301 | 321 | ||
| 302 | spin_lock(&list_lock); | 322 | down_write(&list_rwsem); |
| 303 | if(!slots) { | 323 | if (!slots) { |
| 304 | spin_unlock(&list_lock); | 324 | up_write(&list_rwsem); |
| 305 | return -1; | 325 | return -1; |
| 306 | } | 326 | } |
| 307 | list_for_each_safe(tmp, next, &slot_list) { | 327 | list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) { |
| 308 | slot = list_entry(tmp, struct slot, slot_list); | 328 | if (slot->bus == bus) { |
| 309 | if(slot->bus == bus) { | 329 | list_del(&slot->slot_list); |
| 330 | slots--; | ||
| 331 | |||
| 310 | dbg("deregistering slot %s", slot->hotplug_slot->name); | 332 | dbg("deregistering slot %s", slot->hotplug_slot->name); |
| 311 | status = pci_hp_deregister(slot->hotplug_slot); | 333 | status = pci_hp_deregister(slot->hotplug_slot); |
| 312 | if(status) { | 334 | if (status) { |
| 313 | err("pci_hp_deregister failed with error %d", | 335 | err("pci_hp_deregister failed with error %d", |
| 314 | status); | 336 | status); |
| 315 | return status; | 337 | break; |
| 316 | } | 338 | } |
| 317 | |||
| 318 | list_del(&slot->slot_list); | ||
| 319 | slots--; | ||
| 320 | } | 339 | } |
| 321 | } | 340 | } |
| 322 | spin_unlock(&list_lock); | 341 | up_write(&list_rwsem); |
| 323 | return 0; | 342 | return status; |
| 324 | } | 343 | } |
| 325 | 344 | ||
| 326 | /* This is the interrupt mode interrupt handler */ | 345 | /* This is the interrupt mode interrupt handler */ |
| @@ -330,7 +349,7 @@ cpci_hp_intr(int irq, void *data, struct pt_regs *regs) | |||
| 330 | dbg("entered cpci_hp_intr"); | 349 | dbg("entered cpci_hp_intr"); |
| 331 | 350 | ||
| 332 | /* Check to see if it was our interrupt */ | 351 | /* Check to see if it was our interrupt */ |
| 333 | if((controller->irq_flags & SA_SHIRQ) && | 352 | if ((controller->irq_flags & SA_SHIRQ) && |
| 334 | !controller->ops->check_irq(controller->dev_id)) { | 353 | !controller->ops->check_irq(controller->dev_id)) { |
| 335 | dbg("exited cpci_hp_intr, not our interrupt"); | 354 | dbg("exited cpci_hp_intr, not our interrupt"); |
| 336 | return IRQ_NONE; | 355 | return IRQ_NONE; |
| @@ -347,46 +366,38 @@ cpci_hp_intr(int irq, void *data, struct pt_regs *regs) | |||
| 347 | } | 366 | } |
| 348 | 367 | ||
| 349 | /* | 368 | /* |
| 350 | * According to PICMG 2.12 R2.0, section 6.3.2, upon | 369 | * According to PICMG 2.1 R2.0, section 6.3.2, upon |
| 351 | * initialization, the system driver shall clear the | 370 | * initialization, the system driver shall clear the |
| 352 | * INS bits of the cold-inserted devices. | 371 | * INS bits of the cold-inserted devices. |
| 353 | */ | 372 | */ |
| 354 | static int | 373 | static int |
| 355 | init_slots(void) | 374 | init_slots(int clear_ins) |
| 356 | { | 375 | { |
| 357 | struct slot *slot; | 376 | struct slot *slot; |
| 358 | struct list_head *tmp; | ||
| 359 | struct pci_dev* dev; | 377 | struct pci_dev* dev; |
| 360 | 378 | ||
| 361 | dbg("%s - enter", __FUNCTION__); | 379 | dbg("%s - enter", __FUNCTION__); |
| 362 | spin_lock(&list_lock); | 380 | down_read(&list_rwsem); |
| 363 | if(!slots) { | 381 | if (!slots) { |
| 364 | spin_unlock(&list_lock); | 382 | up_read(&list_rwsem); |
| 365 | return -1; | 383 | return -1; |
| 366 | } | 384 | } |
| 367 | list_for_each(tmp, &slot_list) { | 385 | list_for_each_entry(slot, &slot_list, slot_list) { |
| 368 | slot = list_entry(tmp, struct slot, slot_list); | ||
| 369 | dbg("%s - looking at slot %s", | 386 | dbg("%s - looking at slot %s", |
| 370 | __FUNCTION__, slot->hotplug_slot->name); | 387 | __FUNCTION__, slot->hotplug_slot->name); |
| 371 | if(cpci_check_and_clear_ins(slot)) { | 388 | if (clear_ins && cpci_check_and_clear_ins(slot)) |
| 372 | dbg("%s - cleared INS for slot %s", | 389 | dbg("%s - cleared INS for slot %s", |
| 373 | __FUNCTION__, slot->hotplug_slot->name); | 390 | __FUNCTION__, slot->hotplug_slot->name); |
| 374 | dev = pci_find_slot(slot->bus->number, PCI_DEVFN(slot->number, 0)); | 391 | dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0)); |
| 375 | if(dev) { | 392 | if (dev) { |
| 376 | if(update_adapter_status(slot->hotplug_slot, 1)) { | 393 | if (update_adapter_status(slot->hotplug_slot, 1)) |
| 377 | warn("failure to update adapter file"); | 394 | warn("failure to update adapter file"); |
| 378 | } | 395 | if (update_latch_status(slot->hotplug_slot, 1)) |
| 379 | if(update_latch_status(slot->hotplug_slot, 1)) { | 396 | warn("failure to update latch file"); |
| 380 | warn("failure to update latch file"); | 397 | slot->dev = dev; |
| 381 | } | ||
| 382 | slot->dev = dev; | ||
| 383 | } else { | ||
| 384 | err("%s - no driver attached to device in slot %s", | ||
| 385 | __FUNCTION__, slot->hotplug_slot->name); | ||
| 386 | } | ||
| 387 | } | 398 | } |
| 388 | } | 399 | } |
| 389 | spin_unlock(&list_lock); | 400 | up_read(&list_rwsem); |
| 390 | dbg("%s - exit", __FUNCTION__); | 401 | dbg("%s - exit", __FUNCTION__); |
| 391 | return 0; | 402 | return 0; |
| 392 | } | 403 | } |
| @@ -395,27 +406,28 @@ static int | |||
| 395 | check_slots(void) | 406 | check_slots(void) |
| 396 | { | 407 | { |
| 397 | struct slot *slot; | 408 | struct slot *slot; |
| 398 | struct list_head *tmp; | ||
| 399 | int extracted; | 409 | int extracted; |
| 400 | int inserted; | 410 | int inserted; |
| 411 | u16 hs_csr; | ||
| 401 | 412 | ||
| 402 | spin_lock(&list_lock); | 413 | down_read(&list_rwsem); |
| 403 | if(!slots) { | 414 | if (!slots) { |
| 404 | spin_unlock(&list_lock); | 415 | up_read(&list_rwsem); |
| 405 | err("no slots registered, shutting down"); | 416 | err("no slots registered, shutting down"); |
| 406 | return -1; | 417 | return -1; |
| 407 | } | 418 | } |
| 408 | extracted = inserted = 0; | 419 | extracted = inserted = 0; |
| 409 | list_for_each(tmp, &slot_list) { | 420 | list_for_each_entry(slot, &slot_list, slot_list) { |
| 410 | slot = list_entry(tmp, struct slot, slot_list); | ||
| 411 | dbg("%s - looking at slot %s", | 421 | dbg("%s - looking at slot %s", |
| 412 | __FUNCTION__, slot->hotplug_slot->name); | 422 | __FUNCTION__, slot->hotplug_slot->name); |
| 413 | if(cpci_check_and_clear_ins(slot)) { | 423 | if (cpci_check_and_clear_ins(slot)) { |
| 414 | u16 hs_csr; | 424 | /* |
| 415 | 425 | * Some broken hardware (e.g. PLX 9054AB) asserts | |
| 416 | /* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */ | 426 | * ENUM# twice... |
| 417 | if(slot->dev) { | 427 | */ |
| 418 | warn("slot %s already inserted", slot->hotplug_slot->name); | 428 | if (slot->dev) { |
| 429 | warn("slot %s already inserted", | ||
| 430 | slot->hotplug_slot->name); | ||
| 419 | inserted++; | 431 | inserted++; |
| 420 | continue; | 432 | continue; |
| 421 | } | 433 | } |
| @@ -432,7 +444,7 @@ check_slots(void) | |||
| 432 | /* Configure device */ | 444 | /* Configure device */ |
| 433 | dbg("%s - configuring slot %s", | 445 | dbg("%s - configuring slot %s", |
| 434 | __FUNCTION__, slot->hotplug_slot->name); | 446 | __FUNCTION__, slot->hotplug_slot->name); |
| 435 | if(cpci_configure_slot(slot)) { | 447 | if (cpci_configure_slot(slot)) { |
| 436 | err("%s - could not configure slot %s", | 448 | err("%s - could not configure slot %s", |
| 437 | __FUNCTION__, slot->hotplug_slot->name); | 449 | __FUNCTION__, slot->hotplug_slot->name); |
| 438 | continue; | 450 | continue; |
| @@ -445,13 +457,11 @@ check_slots(void) | |||
| 445 | dbg("%s - slot %s HS_CSR (2) = %04x", | 457 | dbg("%s - slot %s HS_CSR (2) = %04x", |
| 446 | __FUNCTION__, slot->hotplug_slot->name, hs_csr); | 458 | __FUNCTION__, slot->hotplug_slot->name, hs_csr); |
| 447 | 459 | ||
| 448 | if(update_latch_status(slot->hotplug_slot, 1)) { | 460 | if (update_latch_status(slot->hotplug_slot, 1)) |
| 449 | warn("failure to update latch file"); | 461 | warn("failure to update latch file"); |
| 450 | } | ||
| 451 | 462 | ||
| 452 | if(update_adapter_status(slot->hotplug_slot, 1)) { | 463 | if (update_adapter_status(slot->hotplug_slot, 1)) |
| 453 | warn("failure to update adapter file"); | 464 | warn("failure to update adapter file"); |
| 454 | } | ||
| 455 | 465 | ||
| 456 | cpci_led_off(slot); | 466 | cpci_led_off(slot); |
| 457 | 467 | ||
| @@ -461,9 +471,7 @@ check_slots(void) | |||
| 461 | __FUNCTION__, slot->hotplug_slot->name, hs_csr); | 471 | __FUNCTION__, slot->hotplug_slot->name, hs_csr); |
| 462 | 472 | ||
| 463 | inserted++; | 473 | inserted++; |
| 464 | } else if(cpci_check_ext(slot)) { | 474 | } else if (cpci_check_ext(slot)) { |
| 465 | u16 hs_csr; | ||
| 466 | |||
| 467 | /* Process extraction request */ | 475 | /* Process extraction request */ |
| 468 | dbg("%s - slot %s extracted", | 476 | dbg("%s - slot %s extracted", |
| 469 | __FUNCTION__, slot->hotplug_slot->name); | 477 | __FUNCTION__, slot->hotplug_slot->name); |
| @@ -473,23 +481,40 @@ check_slots(void) | |||
| 473 | dbg("%s - slot %s HS_CSR = %04x", | 481 | dbg("%s - slot %s HS_CSR = %04x", |
| 474 | __FUNCTION__, slot->hotplug_slot->name, hs_csr); | 482 | __FUNCTION__, slot->hotplug_slot->name, hs_csr); |
| 475 | 483 | ||
| 476 | if(!slot->extracting) { | 484 | if (!slot->extracting) { |
| 477 | if(update_latch_status(slot->hotplug_slot, 0)) { | 485 | if (update_latch_status(slot->hotplug_slot, 0)) { |
| 478 | warn("failure to update latch file"); | 486 | warn("failure to update latch file"); |
| 479 | } | 487 | } |
| 480 | slot->extracting = 1; | 488 | slot->extracting = 1; |
| 489 | atomic_inc(&extracting); | ||
| 481 | } | 490 | } |
| 482 | extracted++; | 491 | extracted++; |
| 492 | } else if (slot->extracting) { | ||
| 493 | hs_csr = cpci_get_hs_csr(slot); | ||
| 494 | if (hs_csr == 0xffff) { | ||
| 495 | /* | ||
| 496 | * Hmmm, we're likely hosed at this point, should we | ||
| 497 | * bother trying to tell the driver or not? | ||
| 498 | */ | ||
| 499 | err("card in slot %s was improperly removed", | ||
| 500 | slot->hotplug_slot->name); | ||
| 501 | if (update_adapter_status(slot->hotplug_slot, 0)) | ||
| 502 | warn("failure to update adapter file"); | ||
| 503 | slot->extracting = 0; | ||
| 504 | atomic_dec(&extracting); | ||
| 505 | } | ||
| 483 | } | 506 | } |
| 484 | } | 507 | } |
| 485 | spin_unlock(&list_lock); | 508 | up_read(&list_rwsem); |
| 486 | if(inserted || extracted) { | 509 | dbg("inserted=%d, extracted=%d, extracting=%d", |
| 510 | inserted, extracted, atomic_read(&extracting)); | ||
| 511 | if (inserted || extracted) | ||
| 487 | return extracted; | 512 | return extracted; |
| 488 | } | 513 | else if (!atomic_read(&extracting)) { |
| 489 | else { | ||
| 490 | err("cannot find ENUM# source, shutting down"); | 514 | err("cannot find ENUM# source, shutting down"); |
| 491 | return -1; | 515 | return -1; |
| 492 | } | 516 | } |
| 517 | return 0; | ||
| 493 | } | 518 | } |
| 494 | 519 | ||
| 495 | /* This is the interrupt mode worker thread body */ | 520 | /* This is the interrupt mode worker thread body */ |
| @@ -497,54 +522,37 @@ static int | |||
| 497 | event_thread(void *data) | 522 | event_thread(void *data) |
| 498 | { | 523 | { |
| 499 | int rc; | 524 | int rc; |
| 500 | struct slot *slot; | ||
| 501 | struct list_head *tmp; | ||
| 502 | 525 | ||
| 503 | lock_kernel(); | 526 | lock_kernel(); |
| 504 | daemonize("cpci_hp_eventd"); | 527 | daemonize("cpci_hp_eventd"); |
| 505 | unlock_kernel(); | 528 | unlock_kernel(); |
| 506 | 529 | ||
| 507 | dbg("%s - event thread started", __FUNCTION__); | 530 | dbg("%s - event thread started", __FUNCTION__); |
| 508 | while(1) { | 531 | while (1) { |
| 509 | dbg("event thread sleeping"); | 532 | dbg("event thread sleeping"); |
| 510 | down_interruptible(&event_semaphore); | 533 | down_interruptible(&event_semaphore); |
| 511 | dbg("event thread woken, thread_finished = %d", | 534 | dbg("event thread woken, thread_finished = %d", |
| 512 | thread_finished); | 535 | thread_finished); |
| 513 | if(thread_finished || signal_pending(current)) | 536 | if (thread_finished || signal_pending(current)) |
| 514 | break; | 537 | break; |
| 515 | while(controller->ops->query_enum()) { | 538 | do { |
| 516 | rc = check_slots(); | 539 | rc = check_slots(); |
| 517 | if (rc > 0) | 540 | if (rc > 0) { |
| 518 | /* Give userspace a chance to handle extraction */ | 541 | /* Give userspace a chance to handle extraction */ |
| 519 | msleep(500); | 542 | msleep(500); |
| 520 | else if (rc < 0) { | 543 | } else if (rc < 0) { |
| 521 | dbg("%s - error checking slots", __FUNCTION__); | 544 | dbg("%s - error checking slots", __FUNCTION__); |
| 522 | thread_finished = 1; | 545 | thread_finished = 1; |
| 523 | break; | 546 | break; |
| 524 | } | 547 | } |
| 525 | } | 548 | } while (atomic_read(&extracting) && !thread_finished); |
| 526 | /* Check for someone yanking out a board */ | 549 | if (thread_finished) |
| 527 | list_for_each(tmp, &slot_list) { | 550 | break; |
| 528 | slot = list_entry(tmp, struct slot, slot_list); | ||
| 529 | if(slot->extracting) { | ||
| 530 | /* | ||
| 531 | * Hmmm, we're likely hosed at this point, should we | ||
| 532 | * bother trying to tell the driver or not? | ||
| 533 | */ | ||
| 534 | err("card in slot %s was improperly removed", | ||
| 535 | slot->hotplug_slot->name); | ||
| 536 | if(update_adapter_status(slot->hotplug_slot, 0)) { | ||
| 537 | warn("failure to update adapter file"); | ||
| 538 | } | ||
| 539 | slot->extracting = 0; | ||
| 540 | } | ||
| 541 | } | ||
| 542 | 551 | ||
| 543 | /* Re-enable ENUM# interrupt */ | 552 | /* Re-enable ENUM# interrupt */ |
| 544 | dbg("%s - re-enabling irq", __FUNCTION__); | 553 | dbg("%s - re-enabling irq", __FUNCTION__); |
| 545 | controller->ops->enable_irq(); | 554 | controller->ops->enable_irq(); |
| 546 | } | 555 | } |
| 547 | |||
| 548 | dbg("%s - event thread signals exit", __FUNCTION__); | 556 | dbg("%s - event thread signals exit", __FUNCTION__); |
| 549 | up(&thread_exit); | 557 | up(&thread_exit); |
| 550 | return 0; | 558 | return 0; |
| @@ -555,45 +563,27 @@ static int | |||
| 555 | poll_thread(void *data) | 563 | poll_thread(void *data) |
| 556 | { | 564 | { |
| 557 | int rc; | 565 | int rc; |
| 558 | struct slot *slot; | ||
| 559 | struct list_head *tmp; | ||
| 560 | 566 | ||
| 561 | lock_kernel(); | 567 | lock_kernel(); |
| 562 | daemonize("cpci_hp_polld"); | 568 | daemonize("cpci_hp_polld"); |
| 563 | unlock_kernel(); | 569 | unlock_kernel(); |
| 564 | 570 | ||
| 565 | while(1) { | 571 | while (1) { |
| 566 | if(thread_finished || signal_pending(current)) | 572 | if (thread_finished || signal_pending(current)) |
| 567 | break; | 573 | break; |
| 568 | 574 | if (controller->ops->query_enum()) { | |
| 569 | while(controller->ops->query_enum()) { | 575 | do { |
| 570 | rc = check_slots(); | 576 | rc = check_slots(); |
| 571 | if(rc > 0) | 577 | if (rc > 0) { |
| 572 | /* Give userspace a chance to handle extraction */ | 578 | /* Give userspace a chance to handle extraction */ |
| 573 | msleep(500); | 579 | msleep(500); |
| 574 | else if (rc < 0) { | 580 | } else if (rc < 0) { |
| 575 | dbg("%s - error checking slots", __FUNCTION__); | 581 | dbg("%s - error checking slots", __FUNCTION__); |
| 576 | thread_finished = 1; | 582 | thread_finished = 1; |
| 577 | break; | 583 | break; |
| 578 | } | ||
| 579 | } | ||
| 580 | /* Check for someone yanking out a board */ | ||
| 581 | list_for_each(tmp, &slot_list) { | ||
| 582 | slot = list_entry(tmp, struct slot, slot_list); | ||
| 583 | if(slot->extracting) { | ||
| 584 | /* | ||
| 585 | * Hmmm, we're likely hosed at this point, should we | ||
| 586 | * bother trying to tell the driver or not? | ||
| 587 | */ | ||
| 588 | err("card in slot %s was improperly removed", | ||
| 589 | slot->hotplug_slot->name); | ||
| 590 | if(update_adapter_status(slot->hotplug_slot, 0)) { | ||
| 591 | warn("failure to update adapter file"); | ||
| 592 | } | 584 | } |
| 593 | slot->extracting = 0; | 585 | } while (atomic_read(&extracting) && !thread_finished); |
| 594 | } | ||
| 595 | } | 586 | } |
| 596 | |||
| 597 | msleep(100); | 587 | msleep(100); |
| 598 | } | 588 | } |
| 599 | dbg("poll thread signals exit"); | 589 | dbg("poll thread signals exit"); |
| @@ -611,12 +601,11 @@ cpci_start_thread(void) | |||
| 611 | init_MUTEX_LOCKED(&thread_exit); | 601 | init_MUTEX_LOCKED(&thread_exit); |
| 612 | thread_finished = 0; | 602 | thread_finished = 0; |
| 613 | 603 | ||
| 614 | if(controller->irq) { | 604 | if (controller->irq) |
| 615 | pid = kernel_thread(event_thread, NULL, 0); | 605 | pid = kernel_thread(event_thread, NULL, 0); |
| 616 | } else { | 606 | else |
| 617 | pid = kernel_thread(poll_thread, NULL, 0); | 607 | pid = kernel_thread(poll_thread, NULL, 0); |
| 618 | } | 608 | if (pid < 0) { |
| 619 | if(pid < 0) { | ||
| 620 | err("Can't start up our thread"); | 609 | err("Can't start up our thread"); |
| 621 | return -1; | 610 | return -1; |
| 622 | } | 611 | } |
| @@ -629,9 +618,8 @@ cpci_stop_thread(void) | |||
| 629 | { | 618 | { |
| 630 | thread_finished = 1; | 619 | thread_finished = 1; |
| 631 | dbg("thread finish command given"); | 620 | dbg("thread finish command given"); |
| 632 | if(controller->irq) { | 621 | if (controller->irq) |
| 633 | up(&event_semaphore); | 622 | up(&event_semaphore); |
| 634 | } | ||
| 635 | dbg("wait for thread to exit"); | 623 | dbg("wait for thread to exit"); |
| 636 | down(&thread_exit); | 624 | down(&thread_exit); |
| 637 | } | 625 | } |
| @@ -641,42 +629,67 @@ cpci_hp_register_controller(struct cpci_hp_controller *new_controller) | |||
| 641 | { | 629 | { |
| 642 | int status = 0; | 630 | int status = 0; |
| 643 | 631 | ||
| 644 | if(!controller) { | 632 | if (controller) |
| 645 | controller = new_controller; | 633 | return -1; |
| 646 | if(controller->irq) { | 634 | if (!(new_controller && new_controller->ops)) |
| 647 | if(request_irq(controller->irq, | 635 | return -EINVAL; |
| 648 | cpci_hp_intr, | 636 | if (new_controller->irq) { |
| 649 | controller->irq_flags, | 637 | if (!(new_controller->ops->enable_irq && |
| 650 | MY_NAME, controller->dev_id)) { | 638 | new_controller->ops->disable_irq)) |
| 651 | err("Can't get irq %d for the hotplug cPCI controller", controller->irq); | 639 | status = -EINVAL; |
| 652 | status = -ENODEV; | 640 | if (request_irq(new_controller->irq, |
| 653 | } | 641 | cpci_hp_intr, |
| 654 | dbg("%s - acquired controller irq %d", __FUNCTION__, | 642 | new_controller->irq_flags, |
| 655 | controller->irq); | 643 | MY_NAME, |
| 644 | new_controller->dev_id)) { | ||
| 645 | err("Can't get irq %d for the hotplug cPCI controller", | ||
| 646 | new_controller->irq); | ||
| 647 | status = -ENODEV; | ||
| 656 | } | 648 | } |
| 657 | } else { | 649 | dbg("%s - acquired controller irq %d", |
| 658 | err("cPCI hotplug controller already registered"); | 650 | __FUNCTION__, new_controller->irq); |
| 659 | status = -1; | ||
| 660 | } | 651 | } |
| 652 | if (!status) | ||
| 653 | controller = new_controller; | ||
| 661 | return status; | 654 | return status; |
| 662 | } | 655 | } |
| 663 | 656 | ||
| 657 | static void | ||
| 658 | cleanup_slots(void) | ||
| 659 | { | ||
| 660 | struct slot *slot; | ||
| 661 | struct slot *tmp; | ||
| 662 | |||
| 663 | /* | ||
| 664 | * Unregister all of our slots with the pci_hotplug subsystem, | ||
| 665 | * and free up all memory that we had allocated. | ||
| 666 | */ | ||
| 667 | down_write(&list_rwsem); | ||
| 668 | if (!slots) | ||
| 669 | goto cleanup_null; | ||
| 670 | list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) { | ||
| 671 | list_del(&slot->slot_list); | ||
| 672 | pci_hp_deregister(slot->hotplug_slot); | ||
| 673 | } | ||
| 674 | cleanup_null: | ||
| 675 | up_write(&list_rwsem); | ||
| 676 | return; | ||
| 677 | } | ||
| 678 | |||
| 664 | int | 679 | int |
| 665 | cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller) | 680 | cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller) |
| 666 | { | 681 | { |
| 667 | int status = 0; | 682 | int status = 0; |
| 668 | 683 | ||
| 669 | if(controller) { | 684 | if (controller) { |
| 670 | if(!thread_finished) { | 685 | if (!thread_finished) |
| 671 | cpci_stop_thread(); | 686 | cpci_stop_thread(); |
| 672 | } | 687 | if (controller->irq) |
| 673 | if(controller->irq) { | ||
| 674 | free_irq(controller->irq, controller->dev_id); | 688 | free_irq(controller->irq, controller->dev_id); |
| 675 | } | ||
| 676 | controller = NULL; | 689 | controller = NULL; |
| 677 | } else { | 690 | cleanup_slots(); |
| 691 | } else | ||
| 678 | status = -ENODEV; | 692 | status = -ENODEV; |
| 679 | } | ||
| 680 | return status; | 693 | return status; |
| 681 | } | 694 | } |
| 682 | 695 | ||
| @@ -687,32 +700,28 @@ cpci_hp_start(void) | |||
| 687 | int status; | 700 | int status; |
| 688 | 701 | ||
| 689 | dbg("%s - enter", __FUNCTION__); | 702 | dbg("%s - enter", __FUNCTION__); |
| 690 | if(!controller) { | 703 | if (!controller) |
| 691 | return -ENODEV; | 704 | return -ENODEV; |
| 692 | } | ||
| 693 | 705 | ||
| 694 | spin_lock(&list_lock); | 706 | down_read(&list_rwsem); |
| 695 | if(!slots) { | 707 | if (list_empty(&slot_list)) { |
| 696 | spin_unlock(&list_lock); | 708 | up_read(&list_rwsem); |
| 697 | return -ENODEV; | 709 | return -ENODEV; |
| 698 | } | 710 | } |
| 699 | spin_unlock(&list_lock); | 711 | up_read(&list_rwsem); |
| 700 | 712 | ||
| 701 | if(first) { | 713 | status = init_slots(first); |
| 702 | status = init_slots(); | 714 | if (first) |
| 703 | if(status) { | ||
| 704 | return status; | ||
| 705 | } | ||
| 706 | first = 0; | 715 | first = 0; |
| 707 | } | 716 | if (status) |
| 717 | return status; | ||
| 708 | 718 | ||
| 709 | status = cpci_start_thread(); | 719 | status = cpci_start_thread(); |
| 710 | if(status) { | 720 | if (status) |
| 711 | return status; | 721 | return status; |
| 712 | } | ||
| 713 | dbg("%s - thread started", __FUNCTION__); | 722 | dbg("%s - thread started", __FUNCTION__); |
| 714 | 723 | ||
| 715 | if(controller->irq) { | 724 | if (controller->irq) { |
| 716 | /* Start enum interrupt processing */ | 725 | /* Start enum interrupt processing */ |
| 717 | dbg("%s - enabling irq", __FUNCTION__); | 726 | dbg("%s - enabling irq", __FUNCTION__); |
| 718 | controller->ops->enable_irq(); | 727 | controller->ops->enable_irq(); |
| @@ -724,11 +733,9 @@ cpci_hp_start(void) | |||
| 724 | int | 733 | int |
| 725 | cpci_hp_stop(void) | 734 | cpci_hp_stop(void) |
| 726 | { | 735 | { |
| 727 | if(!controller) { | 736 | if (!controller) |
| 728 | return -ENODEV; | 737 | return -ENODEV; |
| 729 | } | 738 | if (controller->irq) { |
| 730 | |||
| 731 | if(controller->irq) { | ||
| 732 | /* Stop enum interrupt processing */ | 739 | /* Stop enum interrupt processing */ |
| 733 | dbg("%s - disabling irq", __FUNCTION__); | 740 | dbg("%s - disabling irq", __FUNCTION__); |
| 734 | controller->ops->disable_irq(); | 741 | controller->ops->disable_irq(); |
| @@ -737,41 +744,10 @@ cpci_hp_stop(void) | |||
| 737 | return 0; | 744 | return 0; |
| 738 | } | 745 | } |
| 739 | 746 | ||
| 740 | static void __exit | ||
| 741 | cleanup_slots(void) | ||
| 742 | { | ||
| 743 | struct list_head *tmp; | ||
| 744 | struct slot *slot; | ||
| 745 | |||
| 746 | /* | ||
| 747 | * Unregister all of our slots with the pci_hotplug subsystem, | ||
| 748 | * and free up all memory that we had allocated. | ||
| 749 | */ | ||
| 750 | spin_lock(&list_lock); | ||
| 751 | if(!slots) { | ||
| 752 | goto null_cleanup; | ||
| 753 | } | ||
| 754 | list_for_each(tmp, &slot_list) { | ||
| 755 | slot = list_entry(tmp, struct slot, slot_list); | ||
| 756 | list_del(&slot->slot_list); | ||
| 757 | pci_hp_deregister(slot->hotplug_slot); | ||
| 758 | kfree(slot->hotplug_slot->info); | ||
| 759 | kfree(slot->hotplug_slot->name); | ||
| 760 | kfree(slot->hotplug_slot); | ||
| 761 | kfree(slot); | ||
| 762 | } | ||
| 763 | null_cleanup: | ||
| 764 | spin_unlock(&list_lock); | ||
| 765 | return; | ||
| 766 | } | ||
| 767 | |||
| 768 | int __init | 747 | int __init |
| 769 | cpci_hotplug_init(int debug) | 748 | cpci_hotplug_init(int debug) |
| 770 | { | 749 | { |
| 771 | spin_lock_init(&list_lock); | ||
| 772 | cpci_debug = debug; | 750 | cpci_debug = debug; |
| 773 | |||
| 774 | info(DRIVER_DESC " version: " DRIVER_VERSION); | ||
| 775 | return 0; | 751 | return 0; |
| 776 | } | 752 | } |
| 777 | 753 | ||
| @@ -781,7 +757,8 @@ cpci_hotplug_exit(void) | |||
| 781 | /* | 757 | /* |
| 782 | * Clean everything up. | 758 | * Clean everything up. |
| 783 | */ | 759 | */ |
| 784 | cleanup_slots(); | 760 | cpci_hp_stop(); |
| 761 | cpci_hp_unregister_controller(controller); | ||
| 785 | } | 762 | } |
| 786 | 763 | ||
| 787 | EXPORT_SYMBOL_GPL(cpci_hp_register_controller); | 764 | 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 2e969616f298..c878028ad215 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * CompactPCI Hot Plug Driver PCI functions | 2 | * CompactPCI Hot Plug Driver PCI functions |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2002 by SOMA Networks, Inc. | 4 | * Copyright (C) 2002,2005 by SOMA Networks, Inc. |
| 5 | * | 5 | * |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| @@ -32,20 +32,16 @@ | |||
| 32 | #include "pci_hotplug.h" | 32 | #include "pci_hotplug.h" |
| 33 | #include "cpci_hotplug.h" | 33 | #include "cpci_hotplug.h" |
| 34 | 34 | ||
| 35 | #if !defined(MODULE) | ||
| 36 | #define MY_NAME "cpci_hotplug" | 35 | #define MY_NAME "cpci_hotplug" |
| 37 | #else | ||
| 38 | #define MY_NAME THIS_MODULE->name | ||
| 39 | #endif | ||
| 40 | 36 | ||
| 41 | extern int cpci_debug; | 37 | extern int cpci_debug; |
| 42 | 38 | ||
| 43 | #define dbg(format, arg...) \ | 39 | #define dbg(format, arg...) \ |
| 44 | do { \ | 40 | do { \ |
| 45 | if(cpci_debug) \ | 41 | if (cpci_debug) \ |
| 46 | printk (KERN_DEBUG "%s: " format "\n", \ | 42 | printk (KERN_DEBUG "%s: " format "\n", \ |
| 47 | MY_NAME , ## arg); \ | 43 | MY_NAME , ## arg); \ |
| 48 | } while(0) | 44 | } while (0) |
| 49 | #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) | 45 | #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) |
| 50 | #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) | 46 | #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) |
| 51 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) | 47 | #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) | |||
| 61 | hs_cap = pci_bus_find_capability(slot->bus, | 57 | hs_cap = pci_bus_find_capability(slot->bus, |
| 62 | slot->devfn, | 58 | slot->devfn, |
| 63 | PCI_CAP_ID_CHSWP); | 59 | PCI_CAP_ID_CHSWP); |
| 64 | if(!hs_cap) { | 60 | if (!hs_cap) |
| 65 | return 0; | 61 | return 0; |
| 66 | } | ||
| 67 | 62 | ||
| 68 | if(pci_bus_read_config_word(slot->bus, | 63 | if (pci_bus_read_config_word(slot->bus, |
| 69 | slot->devfn, | 64 | slot->devfn, |
| 70 | hs_cap + 2, | 65 | hs_cap + 2, |
| 71 | &hs_csr)) { | 66 | &hs_csr)) |
| 72 | return 0; | 67 | return 0; |
| 73 | } | 68 | |
| 74 | return hs_csr & 0x0008 ? 1 : 0; | 69 | return hs_csr & 0x0008 ? 1 : 0; |
| 75 | } | 70 | } |
| 76 | 71 | ||
| @@ -82,27 +77,22 @@ int cpci_set_attention_status(struct slot* slot, int status) | |||
| 82 | hs_cap = pci_bus_find_capability(slot->bus, | 77 | hs_cap = pci_bus_find_capability(slot->bus, |
| 83 | slot->devfn, | 78 | slot->devfn, |
| 84 | PCI_CAP_ID_CHSWP); | 79 | PCI_CAP_ID_CHSWP); |
| 85 | if(!hs_cap) { | 80 | if (!hs_cap) |
| 86 | return 0; | 81 | return 0; |
| 87 | } | 82 | if (pci_bus_read_config_word(slot->bus, |
| 88 | |||
| 89 | if(pci_bus_read_config_word(slot->bus, | ||
| 90 | slot->devfn, | 83 | slot->devfn, |
| 91 | hs_cap + 2, | 84 | hs_cap + 2, |
| 92 | &hs_csr)) { | 85 | &hs_csr)) |
| 93 | return 0; | 86 | return 0; |
| 94 | } | 87 | if (status) |
| 95 | if(status) { | ||
| 96 | hs_csr |= HS_CSR_LOO; | 88 | hs_csr |= HS_CSR_LOO; |
| 97 | } else { | 89 | else |
| 98 | hs_csr &= ~HS_CSR_LOO; | 90 | hs_csr &= ~HS_CSR_LOO; |
| 99 | } | 91 | if (pci_bus_write_config_word(slot->bus, |
| 100 | if(pci_bus_write_config_word(slot->bus, | ||
| 101 | slot->devfn, | 92 | slot->devfn, |
| 102 | hs_cap + 2, | 93 | hs_cap + 2, |
| 103 | hs_csr)) { | 94 | hs_csr)) |
| 104 | return 0; | 95 | return 0; |
| 105 | } | ||
| 106 | return 1; | 96 | return 1; |
| 107 | } | 97 | } |
| 108 | 98 | ||
| @@ -114,51 +104,16 @@ u16 cpci_get_hs_csr(struct slot* slot) | |||
| 114 | hs_cap = pci_bus_find_capability(slot->bus, | 104 | hs_cap = pci_bus_find_capability(slot->bus, |
| 115 | slot->devfn, | 105 | slot->devfn, |
| 116 | PCI_CAP_ID_CHSWP); | 106 | PCI_CAP_ID_CHSWP); |
| 117 | if(!hs_cap) { | 107 | if (!hs_cap) |
| 118 | return 0xFFFF; | 108 | return 0xFFFF; |
| 119 | } | 109 | if (pci_bus_read_config_word(slot->bus, |
| 120 | |||
| 121 | if(pci_bus_read_config_word(slot->bus, | ||
| 122 | slot->devfn, | 110 | slot->devfn, |
| 123 | hs_cap + 2, | 111 | hs_cap + 2, |
| 124 | &hs_csr)) { | 112 | &hs_csr)) |
| 125 | return 0xFFFF; | 113 | return 0xFFFF; |
| 126 | } | ||
| 127 | return hs_csr; | 114 | return hs_csr; |
| 128 | } | 115 | } |
| 129 | 116 | ||
| 130 | #if 0 | ||
| 131 | u16 cpci_set_hs_csr(struct slot* slot, u16 hs_csr) | ||
| 132 | { | ||
| 133 | int hs_cap; | ||
| 134 | u16 new_hs_csr; | ||
| 135 | |||
| 136 | hs_cap = pci_bus_find_capability(slot->bus, | ||
| 137 | slot->devfn, | ||
| 138 | PCI_CAP_ID_CHSWP); | ||
| 139 | if(!hs_cap) { | ||
| 140 | return 0xFFFF; | ||
| 141 | } | ||
| 142 | |||
| 143 | /* Write out the new value */ | ||
| 144 | if(pci_bus_write_config_word(slot->bus, | ||
| 145 | slot->devfn, | ||
| 146 | hs_cap + 2, | ||
| 147 | hs_csr)) { | ||
| 148 | return 0xFFFF; | ||
| 149 | } | ||
| 150 | |||
| 151 | /* Read back what we just wrote out */ | ||
| 152 | if(pci_bus_read_config_word(slot->bus, | ||
| 153 | slot->devfn, | ||
| 154 | hs_cap + 2, | ||
| 155 | &new_hs_csr)) { | ||
| 156 | return 0xFFFF; | ||
| 157 | } | ||
| 158 | return new_hs_csr; | ||
| 159 | } | ||
| 160 | #endif | ||
| 161 | |||
| 162 | int cpci_check_and_clear_ins(struct slot* slot) | 117 | int cpci_check_and_clear_ins(struct slot* slot) |
| 163 | { | 118 | { |
| 164 | int hs_cap; | 119 | int hs_cap; |
| @@ -168,24 +123,22 @@ int cpci_check_and_clear_ins(struct slot* slot) | |||
| 168 | hs_cap = pci_bus_find_capability(slot->bus, | 123 | hs_cap = pci_bus_find_capability(slot->bus, |
| 169 | slot->devfn, | 124 | slot->devfn, |
| 170 | PCI_CAP_ID_CHSWP); | 125 | PCI_CAP_ID_CHSWP); |
| 171 | if(!hs_cap) { | 126 | if (!hs_cap) |
| 172 | return 0; | 127 | return 0; |
| 173 | } | 128 | if (pci_bus_read_config_word(slot->bus, |
| 174 | if(pci_bus_read_config_word(slot->bus, | ||
| 175 | slot->devfn, | 129 | slot->devfn, |
| 176 | hs_cap + 2, | 130 | hs_cap + 2, |
| 177 | &hs_csr)) { | 131 | &hs_csr)) |
| 178 | return 0; | 132 | return 0; |
| 179 | } | 133 | if (hs_csr & HS_CSR_INS) { |
| 180 | if(hs_csr & HS_CSR_INS) { | ||
| 181 | /* Clear INS (by setting it) */ | 134 | /* Clear INS (by setting it) */ |
| 182 | if(pci_bus_write_config_word(slot->bus, | 135 | if (pci_bus_write_config_word(slot->bus, |
| 183 | slot->devfn, | 136 | slot->devfn, |
| 184 | hs_cap + 2, | 137 | hs_cap + 2, |
| 185 | hs_csr)) { | 138 | hs_csr)) |
| 186 | ins = 0; | 139 | ins = 0; |
| 187 | } | 140 | else |
| 188 | ins = 1; | 141 | ins = 1; |
| 189 | } | 142 | } |
| 190 | return ins; | 143 | return ins; |
| 191 | } | 144 | } |
| @@ -199,18 +152,15 @@ int cpci_check_ext(struct slot* slot) | |||
| 199 | hs_cap = pci_bus_find_capability(slot->bus, | 152 | hs_cap = pci_bus_find_capability(slot->bus, |
| 200 | slot->devfn, | 153 | slot->devfn, |
| 201 | PCI_CAP_ID_CHSWP); | 154 | PCI_CAP_ID_CHSWP); |
| 202 | if(!hs_cap) { | 155 | if (!hs_cap) |
| 203 | return 0; | 156 | return 0; |
| 204 | } | 157 | if (pci_bus_read_config_word(slot->bus, |
| 205 | if(pci_bus_read_config_word(slot->bus, | ||
| 206 | slot->devfn, | 158 | slot->devfn, |
| 207 | hs_cap + 2, | 159 | hs_cap + 2, |
| 208 | &hs_csr)) { | 160 | &hs_csr)) |
| 209 | return 0; | 161 | return 0; |
| 210 | } | 162 | if (hs_csr & HS_CSR_EXT) |
| 211 | if(hs_csr & HS_CSR_EXT) { | ||
| 212 | ext = 1; | 163 | ext = 1; |
| 213 | } | ||
| 214 | return ext; | 164 | return ext; |
| 215 | } | 165 | } |
| 216 | 166 | ||
| @@ -222,23 +172,20 @@ int cpci_clear_ext(struct slot* slot) | |||
| 222 | hs_cap = pci_bus_find_capability(slot->bus, | 172 | hs_cap = pci_bus_find_capability(slot->bus, |
| 223 | slot->devfn, | 173 | slot->devfn, |
| 224 | PCI_CAP_ID_CHSWP); | 174 | PCI_CAP_ID_CHSWP); |
| 225 | if(!hs_cap) { | 175 | if (!hs_cap) |
| 226 | return -ENODEV; | 176 | return -ENODEV; |
| 227 | } | 177 | if (pci_bus_read_config_word(slot->bus, |
| 228 | if(pci_bus_read_config_word(slot->bus, | ||
| 229 | slot->devfn, | 178 | slot->devfn, |
| 230 | hs_cap + 2, | 179 | hs_cap + 2, |
| 231 | &hs_csr)) { | 180 | &hs_csr)) |
| 232 | return -ENODEV; | 181 | return -ENODEV; |
| 233 | } | 182 | if (hs_csr & HS_CSR_EXT) { |
| 234 | if(hs_csr & HS_CSR_EXT) { | ||
| 235 | /* Clear EXT (by setting it) */ | 183 | /* Clear EXT (by setting it) */ |
| 236 | if(pci_bus_write_config_word(slot->bus, | 184 | if (pci_bus_write_config_word(slot->bus, |
| 237 | slot->devfn, | 185 | slot->devfn, |
| 238 | hs_cap + 2, | 186 | hs_cap + 2, |
| 239 | hs_csr)) { | 187 | hs_csr)) |
| 240 | return -ENODEV; | 188 | return -ENODEV; |
| 241 | } | ||
| 242 | } | 189 | } |
| 243 | return 0; | 190 | return 0; |
| 244 | } | 191 | } |
| @@ -251,19 +198,16 @@ int cpci_led_on(struct slot* slot) | |||
| 251 | hs_cap = pci_bus_find_capability(slot->bus, | 198 | hs_cap = pci_bus_find_capability(slot->bus, |
| 252 | slot->devfn, | 199 | slot->devfn, |
| 253 | PCI_CAP_ID_CHSWP); | 200 | PCI_CAP_ID_CHSWP); |
| 254 | if(!hs_cap) { | 201 | if (!hs_cap) |
| 255 | return -ENODEV; | 202 | return -ENODEV; |
| 256 | } | 203 | if (pci_bus_read_config_word(slot->bus, |
| 257 | if(pci_bus_read_config_word(slot->bus, | ||
| 258 | slot->devfn, | 204 | slot->devfn, |
| 259 | hs_cap + 2, | 205 | hs_cap + 2, |
| 260 | &hs_csr)) { | 206 | &hs_csr)) |
| 261 | return -ENODEV; | 207 | return -ENODEV; |
| 262 | } | 208 | if ((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) { |
| 263 | if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) { | ||
| 264 | /* Set LOO */ | ||
| 265 | hs_csr |= HS_CSR_LOO; | 209 | hs_csr |= HS_CSR_LOO; |
| 266 | if(pci_bus_write_config_word(slot->bus, | 210 | if (pci_bus_write_config_word(slot->bus, |
| 267 | slot->devfn, | 211 | slot->devfn, |
| 268 | hs_cap + 2, | 212 | hs_cap + 2, |
| 269 | hs_csr)) { | 213 | hs_csr)) { |
| @@ -283,19 +227,16 @@ int cpci_led_off(struct slot* slot) | |||
| 283 | hs_cap = pci_bus_find_capability(slot->bus, | 227 | hs_cap = pci_bus_find_capability(slot->bus, |
| 284 | slot->devfn, | 228 | slot->devfn, |
| 285 | PCI_CAP_ID_CHSWP); | 229 | PCI_CAP_ID_CHSWP); |
| 286 | if(!hs_cap) { | 230 | if (!hs_cap) |
| 287 | return -ENODEV; | 231 | return -ENODEV; |
| 288 | } | 232 | if (pci_bus_read_config_word(slot->bus, |
| 289 | if(pci_bus_read_config_word(slot->bus, | ||
| 290 | slot->devfn, | 233 | slot->devfn, |
| 291 | hs_cap + 2, | 234 | hs_cap + 2, |
| 292 | &hs_csr)) { | 235 | &hs_csr)) |
| 293 | return -ENODEV; | 236 | return -ENODEV; |
| 294 | } | 237 | if (hs_csr & HS_CSR_LOO) { |
| 295 | if(hs_csr & HS_CSR_LOO) { | ||
| 296 | /* Clear LOO */ | ||
| 297 | hs_csr &= ~HS_CSR_LOO; | 238 | hs_csr &= ~HS_CSR_LOO; |
| 298 | if(pci_bus_write_config_word(slot->bus, | 239 | if (pci_bus_write_config_word(slot->bus, |
| 299 | slot->devfn, | 240 | slot->devfn, |
| 300 | hs_cap + 2, | 241 | hs_cap + 2, |
| 301 | hs_csr)) { | 242 | hs_csr)) { |
| @@ -312,268 +253,21 @@ int cpci_led_off(struct slot* slot) | |||
| 312 | * Device configuration functions | 253 | * Device configuration functions |
| 313 | */ | 254 | */ |
| 314 | 255 | ||
| 315 | static int cpci_configure_dev(struct pci_bus *bus, struct pci_dev *dev) | ||
| 316 | { | ||
| 317 | u8 irq_pin; | ||
| 318 | int r; | ||
| 319 | |||
| 320 | dbg("%s - enter", __FUNCTION__); | ||
| 321 | |||
| 322 | /* NOTE: device already setup from prior scan */ | ||
| 323 | |||
| 324 | /* FIXME: How would we know if we need to enable the expansion ROM? */ | ||
| 325 | pci_write_config_word(dev, PCI_ROM_ADDRESS, 0x00L); | ||
| 326 | |||
| 327 | /* Assign resources */ | ||
| 328 | dbg("assigning resources for %02x:%02x.%x", | ||
| 329 | dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); | ||
| 330 | for (r = 0; r < 6; r++) { | ||
| 331 | struct resource *res = dev->resource + r; | ||
| 332 | if(res->flags) | ||
| 333 | pci_assign_resource(dev, r); | ||
| 334 | } | ||
| 335 | dbg("finished assigning resources for %02x:%02x.%x", | ||
| 336 | dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); | ||
| 337 | |||
| 338 | /* Does this function have an interrupt at all? */ | ||
| 339 | dbg("checking for function interrupt"); | ||
| 340 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin); | ||
| 341 | if(irq_pin) { | ||
| 342 | dbg("function uses interrupt pin %d", irq_pin); | ||
| 343 | } | ||
| 344 | |||
| 345 | /* | ||
| 346 | * Need to explicitly set irq field to 0 so that it'll get assigned | ||
| 347 | * by the pcibios platform dependent code called by pci_enable_device. | ||
| 348 | */ | ||
| 349 | dev->irq = 0; | ||
| 350 | |||
| 351 | dbg("enabling device"); | ||
| 352 | pci_enable_device(dev); /* XXX check return */ | ||
| 353 | dbg("now dev->irq = %d", dev->irq); | ||
| 354 | if(irq_pin && dev->irq) { | ||
| 355 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
| 356 | } | ||
| 357 | |||
| 358 | /* Can't use pci_insert_device at the moment, do it manually for now */ | ||
| 359 | pci_proc_attach_device(dev); | ||
| 360 | dbg("notifying drivers"); | ||
| 361 | //pci_announce_device_to_drivers(dev); | ||
| 362 | dbg("%s - exit", __FUNCTION__); | ||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | static int cpci_configure_bridge(struct pci_bus* bus, struct pci_dev* dev) | ||
| 367 | { | ||
| 368 | int rc; | ||
| 369 | struct pci_bus* child; | ||
| 370 | struct resource* r; | ||
| 371 | u8 max, n; | ||
| 372 | u16 command; | ||
| 373 | |||
| 374 | dbg("%s - enter", __FUNCTION__); | ||
| 375 | |||
| 376 | /* Do basic bridge initialization */ | ||
| 377 | rc = pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40); | ||
| 378 | if(rc) { | ||
| 379 | printk(KERN_ERR "%s - write of PCI_LATENCY_TIMER failed\n", __FUNCTION__); | ||
| 380 | } | ||
| 381 | rc = pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x40); | ||
| 382 | if(rc) { | ||
| 383 | printk(KERN_ERR "%s - write of PCI_SEC_LATENCY_TIMER failed\n", __FUNCTION__); | ||
| 384 | } | ||
| 385 | rc = pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4); | ||
| 386 | if(rc) { | ||
| 387 | printk(KERN_ERR "%s - write of PCI_CACHE_LINE_SIZE failed\n", __FUNCTION__); | ||
| 388 | } | ||
| 389 | |||
| 390 | /* | ||
| 391 | * Set parent bridge's subordinate field so that configuration space | ||
| 392 | * access will work in pci_scan_bridge and friends. | ||
| 393 | */ | ||
| 394 | max = pci_max_busnr(); | ||
| 395 | bus->subordinate = max + 1; | ||
| 396 | pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, max + 1); | ||
| 397 | |||
| 398 | /* Scan behind bridge */ | ||
| 399 | n = pci_scan_bridge(bus, dev, max, 2); | ||
| 400 | child = pci_find_bus(0, max + 1); | ||
| 401 | if (!child) | ||
| 402 | return -ENODEV; | ||
| 403 | pci_proc_attach_bus(child); | ||
| 404 | |||
| 405 | /* | ||
| 406 | * Update parent bridge's subordinate field if there were more bridges | ||
| 407 | * behind the bridge that was scanned. | ||
| 408 | */ | ||
| 409 | if(n > max) { | ||
| 410 | bus->subordinate = n; | ||
| 411 | pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, n); | ||
| 412 | } | ||
| 413 | |||
| 414 | /* | ||
| 415 | * Update the bridge resources of the bridge to accommodate devices | ||
| 416 | * behind it. | ||
| 417 | */ | ||
| 418 | pci_bus_size_bridges(child); | ||
| 419 | pci_bus_assign_resources(child); | ||
| 420 | |||
| 421 | /* Enable resource mapping via command register */ | ||
| 422 | command = PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR; | ||
| 423 | r = child->resource[0]; | ||
| 424 | if(r && r->start) { | ||
| 425 | command |= PCI_COMMAND_IO; | ||
| 426 | } | ||
| 427 | r = child->resource[1]; | ||
| 428 | if(r && r->start) { | ||
| 429 | command |= PCI_COMMAND_MEMORY; | ||
| 430 | } | ||
| 431 | r = child->resource[2]; | ||
| 432 | if(r && r->start) { | ||
| 433 | command |= PCI_COMMAND_MEMORY; | ||
| 434 | } | ||
| 435 | rc = pci_write_config_word(dev, PCI_COMMAND, command); | ||
| 436 | if(rc) { | ||
| 437 | err("Error setting command register"); | ||
| 438 | return rc; | ||
| 439 | } | ||
| 440 | |||
| 441 | /* Set bridge control register */ | ||
| 442 | command = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA; | ||
| 443 | rc = pci_write_config_word(dev, PCI_BRIDGE_CONTROL, command); | ||
| 444 | if(rc) { | ||
| 445 | err("Error setting bridge control register"); | ||
| 446 | return rc; | ||
| 447 | } | ||
| 448 | dbg("%s - exit", __FUNCTION__); | ||
| 449 | return 0; | ||
| 450 | } | ||
| 451 | |||
| 452 | static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev, | ||
| 453 | struct pci_bus_wrapped *wrapped_bus) | ||
| 454 | { | ||
| 455 | int rc; | ||
| 456 | struct pci_dev *dev = wrapped_dev->dev; | ||
| 457 | struct pci_bus *bus = wrapped_bus->bus; | ||
| 458 | struct slot* slot; | ||
| 459 | |||
| 460 | dbg("%s - enter", __FUNCTION__); | ||
| 461 | |||
| 462 | /* | ||
| 463 | * We need to fix up the hotplug representation with the Linux | ||
| 464 | * representation. | ||
| 465 | */ | ||
| 466 | if(wrapped_dev->data) { | ||
| 467 | slot = (struct slot*) wrapped_dev->data; | ||
| 468 | slot->dev = dev; | ||
| 469 | } | ||
| 470 | |||
| 471 | /* If it's a bridge, scan behind it for devices */ | ||
| 472 | if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | ||
| 473 | rc = cpci_configure_bridge(bus, dev); | ||
| 474 | if(rc) | ||
| 475 | return rc; | ||
| 476 | } | ||
| 477 | |||
| 478 | /* Actually configure device */ | ||
| 479 | if(dev) { | ||
| 480 | rc = cpci_configure_dev(bus, dev); | ||
| 481 | if(rc) | ||
| 482 | return rc; | ||
| 483 | } | ||
| 484 | dbg("%s - exit", __FUNCTION__); | ||
| 485 | return 0; | ||
| 486 | } | ||
| 487 | |||
| 488 | static int unconfigure_visit_pci_dev_phase2(struct pci_dev_wrapped *wrapped_dev, | ||
| 489 | struct pci_bus_wrapped *wrapped_bus) | ||
| 490 | { | ||
| 491 | struct pci_dev *dev = wrapped_dev->dev; | ||
| 492 | struct slot* slot; | ||
| 493 | |||
| 494 | dbg("%s - enter", __FUNCTION__); | ||
| 495 | if(!dev) | ||
| 496 | return -ENODEV; | ||
| 497 | |||
| 498 | /* Remove the Linux representation */ | ||
| 499 | if(pci_remove_device_safe(dev)) { | ||
| 500 | err("Could not remove device\n"); | ||
| 501 | return -1; | ||
| 502 | } | ||
| 503 | |||
| 504 | /* | ||
| 505 | * Now remove the hotplug representation. | ||
| 506 | */ | ||
| 507 | if(wrapped_dev->data) { | ||
| 508 | slot = (struct slot*) wrapped_dev->data; | ||
| 509 | slot->dev = NULL; | ||
| 510 | } else { | ||
| 511 | dbg("No hotplug representation for %02x:%02x.%x", | ||
| 512 | dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); | ||
| 513 | } | ||
| 514 | dbg("%s - exit", __FUNCTION__); | ||
| 515 | return 0; | ||
| 516 | } | ||
| 517 | |||
| 518 | static int unconfigure_visit_pci_bus_phase2(struct pci_bus_wrapped *wrapped_bus, | ||
| 519 | struct pci_dev_wrapped *wrapped_dev) | ||
| 520 | { | ||
| 521 | struct pci_bus *bus = wrapped_bus->bus; | ||
| 522 | struct pci_bus *parent = bus->self->bus; | ||
| 523 | |||
| 524 | dbg("%s - enter", __FUNCTION__); | ||
| 525 | |||
| 526 | /* The cleanup code for proc entries regarding buses should be in the kernel... */ | ||
| 527 | if(bus->procdir) | ||
| 528 | dbg("detach_pci_bus %s", bus->procdir->name); | ||
| 529 | pci_proc_detach_bus(bus); | ||
| 530 | |||
| 531 | /* The cleanup code should live in the kernel... */ | ||
| 532 | bus->self->subordinate = NULL; | ||
| 533 | |||
| 534 | /* unlink from parent bus */ | ||
| 535 | list_del(&bus->node); | ||
| 536 | |||
| 537 | /* Now, remove */ | ||
| 538 | if(bus) | ||
| 539 | kfree(bus); | ||
| 540 | |||
| 541 | /* Update parent's subordinate field */ | ||
| 542 | if(parent) { | ||
| 543 | u8 n = pci_bus_max_busnr(parent); | ||
| 544 | if(n < parent->subordinate) { | ||
| 545 | parent->subordinate = n; | ||
| 546 | pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, n); | ||
| 547 | } | ||
| 548 | } | ||
| 549 | dbg("%s - exit", __FUNCTION__); | ||
| 550 | return 0; | ||
| 551 | } | ||
| 552 | |||
| 553 | static struct pci_visit configure_functions = { | ||
| 554 | .visit_pci_dev = configure_visit_pci_dev, | ||
| 555 | }; | ||
| 556 | |||
| 557 | static struct pci_visit unconfigure_functions_phase2 = { | ||
| 558 | .post_visit_pci_bus = unconfigure_visit_pci_bus_phase2, | ||
| 559 | .post_visit_pci_dev = unconfigure_visit_pci_dev_phase2 | ||
| 560 | }; | ||
| 561 | |||
| 562 | |||
| 563 | int cpci_configure_slot(struct slot* slot) | 256 | int cpci_configure_slot(struct slot* slot) |
| 564 | { | 257 | { |
| 565 | int rc = 0; | 258 | unsigned char busnr; |
| 259 | struct pci_bus *child; | ||
| 566 | 260 | ||
| 567 | dbg("%s - enter", __FUNCTION__); | 261 | dbg("%s - enter", __FUNCTION__); |
| 568 | 262 | ||
| 569 | if(slot->dev == NULL) { | 263 | if (slot->dev == NULL) { |
| 570 | dbg("pci_dev null, finding %02x:%02x:%x", | 264 | dbg("pci_dev null, finding %02x:%02x:%x", |
| 571 | slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn)); | 265 | slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn)); |
| 572 | slot->dev = pci_find_slot(slot->bus->number, slot->devfn); | 266 | slot->dev = pci_get_slot(slot->bus, slot->devfn); |
| 573 | } | 267 | } |
| 574 | 268 | ||
| 575 | /* Still NULL? Well then scan for it! */ | 269 | /* Still NULL? Well then scan for it! */ |
| 576 | if(slot->dev == NULL) { | 270 | if (slot->dev == NULL) { |
| 577 | int n; | 271 | int n; |
| 578 | dbg("pci_dev still null"); | 272 | dbg("pci_dev still null"); |
| 579 | 273 | ||
| @@ -583,79 +277,47 @@ int cpci_configure_slot(struct slot* slot) | |||
| 583 | */ | 277 | */ |
| 584 | n = pci_scan_slot(slot->bus, slot->devfn); | 278 | n = pci_scan_slot(slot->bus, slot->devfn); |
| 585 | dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n); | 279 | dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n); |
| 586 | if(n > 0) | 280 | if (n > 0) |
| 587 | pci_bus_add_devices(slot->bus); | 281 | pci_bus_add_devices(slot->bus); |
| 588 | slot->dev = pci_find_slot(slot->bus->number, slot->devfn); | 282 | slot->dev = pci_get_slot(slot->bus, slot->devfn); |
| 589 | if(slot->dev == NULL) { | 283 | if (slot->dev == NULL) { |
| 590 | err("Could not find PCI device for slot %02x", slot->number); | 284 | err("Could not find PCI device for slot %02x", slot->number); |
| 591 | return 0; | 285 | return 1; |
| 592 | } | 286 | } |
| 593 | } | 287 | } |
| 594 | dbg("slot->dev = %p", slot->dev); | 288 | |
| 595 | if(slot->dev) { | 289 | if (slot->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { |
| 596 | struct pci_dev *dev; | 290 | pci_read_config_byte(slot->dev, PCI_SECONDARY_BUS, &busnr); |
| 597 | struct pci_dev_wrapped wrapped_dev; | 291 | child = pci_add_new_bus(slot->dev->bus, slot->dev, busnr); |
| 598 | struct pci_bus_wrapped wrapped_bus; | 292 | pci_do_scan_bus(child); |
| 599 | int i; | 293 | pci_bus_size_bridges(child); |
| 600 | |||
| 601 | memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped)); | ||
| 602 | memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped)); | ||
| 603 | |||
| 604 | for (i = 0; i < 8; i++) { | ||
| 605 | dev = pci_find_slot(slot->bus->number, | ||
| 606 | PCI_DEVFN(PCI_SLOT(slot->dev->devfn), i)); | ||
| 607 | if(!dev) | ||
| 608 | continue; | ||
| 609 | wrapped_dev.dev = dev; | ||
| 610 | wrapped_bus.bus = slot->dev->bus; | ||
| 611 | if(i) | ||
| 612 | wrapped_dev.data = NULL; | ||
| 613 | else | ||
| 614 | wrapped_dev.data = (void*) slot; | ||
| 615 | rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus); | ||
| 616 | } | ||
| 617 | } | 294 | } |
| 618 | 295 | ||
| 619 | dbg("%s - exit, rc = %d", __FUNCTION__, rc); | 296 | pci_bus_assign_resources(slot->dev->bus); |
| 620 | return rc; | 297 | |
| 298 | dbg("%s - exit", __FUNCTION__); | ||
| 299 | return 0; | ||
| 621 | } | 300 | } |
| 622 | 301 | ||
| 623 | int cpci_unconfigure_slot(struct slot* slot) | 302 | int cpci_unconfigure_slot(struct slot* slot) |
| 624 | { | 303 | { |
| 625 | int rc = 0; | ||
| 626 | int i; | 304 | int i; |
| 627 | struct pci_dev_wrapped wrapped_dev; | ||
| 628 | struct pci_bus_wrapped wrapped_bus; | ||
| 629 | struct pci_dev *dev; | 305 | struct pci_dev *dev; |
| 630 | 306 | ||
| 631 | dbg("%s - enter", __FUNCTION__); | 307 | dbg("%s - enter", __FUNCTION__); |
| 632 | 308 | if (!slot->dev) { | |
| 633 | if(!slot->dev) { | ||
| 634 | err("No device for slot %02x\n", slot->number); | 309 | err("No device for slot %02x\n", slot->number); |
| 635 | return -ENODEV; | 310 | return -ENODEV; |
| 636 | } | 311 | } |
| 637 | 312 | ||
| 638 | memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped)); | ||
| 639 | memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped)); | ||
| 640 | |||
| 641 | for (i = 0; i < 8; i++) { | 313 | for (i = 0; i < 8; i++) { |
| 642 | dev = pci_find_slot(slot->bus->number, | 314 | dev = pci_get_slot(slot->bus, |
| 643 | PCI_DEVFN(PCI_SLOT(slot->devfn), i)); | 315 | PCI_DEVFN(PCI_SLOT(slot->devfn), i)); |
| 644 | if(dev) { | 316 | if (dev) { |
| 645 | wrapped_dev.dev = dev; | 317 | pci_remove_bus_device(dev); |
| 646 | wrapped_bus.bus = dev->bus; | 318 | slot->dev = NULL; |
| 647 | if(i) | ||
| 648 | wrapped_dev.data = NULL; | ||
| 649 | else | ||
| 650 | wrapped_dev.data = (void*) slot; | ||
| 651 | dbg("%s - unconfigure phase 2", __FUNCTION__); | ||
| 652 | rc = pci_visit_dev(&unconfigure_functions_phase2, | ||
| 653 | &wrapped_dev, | ||
| 654 | &wrapped_bus); | ||
| 655 | if(rc) | ||
| 656 | break; | ||
| 657 | } | 319 | } |
| 658 | } | 320 | } |
| 659 | dbg("%s - exit, rc = %d", __FUNCTION__, rc); | 321 | dbg("%s - exit", __FUNCTION__); |
| 660 | return rc; | 322 | return 0; |
| 661 | } | 323 | } |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index f313121d5141..46b294a12418 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
| @@ -130,6 +130,7 @@ struct controller { | |||
| 130 | u8 slot_bus; /* Bus where the slots handled by this controller sit */ | 130 | u8 slot_bus; /* Bus where the slots handled by this controller sit */ |
| 131 | u8 ctrlcap; | 131 | u8 ctrlcap; |
| 132 | u16 vendor_id; | 132 | u16 vendor_id; |
| 133 | u8 cap_base; | ||
| 133 | }; | 134 | }; |
| 134 | 135 | ||
| 135 | struct irq_mapping { | 136 | struct irq_mapping { |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index ed1fd8d6178d..df4915dbc321 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) | |||
| 607 | static struct pcie_port_service_id port_pci_ids[] = { { | 607 | static struct pcie_port_service_id port_pci_ids[] = { { |
| 608 | .vendor = PCI_ANY_ID, | 608 | .vendor = PCI_ANY_ID, |
| 609 | .device = PCI_ANY_ID, | 609 | .device = PCI_ANY_ID, |
| 610 | .port_type = PCIE_RC_PORT, | 610 | .port_type = PCIE_ANY_PORT, |
| 611 | .service_type = PCIE_PORT_SERVICE_HP, | 611 | .service_type = PCIE_PORT_SERVICE_HP, |
| 612 | .driver_data = 0, | 612 | .driver_data = 0, |
| 613 | }, { /* end: all zeroes */ } | 613 | }, { /* end: all zeroes */ } |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 9e70c4681f77..1cda30bd6e47 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
| @@ -109,20 +109,20 @@ enum ctrl_offsets { | |||
| 109 | }; | 109 | }; |
| 110 | static int pcie_cap_base = 0; /* Base of the PCI Express capability item structure */ | 110 | static int pcie_cap_base = 0; /* Base of the PCI Express capability item structure */ |
| 111 | 111 | ||
| 112 | #define PCIE_CAP_ID ( pcie_cap_base + PCIECAPID ) | 112 | #define PCIE_CAP_ID(cb) ( cb + PCIECAPID ) |
| 113 | #define NXT_CAP_PTR ( pcie_cap_base + NXTCAPPTR ) | 113 | #define NXT_CAP_PTR(cb) ( cb + NXTCAPPTR ) |
| 114 | #define CAP_REG ( pcie_cap_base + CAPREG ) | 114 | #define CAP_REG(cb) ( cb + CAPREG ) |
| 115 | #define DEV_CAP ( pcie_cap_base + DEVCAP ) | 115 | #define DEV_CAP(cb) ( cb + DEVCAP ) |
| 116 | #define DEV_CTRL ( pcie_cap_base + DEVCTRL ) | 116 | #define DEV_CTRL(cb) ( cb + DEVCTRL ) |
| 117 | #define DEV_STATUS ( pcie_cap_base + DEVSTATUS ) | 117 | #define DEV_STATUS(cb) ( cb + DEVSTATUS ) |
| 118 | #define LNK_CAP ( pcie_cap_base + LNKCAP ) | 118 | #define LNK_CAP(cb) ( cb + LNKCAP ) |
| 119 | #define LNK_CTRL ( pcie_cap_base + LNKCTRL ) | 119 | #define LNK_CTRL(cb) ( cb + LNKCTRL ) |
| 120 | #define LNK_STATUS ( pcie_cap_base + LNKSTATUS ) | 120 | #define LNK_STATUS(cb) ( cb + LNKSTATUS ) |
| 121 | #define SLOT_CAP ( pcie_cap_base + SLOTCAP ) | 121 | #define SLOT_CAP(cb) ( cb + SLOTCAP ) |
| 122 | #define SLOT_CTRL ( pcie_cap_base + SLOTCTRL ) | 122 | #define SLOT_CTRL(cb) ( cb + SLOTCTRL ) |
| 123 | #define SLOT_STATUS ( pcie_cap_base + SLOTSTATUS ) | 123 | #define SLOT_STATUS(cb) ( cb + SLOTSTATUS ) |
| 124 | #define ROOT_CTRL ( pcie_cap_base + ROOTCTRL ) | 124 | #define ROOT_CTRL(cb) ( cb + ROOTCTRL ) |
| 125 | #define ROOT_STATUS ( pcie_cap_base + ROOTSTATUS ) | 125 | #define ROOT_STATUS(cb) ( cb + ROOTSTATUS ) |
| 126 | 126 | ||
| 127 | #define hp_register_read_word(pdev, reg , value) \ | 127 | #define hp_register_read_word(pdev, reg , value) \ |
| 128 | pci_read_config_word(pdev, reg, &value) | 128 | pci_read_config_word(pdev, reg, &value) |
| @@ -303,7 +303,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) | |||
| 303 | return -1; | 303 | return -1; |
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); | 306 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); |
| 307 | if (retval) { | 307 | if (retval) { |
| 308 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 308 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
| 309 | return retval; | 309 | return retval; |
| @@ -317,7 +317,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) | |||
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd); | 319 | dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd); |
| 320 | retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, cmd | CMD_CMPL_INTR_ENABLE); | 320 | retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE); |
| 321 | if (retval) { | 321 | if (retval) { |
| 322 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 322 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
| 323 | return retval; | 323 | return retval; |
| @@ -342,7 +342,7 @@ static int hpc_check_lnk_status(struct controller *ctrl) | |||
| 342 | return -1; | 342 | return -1; |
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status); | 345 | retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(ctrl->cap_base), lnk_status); |
| 346 | 346 | ||
| 347 | if (retval) { | 347 | if (retval) { |
| 348 | err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); | 348 | 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) | |||
| 376 | return -1; | 376 | return -1; |
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); | 379 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); |
| 380 | 380 | ||
| 381 | if (retval) { | 381 | if (retval) { |
| 382 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 382 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 383 | return retval; | 383 | return retval; |
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL, slot_ctrl); | 386 | dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); |
| 387 | 387 | ||
| 388 | atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6; | 388 | atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6; |
| 389 | 389 | ||
| @@ -423,13 +423,13 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) | |||
| 423 | return -1; | 423 | return -1; |
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); | 426 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); |
| 427 | 427 | ||
| 428 | if (retval) { | 428 | if (retval) { |
| 429 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 429 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 430 | return retval; | 430 | return retval; |
| 431 | } | 431 | } |
| 432 | dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl); | 432 | dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); |
| 433 | 433 | ||
| 434 | pwr_state = (slot_ctrl & PWR_CTRL) >> 10; | 434 | pwr_state = (slot_ctrl & PWR_CTRL) >> 10; |
| 435 | 435 | ||
| @@ -463,7 +463,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status) | |||
| 463 | return -1; | 463 | return -1; |
| 464 | } | 464 | } |
| 465 | 465 | ||
| 466 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); | 466 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); |
| 467 | 467 | ||
| 468 | if (retval) { | 468 | if (retval) { |
| 469 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 469 | 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) | |||
| 490 | return -1; | 490 | return -1; |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); | 493 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); |
| 494 | 494 | ||
| 495 | if (retval) { | 495 | if (retval) { |
| 496 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 496 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
| @@ -518,7 +518,7 @@ static int hpc_query_power_fault(struct slot * slot) | |||
| 518 | return -1; | 518 | return -1; |
| 519 | } | 519 | } |
| 520 | 520 | ||
| 521 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); | 521 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); |
| 522 | 522 | ||
| 523 | if (retval) { | 523 | if (retval) { |
| 524 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 524 | 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) | |||
| 549 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | 549 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); |
| 550 | return -1; | 550 | return -1; |
| 551 | } | 551 | } |
| 552 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); | 552 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); |
| 553 | 553 | ||
| 554 | if (rc) { | 554 | if (rc) { |
| 555 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 555 | 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) | |||
| 574 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | 574 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
| 575 | 575 | ||
| 576 | pcie_write_cmd(slot, slot_cmd); | 576 | pcie_write_cmd(slot, slot_cmd); |
| 577 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, slot_cmd); | 577 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
| 578 | 578 | ||
| 579 | return rc; | 579 | return rc; |
| 580 | } | 580 | } |
| @@ -598,7 +598,7 @@ static void hpc_set_green_led_on(struct slot *slot) | |||
| 598 | return ; | 598 | return ; |
| 599 | } | 599 | } |
| 600 | 600 | ||
| 601 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); | 601 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); |
| 602 | 602 | ||
| 603 | if (rc) { | 603 | if (rc) { |
| 604 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 604 | 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) | |||
| 611 | 611 | ||
| 612 | pcie_write_cmd(slot, slot_cmd); | 612 | pcie_write_cmd(slot, slot_cmd); |
| 613 | 613 | ||
| 614 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd); | 614 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
| 615 | return; | 615 | return; |
| 616 | } | 616 | } |
| 617 | 617 | ||
| @@ -633,7 +633,7 @@ static void hpc_set_green_led_off(struct slot *slot) | |||
| 633 | return ; | 633 | return ; |
| 634 | } | 634 | } |
| 635 | 635 | ||
| 636 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); | 636 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); |
| 637 | 637 | ||
| 638 | if (rc) { | 638 | if (rc) { |
| 639 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 639 | 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) | |||
| 646 | if (!pciehp_poll_mode) | 646 | if (!pciehp_poll_mode) |
| 647 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | 647 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
| 648 | pcie_write_cmd(slot, slot_cmd); | 648 | pcie_write_cmd(slot, slot_cmd); |
| 649 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, slot_cmd); | 649 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
| 650 | 650 | ||
| 651 | return; | 651 | return; |
| 652 | } | 652 | } |
| @@ -669,7 +669,7 @@ static void hpc_set_green_led_blink(struct slot *slot) | |||
| 669 | return ; | 669 | return ; |
| 670 | } | 670 | } |
| 671 | 671 | ||
| 672 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); | 672 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); |
| 673 | 673 | ||
| 674 | if (rc) { | 674 | if (rc) { |
| 675 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 675 | 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) | |||
| 683 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | 683 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
| 684 | pcie_write_cmd(slot, slot_cmd); | 684 | pcie_write_cmd(slot, slot_cmd); |
| 685 | 685 | ||
| 686 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd); | 686 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
| 687 | return; | 687 | return; |
| 688 | } | 688 | } |
| 689 | 689 | ||
| @@ -707,7 +707,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl, | |||
| 707 | *first_device_num = 0; | 707 | *first_device_num = 0; |
| 708 | *num_ctlr_slots = 1; | 708 | *num_ctlr_slots = 1; |
| 709 | 709 | ||
| 710 | rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap); | 710 | rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap); |
| 711 | 711 | ||
| 712 | if (rc) { | 712 | if (rc) { |
| 713 | err("%s : hp_register_read_dword SLOT_CAP failed\n", __FUNCTION__); | 713 | err("%s : hp_register_read_dword SLOT_CAP failed\n", __FUNCTION__); |
| @@ -793,13 +793,13 @@ static int hpc_power_on_slot(struct slot * slot) | |||
| 793 | return -1; | 793 | return -1; |
| 794 | } | 794 | } |
| 795 | 795 | ||
| 796 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); | 796 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); |
| 797 | 797 | ||
| 798 | if (retval) { | 798 | if (retval) { |
| 799 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 799 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 800 | return retval; | 800 | return retval; |
| 801 | } | 801 | } |
| 802 | dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL, | 802 | dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), |
| 803 | slot_ctrl); | 803 | slot_ctrl); |
| 804 | 804 | ||
| 805 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; | 805 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; |
| @@ -813,7 +813,7 @@ static int hpc_power_on_slot(struct slot * slot) | |||
| 813 | err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd); | 813 | err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd); |
| 814 | return -1; | 814 | return -1; |
| 815 | } | 815 | } |
| 816 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd); | 816 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
| 817 | 817 | ||
| 818 | DBG_LEAVE_ROUTINE | 818 | DBG_LEAVE_ROUTINE |
| 819 | 819 | ||
| @@ -842,13 +842,13 @@ static int hpc_power_off_slot(struct slot * slot) | |||
| 842 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | 842 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); |
| 843 | return -1; | 843 | return -1; |
| 844 | } | 844 | } |
| 845 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); | 845 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); |
| 846 | 846 | ||
| 847 | if (retval) { | 847 | if (retval) { |
| 848 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 848 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 849 | return retval; | 849 | return retval; |
| 850 | } | 850 | } |
| 851 | dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL, | 851 | dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), |
| 852 | slot_ctrl); | 852 | slot_ctrl); |
| 853 | 853 | ||
| 854 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; | 854 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; |
| @@ -862,7 +862,7 @@ static int hpc_power_off_slot(struct slot * slot) | |||
| 862 | err("%s: Write command failed!\n", __FUNCTION__); | 862 | err("%s: Write command failed!\n", __FUNCTION__); |
| 863 | return -1; | 863 | return -1; |
| 864 | } | 864 | } |
| 865 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd); | 865 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); |
| 866 | 866 | ||
| 867 | DBG_LEAVE_ROUTINE | 867 | DBG_LEAVE_ROUTINE |
| 868 | 868 | ||
| @@ -900,7 +900,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
| 900 | return IRQ_NONE; | 900 | return IRQ_NONE; |
| 901 | } | 901 | } |
| 902 | 902 | ||
| 903 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); | 903 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
| 904 | if (rc) { | 904 | if (rc) { |
| 905 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 905 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
| 906 | return IRQ_NONE; | 906 | return IRQ_NONE; |
| @@ -918,7 +918,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
| 918 | dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc); | 918 | dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc); |
| 919 | /* Mask Hot-plug Interrupt Enable */ | 919 | /* Mask Hot-plug Interrupt Enable */ |
| 920 | if (!pciehp_poll_mode) { | 920 | if (!pciehp_poll_mode) { |
| 921 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word); | 921 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); |
| 922 | if (rc) { | 922 | if (rc) { |
| 923 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 923 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 924 | return IRQ_NONE; | 924 | return IRQ_NONE; |
| @@ -928,14 +928,14 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
| 928 | dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | 928 | dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); |
| 929 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; | 929 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; |
| 930 | 930 | ||
| 931 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word); | 931 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); |
| 932 | if (rc) { | 932 | if (rc) { |
| 933 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 933 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
| 934 | return IRQ_NONE; | 934 | return IRQ_NONE; |
| 935 | } | 935 | } |
| 936 | dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | 936 | dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); |
| 937 | 937 | ||
| 938 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); | 938 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
| 939 | if (rc) { | 939 | if (rc) { |
| 940 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 940 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
| 941 | return IRQ_NONE; | 941 | return IRQ_NONE; |
| @@ -944,7 +944,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
| 944 | 944 | ||
| 945 | /* Clear command complete interrupt caused by this write */ | 945 | /* Clear command complete interrupt caused by this write */ |
| 946 | temp_word = 0x1f; | 946 | temp_word = 0x1f; |
| 947 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word); | 947 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); |
| 948 | if (rc) { | 948 | if (rc) { |
| 949 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 949 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); |
| 950 | return IRQ_NONE; | 950 | return IRQ_NONE; |
| @@ -975,14 +975,14 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
| 975 | 975 | ||
| 976 | /* Clear all events after serving them */ | 976 | /* Clear all events after serving them */ |
| 977 | temp_word = 0x1F; | 977 | temp_word = 0x1F; |
| 978 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word); | 978 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); |
| 979 | if (rc) { | 979 | if (rc) { |
| 980 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 980 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); |
| 981 | return IRQ_NONE; | 981 | return IRQ_NONE; |
| 982 | } | 982 | } |
| 983 | /* Unmask Hot-plug Interrupt Enable */ | 983 | /* Unmask Hot-plug Interrupt Enable */ |
| 984 | if (!pciehp_poll_mode) { | 984 | if (!pciehp_poll_mode) { |
| 985 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word); | 985 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); |
| 986 | if (rc) { | 986 | if (rc) { |
| 987 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 987 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 988 | return IRQ_NONE; | 988 | return IRQ_NONE; |
| @@ -992,14 +992,14 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
| 992 | dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | 992 | dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); |
| 993 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; | 993 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; |
| 994 | 994 | ||
| 995 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word); | 995 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); |
| 996 | if (rc) { | 996 | if (rc) { |
| 997 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 997 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
| 998 | return IRQ_NONE; | 998 | return IRQ_NONE; |
| 999 | } | 999 | } |
| 1000 | dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | 1000 | dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); |
| 1001 | 1001 | ||
| 1002 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); | 1002 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
| 1003 | if (rc) { | 1003 | if (rc) { |
| 1004 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 1004 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
| 1005 | return IRQ_NONE; | 1005 | return IRQ_NONE; |
| @@ -1008,7 +1008,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
| 1008 | 1008 | ||
| 1009 | /* Clear command complete interrupt caused by this write */ | 1009 | /* Clear command complete interrupt caused by this write */ |
| 1010 | temp_word = 0x1F; | 1010 | temp_word = 0x1F; |
| 1011 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word); | 1011 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); |
| 1012 | if (rc) { | 1012 | if (rc) { |
| 1013 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 1013 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); |
| 1014 | return IRQ_NONE; | 1014 | return IRQ_NONE; |
| @@ -1038,7 +1038,7 @@ static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value) | |||
| 1038 | return -1; | 1038 | return -1; |
| 1039 | } | 1039 | } |
| 1040 | 1040 | ||
| 1041 | retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap); | 1041 | retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap); |
| 1042 | 1042 | ||
| 1043 | if (retval) { | 1043 | if (retval) { |
| 1044 | err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__); | 1044 | 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 | |||
| 1079 | return -1; | 1079 | return -1; |
| 1080 | } | 1080 | } |
| 1081 | 1081 | ||
| 1082 | retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap); | 1082 | retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap); |
| 1083 | 1083 | ||
| 1084 | if (retval) { | 1084 | if (retval) { |
| 1085 | err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__); | 1085 | 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) | |||
| 1141 | return -1; | 1141 | return -1; |
| 1142 | } | 1142 | } |
| 1143 | 1143 | ||
| 1144 | retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status); | 1144 | retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status); |
| 1145 | 1145 | ||
| 1146 | if (retval) { | 1146 | if (retval) { |
| 1147 | err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); | 1147 | 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 | |||
| 1182 | return -1; | 1182 | return -1; |
| 1183 | } | 1183 | } |
| 1184 | 1184 | ||
| 1185 | retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status); | 1185 | retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status); |
| 1186 | 1186 | ||
| 1187 | if (retval) { | 1187 | if (retval) { |
| 1188 | err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); | 1188 | err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); |
| @@ -1292,47 +1292,48 @@ int pcie_init(struct controller * ctrl, | |||
| 1292 | goto abort_free_ctlr; | 1292 | goto abort_free_ctlr; |
| 1293 | } | 1293 | } |
| 1294 | 1294 | ||
| 1295 | pcie_cap_base = cap_base; | 1295 | ctrl->cap_base = cap_base; |
| 1296 | 1296 | ||
| 1297 | dbg("%s: pcie_cap_base %x\n", __FUNCTION__, pcie_cap_base); | 1297 | dbg("%s: pcie_cap_base %x\n", __FUNCTION__, pcie_cap_base); |
| 1298 | 1298 | ||
| 1299 | rc = hp_register_read_word(pdev, CAP_REG, cap_reg); | 1299 | rc = hp_register_read_word(pdev, CAP_REG(ctrl->cap_base), cap_reg); |
| 1300 | if (rc) { | 1300 | if (rc) { |
| 1301 | err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__); | 1301 | err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__); |
| 1302 | goto abort_free_ctlr; | 1302 | goto abort_free_ctlr; |
| 1303 | } | 1303 | } |
| 1304 | dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG, cap_reg); | 1304 | dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG(ctrl->cap_base), cap_reg); |
| 1305 | 1305 | ||
| 1306 | if (((cap_reg & SLOT_IMPL) == 0) || ((cap_reg & DEV_PORT_TYPE) != 0x0040)){ | 1306 | if (((cap_reg & SLOT_IMPL) == 0) || (((cap_reg & DEV_PORT_TYPE) != 0x0040) |
| 1307 | && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) { | ||
| 1307 | dbg("%s : This is not a root port or the port is not connected to a slot\n", __FUNCTION__); | 1308 | dbg("%s : This is not a root port or the port is not connected to a slot\n", __FUNCTION__); |
| 1308 | goto abort_free_ctlr; | 1309 | goto abort_free_ctlr; |
| 1309 | } | 1310 | } |
| 1310 | 1311 | ||
| 1311 | rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap); | 1312 | rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap); |
| 1312 | if (rc) { | 1313 | if (rc) { |
| 1313 | err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__); | 1314 | err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__); |
| 1314 | goto abort_free_ctlr; | 1315 | goto abort_free_ctlr; |
| 1315 | } | 1316 | } |
| 1316 | dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP, slot_cap); | 1317 | dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP(ctrl->cap_base), slot_cap); |
| 1317 | 1318 | ||
| 1318 | if (!(slot_cap & HP_CAP)) { | 1319 | if (!(slot_cap & HP_CAP)) { |
| 1319 | dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__); | 1320 | dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__); |
| 1320 | goto abort_free_ctlr; | 1321 | goto abort_free_ctlr; |
| 1321 | } | 1322 | } |
| 1322 | /* For debugging purpose */ | 1323 | /* For debugging purpose */ |
| 1323 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); | 1324 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
| 1324 | if (rc) { | 1325 | if (rc) { |
| 1325 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 1326 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
| 1326 | goto abort_free_ctlr; | 1327 | goto abort_free_ctlr; |
| 1327 | } | 1328 | } |
| 1328 | dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status); | 1329 | dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), slot_status); |
| 1329 | 1330 | ||
| 1330 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); | 1331 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), slot_ctrl); |
| 1331 | if (rc) { | 1332 | if (rc) { |
| 1332 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 1333 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 1333 | goto abort_free_ctlr; | 1334 | goto abort_free_ctlr; |
| 1334 | } | 1335 | } |
| 1335 | dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl); | 1336 | dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), slot_ctrl); |
| 1336 | 1337 | ||
| 1337 | if (first) { | 1338 | if (first) { |
| 1338 | spin_lock_init(&hpc_event_lock); | 1339 | spin_lock_init(&hpc_event_lock); |
| @@ -1372,36 +1373,37 @@ int pcie_init(struct controller * ctrl, | |||
| 1372 | php_ctlr->num_slots = 1; | 1373 | php_ctlr->num_slots = 1; |
| 1373 | 1374 | ||
| 1374 | /* Mask Hot-plug Interrupt Enable */ | 1375 | /* Mask Hot-plug Interrupt Enable */ |
| 1375 | rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word); | 1376 | rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); |
| 1376 | if (rc) { | 1377 | if (rc) { |
| 1377 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 1378 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 1378 | goto abort_free_ctlr; | 1379 | goto abort_free_ctlr; |
| 1379 | } | 1380 | } |
| 1380 | 1381 | ||
| 1381 | dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word); | 1382 | dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word); |
| 1382 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; | 1383 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; |
| 1383 | 1384 | ||
| 1384 | rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word); | 1385 | rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); |
| 1385 | if (rc) { | 1386 | if (rc) { |
| 1386 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 1387 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
| 1387 | goto abort_free_ctlr; | 1388 | goto abort_free_ctlr; |
| 1388 | } | 1389 | } |
| 1389 | dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word); | 1390 | dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word); |
| 1390 | 1391 | ||
| 1391 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); | 1392 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
| 1392 | if (rc) { | 1393 | if (rc) { |
| 1393 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 1394 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
| 1394 | goto abort_free_ctlr; | 1395 | goto abort_free_ctlr; |
| 1395 | } | 1396 | } |
| 1396 | dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status); | 1397 | dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base) |
| 1398 | , slot_status); | ||
| 1397 | 1399 | ||
| 1398 | temp_word = 0x1F; /* Clear all events */ | 1400 | temp_word = 0x1F; /* Clear all events */ |
| 1399 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word); | 1401 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); |
| 1400 | if (rc) { | 1402 | if (rc) { |
| 1401 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 1403 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); |
| 1402 | goto abort_free_ctlr; | 1404 | goto abort_free_ctlr; |
| 1403 | } | 1405 | } |
| 1404 | dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word); | 1406 | dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word); |
| 1405 | 1407 | ||
| 1406 | if (pciehp_poll_mode) {/* Install interrupt polling code */ | 1408 | if (pciehp_poll_mode) {/* Install interrupt polling code */ |
| 1407 | /* Install and start the interrupt polling timer */ | 1409 | /* Install and start the interrupt polling timer */ |
| @@ -1417,12 +1419,12 @@ int pcie_init(struct controller * ctrl, | |||
| 1417 | } | 1419 | } |
| 1418 | } | 1420 | } |
| 1419 | 1421 | ||
| 1420 | rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word); | 1422 | rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); |
| 1421 | if (rc) { | 1423 | if (rc) { |
| 1422 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 1424 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); |
| 1423 | goto abort_free_ctlr; | 1425 | goto abort_free_ctlr; |
| 1424 | } | 1426 | } |
| 1425 | dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word); | 1427 | dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word); |
| 1426 | dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap); | 1428 | dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap); |
| 1427 | 1429 | ||
| 1428 | intr_enable = intr_enable | PRSN_DETECT_ENABLE; | 1430 | intr_enable = intr_enable | PRSN_DETECT_ENABLE; |
| @@ -1446,27 +1448,27 @@ int pcie_init(struct controller * ctrl, | |||
| 1446 | dbg("%s: temp_word %x\n", __FUNCTION__, temp_word); | 1448 | dbg("%s: temp_word %x\n", __FUNCTION__, temp_word); |
| 1447 | 1449 | ||
| 1448 | /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */ | 1450 | /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */ |
| 1449 | rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word); | 1451 | rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); |
| 1450 | if (rc) { | 1452 | if (rc) { |
| 1451 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 1453 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); |
| 1452 | goto abort_free_ctlr; | 1454 | goto abort_free_ctlr; |
| 1453 | } | 1455 | } |
| 1454 | dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word); | 1456 | dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word); |
| 1455 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); | 1457 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); |
| 1456 | if (rc) { | 1458 | if (rc) { |
| 1457 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 1459 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); |
| 1458 | goto abort_free_ctlr; | 1460 | goto abort_free_ctlr; |
| 1459 | } | 1461 | } |
| 1460 | dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, | 1462 | dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, |
| 1461 | SLOT_STATUS, slot_status); | 1463 | SLOT_STATUS(ctrl->cap_base), slot_status); |
| 1462 | 1464 | ||
| 1463 | temp_word = 0x1F; /* Clear all events */ | 1465 | temp_word = 0x1F; /* Clear all events */ |
| 1464 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word); | 1466 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); |
| 1465 | if (rc) { | 1467 | if (rc) { |
| 1466 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 1468 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); |
| 1467 | goto abort_free_ctlr; | 1469 | goto abort_free_ctlr; |
| 1468 | } | 1470 | } |
| 1469 | dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word); | 1471 | dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word); |
| 1470 | 1472 | ||
| 1471 | /* Add this HPC instance into the HPC list */ | 1473 | /* Add this HPC instance into the HPC list */ |
| 1472 | spin_lock(&list_lock); | 1474 | spin_lock(&list_lock); |
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index f0c53f850aed..a70a5c5705f2 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 = { | |||
| 95 | */ | 95 | */ |
| 96 | static void release_slot(struct hotplug_slot *hotplug_slot) | 96 | static void release_slot(struct hotplug_slot *hotplug_slot) |
| 97 | { | 97 | { |
| 98 | struct slot *slot = (struct slot *)hotplug_slot->private; | 98 | struct slot *slot = hotplug_slot->private; |
| 99 | 99 | ||
| 100 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 100 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
| 101 | 101 | ||
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 9f90eb8e6ecd..490a9553a062 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) | |||
| 1885 | func = shpchp_slot_find(p_slot->bus, p_slot->device, 0); | 1885 | func = shpchp_slot_find(p_slot->bus, p_slot->device, 0); |
| 1886 | if (!func) { | 1886 | if (!func) { |
| 1887 | dbg("%s: Error! slot NULL\n", __FUNCTION__); | 1887 | dbg("%s: Error! slot NULL\n", __FUNCTION__); |
| 1888 | return 1; | 1888 | return -ENODEV; |
| 1889 | } | 1889 | } |
| 1890 | 1890 | ||
| 1891 | /* Check to see if (latch closed, card present, power off) */ | 1891 | /* Check to see if (latch closed, card present, power off) */ |
| @@ -1894,19 +1894,19 @@ int shpchp_enable_slot (struct slot *p_slot) | |||
| 1894 | if (rc || !getstatus) { | 1894 | if (rc || !getstatus) { |
| 1895 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); | 1895 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); |
| 1896 | up(&p_slot->ctrl->crit_sect); | 1896 | up(&p_slot->ctrl->crit_sect); |
| 1897 | return 1; | 1897 | return -ENODEV; |
| 1898 | } | 1898 | } |
| 1899 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 1899 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 1900 | if (rc || getstatus) { | 1900 | if (rc || getstatus) { |
| 1901 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); | 1901 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); |
| 1902 | up(&p_slot->ctrl->crit_sect); | 1902 | up(&p_slot->ctrl->crit_sect); |
| 1903 | return 1; | 1903 | return -ENODEV; |
| 1904 | } | 1904 | } |
| 1905 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 1905 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
| 1906 | if (rc || getstatus) { | 1906 | if (rc || getstatus) { |
| 1907 | info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); | 1907 | info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); |
| 1908 | up(&p_slot->ctrl->crit_sect); | 1908 | up(&p_slot->ctrl->crit_sect); |
| 1909 | return 1; | 1909 | return -ENODEV; |
| 1910 | } | 1910 | } |
| 1911 | up(&p_slot->ctrl->crit_sect); | 1911 | up(&p_slot->ctrl->crit_sect); |
| 1912 | 1912 | ||
| @@ -1914,7 +1914,7 @@ int shpchp_enable_slot (struct slot *p_slot) | |||
| 1914 | 1914 | ||
| 1915 | func = shpchp_slot_create(p_slot->bus); | 1915 | func = shpchp_slot_create(p_slot->bus); |
| 1916 | if (func == NULL) | 1916 | if (func == NULL) |
| 1917 | return 1; | 1917 | return -ENOMEM; |
| 1918 | 1918 | ||
| 1919 | func->bus = p_slot->bus; | 1919 | func->bus = p_slot->bus; |
| 1920 | func->device = p_slot->device; | 1920 | func->device = p_slot->device; |
| @@ -1939,7 +1939,7 @@ int shpchp_enable_slot (struct slot *p_slot) | |||
| 1939 | /* Setup slot structure with entry for empty slot */ | 1939 | /* Setup slot structure with entry for empty slot */ |
| 1940 | func = shpchp_slot_create(p_slot->bus); | 1940 | func = shpchp_slot_create(p_slot->bus); |
| 1941 | if (func == NULL) | 1941 | if (func == NULL) |
| 1942 | return (1); /* Out of memory */ | 1942 | return -ENOMEM; /* Out of memory */ |
| 1943 | 1943 | ||
| 1944 | func->bus = p_slot->bus; | 1944 | func->bus = p_slot->bus; |
| 1945 | func->device = p_slot->device; | 1945 | func->device = p_slot->device; |
| @@ -1972,7 +1972,7 @@ int shpchp_disable_slot (struct slot *p_slot) | |||
| 1972 | struct pci_func *func; | 1972 | struct pci_func *func; |
| 1973 | 1973 | ||
| 1974 | if (!p_slot->ctrl) | 1974 | if (!p_slot->ctrl) |
| 1975 | return 1; | 1975 | return -ENODEV; |
| 1976 | 1976 | ||
| 1977 | pci_bus = p_slot->ctrl->pci_dev->subordinate; | 1977 | pci_bus = p_slot->ctrl->pci_dev->subordinate; |
| 1978 | 1978 | ||
| @@ -1983,19 +1983,19 @@ int shpchp_disable_slot (struct slot *p_slot) | |||
| 1983 | if (ret || !getstatus) { | 1983 | if (ret || !getstatus) { |
| 1984 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); | 1984 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); |
| 1985 | up(&p_slot->ctrl->crit_sect); | 1985 | up(&p_slot->ctrl->crit_sect); |
| 1986 | return 1; | 1986 | return -ENODEV; |
| 1987 | } | 1987 | } |
| 1988 | ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 1988 | ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 1989 | if (ret || getstatus) { | 1989 | if (ret || getstatus) { |
| 1990 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); | 1990 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); |
| 1991 | up(&p_slot->ctrl->crit_sect); | 1991 | up(&p_slot->ctrl->crit_sect); |
| 1992 | return 1; | 1992 | return -ENODEV; |
| 1993 | } | 1993 | } |
| 1994 | ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 1994 | ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
| 1995 | if (ret || !getstatus) { | 1995 | if (ret || !getstatus) { |
| 1996 | info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); | 1996 | info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); |
| 1997 | up(&p_slot->ctrl->crit_sect); | 1997 | up(&p_slot->ctrl->crit_sect); |
| 1998 | return 1; | 1998 | return -ENODEV; |
| 1999 | } | 1999 | } |
| 2000 | up(&p_slot->ctrl->crit_sect); | 2000 | up(&p_slot->ctrl->crit_sect); |
| 2001 | 2001 | ||
| @@ -2011,7 +2011,7 @@ int shpchp_disable_slot (struct slot *p_slot) | |||
| 2011 | /* Check the Class Code */ | 2011 | /* Check the Class Code */ |
| 2012 | rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); | 2012 | rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); |
| 2013 | if (rc) | 2013 | if (rc) |
| 2014 | return rc; | 2014 | return -ENODEV; |
| 2015 | 2015 | ||
| 2016 | if (class_code == PCI_BASE_CLASS_DISPLAY) { | 2016 | if (class_code == PCI_BASE_CLASS_DISPLAY) { |
| 2017 | /* Display/Video adapter (not supported) */ | 2017 | /* Display/Video adapter (not supported) */ |
| @@ -2020,13 +2020,13 @@ int shpchp_disable_slot (struct slot *p_slot) | |||
| 2020 | /* See if it's a bridge */ | 2020 | /* See if it's a bridge */ |
| 2021 | rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); | 2021 | rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); |
| 2022 | if (rc) | 2022 | if (rc) |
| 2023 | return rc; | 2023 | return -ENODEV; |
| 2024 | 2024 | ||
| 2025 | /* If it's a bridge, check the VGA Enable bit */ | 2025 | /* If it's a bridge, check the VGA Enable bit */ |
| 2026 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { | 2026 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { |
| 2027 | rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR); | 2027 | rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR); |
| 2028 | if (rc) | 2028 | if (rc) |
| 2029 | return rc; | 2029 | return -ENODEV; |
| 2030 | 2030 | ||
| 2031 | /* If the VGA Enable bit is set, remove isn't supported */ | 2031 | /* If the VGA Enable bit is set, remove isn't supported */ |
| 2032 | if (BCR & PCI_BRIDGE_CTL_VGA) { | 2032 | if (BCR & PCI_BRIDGE_CTL_VGA) { |
| @@ -2042,12 +2042,12 @@ int shpchp_disable_slot (struct slot *p_slot) | |||
| 2042 | if ((func != NULL) && !rc) { | 2042 | if ((func != NULL) && !rc) { |
| 2043 | rc = remove_board(func, p_slot->ctrl); | 2043 | rc = remove_board(func, p_slot->ctrl); |
| 2044 | } else if (!rc) | 2044 | } else if (!rc) |
| 2045 | rc = 1; | 2045 | rc = -ENODEV; |
| 2046 | 2046 | ||
| 2047 | if (p_slot) | 2047 | if (p_slot) |
| 2048 | update_slot_info(p_slot); | 2048 | update_slot_info(p_slot); |
| 2049 | 2049 | ||
| 2050 | return(rc); | 2050 | return rc; |
| 2051 | } | 2051 | } |
| 2052 | 2052 | ||
| 2053 | 2053 | ||
diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c index 243a51d88b86..7957cdc72cd0 100644 --- a/drivers/pci/hotplug/shpchprm_acpi.c +++ b/drivers/pci/hotplug/shpchprm_acpi.c | |||
| @@ -1626,7 +1626,7 @@ int shpchprm_set_hpp( | |||
| 1626 | pci_bus->number = func->bus; | 1626 | pci_bus->number = func->bus; |
| 1627 | devfn = PCI_DEVFN(func->device, func->function); | 1627 | devfn = PCI_DEVFN(func->device, func->function); |
| 1628 | 1628 | ||
| 1629 | ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); | 1629 | ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus); |
| 1630 | 1630 | ||
| 1631 | if (ab) { | 1631 | if (ab) { |
| 1632 | if (ab->_hpp) { | 1632 | if (ab->_hpp) { |
| @@ -1681,7 +1681,7 @@ void shpchprm_enable_card( | |||
| 1681 | | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; | 1681 | | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; |
| 1682 | bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA; | 1682 | bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA; |
| 1683 | 1683 | ||
| 1684 | ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); | 1684 | ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus); |
| 1685 | if (ab) { | 1685 | if (ab) { |
| 1686 | if (ab->_hpp) { | 1686 | if (ab->_hpp) { |
| 1687 | if (ab->_hpp->enable_perr) { | 1687 | if (ab->_hpp->enable_perr) { |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 8568b207f189..6ca0061137a6 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
| @@ -73,6 +73,17 @@ resource_show(struct device * dev, char * buf) | |||
| 73 | return (str - buf); | 73 | return (str - buf); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | static ssize_t modalias_show(struct device *dev, char *buf) | ||
| 77 | { | ||
| 78 | struct pci_dev *pci_dev = to_pci_dev(dev); | ||
| 79 | |||
| 80 | return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n", | ||
| 81 | pci_dev->vendor, pci_dev->device, | ||
| 82 | pci_dev->subsystem_vendor, pci_dev->subsystem_device, | ||
| 83 | (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8), | ||
| 84 | (u8)(pci_dev->class)); | ||
| 85 | } | ||
| 86 | |||
| 76 | struct device_attribute pci_dev_attrs[] = { | 87 | struct device_attribute pci_dev_attrs[] = { |
| 77 | __ATTR_RO(resource), | 88 | __ATTR_RO(resource), |
| 78 | __ATTR_RO(vendor), | 89 | __ATTR_RO(vendor), |
| @@ -82,6 +93,7 @@ struct device_attribute pci_dev_attrs[] = { | |||
| 82 | __ATTR_RO(class), | 93 | __ATTR_RO(class), |
| 83 | __ATTR_RO(irq), | 94 | __ATTR_RO(irq), |
| 84 | __ATTR_RO(local_cpus), | 95 | __ATTR_RO(local_cpus), |
| 96 | __ATTR_RO(modalias), | ||
| 85 | __ATTR_NULL, | 97 | __ATTR_NULL, |
| 86 | }; | 98 | }; |
| 87 | 99 | ||
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 79cdc16c52c8..744da0d4ae5f 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
| @@ -32,33 +32,6 @@ extern unsigned char pci_max_busnr(void); | |||
| 32 | extern unsigned char pci_bus_max_busnr(struct pci_bus *bus); | 32 | extern unsigned char pci_bus_max_busnr(struct pci_bus *bus); |
| 33 | extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap); | 33 | extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap); |
| 34 | 34 | ||
| 35 | struct pci_dev_wrapped { | ||
| 36 | struct pci_dev *dev; | ||
| 37 | void *data; | ||
| 38 | }; | ||
| 39 | |||
| 40 | struct pci_bus_wrapped { | ||
| 41 | struct pci_bus *bus; | ||
| 42 | void *data; | ||
| 43 | }; | ||
| 44 | |||
| 45 | struct pci_visit { | ||
| 46 | int (* pre_visit_pci_bus) (struct pci_bus_wrapped *, | ||
| 47 | struct pci_dev_wrapped *); | ||
| 48 | int (* post_visit_pci_bus) (struct pci_bus_wrapped *, | ||
| 49 | struct pci_dev_wrapped *); | ||
| 50 | |||
| 51 | int (* pre_visit_pci_dev) (struct pci_dev_wrapped *, | ||
| 52 | struct pci_bus_wrapped *); | ||
| 53 | int (* visit_pci_dev) (struct pci_dev_wrapped *, | ||
| 54 | struct pci_bus_wrapped *); | ||
| 55 | int (* post_visit_pci_dev) (struct pci_dev_wrapped *, | ||
| 56 | struct pci_bus_wrapped *); | ||
| 57 | }; | ||
| 58 | |||
| 59 | extern int pci_visit_dev(struct pci_visit *fn, | ||
| 60 | struct pci_dev_wrapped *wrapped_dev, | ||
| 61 | struct pci_bus_wrapped *wrapped_parent); | ||
| 62 | extern void pci_remove_legacy_files(struct pci_bus *bus); | 35 | extern void pci_remove_legacy_files(struct pci_bus *bus); |
| 63 | 36 | ||
| 64 | /* Lock for read/write access to pci device and bus lists */ | 37 | /* 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 4037a3e568de..3e84b501e6a4 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) | |||
| 39 | driver->id_table->vendor != pciedev->id.vendor) || | 39 | driver->id_table->vendor != pciedev->id.vendor) || |
| 40 | (driver->id_table->device != PCI_ANY_ID && | 40 | (driver->id_table->device != PCI_ANY_ID && |
| 41 | driver->id_table->device != pciedev->id.device) || | 41 | driver->id_table->device != pciedev->id.device) || |
| 42 | driver->id_table->port_type != pciedev->id.port_type || | 42 | (driver->id_table->port_type != PCIE_ANY_PORT && |
| 43 | driver->id_table->port_type != pciedev->id.port_type) || | ||
| 43 | driver->id_table->service_type != pciedev->id.service_type ) | 44 | driver->id_table->service_type != pciedev->id.service_type ) |
| 44 | return 0; | 45 | return 0; |
| 45 | 46 | ||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 026aa04669a2..637e9493034b 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
| 21 | #include <linux/acpi.h> | ||
| 21 | #include "pci.h" | 22 | #include "pci.h" |
| 22 | 23 | ||
| 23 | /* Deal with broken BIOS'es that neglect to enable passive release, | 24 | /* 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, | |||
| 467 | * non-x86 architectures (yes Via exists on PPC among other places), | 468 | * non-x86 architectures (yes Via exists on PPC among other places), |
| 468 | * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get | 469 | * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get |
| 469 | * interrupts delivered properly. | 470 | * interrupts delivered properly. |
| 470 | * | ||
| 471 | * TODO: When we have device-specific interrupt routers, | ||
| 472 | * quirk_via_irqpic will go away from quirks. | ||
| 473 | */ | 471 | */ |
| 474 | 472 | ||
| 475 | /* | 473 | /* |
| @@ -494,6 +492,29 @@ static void __devinit quirk_via_acpi(struct pci_dev *d) | |||
| 494 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi ); | 492 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi ); |
| 495 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi ); | 493 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi ); |
| 496 | 494 | ||
| 495 | static void quirk_via_irqpic(struct pci_dev *dev) | ||
| 496 | { | ||
| 497 | u8 irq, new_irq; | ||
| 498 | |||
| 499 | #ifdef CONFIG_X86_IO_APIC | ||
| 500 | if (nr_ioapics && !skip_ioapic_setup) | ||
| 501 | return; | ||
| 502 | #endif | ||
| 503 | #ifdef CONFIG_ACPI | ||
| 504 | if (acpi_irq_model != ACPI_IRQ_MODEL_PIC) | ||
| 505 | return; | ||
| 506 | #endif | ||
| 507 | new_irq = dev->irq & 0xf; | ||
| 508 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); | ||
| 509 | if (new_irq != irq) { | ||
| 510 | printk(KERN_INFO "PCI: Via PIC IRQ fixup for %s, from %d to %d\n", | ||
| 511 | pci_name(dev), irq, new_irq); | ||
| 512 | udelay(15); /* unknown if delay really needed */ | ||
| 513 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); | ||
| 514 | } | ||
| 515 | } | ||
| 516 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irqpic); | ||
| 517 | |||
| 497 | /* | 518 | /* |
| 498 | * PIIX3 USB: We have to disable USB interrupts that are | 519 | * PIIX3 USB: We have to disable USB interrupts that are |
| 499 | * hardwired to PIRQD# and may be shared with an | 520 | * hardwired to PIRQD# and may be shared with an |
| @@ -683,19 +704,6 @@ static void __init quirk_disable_pxb(struct pci_dev *pdev) | |||
| 683 | } | 704 | } |
| 684 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb ); | 705 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb ); |
| 685 | 706 | ||
| 686 | /* | ||
| 687 | * VIA northbridges care about PCI_INTERRUPT_LINE | ||
| 688 | */ | ||
| 689 | int via_interrupt_line_quirk; | ||
| 690 | |||
| 691 | static void __devinit quirk_via_bridge(struct pci_dev *pdev) | ||
| 692 | { | ||
| 693 | if(pdev->devfn == 0) { | ||
| 694 | printk(KERN_INFO "PCI: Via IRQ fixup\n"); | ||
| 695 | via_interrupt_line_quirk = 1; | ||
| 696 | } | ||
| 697 | } | ||
| 698 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_bridge ); | ||
| 699 | 707 | ||
| 700 | /* | 708 | /* |
| 701 | * Serverworks CSB5 IDE does not fully support native mode | 709 | * Serverworks CSB5 IDE does not fully support native mode |
