[PATCH] PCI Hotplug/powerpc: more removal of duplicated code
[safe/jmp/linux-2.6] / drivers / pci / hotplug / rpaphp_pci.c
1 /*
2  * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform.
3  * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com>
4  *
5  * All rights reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or (at
10  * your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
15  * NON INFRINGEMENT.  See the GNU General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  * Send feedback to <lxie@us.ibm.com>
23  *
24  */
25 #include <linux/pci.h>
26 #include <linux/string.h>
27
28 #include <asm/pci-bridge.h>
29 #include <asm/rtas.h>
30 #include <asm/machdep.h>
31
32 #include "../pci.h"             /* for pci_add_new_bus */
33 #include "rpaphp.h"
34
35 static struct pci_bus *find_bus_among_children(struct pci_bus *bus,
36                                         struct device_node *dn)
37 {
38         struct pci_bus *child = NULL;
39         struct list_head *tmp;
40         struct device_node *busdn;
41
42         busdn = pci_bus_to_OF_node(bus);
43         if (busdn == dn)
44                 return bus;
45
46         list_for_each(tmp, &bus->children) {
47                 child = find_bus_among_children(pci_bus_b(tmp), dn);
48                 if (child)
49                         break;
50         }
51         return child;
52 }
53
54 struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn)
55 {
56         struct pci_dn *pdn = dn->data;
57
58         if (!pdn  || !pdn->phb || !pdn->phb->bus)
59                 return NULL;
60
61         return find_bus_among_children(pdn->phb->bus, dn);
62 }
63 EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus);
64
65 static int rpaphp_get_sensor_state(struct slot *slot, int *state)
66 {
67         int rc;
68         int setlevel;
69
70         rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state);
71
72         if (rc < 0) {
73                 if (rc == -EFAULT || rc == -EEXIST) {
74                         dbg("%s: slot must be power up to get sensor-state\n",
75                             __FUNCTION__);
76
77                         /* some slots have to be powered up 
78                          * before get-sensor will succeed.
79                          */
80                         rc = rtas_set_power_level(slot->power_domain, POWER_ON,
81                                                   &setlevel);
82                         if (rc < 0) {
83                                 dbg("%s: power on slot[%s] failed rc=%d.\n",
84                                     __FUNCTION__, slot->name, rc);
85                         } else {
86                                 rc = rtas_get_sensor(DR_ENTITY_SENSE,
87                                                      slot->index, state);
88                         }
89                 } else if (rc == -ENODEV)
90                         info("%s: slot is unusable\n", __FUNCTION__);
91                 else
92                         err("%s failed to get sensor state\n", __FUNCTION__);
93         }
94         return rc;
95 }
96
97 /**
98  * get_pci_adapter_status - get the status of a slot
99  * 
100  * 0-- slot is empty
101  * 1-- adapter is configured
102  * 2-- adapter is not configured
103  * 3-- not valid
104  */
105 int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
106 {
107         struct pci_bus *bus;
108         int state, rc;
109
110         *value = NOT_VALID;
111         rc = rpaphp_get_sensor_state(slot, &state);
112         if (rc)
113                 goto exit;
114
115         if (state == EMPTY)
116                 *value = EMPTY;
117         else if (state == PRESENT) {
118                 if (!is_init) {
119                         /* at run-time slot->state can be changed by */
120                         /* config/unconfig adapter */
121                         *value = slot->state;
122                 } else {
123                         bus = rpaphp_find_pci_bus(slot->dn);
124                         if (bus && !list_empty(&bus->devices))
125                                 *value = CONFIGURED;
126                         else
127                                 *value = NOT_CONFIGURED;
128                 }
129         }
130 exit:
131         return rc;
132 }
133
134 /* Must be called before pci_bus_add_devices */
135 void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
136 {
137         struct pci_dev *dev;
138
139         list_for_each_entry(dev, &bus->devices, bus_list) {
140                 /*
141                  * Skip already-present devices (which are on the
142                  * global device list.)
143                  */
144                 if (list_empty(&dev->global_list)) {
145                         int i;
146                         
147                         /* Need to setup IOMMU tables */
148                         ppc_md.iommu_dev_setup(dev);
149
150                         if(fix_bus)
151                                 pcibios_fixup_device_resources(dev, bus);
152                         pci_read_irq_line(dev);
153                         for (i = 0; i < PCI_NUM_RESOURCES; i++) {
154                                 struct resource *r = &dev->resource[i];
155
156                                 if (r->parent || !r->start || !r->flags)
157                                         continue;
158                                 pci_claim_resource(dev, i);
159                         }
160                 }
161         }
162 }
163
164 static void rpaphp_eeh_add_bus_device(struct pci_bus *bus)
165 {
166         struct pci_dev *dev;
167
168         list_for_each_entry(dev, &bus->devices, bus_list) {
169                 eeh_add_device_late(dev);
170                 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
171                         struct pci_bus *subbus = dev->subordinate;
172                         if (subbus)
173                                 rpaphp_eeh_add_bus_device (subbus);
174                 }
175         }
176 }
177
178 static int rpaphp_pci_config_bridge(struct pci_dev *dev)
179 {
180         u8 sec_busno;
181         struct pci_bus *child_bus;
182         struct pci_dev *child_dev;
183
184         dbg("Enter %s:  BRIDGE dev=%s\n", __FUNCTION__, pci_name(dev));
185
186         /* get busno of downstream bus */
187         pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
188                 
189         /* add to children of PCI bridge dev->bus */
190         child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
191         if (!child_bus) {
192                 err("%s: could not add second bus\n", __FUNCTION__);
193                 return -EIO;
194         }
195         sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
196         /* do pci_scan_child_bus */
197         pci_scan_child_bus(child_bus);
198
199         list_for_each_entry(child_dev, &child_bus->devices, bus_list) {
200                 eeh_add_device_late(child_dev);
201         }
202
203          /* fixup new pci devices without touching bus struct */
204         rpaphp_fixup_new_pci_devices(child_bus, 0);
205
206         /* Make the discovered devices available */
207         pci_bus_add_devices(child_bus);
208         return 0;
209 }
210
211 void rpaphp_init_new_devs(struct pci_bus *bus)
212 {
213         rpaphp_fixup_new_pci_devices(bus, 0);
214         rpaphp_eeh_add_bus_device(bus);
215 }
216 EXPORT_SYMBOL_GPL(rpaphp_init_new_devs);
217
218 /*****************************************************************************
219  rpaphp_pci_config_slot() will  configure all devices under the
220  given slot->dn and return the the first pci_dev.
221  *****************************************************************************/
222 static struct pci_dev *
223 rpaphp_pci_config_slot(struct pci_bus *bus)
224 {
225         struct device_node *dn = pci_bus_to_OF_node(bus);
226         struct pci_dev *dev = NULL;
227         int slotno;
228         int num;
229
230         dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
231         if (!dn || !dn->child)
232                 return NULL;
233
234         if (_machine == PLATFORM_PSERIES_LPAR) {
235                 of_scan_bus(dn, bus);
236                 if (list_empty(&bus->devices)) {
237                         err("%s: No new device found\n", __FUNCTION__);
238                         return NULL;
239                 }
240
241                 rpaphp_init_new_devs(bus);
242                 pci_bus_add_devices(bus);
243                 dev = list_entry(&bus->devices, struct pci_dev, bus_list);
244         } else {
245                 slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
246
247                 /* pci_scan_slot should find all children */
248                 num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
249                 if (num) {
250                         rpaphp_fixup_new_pci_devices(bus, 1);
251                         pci_bus_add_devices(bus);
252                 }
253                 if (list_empty(&bus->devices)) {
254                         err("%s: No new device found\n", __FUNCTION__);
255                         return NULL;
256                 }
257                 list_for_each_entry(dev, &bus->devices, bus_list) {
258                         if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
259                                 rpaphp_pci_config_bridge(dev);
260
261                         rpaphp_eeh_add_bus_device(bus);
262                 }
263         }
264
265         return dev;
266 }
267
268 static void print_slot_pci_funcs(struct pci_bus *bus)
269 {
270         struct device_node *dn;
271         struct pci_dev *dev;
272
273         dn = pci_bus_to_OF_node(bus);
274         if (!dn)
275                 return;
276
277         dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name);
278         list_for_each_entry (dev, &bus->devices, bus_list)
279                 dbg("\t%s\n", pci_name(dev));
280         return;
281 }
282
283 int rpaphp_config_pci_adapter(struct pci_bus *bus)
284 {
285         struct device_node *dn = pci_bus_to_OF_node(bus);
286         struct pci_dev *dev;
287         int rc = -ENODEV;
288
289         dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name);
290         if (!dn)
291                 goto exit;
292
293         eeh_add_device_tree_early(dn);
294         dev = rpaphp_pci_config_slot(bus);
295         if (!dev) {
296                 err("%s: can't find any devices.\n", __FUNCTION__);
297                 goto exit;
298         }
299         print_slot_pci_funcs(bus);
300         rc = 0;
301 exit:
302         dbg("Exit %s:  rc=%d\n", __FUNCTION__, rc);
303         return rc;
304 }
305 EXPORT_SYMBOL_GPL(rpaphp_config_pci_adapter);
306
307 static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
308 {
309         eeh_remove_device(dev);
310         if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
311                 struct pci_bus *bus = dev->subordinate;
312                 struct list_head *ln;
313                 if (!bus)
314                         return; 
315                 for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
316                         struct pci_dev *pdev = pci_dev_b(ln);
317                         if (pdev)
318                                 rpaphp_eeh_remove_bus_device(pdev);
319                 }
320
321         }
322         return;
323 }
324
325 int rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
326 {
327         struct pci_dev *dev, *tmp;
328
329         list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
330                 rpaphp_eeh_remove_bus_device(dev);
331                 pci_remove_bus_device(dev);
332         }
333         return 0;
334 }
335 EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter);
336
337 static int setup_pci_hotplug_slot_info(struct slot *slot)
338 {
339         dbg("%s Initilize the PCI slot's hotplug->info structure ...\n",
340             __FUNCTION__);
341         rpaphp_get_power_status(slot, &slot->hotplug_slot->info->power_status);
342         rpaphp_get_pci_adapter_status(slot, 1,
343                                       &slot->hotplug_slot->info->
344                                       adapter_status);
345         if (slot->hotplug_slot->info->adapter_status == NOT_VALID) {
346                 err("%s: NOT_VALID: skip dn->full_name=%s\n",
347                     __FUNCTION__, slot->dn->full_name);
348                 return -EINVAL;
349         }
350         return 0;
351 }
352
353 static void set_slot_name(struct slot *slot)
354 {
355         struct pci_bus *bus = slot->bus;
356         struct pci_dev *bridge;
357
358         bridge = bus->self;
359         if (bridge)
360                 strcpy(slot->name, pci_name(bridge));
361         else
362                 sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
363                         bus->number);
364 }
365
366 static int setup_pci_slot(struct slot *slot)
367 {
368         struct device_node *dn = slot->dn;
369         struct pci_bus *bus;
370
371         BUG_ON(!dn);
372         bus = rpaphp_find_pci_bus(dn);
373         if (!bus) {
374                 err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name);
375                 goto exit_rc;
376         }
377
378         slot->bus = bus;
379         slot->pci_devs = &bus->devices;
380         set_slot_name(slot);
381
382         /* find slot's pci_dev if it's not empty */
383         if (slot->hotplug_slot->info->adapter_status == EMPTY) {
384                 slot->state = EMPTY;    /* slot is empty */
385         } else {
386                 /* slot is occupied */
387                 if (!dn->child) {
388                         /* non-empty slot has to have child */
389                         err("%s: slot[%s]'s device_node doesn't have child for adapter\n", 
390                                 __FUNCTION__, slot->name);
391                         goto exit_rc;
392                 }
393
394                 if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
395                         dbg("%s CONFIGURING pci adapter in slot[%s]\n",  
396                                 __FUNCTION__, slot->name);
397                         if (rpaphp_config_pci_adapter(slot->bus)) {
398                                 err("%s: CONFIG pci adapter failed\n", __FUNCTION__);
399                                 goto exit_rc;           
400                         }
401
402                 } else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) {
403                         err("%s: slot[%s]'s adapter_status is NOT_VALID.\n",
404                                 __FUNCTION__, slot->name);
405                         goto exit_rc;
406                 }
407                 print_slot_pci_funcs(slot->bus);
408                 if (!list_empty(slot->pci_devs)) {
409                         slot->state = CONFIGURED;
410                 } else {
411                         /* DLPAR add as opposed to 
412                          * boot time */
413                         slot->state = NOT_CONFIGURED;
414                 }
415         }
416         return 0;
417 exit_rc:
418         dealloc_slot_struct(slot);
419         return -EINVAL;
420 }
421
422 int register_pci_slot(struct slot *slot)
423 {
424         int rc = -EINVAL;
425
426         if (setup_pci_hotplug_slot_info(slot))
427                 goto exit_rc;
428         if (setup_pci_slot(slot))
429                 goto exit_rc;
430         rc = register_slot(slot);
431 exit_rc:
432         return rc;
433 }
434
435 int rpaphp_enable_pci_slot(struct slot *slot)
436 {
437         int retval = 0, state;
438
439         retval = rpaphp_get_sensor_state(slot, &state);
440         if (retval)
441                 goto exit;
442         dbg("%s: sensor state[%d]\n", __FUNCTION__, state);
443         /* if slot is not empty, enable the adapter */
444         if (state == PRESENT) {
445                 dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name);
446                 retval = rpaphp_config_pci_adapter(slot->bus);
447                 if (!retval) {
448                         slot->state = CONFIGURED;
449                         info("%s: devices in slot[%s] configured\n",
450                                         __FUNCTION__, slot->name);
451                 } else {
452                         slot->state = NOT_CONFIGURED;
453                         dbg("%s: no pci_dev struct for adapter in slot[%s]\n",
454                             __FUNCTION__, slot->name);
455                 }
456         } else if (state == EMPTY) {
457                 dbg("%s : slot[%s] is empty\n", __FUNCTION__, slot->name);
458                 slot->state = EMPTY;
459         } else {
460                 err("%s: slot[%s] is in invalid state\n", __FUNCTION__,
461                     slot->name);
462                 slot->state = NOT_VALID;
463                 retval = -EINVAL;
464         }
465 exit:
466         dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
467         return retval;
468 }