xref: /kvmtool/devices.c (revision 21ff329de8997d20acba0da657ef17671eb861ab)
1*21ff329dSWill Deacon #include "kvm/devices.h"
2*21ff329dSWill Deacon #include "kvm/kvm.h"
3*21ff329dSWill Deacon 
4*21ff329dSWill Deacon #include <linux/err.h>
5*21ff329dSWill Deacon #include <linux/rbtree.h>
6*21ff329dSWill Deacon 
7*21ff329dSWill Deacon struct device_bus {
8*21ff329dSWill Deacon 	struct rb_root	root;
9*21ff329dSWill Deacon 	int		dev_num;
10*21ff329dSWill Deacon };
11*21ff329dSWill Deacon 
12*21ff329dSWill Deacon static struct device_bus device_trees[DEVICE_BUS_MAX] = {
13*21ff329dSWill Deacon 	[0 ... (DEVICE_BUS_MAX - 1)] = { RB_ROOT, 0 },
14*21ff329dSWill Deacon };
15*21ff329dSWill Deacon 
16*21ff329dSWill Deacon int device__register(struct device_header *dev)
17*21ff329dSWill Deacon {
18*21ff329dSWill Deacon 	struct device_bus *bus;
19*21ff329dSWill Deacon 	struct rb_node **node, *parent = NULL;
20*21ff329dSWill Deacon 
21*21ff329dSWill Deacon 	if (dev->bus_type >= DEVICE_BUS_MAX) {
22*21ff329dSWill Deacon 		pr_warning("Ignoring device registration on unknown bus %d\n",
23*21ff329dSWill Deacon 			   dev->bus_type);
24*21ff329dSWill Deacon 		return -EINVAL;
25*21ff329dSWill Deacon 	}
26*21ff329dSWill Deacon 
27*21ff329dSWill Deacon 	bus = &device_trees[dev->bus_type];
28*21ff329dSWill Deacon 	dev->dev_num = bus->dev_num++;
29*21ff329dSWill Deacon 
30*21ff329dSWill Deacon 	node = &bus->root.rb_node;
31*21ff329dSWill Deacon 	while (*node) {
32*21ff329dSWill Deacon 		int num = rb_entry(*node, struct device_header, node)->dev_num;
33*21ff329dSWill Deacon 		int result = dev->dev_num - num;
34*21ff329dSWill Deacon 
35*21ff329dSWill Deacon 		if (result < 0)
36*21ff329dSWill Deacon 			node = &((*node)->rb_left);
37*21ff329dSWill Deacon 		else if (result > 0)
38*21ff329dSWill Deacon 			node = &((*node)->rb_right);
39*21ff329dSWill Deacon 		else
40*21ff329dSWill Deacon 			return -EEXIST;
41*21ff329dSWill Deacon 	}
42*21ff329dSWill Deacon 
43*21ff329dSWill Deacon 	rb_link_node(&dev->node, parent, node);
44*21ff329dSWill Deacon 	rb_insert_color(&dev->node, &bus->root);
45*21ff329dSWill Deacon 	return 0;
46*21ff329dSWill Deacon }
47*21ff329dSWill Deacon 
48*21ff329dSWill Deacon struct device_header *device__find_dev(enum device_bus_type bus_type, u8 dev_num)
49*21ff329dSWill Deacon {
50*21ff329dSWill Deacon 	struct rb_node *node;
51*21ff329dSWill Deacon 
52*21ff329dSWill Deacon 	if (bus_type >= DEVICE_BUS_MAX)
53*21ff329dSWill Deacon 		return ERR_PTR(-EINVAL);
54*21ff329dSWill Deacon 
55*21ff329dSWill Deacon 	node = device_trees[bus_type].root.rb_node;
56*21ff329dSWill Deacon 	while (node) {
57*21ff329dSWill Deacon 		struct device_header *dev = rb_entry(node, struct device_header,
58*21ff329dSWill Deacon 						     node);
59*21ff329dSWill Deacon 		if (dev_num < dev->dev_num) {
60*21ff329dSWill Deacon 			node = node->rb_left;
61*21ff329dSWill Deacon 		} else if (dev_num > dev->dev_num) {
62*21ff329dSWill Deacon 			node = node->rb_right;
63*21ff329dSWill Deacon 		} else {
64*21ff329dSWill Deacon 			return dev;
65*21ff329dSWill Deacon 		}
66*21ff329dSWill Deacon 	}
67*21ff329dSWill Deacon 
68*21ff329dSWill Deacon 	return NULL;
69*21ff329dSWill Deacon }
70*21ff329dSWill Deacon 
71*21ff329dSWill Deacon struct device_header *device__first_dev(enum device_bus_type bus_type)
72*21ff329dSWill Deacon {
73*21ff329dSWill Deacon 	struct rb_node *node;
74*21ff329dSWill Deacon 
75*21ff329dSWill Deacon 	if (bus_type >= DEVICE_BUS_MAX)
76*21ff329dSWill Deacon 		return NULL;
77*21ff329dSWill Deacon 
78*21ff329dSWill Deacon 	node = rb_first(&device_trees[bus_type].root);
79*21ff329dSWill Deacon 	return node ? rb_entry(node, struct device_header, node) : NULL;
80*21ff329dSWill Deacon }
81*21ff329dSWill Deacon 
82*21ff329dSWill Deacon struct device_header *device__next_dev(struct device_header *dev)
83*21ff329dSWill Deacon {
84*21ff329dSWill Deacon 	struct rb_node *node = rb_next(&dev->node);
85*21ff329dSWill Deacon 	return node ? rb_entry(node, struct device_header, node) : NULL;
86*21ff329dSWill Deacon }
87