ia64/linux-2.6.18-xen.hg

view drivers/pci/guestdev.c @ 912:dd42cdb0ab89

[IA64] Build blktap2 driver by default in x86 builds.

add CONFIG_XEN_BLKDEV_TAP2=y to buildconfigs/linux-defconfig_xen_ia64.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Mon Jun 29 12:09:16 2009 +0900 (2009-06-29)
parents 20be7f6d414a
children
line source
1 /*
2 * Copyright (c) 2008, 2009 NEC Corporation.
3 * Copyright (c) 2009 Isaku Yamahata
4 * VA Linux Systems Japan K.K.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place - Suite 330, Boston, MA 02111-1307 USA.
18 */
20 #include <linux/kernel.h>
21 #include <linux/list.h>
22 #include <linux/mm.h>
23 #include <linux/pci.h>
24 #include <linux/module.h>
25 #include <linux/string.h>
26 #include <linux/acpi.h>
27 #include <asm-x86_64/setup.h>
29 #define HID_LEN 8
30 #define UID_LEN 8
31 #define DEV_LEN 2
32 #define FUNC_LEN 1
33 #define DEV_NUM_MAX 31
34 #define FUNC_NUM_MAX 7
35 #define INVALID_SEG (-1)
36 #define INVALID_BBN (-1)
37 #define GUESTDEV_STR_MAX 128
39 #define GUESTDEV_FLAG_TYPE_MASK 0x3
40 #define GUESTDEV_FLAG_DEVICEPATH 0x1
41 #define GUESTDEV_FLAG_SBDF 0x2
43 #define GUESTDEV_OPT_IOMUL 0x1
45 struct guestdev {
46 int flags;
47 int options;
48 struct list_head root_list;
49 union {
50 struct devicepath {
51 char hid[HID_LEN + 1];
52 char uid[UID_LEN + 1];
53 int seg;
54 int bbn;
55 struct devicepath_node *child;
56 } devicepath;
57 struct sbdf {
58 int seg;
59 int bus;
60 int dev;
61 int func;
62 } sbdf;
63 } u;
64 };
66 struct devicepath_node {
67 int dev;
68 int func;
69 struct devicepath_node *child;
70 };
72 struct pcidev_sbdf {
73 int seg;
74 int bus;
75 struct pcidev_sbdf_node *child;
76 };
78 struct pcidev_sbdf_node {
79 int dev;
80 int func;
81 struct pcidev_sbdf_node *child;
82 };
84 static int reassign_resources = 0;
86 static char guestdev_param[COMMAND_LINE_SIZE];
87 LIST_HEAD(guestdev_list);
89 /* Get hid and uid */
90 static int __init pci_get_hid_uid(char *str, char *hid, char *uid)
91 {
92 char *sp, *ep;
93 int len;
95 sp = str;
96 ep = strchr(sp, ':');
97 if (!ep) {
98 ep = strchr(sp, '-');
99 if (!ep)
100 goto format_err_end;
101 }
102 /* hid length */
103 len = ep - sp;
104 if (len <= 0 || HID_LEN < len)
105 goto format_err_end;
107 strlcpy(hid, sp, len);
109 if (*ep == '-') { /* no uid */
110 uid[0] = '\0';
111 return TRUE;
112 }
114 sp = ep + 1;
115 ep = strchr(sp, '-');
116 if (!ep)
117 ep = strchr(sp, '\0');
119 /* uid length */
120 len = ep - sp;
121 if (len <= 0 || UID_LEN < len)
122 goto format_err_end;
124 strlcpy(uid, sp, len);
125 return TRUE;
127 format_err_end:
128 return FALSE;
129 }
131 /* Get device and function */
132 static int __init pci_get_dev_func(char *str, int *dev, int *func)
133 {
134 if (sscanf(str, "%02x.%01x", dev, func) != 2)
135 goto format_err_end;
137 if (*dev < 0 || DEV_NUM_MAX < *dev)
138 goto format_err_end;
140 if (*func < 0 || FUNC_NUM_MAX < *func)
141 goto format_err_end;
143 return TRUE;
145 format_err_end:
146 return FALSE;
147 }
149 /* Check extended guestdev parameter format error */
150 static int __init pci_check_extended_guestdev_format(char *str)
151 {
152 int flg;
153 char *p;
155 /* Check extended format */
156 if (strpbrk(str, "(|)") == NULL)
157 return TRUE;
159 flg = 0;
160 p = str;
161 while (*p) {
162 switch (*p) {
163 case '(':
164 /* Check nesting error */
165 if (flg != 0)
166 goto format_err_end;
167 flg = 1;
168 /* Check position of '(' is head or
169 previos charactor of '(' is not '-'. */
170 if (p == str || *(p - 1) != '-')
171 goto format_err_end;
172 break;
173 case ')':
174 /* Check nesting error */
175 if (flg != 1)
176 goto format_err_end;
177 flg = 0;
178 /* Check next charactor of ')' is not '\0' */
179 if (*(p + 1) != '\0')
180 goto format_err_end;
181 break;
182 case '|':
183 /* Check position of '|' is outside of '(' and ')' */
184 if (flg != 1)
185 goto format_err_end;
186 break;
187 default:
188 break;
189 }
190 p++;
191 }
192 /* Check number of '(' and ')' are not equal */
193 if (flg != 0)
194 goto format_err_end;
195 return TRUE;
197 format_err_end:
198 printk(KERN_ERR
199 "PCI: The format of the guestdev parameter is illegal. [%s]\n",
200 str);
201 return FALSE;
202 }
204 /* Make guestdev strings */
205 static void pci_make_guestdev_str(struct guestdev *gdev,
206 char *gdev_str, int buf_size)
207 {
208 struct devicepath_node *node;
209 int count;
211 switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
212 case GUESTDEV_FLAG_DEVICEPATH:
213 memset(gdev_str, 0, buf_size);
215 if (strlen(gdev->u.devicepath.uid))
216 count = snprintf(gdev_str, buf_size, "%s:%s",
217 gdev->u.devicepath.hid,
218 gdev->u.devicepath.uid);
219 else
220 count = snprintf(gdev_str, buf_size, "%s",
221 gdev->u.devicepath.hid);
222 if (count < 0)
223 return;
225 node = gdev->u.devicepath.child;
226 while (node) {
227 gdev_str += count;
228 buf_size -= count;
229 if (buf_size <= 0)
230 return;
231 count = snprintf(gdev_str, buf_size, "-%02x.%01x",
232 node->dev, node->func);
233 if (count < 0)
234 return;
235 node = node->child;
236 }
237 break;
238 case GUESTDEV_FLAG_SBDF:
239 snprintf(gdev_str, buf_size, "%04x:%02x:%02x.%01x",
240 gdev->u.sbdf.seg, gdev->u.sbdf.bus,
241 gdev->u.sbdf.dev, gdev->u.sbdf.func);
242 break;
243 default:
244 BUG();
245 }
246 }
248 /* Free guestdev and nodes */
249 static void __init pci_free_guestdev(struct guestdev *gdev)
250 {
251 struct devicepath_node *node, *next;
253 if (!gdev)
254 return;
255 if (gdev->flags & GUESTDEV_FLAG_DEVICEPATH) {
256 node = gdev->u.devicepath.child;
257 while (node) {
258 next = node->child;
259 kfree(node);
260 node = next;
261 }
262 }
263 list_del(&gdev->root_list);
264 kfree(gdev);
265 }
267 /* Copy guestdev and nodes */
268 struct guestdev __init *pci_copy_guestdev(struct guestdev *gdev_src)
269 {
270 struct guestdev *gdev;
271 struct devicepath_node *node, *node_src, *node_upper;
273 BUG_ON(!(gdev_src->flags & GUESTDEV_FLAG_DEVICEPATH));
275 gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
276 if (!gdev)
277 goto allocate_err_end;
279 memset(gdev, 0, sizeof(*gdev));
280 INIT_LIST_HEAD(&gdev->root_list);
281 gdev->flags = gdev_src->flags;
282 gdev->options = gdev_src->options;
283 strcpy(gdev->u.devicepath.hid, gdev_src->u.devicepath.hid);
284 strcpy(gdev->u.devicepath.uid, gdev_src->u.devicepath.uid);
285 gdev->u.devicepath.seg = gdev_src->u.devicepath.seg;
286 gdev->u.devicepath.bbn = gdev_src->u.devicepath.bbn;
288 node_upper = NULL;
290 node_src = gdev_src->u.devicepath.child;
291 while (node_src) {
292 node = kmalloc(sizeof(*node), GFP_KERNEL);
293 if (!node)
294 goto allocate_err_end;
295 memset(node, 0, sizeof(*node));
296 node->dev = node_src->dev;
297 node->func = node_src->func;
298 if (!node_upper)
299 gdev->u.devicepath.child = node;
300 else
301 node_upper->child = node;
302 node_upper = node;
303 node_src = node_src->child;
304 }
306 return gdev;
308 allocate_err_end:
309 if (gdev)
310 pci_free_guestdev(gdev);
311 printk(KERN_ERR "PCI: Failed to allocate memory.\n");
312 return NULL;
313 }
315 /* Make guestdev from path strings */
316 static int __init pci_make_devicepath_guestdev(char *path_str, int options)
317 {
318 char hid[HID_LEN + 1], uid[UID_LEN + 1];
319 char *sp, *ep;
320 struct guestdev *gdev, *gdev_org;
321 struct devicepath_node *node, *node_tmp;
322 int dev, func, ret_val;
324 ret_val = 0;
325 gdev = gdev_org = NULL;
326 sp = path_str;
327 /* Look for end of hid:uid'-' */
328 ep = strchr(sp, '-');
329 /* Only hid, uid. (No dev, func) */
330 if (!ep)
331 goto format_err_end;
333 memset(hid, 0 ,sizeof(hid));
334 memset(uid, 0, sizeof(uid));
335 if (!pci_get_hid_uid(sp, hid, uid))
336 goto format_err_end;
338 gdev_org = kmalloc(sizeof(*gdev_org), GFP_KERNEL);
339 if (!gdev_org)
340 goto allocate_err_end;
341 memset(gdev_org, 0, sizeof(*gdev_org));
342 INIT_LIST_HEAD(&gdev_org->root_list);
343 gdev_org->flags = GUESTDEV_FLAG_DEVICEPATH;
344 gdev_org->options = options;
345 strcpy(gdev_org->u.devicepath.hid, hid);
346 strcpy(gdev_org->u.devicepath.uid, uid);
347 gdev_org->u.devicepath.seg = INVALID_SEG;
348 gdev_org->u.devicepath.bbn = INVALID_BBN;
350 gdev = gdev_org;
352 sp = ep + 1;
353 ep = sp;
354 do {
355 if (*sp == '(') {
356 sp++;
357 if (strchr(sp, '|')) {
358 gdev = pci_copy_guestdev(gdev_org);
359 if (!gdev) {
360 ret_val = -ENOMEM;
361 goto end;
362 }
363 }
364 continue;
365 }
366 if (gdev && pci_get_dev_func(sp, &dev, &func)) {
367 node = kmalloc(sizeof(*node), GFP_KERNEL);
368 if (!node)
369 goto allocate_err_end;
370 memset(node, 0, sizeof(*node));
371 node->dev = dev;
372 node->func = func;
373 /* add node to end of guestdev */
374 if (gdev->u.devicepath.child) {
375 node_tmp = gdev->u.devicepath.child;
376 while (node_tmp->child) {
377 node_tmp = node_tmp->child;
378 }
379 node_tmp->child = node;
380 } else
381 gdev->u.devicepath.child = node;
382 } else if (gdev) {
383 printk(KERN_ERR
384 "PCI: Can't obtain dev# and #func# from %s.\n",
385 sp);
386 ret_val = -EINVAL;
387 if (gdev == gdev_org)
388 goto end;
389 pci_free_guestdev(gdev);
390 gdev = NULL;
391 }
393 ep = strpbrk(sp, "-|)");
394 if (!ep)
395 ep = strchr(sp, '\0');
396 /* Is *ep '|' OR ')' OR '\0' ? */
397 if (*ep != '-') {
398 if (gdev)
399 list_add_tail(&gdev->root_list, &guestdev_list);
400 if (*ep == '|') {
401 /* Between '|' and '|' ? */
402 if (strchr(ep + 1, '|')) {
403 gdev = pci_copy_guestdev(gdev_org);
404 if (!gdev) {
405 ret_val = -ENOMEM;
406 goto end;
407 }
408 } else {
409 gdev = gdev_org;
410 gdev_org = NULL;
411 }
412 } else {
413 gdev_org = NULL;
414 gdev = NULL;
415 }
416 }
417 if (*ep == ')')
418 ep++;
419 sp = ep + 1;
420 } while (*ep != '\0');
422 goto end;
424 format_err_end:
425 printk(KERN_ERR
426 "PCI: The format of the guestdev parameter is illegal. [%s]\n",
427 path_str);
428 ret_val = -EINVAL;
429 goto end;
431 allocate_err_end:
432 printk(KERN_ERR "PCI: Failed to allocate memory.\n");
433 ret_val = -ENOMEM;
434 goto end;
436 end:
437 if (gdev_org && (gdev_org != gdev))
438 pci_free_guestdev(gdev_org);
439 if (gdev)
440 pci_free_guestdev(gdev);
441 return ret_val;
442 }
444 static int __init pci_make_sbdf_guestdev(char* str, int options)
445 {
446 struct guestdev *gdev;
447 int seg, bus, dev, func;
449 if (sscanf(str, "%x:%x:%x.%x", &seg, &bus, &dev, &func) != 4) {
450 seg = 0;
451 if (sscanf(str, "%x:%x.%x", &bus, &dev, &func) != 3)
452 return -EINVAL;
453 }
454 gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
455 if (!gdev) {
456 printk(KERN_ERR "PCI: Failed to allocate memory.\n");
457 return -ENOMEM;
458 }
459 INIT_LIST_HEAD(&gdev->root_list);
460 gdev->flags = GUESTDEV_FLAG_SBDF;
461 gdev->options = options;
462 gdev->u.sbdf.seg = seg;
463 gdev->u.sbdf.bus = bus;
464 gdev->u.sbdf.dev = dev;
465 gdev->u.sbdf.func = func;
466 list_add_tail(&gdev->root_list, &guestdev_list);
467 return 0;
468 }
470 static int __init pci_parse_options(const char *str)
471 {
472 int options = 0;
473 char *ep;
475 while (str) {
476 str++;
477 ep = strchr(str, '+');
478 if (ep)
479 ep = '\0'; /* Chop */
481 if (!strcmp(str, "iomul"))
482 options |= GUESTDEV_OPT_IOMUL;
484 str = ep;
485 }
486 return options;
487 }
489 /* Parse guestdev parameter */
490 static int __init pci_parse_guestdev(void)
491 {
492 int len;
493 char *sp, *ep, *op;
494 int options;
495 struct list_head *head;
496 struct guestdev *gdev;
497 char path_str[GUESTDEV_STR_MAX];
498 int ret_val = 0;
500 len = strlen(guestdev_param);
501 if (len == 0)
502 return 0;
504 sp = guestdev_param;
506 do {
507 ep = strchr(sp, ',');
508 /* Chop */
509 if (ep)
510 *ep = '\0';
511 options = 0;
512 op = strchr(sp, '+');
513 if (op && (!ep || op < ep)) {
514 options = pci_parse_options(op);
515 *op = '\0'; /* Chop */
516 }
517 ret_val = pci_make_sbdf_guestdev(sp, options);
518 if (ret_val == -EINVAL) {
519 if (pci_check_extended_guestdev_format(sp)) {
520 ret_val = pci_make_devicepath_guestdev(
521 sp, options);
522 if (ret_val && ret_val != -EINVAL)
523 break;
524 }
525 } else if (ret_val)
526 break;
528 if (ep)
529 ep++;
530 sp = ep;
531 } while (ep);
533 list_for_each(head, &guestdev_list) {
534 gdev = list_entry(head, struct guestdev, root_list);
535 pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX);
536 printk(KERN_DEBUG
537 "PCI: %s has been reserved for guest domain.\n",
538 path_str);
539 }
540 return 0;
541 }
543 arch_initcall(pci_parse_guestdev);
545 /* Get command line */
546 static int __init pci_guestdev_setup(char *str)
547 {
548 if (strlen(str) >= COMMAND_LINE_SIZE)
549 return 0;
550 strlcpy(guestdev_param, str, sizeof(guestdev_param));
551 return 1;
552 }
554 __setup("guestdev=", pci_guestdev_setup);
556 /* Free sbdf and nodes */
557 static void pci_free_sbdf(struct pcidev_sbdf *sbdf)
558 {
559 struct pcidev_sbdf_node *node, *next;
561 node = sbdf->child;
562 while (node) {
563 next = node->child;
564 kfree(node);
565 node = next;
566 }
567 /* Skip kfree(sbdf) */
568 }
570 /* Does PCI device belong to sub tree specified by guestdev with device path? */
571 typedef int (*pci_node_match_t)(const struct devicepath_node *gdev_node,
572 const struct pcidev_sbdf_node *sbdf_node,
573 int options);
575 static int pci_node_match(const struct devicepath_node *gdev_node,
576 const struct pcidev_sbdf_node *sbdf_node,
577 int options_unused)
578 {
579 return (gdev_node->dev == sbdf_node->dev &&
580 gdev_node->func == sbdf_node->func);
581 }
583 static int pci_is_in_devicepath_sub_tree(struct guestdev *gdev,
584 struct pcidev_sbdf *sbdf,
585 pci_node_match_t match)
586 {
587 int seg, bbn;
588 struct devicepath_node *gdev_node;
589 struct pcidev_sbdf_node *sbdf_node;
591 if (!gdev || !sbdf)
592 return FALSE;
594 BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH));
596 /* Compare seg and bbn */
597 if (gdev->u.devicepath.seg == INVALID_SEG ||
598 gdev->u.devicepath.bbn == INVALID_BBN) {
599 if (acpi_pci_get_root_seg_bbn(gdev->u.devicepath.hid,
600 gdev->u.devicepath.uid, &seg, &bbn)) {
601 gdev->u.devicepath.seg = seg;
602 gdev->u.devicepath.bbn = bbn;
603 } else
604 return FALSE;
605 }
607 if (gdev->u.devicepath.seg != sbdf->seg ||
608 gdev->u.devicepath.bbn != sbdf->bus)
609 return FALSE;
611 gdev_node = gdev->u.devicepath.child;
612 sbdf_node = sbdf->child;
614 /* Compare dev and func */
615 while (gdev_node) {
616 if (!sbdf_node)
617 return FALSE;
618 if (!match(gdev_node, sbdf_node, gdev->options))
619 return FALSE;
620 gdev_node = gdev_node->child;
621 sbdf_node = sbdf_node->child;
622 }
623 return TRUE;
624 }
626 /* Get sbdf from device */
627 static int pci_get_sbdf_from_pcidev(
628 struct pci_dev *dev, struct pcidev_sbdf *sbdf)
629 {
630 struct pcidev_sbdf_node *node;
632 if (!dev)
633 return FALSE;
635 for(;;) {
636 node = kmalloc(sizeof(*node), GFP_KERNEL);
637 if (!node) {
638 printk(KERN_ERR "PCI: Failed to allocate memory.\n");
639 goto err_end;
640 }
641 memset(node, 0, sizeof(*node));
642 node->dev = PCI_SLOT(dev->devfn);
643 node->func = PCI_FUNC(dev->devfn);
645 if (!sbdf->child)
646 sbdf->child = node;
647 else {
648 node->child = sbdf->child;
649 sbdf->child = node;
650 }
651 if (!dev->bus)
652 goto err_end;
653 if (!dev->bus->self)
654 break;
655 dev = dev->bus->self;
656 }
657 if (sscanf(dev->dev.bus_id, "%04x:%02x", &sbdf->seg, &sbdf->bus) != 2)
658 goto err_end;
659 return TRUE;
661 err_end:
662 pci_free_sbdf(sbdf);
663 return FALSE;
664 }
666 /* Does PCI device belong to sub tree specified by guestdev with sbdf? */
667 typedef int (*pci_sbdf_match_t)(const struct guestdev *gdev,
668 const struct pci_dev *dev);
670 static int pci_sbdf_match(const struct guestdev *gdev,
671 const struct pci_dev *dev)
672 {
673 int seg, bus;
675 if (sscanf(dev->dev.bus_id, "%04x:%02x", &seg, &bus) != 2)
676 return FALSE;
678 return gdev->u.sbdf.seg == seg &&
679 gdev->u.sbdf.bus == bus &&
680 gdev->u.sbdf.dev == PCI_SLOT(dev->devfn) &&
681 gdev->u.sbdf.func == PCI_FUNC(dev->devfn);
682 }
684 static int pci_is_in_sbdf_sub_tree(struct guestdev *gdev, struct pci_dev *dev,
685 pci_sbdf_match_t match)
686 {
687 BUG_ON(!(gdev->flags & GUESTDEV_FLAG_SBDF));
688 for (;;) {
689 if (match(gdev, dev))
690 return TRUE;
691 if (!dev->bus || !dev->bus->self)
692 break;
693 dev = dev->bus->self;
694 }
695 return FALSE;
696 }
698 /* Does PCI device belong to sub tree specified by guestdev parameter? */
699 static int __pci_is_guestdev(struct pci_dev *dev, pci_node_match_t node_match,
700 pci_sbdf_match_t sbdf_match)
701 {
702 struct guestdev *gdev;
703 struct pcidev_sbdf pcidev_sbdf, *sbdf = NULL;
704 struct list_head *head;
705 int result = FALSE;
707 if (!dev)
708 return FALSE;
710 list_for_each(head, &guestdev_list) {
711 gdev = list_entry(head, struct guestdev, root_list);
712 switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
713 case GUESTDEV_FLAG_DEVICEPATH:
714 if (sbdf == NULL) {
715 sbdf = &pcidev_sbdf;
716 memset(sbdf, 0 ,sizeof(*sbdf));
717 if (!pci_get_sbdf_from_pcidev(dev, sbdf))
718 goto out;
719 }
720 if (pci_is_in_devicepath_sub_tree(gdev, sbdf,
721 node_match)) {
722 result = TRUE;
723 goto out;
724 }
725 break;
726 case GUESTDEV_FLAG_SBDF:
727 if (pci_is_in_sbdf_sub_tree(gdev, dev, sbdf_match)) {
728 result = TRUE;
729 goto out;
730 }
731 break;
732 default:
733 BUG();
734 }
735 }
736 out:
737 if (sbdf)
738 pci_free_sbdf(sbdf);
739 return result;
740 }
742 int pci_is_guestdev(struct pci_dev *dev)
743 {
744 return __pci_is_guestdev(dev, pci_node_match, pci_sbdf_match);
745 }
746 EXPORT_SYMBOL(pci_is_guestdev);
748 static int __init pci_set_reassign_resources(char *str)
749 {
750 reassign_resources = 1;
752 return 1;
753 }
755 __setup("reassign_resources", pci_set_reassign_resources);
757 int pci_is_reassigndev(struct pci_dev *dev)
758 {
759 if (reassign_resources)
760 return pci_is_guestdev(dev);
761 return FALSE;
762 }
763 EXPORT_SYMBOL(pci_is_reassigndev);
765 #ifdef CONFIG_PCI_IOMULTI
766 static int pci_iomul_node_match(const struct devicepath_node *gdev_node,
767 const struct pcidev_sbdf_node *sbdf_node,
768 int options)
769 {
770 return (options & GUESTDEV_OPT_IOMUL) &&
771 ((gdev_node->child != NULL &&
772 sbdf_node->child != NULL &&
773 gdev_node->dev == sbdf_node->dev &&
774 gdev_node->func == sbdf_node->func) ||
775 (gdev_node->child == NULL &&
776 sbdf_node->child == NULL &&
777 gdev_node->dev == sbdf_node->dev));
778 }
780 static int pci_iomul_sbdf_match(const struct guestdev *gdev,
781 const struct pci_dev *dev)
782 {
783 int seg, bus;
785 if (sscanf(dev->dev.bus_id, "%04x:%02x", &seg, &bus) != 2)
786 return FALSE;
788 return (gdev->options & GUESTDEV_OPT_IOMUL) &&
789 gdev->u.sbdf.seg == seg &&
790 gdev->u.sbdf.bus == bus &&
791 gdev->u.sbdf.dev == PCI_SLOT(dev->devfn);
792 }
794 int pci_is_iomuldev(struct pci_dev *dev)
795 {
796 return __pci_is_guestdev(dev,
797 pci_iomul_node_match, pci_iomul_sbdf_match);
798 }
799 EXPORT_SYMBOL_GPL(pci_is_iomuldev);
800 #endif /* CONFIG_PCI_IOMULTI */
802 /* Check whether the devicepath exists under the pci root bus */
803 static int __init pci_check_devicepath_exists(
804 struct guestdev *gdev, struct pci_bus *bus)
805 {
806 struct devicepath_node *node;
807 struct pci_dev *dev;
809 BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH));
811 node = gdev->u.devicepath.child;
812 while (node) {
813 if (!bus)
814 return FALSE;
815 dev = pci_get_slot(bus, PCI_DEVFN(node->dev, node->func));
816 if (!dev)
817 return FALSE;
818 bus = dev->subordinate;
819 node = node->child;
820 pci_dev_put(dev);
821 }
822 return TRUE;
823 }
825 /* Check whether the guestdev exists in the PCI device tree */
826 static int __init pci_check_guestdev_exists(void)
827 {
828 struct list_head *head;
829 struct guestdev *gdev;
830 int seg, bbn;
831 struct pci_bus *bus;
832 struct pci_dev *dev;
833 char path_str[GUESTDEV_STR_MAX];
835 list_for_each(head, &guestdev_list) {
836 gdev = list_entry(head, struct guestdev, root_list);
837 switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
838 case GUESTDEV_FLAG_DEVICEPATH:
839 if (gdev->u.devicepath.seg == INVALID_SEG ||
840 gdev->u.devicepath.bbn == INVALID_BBN) {
841 if (acpi_pci_get_root_seg_bbn(
842 gdev->u.devicepath.hid,
843 gdev->u.devicepath.uid, &seg, &bbn)) {
844 gdev->u.devicepath.seg = seg;
845 gdev->u.devicepath.bbn = bbn;
846 } else {
847 pci_make_guestdev_str(gdev,
848 path_str, GUESTDEV_STR_MAX);
849 printk(KERN_INFO
850 "PCI: Device does not exist. %s\n",
851 path_str);
852 continue;
853 }
854 }
856 bus = pci_find_bus(gdev->u.devicepath.seg,
857 gdev->u.devicepath.bbn);
858 if (!bus ||
859 !pci_check_devicepath_exists(gdev, bus)) {
860 pci_make_guestdev_str(gdev, path_str,
861 GUESTDEV_STR_MAX);
862 printk(KERN_INFO
863 "PCI: Device does not exist. %s\n",
864 path_str);
865 }
866 break;
867 case GUESTDEV_FLAG_SBDF:
868 bus = pci_find_bus(gdev->u.sbdf.seg, gdev->u.sbdf.bus);
869 if (bus) {
870 dev = pci_get_slot(bus,
871 PCI_DEVFN(gdev->u.sbdf.dev,
872 gdev->u.sbdf.func));
873 if (dev) {
874 pci_dev_put(dev);
875 continue;
876 }
877 }
878 pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX);
879 printk(KERN_INFO "PCI: Device does not exist. %s\n",
880 path_str);
881 break;
882 default:
883 BUG();
884 }
885 }
886 return 0;
887 }
889 fs_initcall(pci_check_guestdev_exists);