aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/pci/hotplug.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/pci/hotplug.c')
-rw-r--r--drivers/pci/hotplug.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
new file mode 100644
index 000000000000..d471b3ea5d12
--- /dev/null
+++ b/drivers/pci/hotplug.c
@@ -0,0 +1,163 @@
1#include <linux/kernel.h>
2#include <linux/pci.h>
3#include <linux/module.h>
4#include "pci.h"
5
6int 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
60static 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
95static 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 * Every bus and every function is presented to a custom
124 * function that can act upon it.
125 */
126int pci_visit_dev(struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev,
127 struct pci_bus_wrapped *wrapped_parent)
128{
129 struct pci_dev* dev = wrapped_dev ? wrapped_dev->dev : NULL;
130 int result = 0;
131
132 if (!dev)
133 return 0;
134
135 if (fn->pre_visit_pci_dev) {
136 result = fn->pre_visit_pci_dev(wrapped_dev, wrapped_parent);
137 if (result)
138 return result;
139 }
140
141 switch (dev->class >> 8) {
142 case PCI_CLASS_BRIDGE_PCI:
143 result = pci_visit_bridge(fn, wrapped_dev,
144 wrapped_parent);
145 if (result)
146 return result;
147 break;
148 default:
149 pr_debug("PCI: Scanning device %s\n", pci_name(dev));
150 if (fn->visit_pci_dev) {
151 result = fn->visit_pci_dev (wrapped_dev,
152 wrapped_parent);
153 if (result)
154 return result;
155 }
156 }
157
158 if (fn->post_visit_pci_dev)
159 result = fn->post_visit_pci_dev(wrapped_dev, wrapped_parent);
160
161 return result;
162}
163EXPORT_SYMBOL(pci_visit_dev);