patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / 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 <asm/pci-bridge.h>
27 #include "../pci.h"             /* for pci_add_new_bus */
28
29 #include "rpaphp.h"
30
31 struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn)
32 {
33         struct pci_dev *retval_dev = NULL, *dev;
34         char bus_id[BUS_ID_SIZE];
35
36         sprintf(bus_id, "%04x:%02x:%02x.%d",dn->phb->global_number,
37                 dn->busno, PCI_SLOT(dn->devfn), PCI_FUNC(dn->devfn));
38
39         dbg("Enter rpaphp_find_pci_dev() full_name=%s bus_id=%s\n", 
40                 dn->full_name, bus_id);
41         
42         while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
43                if (!strcmp(pci_name(dev), bus_id)) {
44                         retval_dev = dev;
45                         dbg("rpaphp_find_pci_dev(): found dev=%p\n\n", dev);
46                         break;
47                 }
48         }
49         return retval_dev;
50
51 }
52
53 EXPORT_SYMBOL_GPL(rpaphp_find_pci_dev);
54
55 int rpaphp_claim_resource(struct pci_dev *dev, int resource)
56 {
57         struct resource *res = &dev->resource[resource];
58         struct resource *root = pci_find_parent_resource(dev, res);
59         char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
60         int err = -EINVAL;
61
62         if (root != NULL) {
63                 err = request_resource(root, res);
64         }
65
66         if (err) {
67                 err("PCI: %s region %d of %s %s [%lx:%lx]\n",
68                     root ? "Address space collision on" :
69                     "No parent found for",
70                     resource, dtype, pci_name(dev), res->start, res->end);
71         }
72         return err;
73 }
74
75 EXPORT_SYMBOL_GPL(rpaphp_claim_resource);
76
77 static struct pci_dev *rpaphp_find_bridge_pdev(struct slot *slot)
78 {
79         return rpaphp_find_pci_dev(slot->dn);
80 }
81
82 static struct pci_dev *rpaphp_find_adapter_pdev(struct slot *slot)
83 {
84         return rpaphp_find_pci_dev(slot->dn->child);
85 }
86
87 static int rpaphp_get_sensor_state(struct slot *slot, int *state)
88 {
89         int rc;
90         int setlevel;
91
92         rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state);
93
94         if (rc) {
95                 if (rc == NEED_POWER || rc == PWR_ONLY) {
96                         dbg("%s: slot must be power up to get sensor-state\n",
97                             __FUNCTION__);
98
99                         /* some slots have to be powered up 
100                          * before get-sensor will succeed.
101                          */
102                         rc = rtas_set_power_level(slot->power_domain, POWER_ON,
103                                                   &setlevel);
104                         if (rc) {
105                                 dbg("%s: power on slot[%s] failed rc=%d.\n",
106                                     __FUNCTION__, slot->name, rc);
107                         } else {
108                                 rc = rtas_get_sensor(DR_ENTITY_SENSE,
109                                                      slot->index, state);
110                         }
111                 } else if (rc == ERR_SENSE_USE)
112                         info("%s: slot is unusable\n", __FUNCTION__);
113                 else
114                         err("%s failed to get sensor state\n", __FUNCTION__);
115         }
116         return rc;
117 }
118
119 /**
120  * get_pci_adapter_status - get the status of a slot
121  * 
122  * 0-- slot is empty
123  * 1-- adapter is configured
124  * 2-- adapter is not configured
125  * 3-- not valid
126  */
127 int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
128 {
129         int state, rc;
130         *value = NOT_VALID;
131
132         rc = rpaphp_get_sensor_state(slot, &state);
133         if (rc)
134                 goto exit;
135         if (state == PRESENT) {
136                 if (!is_init)
137                         /* at run-time slot->state can be changed by */
138                         /* config/unconfig adapter */
139                         *value = slot->state;
140                 else {
141                         if (!slot->dn->child)
142                                 dbg("%s: %s is not valid OFDT node\n",
143                                     __FUNCTION__, slot->dn->full_name);
144                         else if (rpaphp_find_pci_dev(slot->dn->child))
145                                 *value = CONFIGURED;
146                         else {
147                                 dbg("%s: can't find pdev of adapter in slot[%s]\n", __FUNCTION__, slot->name);
148                                 *value = NOT_CONFIGURED;
149                         }
150                 }
151         } else if (state == EMPTY) {
152                 dbg("slot is empty\n");
153                 *value = state;
154         }
155
156 exit:
157         return rc;
158 }
159
160 /* Must be called before pci_bus_add_devices */
161 static void rpaphp_fixup_new_pci_devices(struct pci_bus *bus)
162 {
163         struct pci_dev *dev;
164
165         list_for_each_entry(dev, &bus->devices, bus_list) {
166                 /*
167                  * Skip already-present devices (which are on the
168                  * global device list.)
169                  */
170                 if (list_empty(&dev->global_list)) {
171                         int i;
172
173                         pcibios_fixup_device_resources(dev, bus);
174                         pci_read_irq_line(dev);
175                         for (i = 0; i < PCI_NUM_RESOURCES; i++) {
176                                 struct resource *r = &dev->resource[i];
177
178                                 if (r->parent || !r->start || !r->flags)
179                                         continue;
180                                 rpaphp_claim_resource(dev, i);
181                         }
182                 }
183         }
184 }
185
186 static void
187 rpaphp_pci_config_device(struct pci_bus *pci_bus, struct device_node *dn)
188 {
189         int num;
190
191         num = pci_scan_slot(pci_bus, PCI_DEVFN(PCI_SLOT(dn->devfn), 0));
192         if (num) {
193                 rpaphp_fixup_new_pci_devices(pci_bus);
194                 pci_bus_add_devices(pci_bus);
195         }
196 }
197
198 static int rpaphp_pci_config_bridge(struct pci_dev *dev, struct device_node *dn);
199
200 /*****************************************************************************
201  rpaphp_pci_config_dn() will recursively configure all devices under the 
202  given slot->dn and return the dn's pci_dev.
203  *****************************************************************************/
204 static struct pci_dev *
205 rpaphp_pci_config_dn(struct device_node *dn, struct pci_bus *bus)
206 {
207         struct device_node *local;
208         struct pci_dev *dev;
209
210         for (local = dn->child; local; local = local->sibling) {
211                 rpaphp_pci_config_device(bus, local);
212                 dev = rpaphp_find_pci_dev(local);
213                 if (!rpaphp_pci_config_bridge(dev, local))
214                         return NULL;
215         }
216
217         return dev;
218 }
219
220 static int rpaphp_pci_config_bridge(struct pci_dev *dev, struct device_node *dn)
221 {
222         if (dev && dn->child) { /* dn is a PCI bridge node */
223                 struct pci_bus *child;
224                 u8 sec_busno;
225
226                 /* get busno of downstream bus */
227                 pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
228
229                 /* add to children of PCI bridge dev->bus */
230                 child = pci_add_new_bus(dev->bus, dev, sec_busno);
231                 if (!child) {
232                         err("%s: could not add second bus\n", __FUNCTION__);
233                         return 0;
234                 }
235                 sprintf(child->name, "PCI Bus #%02x", child->number);
236                 /* Fixup subordinate bridge bases and resureces */
237                 pcibios_fixup_bus(child);
238
239                 /* may need do more stuff here */
240                 rpaphp_pci_config_dn(dn, dev->subordinate);
241         }
242         return 1;
243 }
244
245 static struct pci_dev *rpaphp_config_pci_adapter(struct slot *slot)
246 {
247         struct pci_bus *pci_bus;
248         struct pci_dev *dev = NULL;
249
250         dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name);
251
252         if (slot->bridge) {
253
254                 pci_bus = slot->bridge->subordinate;
255                 if (!pci_bus) {
256                         err("%s: can't find bus structure\n", __FUNCTION__);
257                         goto exit;
258                 }
259
260                 eeh_add_device_early(slot->dn->child);
261                 dev = rpaphp_pci_config_dn(slot->dn, pci_bus);
262                 eeh_add_device_late(dev);
263         } else {
264                 /* slot is not enabled */
265                 err("slot doesn't have pci_dev structure\n");
266                 dev = NULL;
267         }
268
269 exit:
270         dbg("Exit %s: pci_dev %s\n", __FUNCTION__, dev ? "found" : "not found");
271         return dev;
272 }
273
274 int rpaphp_unconfig_pci_adapter(struct slot *slot)
275 {
276         int retval = 0;
277
278         dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name);
279         if (!slot->dev.pci_dev) {
280                 info("%s: no card in slot[%s]\n", __FUNCTION__, slot->name);
281
282                 retval = -EINVAL;
283                 goto exit;
284         }
285         /* remove the device from the pci core */
286         eeh_remove_device(slot->dev.pci_dev);
287         pci_remove_bus_device(slot->dev.pci_dev);
288
289         slot->state = NOT_CONFIGURED;
290         info("%s: adapter in slot[%s] unconfigured.\n", __FUNCTION__,
291              slot->name);
292 exit:
293         dbg("Exit %s, rc=0x%x\n", __FUNCTION__, retval);
294         return retval;
295 }
296
297 static int setup_pci_hotplug_slot_info(struct slot *slot)
298 {
299         dbg("%s Initilize the PCI slot's hotplug->info structure ...\n",
300             __FUNCTION__);
301         rpaphp_get_power_status(slot, &slot->hotplug_slot->info->power_status);
302         rpaphp_get_pci_adapter_status(slot, 1,
303                                       &slot->hotplug_slot->info->
304                                       adapter_status);
305         if (slot->hotplug_slot->info->adapter_status == NOT_VALID) {
306                 dbg("%s: NOT_VALID: skip dn->full_name=%s\n",
307                     __FUNCTION__, slot->dn->full_name);
308                 return -1;
309         }
310         return 0;
311 }
312
313 static int setup_pci_slot(struct slot *slot)
314 {
315         slot->bridge = rpaphp_find_bridge_pdev(slot);
316         if (!slot->bridge) {    /* slot being added doesn't have pci_dev yet */
317                 dbg("%s: no pci_dev for bridge dn %s\n", __FUNCTION__, slot->name);
318                 dealloc_slot_struct(slot);
319                 return 1;
320         }
321         
322         strcpy(slot->name, pci_name(slot->bridge));
323         /* find slot's pci_dev if it's not empty */
324         if (slot->hotplug_slot->info->adapter_status == EMPTY) {
325                 slot->state = EMPTY;    /* slot is empty */
326                 slot->dev.pci_dev = NULL;
327         } else {
328                 /* slot is occupied */
329                 if (!(slot->dn->child)) {
330                         /* non-empty slot has to have child */
331                         err("%s: slot[%s]'s device_node doesn't have child for adapter\n", __FUNCTION__, slot->name);
332                         dealloc_slot_struct(slot);
333                         return 1;
334                 }
335                 slot->dev.pci_dev = rpaphp_find_adapter_pdev(slot);
336                 if (slot->dev.pci_dev) {
337                         slot->state = CONFIGURED;
338                 
339                 } else {
340                         /* DLPAR add as opposed to 
341                          * boot time */
342                         slot->state = NOT_CONFIGURED;
343                 }
344         }
345         return 0;
346 }
347
348 int register_pci_slot(struct slot *slot)
349 {
350         int rc = 1;
351
352         slot->dev_type = PCI_DEV;
353         if (setup_pci_hotplug_slot_info(slot))
354                 goto exit_rc;
355         if (setup_pci_slot(slot))
356                 goto exit_rc;
357         rc = register_slot(slot);
358 exit_rc:
359         if (rc)
360                 dealloc_slot_struct(slot);
361         return rc;
362 }
363
364 int rpaphp_enable_pci_slot(struct slot *slot)
365 {
366         int retval = 0, state;
367
368         retval = rpaphp_get_sensor_state(slot, &state);
369         if (retval)
370                 goto exit;
371         dbg("%s: sensor state[%d]\n", __FUNCTION__, state);
372         /* if slot is not empty, enable the adapter */
373         if (state == PRESENT) {
374                 dbg("%s : slot[%s] is occupid.\n", __FUNCTION__, slot->name);
375                 if ((slot->dev.pci_dev =
376                      rpaphp_config_pci_adapter(slot)) != NULL) {
377                         slot->state = CONFIGURED;
378                         dbg("%s: PCI adapter %s in slot[%s] has been configured\n", 
379                                 __FUNCTION__, pci_name(slot->dev.pci_dev), slot->name);
380                 } else {
381                         slot->state = NOT_CONFIGURED;
382                         dbg("%s: no pci_dev struct for adapter in slot[%s]\n",
383                             __FUNCTION__, slot->name);
384                 }
385         } else if (state == EMPTY) {
386                 dbg("%s : slot[%s] is empty\n", __FUNCTION__, slot->name);
387                 slot->state = EMPTY;
388         } else {
389                 err("%s: slot[%s] is in invalid state\n", __FUNCTION__,
390                     slot->name);
391                 slot->state = NOT_VALID;
392                 retval = -EINVAL;
393         }
394 exit:
395         if (slot->state != NOT_VALID)
396                 rpaphp_set_attention_status(slot, LED_ON);
397         else
398                 rpaphp_set_attention_status(slot, LED_ID);
399         dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
400         return retval;
401 }