ia64/linux-2.6.18-xen.hg

view drivers/xen/pcifront/pci_op.c @ 470:5baef0e18e36

xenbus: prevent warnings on unhandled enumeration values

XenbusStateReconfiguring/XenbusStateReconfigured were introduced by
c/s 437, but aren't handled in many switch statements. This c/s also
introduced a possibly un-referenced label, which also gets eliminated
here.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Mar 05 17:28:41 2008 +0000 (2008-03-05)
parents 4b9f2293d750
children 7a8ac7a685ba
line source
1 /*
2 * PCI Frontend Operations - Communicates with frontend
3 *
4 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
5 */
6 #include <linux/module.h>
7 #include <linux/version.h>
8 #include <linux/init.h>
9 #include <linux/pci.h>
10 #include <linux/spinlock.h>
11 #include <linux/time.h>
12 #include <xen/evtchn.h>
13 #include "pcifront.h"
15 static int verbose_request = 0;
16 module_param(verbose_request, int, 0644);
18 #ifdef __ia64__
19 static void pcifront_init_sd(struct pcifront_sd *sd,
20 unsigned int domain, unsigned int bus,
21 struct pcifront_device *pdev)
22 {
23 int err, i, j, k, len, root_num, res_count;
24 struct acpi_resource res;
25 unsigned int d, b, byte;
26 unsigned long magic;
27 char str[64], tmp[3];
28 unsigned char *buf, *bufp;
29 u8 *ptr;
31 memset(sd, 0, sizeof(*sd));
33 sd->segment = domain;
34 sd->node = -1; /* Revisit for NUMA */
35 sd->platform_data = pdev;
37 /* Look for resources for this controller in xenbus. */
38 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, "root_num",
39 "%d", &root_num);
40 if (err != 1)
41 return;
43 for (i = 0; i < root_num; i++) {
44 len = snprintf(str, sizeof(str), "root-%d", i);
45 if (unlikely(len >= (sizeof(str) - 1)))
46 return;
48 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
49 str, "%x:%x", &d, &b);
50 if (err != 2)
51 return;
53 if (d == domain && b == bus)
54 break;
55 }
57 if (i == root_num)
58 return;
60 len = snprintf(str, sizeof(str), "root-resource-magic");
62 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
63 str, "%lx", &magic);
65 if (err != 1)
66 return; /* No resources, nothing to do */
68 if (magic != (sizeof(res) * 2) + 1) {
69 printk(KERN_WARNING "pcifront: resource magic mismatch\n");
70 return;
71 }
73 len = snprintf(str, sizeof(str), "root-%d-resources", i);
74 if (unlikely(len >= (sizeof(str) - 1)))
75 return;
77 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
78 str, "%d", &res_count);
80 if (err != 1)
81 return; /* No resources, nothing to do */
83 sd->window = kzalloc(sizeof(*sd->window) * res_count, GFP_KERNEL);
84 if (!sd->window)
85 return;
87 /* magic is also the size of the byte stream in xenbus */
88 buf = kmalloc(magic, GFP_KERNEL);
89 if (!buf) {
90 kfree(sd->window);
91 sd->window = NULL;
92 return;
93 }
95 /* Read the resources out of xenbus */
96 for (j = 0; j < res_count; j++) {
97 memset(&res, 0, sizeof(res));
98 memset(buf, 0, magic);
100 len = snprintf(str, sizeof(str), "root-%d-resource-%d", i, j);
101 if (unlikely(len >= (sizeof(str) - 1)))
102 return;
104 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str,
105 "%s", buf);
106 if (err != 1) {
107 printk(KERN_WARNING "pcifront: error reading "
108 "resource %d on bus %04x:%02x\n",
109 j, domain, bus);
110 continue;
111 }
113 bufp = buf;
114 ptr = (u8 *)&res;
115 memset(tmp, 0, sizeof(tmp));
117 /* Copy ASCII byte stream into structure */
118 for (k = 0; k < magic - 1; k += 2) {
119 memcpy(tmp, bufp, 2);
120 bufp += 2;
122 sscanf(tmp, "%02x", &byte);
123 *ptr = byte;
124 ptr++;
125 }
127 xen_add_resource(sd, domain, bus, &res);
128 sd->windows++;
129 }
130 kfree(buf);
131 }
132 #endif
134 static int errno_to_pcibios_err(int errno)
135 {
136 switch (errno) {
137 case XEN_PCI_ERR_success:
138 return PCIBIOS_SUCCESSFUL;
140 case XEN_PCI_ERR_dev_not_found:
141 return PCIBIOS_DEVICE_NOT_FOUND;
143 case XEN_PCI_ERR_invalid_offset:
144 case XEN_PCI_ERR_op_failed:
145 return PCIBIOS_BAD_REGISTER_NUMBER;
147 case XEN_PCI_ERR_not_implemented:
148 return PCIBIOS_FUNC_NOT_SUPPORTED;
150 case XEN_PCI_ERR_access_denied:
151 return PCIBIOS_SET_FAILED;
152 }
153 return errno;
154 }
156 static int do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
157 {
158 int err = 0;
159 struct xen_pci_op *active_op = &pdev->sh_info->op;
160 unsigned long irq_flags;
161 evtchn_port_t port = pdev->evtchn;
162 s64 ns, ns_timeout;
163 struct timeval tv;
165 spin_lock_irqsave(&pdev->sh_info_lock, irq_flags);
167 memcpy(active_op, op, sizeof(struct xen_pci_op));
169 /* Go */
170 wmb();
171 set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
172 notify_remote_via_evtchn(port);
174 /*
175 * We set a poll timeout of 3 seconds but give up on return after
176 * 2 seconds. It is better to time out too late rather than too early
177 * (in the latter case we end up continually re-executing poll() with a
178 * timeout in the past). 1s difference gives plenty of slack for error.
179 */
180 do_gettimeofday(&tv);
181 ns_timeout = timeval_to_ns(&tv) + 2 * (s64)NSEC_PER_SEC;
183 clear_evtchn(port);
185 while (test_bit(_XEN_PCIF_active,
186 (unsigned long *)&pdev->sh_info->flags)) {
187 if (HYPERVISOR_poll(&port, 1, jiffies + 3*HZ))
188 BUG();
189 clear_evtchn(port);
190 do_gettimeofday(&tv);
191 ns = timeval_to_ns(&tv);
192 if (ns > ns_timeout) {
193 dev_err(&pdev->xdev->dev,
194 "pciback not responding!!!\n");
195 clear_bit(_XEN_PCIF_active,
196 (unsigned long *)&pdev->sh_info->flags);
197 err = XEN_PCI_ERR_dev_not_found;
198 goto out;
199 }
200 }
202 memcpy(op, active_op, sizeof(struct xen_pci_op));
204 err = op->err;
205 out:
206 spin_unlock_irqrestore(&pdev->sh_info_lock, irq_flags);
207 return err;
208 }
210 /* Access to this function is spinlocked in drivers/pci/access.c */
211 static int pcifront_bus_read(struct pci_bus *bus, unsigned int devfn,
212 int where, int size, u32 * val)
213 {
214 int err = 0;
215 struct xen_pci_op op = {
216 .cmd = XEN_PCI_OP_conf_read,
217 .domain = pci_domain_nr(bus),
218 .bus = bus->number,
219 .devfn = devfn,
220 .offset = where,
221 .size = size,
222 };
223 struct pcifront_sd *sd = bus->sysdata;
224 struct pcifront_device *pdev = pcifront_get_pdev(sd);
226 if (verbose_request)
227 dev_info(&pdev->xdev->dev,
228 "read dev=%04x:%02x:%02x.%01x - offset %x size %d\n",
229 pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
230 PCI_FUNC(devfn), where, size);
232 err = do_pci_op(pdev, &op);
234 if (likely(!err)) {
235 if (verbose_request)
236 dev_info(&pdev->xdev->dev, "read got back value %x\n",
237 op.value);
239 *val = op.value;
240 } else if (err == -ENODEV) {
241 /* No device here, pretend that it just returned 0 */
242 err = 0;
243 *val = 0;
244 }
246 return errno_to_pcibios_err(err);
247 }
249 /* Access to this function is spinlocked in drivers/pci/access.c */
250 static int pcifront_bus_write(struct pci_bus *bus, unsigned int devfn,
251 int where, int size, u32 val)
252 {
253 struct xen_pci_op op = {
254 .cmd = XEN_PCI_OP_conf_write,
255 .domain = pci_domain_nr(bus),
256 .bus = bus->number,
257 .devfn = devfn,
258 .offset = where,
259 .size = size,
260 .value = val,
261 };
262 struct pcifront_sd *sd = bus->sysdata;
263 struct pcifront_device *pdev = pcifront_get_pdev(sd);
265 if (verbose_request)
266 dev_info(&pdev->xdev->dev,
267 "write dev=%04x:%02x:%02x.%01x - "
268 "offset %x size %d val %x\n",
269 pci_domain_nr(bus), bus->number,
270 PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
272 return errno_to_pcibios_err(do_pci_op(pdev, &op));
273 }
275 struct pci_ops pcifront_bus_ops = {
276 .read = pcifront_bus_read,
277 .write = pcifront_bus_write,
278 };
280 /* Claim resources for the PCI frontend as-is, backend won't allow changes */
281 static void pcifront_claim_resource(struct pci_dev *dev, void *data)
282 {
283 struct pcifront_device *pdev = data;
284 int i;
285 struct resource *r;
287 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
288 r = &dev->resource[i];
290 if (!r->parent && r->start && r->flags) {
291 dev_dbg(&pdev->xdev->dev, "claiming resource %s/%d\n",
292 pci_name(dev), i);
293 pci_claim_resource(dev, i);
294 }
295 }
296 }
298 int pcifront_scan_root(struct pcifront_device *pdev,
299 unsigned int domain, unsigned int bus)
300 {
301 struct pci_bus *b;
302 struct pcifront_sd *sd = NULL;
303 struct pci_bus_entry *bus_entry = NULL;
304 int err = 0;
306 #ifndef CONFIG_PCI_DOMAINS
307 if (domain != 0) {
308 dev_err(&pdev->xdev->dev,
309 "PCI Root in non-zero PCI Domain! domain=%d\n", domain);
310 dev_err(&pdev->xdev->dev,
311 "Please compile with CONFIG_PCI_DOMAINS\n");
312 err = -EINVAL;
313 goto err_out;
314 }
315 #endif
317 dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n",
318 domain, bus);
320 bus_entry = kmalloc(sizeof(*bus_entry), GFP_KERNEL);
321 sd = kmalloc(sizeof(*sd), GFP_KERNEL);
322 if (!bus_entry || !sd) {
323 err = -ENOMEM;
324 goto err_out;
325 }
326 pcifront_init_sd(sd, domain, bus, pdev);
328 b = pci_scan_bus_parented(&pdev->xdev->dev, bus,
329 &pcifront_bus_ops, sd);
330 if (!b) {
331 dev_err(&pdev->xdev->dev,
332 "Error creating PCI Frontend Bus!\n");
333 err = -ENOMEM;
334 goto err_out;
335 }
337 pcifront_setup_root_resources(b, sd);
338 bus_entry->bus = b;
340 list_add(&bus_entry->list, &pdev->root_buses);
342 /* Claim resources before going "live" with our devices */
343 pci_walk_bus(b, pcifront_claim_resource, pdev);
345 pci_bus_add_devices(b);
347 return 0;
349 err_out:
350 kfree(bus_entry);
351 kfree(sd);
353 return err;
354 }
356 int pcifront_rescan_root(struct pcifront_device *pdev,
357 unsigned int domain, unsigned int bus)
358 {
359 struct pci_bus *b;
360 struct pci_dev *d;
361 unsigned int devfn;
363 #ifndef CONFIG_PCI_DOMAINS
364 if (domain != 0) {
365 dev_err(&pdev->xdev->dev,
366 "PCI Root in non-zero PCI Domain! domain=%d\n", domain);
367 dev_err(&pdev->xdev->dev,
368 "Please compile with CONFIG_PCI_DOMAINS\n");
369 return -EINVAL;
370 }
371 #endif
373 dev_info(&pdev->xdev->dev, "Rescanning PCI Frontend Bus %04x:%02x\n",
374 domain, bus);
376 b = pci_find_bus(domain, bus);
377 if(!b)
378 /* If the bus is unknown, create it. */
379 return pcifront_scan_root(pdev, domain, bus);
381 /* Rescan the bus for newly attached functions and add.
382 * We omit handling of PCI bridge attachment because pciback prevents
383 * bridges from being exported.
384 */
385 for (devfn = 0; devfn < 0x100; devfn++) {
386 d = pci_get_slot(b, devfn);
387 if(d) {
388 /* Device is already known. */
389 pci_dev_put(d);
390 continue;
391 }
393 d = pci_scan_single_device(b, devfn);
394 if (d) {
395 dev_info(&pdev->xdev->dev, "New device on "
396 "%04x:%02x:%02x.%02x found.\n", domain, bus,
397 PCI_SLOT(devfn), PCI_FUNC(devfn));
398 pci_bus_add_device(d);
399 }
400 }
402 return 0;
403 }
405 static void free_root_bus_devs(struct pci_bus *bus)
406 {
407 struct pci_dev *dev;
409 while (!list_empty(&bus->devices)) {
410 dev = container_of(bus->devices.next, struct pci_dev,
411 bus_list);
412 dev_dbg(&dev->dev, "removing device\n");
413 pci_remove_bus_device(dev);
414 }
415 }
417 void pcifront_free_roots(struct pcifront_device *pdev)
418 {
419 struct pci_bus_entry *bus_entry, *t;
421 dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n");
423 list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) {
424 list_del(&bus_entry->list);
426 free_root_bus_devs(bus_entry->bus);
428 kfree(bus_entry->bus->sysdata);
430 device_unregister(bus_entry->bus->bridge);
431 pci_remove_bus(bus_entry->bus);
433 kfree(bus_entry);
434 }
435 }