121ff329dSWill Deacon #include "kvm/devices.h"
221ff329dSWill Deacon #include "kvm/kvm.h"
321ff329dSWill Deacon
421ff329dSWill Deacon #include <linux/err.h>
521ff329dSWill Deacon #include <linux/rbtree.h>
621ff329dSWill Deacon
721ff329dSWill Deacon struct device_bus {
821ff329dSWill Deacon struct rb_root root;
921ff329dSWill Deacon int dev_num;
1021ff329dSWill Deacon };
1121ff329dSWill Deacon
1221ff329dSWill Deacon static struct device_bus device_trees[DEVICE_BUS_MAX] = {
1321ff329dSWill Deacon [0 ... (DEVICE_BUS_MAX - 1)] = { RB_ROOT, 0 },
1421ff329dSWill Deacon };
1521ff329dSWill Deacon
device__register(struct device_header * dev)1621ff329dSWill Deacon int device__register(struct device_header *dev)
1721ff329dSWill Deacon {
1821ff329dSWill Deacon struct device_bus *bus;
1921ff329dSWill Deacon struct rb_node **node, *parent = NULL;
2021ff329dSWill Deacon
2121ff329dSWill Deacon if (dev->bus_type >= DEVICE_BUS_MAX) {
2221ff329dSWill Deacon pr_warning("Ignoring device registration on unknown bus %d\n",
2321ff329dSWill Deacon dev->bus_type);
2421ff329dSWill Deacon return -EINVAL;
2521ff329dSWill Deacon }
2621ff329dSWill Deacon
2721ff329dSWill Deacon bus = &device_trees[dev->bus_type];
2821ff329dSWill Deacon dev->dev_num = bus->dev_num++;
2921ff329dSWill Deacon
3021ff329dSWill Deacon node = &bus->root.rb_node;
3121ff329dSWill Deacon while (*node) {
3221ff329dSWill Deacon int num = rb_entry(*node, struct device_header, node)->dev_num;
3321ff329dSWill Deacon int result = dev->dev_num - num;
3421ff329dSWill Deacon
35*b6dcc466SJames Morse parent = *node;
3621ff329dSWill Deacon if (result < 0)
3721ff329dSWill Deacon node = &((*node)->rb_left);
3821ff329dSWill Deacon else if (result > 0)
3921ff329dSWill Deacon node = &((*node)->rb_right);
4021ff329dSWill Deacon else
4121ff329dSWill Deacon return -EEXIST;
4221ff329dSWill Deacon }
4321ff329dSWill Deacon
4421ff329dSWill Deacon rb_link_node(&dev->node, parent, node);
4521ff329dSWill Deacon rb_insert_color(&dev->node, &bus->root);
4621ff329dSWill Deacon return 0;
4721ff329dSWill Deacon }
4821ff329dSWill Deacon
device__unregister(struct device_header * dev)49bb7b03f3SWill Deacon void device__unregister(struct device_header *dev)
50bb7b03f3SWill Deacon {
51bb7b03f3SWill Deacon struct device_bus *bus = &device_trees[dev->bus_type];
52bb7b03f3SWill Deacon rb_erase(&dev->node, &bus->root);
53bb7b03f3SWill Deacon }
54bb7b03f3SWill Deacon
device__find_dev(enum device_bus_type bus_type,u8 dev_num)5521ff329dSWill Deacon struct device_header *device__find_dev(enum device_bus_type bus_type, u8 dev_num)
5621ff329dSWill Deacon {
5721ff329dSWill Deacon struct rb_node *node;
5821ff329dSWill Deacon
5921ff329dSWill Deacon if (bus_type >= DEVICE_BUS_MAX)
6021ff329dSWill Deacon return ERR_PTR(-EINVAL);
6121ff329dSWill Deacon
6221ff329dSWill Deacon node = device_trees[bus_type].root.rb_node;
6321ff329dSWill Deacon while (node) {
6421ff329dSWill Deacon struct device_header *dev = rb_entry(node, struct device_header,
6521ff329dSWill Deacon node);
6621ff329dSWill Deacon if (dev_num < dev->dev_num) {
6721ff329dSWill Deacon node = node->rb_left;
6821ff329dSWill Deacon } else if (dev_num > dev->dev_num) {
6921ff329dSWill Deacon node = node->rb_right;
7021ff329dSWill Deacon } else {
7121ff329dSWill Deacon return dev;
7221ff329dSWill Deacon }
7321ff329dSWill Deacon }
7421ff329dSWill Deacon
7521ff329dSWill Deacon return NULL;
7621ff329dSWill Deacon }
7721ff329dSWill Deacon
device__first_dev(enum device_bus_type bus_type)7821ff329dSWill Deacon struct device_header *device__first_dev(enum device_bus_type bus_type)
7921ff329dSWill Deacon {
8021ff329dSWill Deacon struct rb_node *node;
8121ff329dSWill Deacon
8221ff329dSWill Deacon if (bus_type >= DEVICE_BUS_MAX)
8321ff329dSWill Deacon return NULL;
8421ff329dSWill Deacon
8521ff329dSWill Deacon node = rb_first(&device_trees[bus_type].root);
8621ff329dSWill Deacon return node ? rb_entry(node, struct device_header, node) : NULL;
8721ff329dSWill Deacon }
8821ff329dSWill Deacon
device__next_dev(struct device_header * dev)8921ff329dSWill Deacon struct device_header *device__next_dev(struct device_header *dev)
9021ff329dSWill Deacon {
9121ff329dSWill Deacon struct rb_node *node = rb_next(&dev->node);
9221ff329dSWill Deacon return node ? rb_entry(node, struct device_header, node) : NULL;
9321ff329dSWill Deacon }
94