]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/pci/hotplug.c
[PATCH] DocBook: fix some descriptions
[net-next-2.6.git] / drivers / pci / hotplug.c
1 #include <linux/kernel.h>
2 #include <linux/pci.h>
3 #include <linux/module.h>
4 #include "pci.h"
5
6 int pci_hotplug (struct device *dev, char **envp, int num_envp,
7                  char *buffer, int buffer_size)
8 {
9         struct pci_dev *pdev;
10         char *scratch;
11         int i = 0;
12         int length = 0;
13
14         if (!dev)
15                 return -ENODEV;
16
17         pdev = to_pci_dev(dev);
18         if (!pdev)
19                 return -ENODEV;
20
21         scratch = buffer;
22
23         /* stuff we want to pass to /sbin/hotplug */
24         envp[i++] = scratch;
25         length += scnprintf (scratch, buffer_size - length, "PCI_CLASS=%04X",
26                             pdev->class);
27         if ((buffer_size - length <= 0) || (i >= num_envp))
28                 return -ENOMEM;
29         ++length;
30         scratch += length;
31
32         envp[i++] = scratch;
33         length += scnprintf (scratch, buffer_size - length, "PCI_ID=%04X:%04X",
34                             pdev->vendor, pdev->device);
35         if ((buffer_size - length <= 0) || (i >= num_envp))
36                 return -ENOMEM;
37         ++length;
38         scratch += length;
39
40         envp[i++] = scratch;
41         length += scnprintf (scratch, buffer_size - length,
42                             "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
43                             pdev->subsystem_device);
44         if ((buffer_size - length <= 0) || (i >= num_envp))
45                 return -ENOMEM;
46         ++length;
47         scratch += length;
48
49         envp[i++] = scratch;
50         length += scnprintf (scratch, buffer_size - length, "PCI_SLOT_NAME=%s",
51                             pci_name(pdev));
52         if ((buffer_size - length <= 0) || (i >= num_envp))
53                 return -ENOMEM;
54
55         envp[i] = NULL;
56
57         return 0;
58 }
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);