diff options
author | Dave Kleikamp <shaggy@austin.ibm.com> | 2005-06-02 13:12:57 -0400 |
---|---|---|
committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2005-06-02 13:12:57 -0400 |
commit | 7078253c085c037c070ca4e8bc9e9e7f18aa1e84 (patch) | |
tree | eaf56c1a77b0de6ee82e23cee4433b2c4a47e67e /drivers/pci | |
parent | 259692bd5a2b2c2d351dd90748ba4126bc2a21b9 (diff) | |
parent | 1e86d1c648508fd50e6c9960576b87906a7906ad (diff) |
Merge with /home/shaggy/git/linus-clean/
Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
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 |