[PATCH] patch 1/8] pciehp: use the PCI core for hotplug resource management
[linux-2.6.git] / drivers / pci / hotplug / pciehp_pci.c
1 /*
2  * PCI Express Hot Plug Controller Driver
3  *
4  * Copyright (C) 1995,2001 Compaq Computer Corporation
5  * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6  * Copyright (C) 2001 IBM Corp.
7  * Copyright (C) 2003-2004 Intel Corporation
8  *
9  * All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or (at
14  * your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
19  * NON INFRINGEMENT.  See the GNU General Public License for more
20  * details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
27  *
28  */
29
30 #include <linux/config.h>
31 #include <linux/module.h>
32 #include <linux/kernel.h>
33 #include <linux/types.h>
34 #include <linux/slab.h>
35 #include <linux/workqueue.h>
36 #include <linux/proc_fs.h>
37 #include <linux/pci.h>
38 #include "../pci.h"
39 #include "pciehp.h"
40
41
42 int pciehp_configure_device(struct slot *p_slot)
43 {
44         struct pci_dev *dev;
45         struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
46         int num, fn;
47
48         dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
49         if (dev) {
50                 err("Device %s already exists at %x:%x, cannot hot-add\n",
51                                 pci_name(dev), p_slot->bus, p_slot->device);
52                 return -EINVAL;
53         }
54
55         num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
56         if (num == 0) {
57                 err("No new device found\n");
58                 return -ENODEV;
59         }
60
61         for (fn = 0; fn < 8; fn++) {
62                 if (!(dev = pci_find_slot(p_slot->bus,
63                                         PCI_DEVFN(p_slot->device, fn))))
64                         continue;
65                 if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
66                         err("Cannot hot-add display device %s\n",
67                                         pci_name(dev));
68                         continue;
69                 }
70                 if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
71                                 (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
72                         /* Find an unused bus number for the new bridge */
73                         struct pci_bus *child;
74                         unsigned char busnr, start = parent->secondary;
75                         unsigned char end = parent->subordinate;
76                         for (busnr = start; busnr <= end; busnr++) {
77                                 if (!pci_find_bus(pci_domain_nr(parent),
78                                                         busnr))
79                                         break;
80                         }
81                         if (busnr >= end) {
82                                 err("No free bus for hot-added bridge\n");
83                                 continue;
84                         }
85                         child = pci_add_new_bus(parent, dev, busnr);
86                         if (!child) {
87                                 err("Cannot add new bus for %s\n",
88                                                 pci_name(dev));
89                                 continue;
90                         }
91                         child->subordinate = pci_do_scan_bus(child);
92                         pci_bus_size_bridges(child);
93                 }
94                 /* TBD: program firmware provided _HPP values */
95                 /* program_fw_provided_values(dev); */
96         }
97
98         pci_bus_assign_resources(parent);
99         pci_bus_add_devices(parent);
100         pci_enable_bridges(parent);
101         return 0;
102 }
103
104 int pciehp_unconfigure_device(struct pci_func* func) 
105 {
106         int rc = 0;
107         int j;
108         struct pci_bus *pbus;
109
110         dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus,
111                                 func->device, func->function);
112         pbus = func->pci_dev->bus;
113
114         for (j=0; j<8 ; j++) {
115                 struct pci_dev* temp = pci_find_slot(func->bus,
116                                 (func->device << 3) | j);
117                 if (temp) {
118                         pci_remove_bus_device(temp);
119                 }
120         }
121         /* 
122          * Some PCI Express root ports require fixup after hot-plug operation.
123          */
124         if (pcie_mch_quirk) 
125                 pci_fixup_device(pci_fixup_final, pbus->self);
126         
127         return rc;
128 }
129
130 /*
131  * pciehp_save_config
132  *
133  * Reads configuration for all slots in a PCI bus and saves info.
134  *
135  * Note:  For non-hot plug busses, the slot # saved is the device #
136  *
137  * returns 0 if success
138  */
139 int pciehp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
140 {
141         int rc;
142         u8 class_code;
143         u8 header_type;
144         u32 ID;
145         u8 secondary_bus;
146         struct pci_func *new_slot;
147         int sub_bus;
148         int max_functions;
149         int function;
150         u8 DevError;
151         int device = 0;
152         int cloop = 0;
153         int stop_it;
154         int index;
155         int is_hot_plug = num_ctlr_slots || first_device_num;
156         struct pci_bus lpci_bus, *pci_bus;
157         int FirstSupported, LastSupported;
158
159         dbg("%s: Enter\n", __FUNCTION__);
160
161         memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
162         pci_bus = &lpci_bus;
163
164         dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
165                                 num_ctlr_slots, first_device_num);
166
167         /*   Decide which slots are supported */
168         if (is_hot_plug) {
169                 /*********************************
170                  *  is_hot_plug is the slot mask
171                  *********************************/
172                 FirstSupported = first_device_num;
173                 LastSupported = FirstSupported + num_ctlr_slots - 1;
174         } else {
175                 FirstSupported = 0;
176                 LastSupported = 0x1F;
177         }
178
179         dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported,
180                                         LastSupported);
181
182         /*   Save PCI configuration space for all devices in supported slots */
183         dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number);
184         pci_bus->number = busnumber;
185         dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device);
186         for (device = FirstSupported; device <= LastSupported; device++) {
187                 ID = 0xFFFFFFFF;
188                 rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
189                                         PCI_VENDOR_ID, &ID);
190
191                 if (ID != 0xFFFFFFFF) {   /*  device in slot */
192                         dbg("%s: ID = %x\n", __FUNCTION__, ID);
193                         rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
194                                         0x0B, &class_code);
195                         if (rc)
196                                 return rc;
197
198                         rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
199                                         PCI_HEADER_TYPE, &header_type);
200                         if (rc)
201                                 return rc;
202
203                         dbg("class_code = %x, header_type = %x\n", class_code, header_type);
204
205                         /* If multi-function device, set max_functions to 8 */
206                         if (header_type & 0x80)
207                                 max_functions = 8;
208                         else
209                                 max_functions = 1;
210
211                         function = 0;
212
213                         do {
214                                 DevError = 0;
215                                 dbg("%s: In do loop\n", __FUNCTION__);
216
217                                 if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {   /* P-P Bridge */
218                                         /* Recurse the subordinate bus
219                                          * get the subordinate bus number
220                                          */
221                                         rc = pci_bus_read_config_byte(pci_bus,
222                                                 PCI_DEVFN(device, function), 
223                                                 PCI_SECONDARY_BUS, &secondary_bus);
224                                         if (rc) {
225                                                 return rc;
226                                         } else {
227                                                 sub_bus = (int) secondary_bus;
228
229                                                 /* Save secondary bus cfg spc with this recursive call. */
230                                                 rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
231                                                 if (rc)
232                                                         return rc;
233                                         }
234                                 }
235
236                                 index = 0;
237                                 new_slot = pciehp_slot_find(busnumber, device, index++);
238
239                                 dbg("%s: new_slot = %p bus %x dev %x fun %x\n",
240                                 __FUNCTION__, new_slot, busnumber, device, index-1);
241
242                                 while (new_slot && (new_slot->function != (u8) function)) {
243                                         new_slot = pciehp_slot_find(busnumber, device, index++);
244                                         dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n",
245                                         __FUNCTION__, new_slot, busnumber, device, index-1);
246                                 }
247                                 if (!new_slot) {
248                                         /* Setup slot structure. */
249                                         new_slot = pciehp_slot_create(busnumber);
250                                         dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n",
251                                         __FUNCTION__, new_slot, busnumber, device, function);
252
253                                         if (new_slot == NULL)
254                                                 return(1);
255                                 }
256
257                                 new_slot->bus = (u8) busnumber;
258                                 new_slot->device = (u8) device;
259                                 new_slot->function = (u8) function;
260                                 new_slot->is_a_board = 1;
261                                 new_slot->switch_save = 0x10;
262                                 /* In case of unsupported board */
263                                 new_slot->status = DevError;
264                                 new_slot->pci_dev = pci_find_slot(new_slot->bus,
265                                         (new_slot->device << 3) | new_slot->function);
266                                 dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
267
268                                 for (cloop = 0; cloop < 0x20; cloop++) {
269                                         rc = pci_bus_read_config_dword(pci_bus,
270                                                 PCI_DEVFN(device, function),
271                                                 cloop << 2, 
272                                                 (u32 *) &(new_slot->config_space [cloop]));
273                                         /* dbg("new_slot->config_space[%x] = %x\n",
274                                                 cloop, new_slot->config_space[cloop]); */
275                                         if (rc)
276                                                 return rc;
277                                 }
278
279                                 function++;
280
281                                 stop_it = 0;
282
283                                 /*  this loop skips to the next present function
284                                  *  reading in Class Code and Header type.
285                                  */
286
287                                 while ((function < max_functions)&&(!stop_it)) {
288                                         dbg("%s: In while loop \n", __FUNCTION__);
289                                         rc = pci_bus_read_config_dword(pci_bus,
290                                                         PCI_DEVFN(device, function),
291                                                         PCI_VENDOR_ID, &ID);
292
293                                         if (ID == 0xFFFFFFFF) {  /* nothing there. */
294                                                 function++;
295                                                 dbg("Nothing there\n");
296                                         } else {  /* Something there */
297                                                 rc = pci_bus_read_config_byte(pci_bus,
298                                                         PCI_DEVFN(device, function),
299                                                         0x0B, &class_code);
300                                                 if (rc)
301                                                         return rc;
302
303                                                 rc = pci_bus_read_config_byte(pci_bus,
304                                                         PCI_DEVFN(device, function),
305                                                         PCI_HEADER_TYPE, &header_type);
306                                                 if (rc)
307                                                         return rc;
308
309                                                 dbg("class_code = %x, header_type = %x\n", class_code, header_type);
310                                                 stop_it++;
311                                         }
312                                 }
313
314                         } while (function < max_functions);
315                         /* End of IF (device in slot?) */
316                 } else if (is_hot_plug) {
317                         /* Setup slot structure with entry for empty slot */
318                         new_slot = pciehp_slot_create(busnumber);
319
320                         if (new_slot == NULL) {
321                                 return(1);
322                         }
323                         dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot,
324                                 new_slot->bus, new_slot->device, new_slot->function);
325
326                         new_slot->bus = (u8) busnumber;
327                         new_slot->device = (u8) device;
328                         new_slot->function = 0;
329                         new_slot->is_a_board = 0;
330                         new_slot->presence_save = 0;
331                         new_slot->switch_save = 0;
332                 }
333         }                       /* End of FOR loop */
334
335         dbg("%s: Exit\n", __FUNCTION__);
336         return(0);
337 }
338
339
340 /*
341  * pciehp_save_slot_config
342  *
343  * Saves configuration info for all PCI devices in a given slot
344  * including subordinate busses.
345  *
346  * returns 0 if success
347  */
348 int pciehp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot)
349 {
350         int rc;
351         u8 class_code;
352         u8 header_type;
353         u32 ID;
354         u8 secondary_bus;
355         int sub_bus;
356         int max_functions;
357         int function;
358         int cloop = 0;
359         int stop_it;
360         struct pci_bus lpci_bus, *pci_bus;
361         memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
362         pci_bus = &lpci_bus;
363         pci_bus->number = new_slot->bus;
364
365         ID = 0xFFFFFFFF;
366
367         pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0),
368                                         PCI_VENDOR_ID, &ID);
369
370         if (ID != 0xFFFFFFFF) {   /*  device in slot */
371                 pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
372                                         0x0B, &class_code);
373
374                 pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
375                                         PCI_HEADER_TYPE, &header_type);
376
377                 if (header_type & 0x80) /* Multi-function device */
378                         max_functions = 8;
379                 else
380                         max_functions = 1;
381
382                 function = 0;
383
384                 do {
385                         if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {     /* PCI-PCI Bridge */
386                                 /*  Recurse the subordinate bus */
387                                 pci_bus_read_config_byte(pci_bus,
388                                         PCI_DEVFN(new_slot->device, function), 
389                                         PCI_SECONDARY_BUS, &secondary_bus);
390
391                                 sub_bus = (int) secondary_bus;
392
393                                 /* Save the config headers for the secondary bus. */
394                                 rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
395
396                                 if (rc)
397                                         return rc;
398
399                         }       /* End of IF */
400
401                         new_slot->status = 0;
402
403                         for (cloop = 0; cloop < 0x20; cloop++) {
404                                 pci_bus_read_config_dword(pci_bus,
405                                         PCI_DEVFN(new_slot->device, function), 
406                                         cloop << 2,
407                                         (u32 *) &(new_slot->config_space [cloop]));
408                         }
409
410                         function++;
411
412                         stop_it = 0;
413
414                         /*  this loop skips to the next present function
415                          *  reading in the Class Code and the Header type.
416                          */
417
418                         while ((function < max_functions) && (!stop_it)) {
419                                 pci_bus_read_config_dword(pci_bus,
420                                         PCI_DEVFN(new_slot->device, function),
421                                         PCI_VENDOR_ID, &ID);
422
423                                 if (ID == 0xFFFFFFFF) {  /* nothing there. */
424                                         function++;
425                                 } else {  /* Something there */
426                                         pci_bus_read_config_byte(pci_bus,
427                                                 PCI_DEVFN(new_slot->device, function),
428                                                 0x0B, &class_code);
429
430                                         pci_bus_read_config_byte(pci_bus,
431                                                 PCI_DEVFN(new_slot->device, function),
432                                                 PCI_HEADER_TYPE, &header_type);
433
434                                         stop_it++;
435                                 }
436                         }
437
438                 } while (function < max_functions);
439         }                       /* End of IF (device in slot?) */
440         else {
441                 return 2;
442         }
443
444         return 0;
445 }
446