1*c383fe9cSSasha Levin #include "kvm/irq.h" 2*c383fe9cSSasha Levin 3*c383fe9cSSasha Levin #include <linux/types.h> 4*c383fe9cSSasha Levin #include <linux/rbtree.h> 5*c383fe9cSSasha Levin #include <linux/list.h> 6*c383fe9cSSasha Levin 7*c383fe9cSSasha Levin #include <stddef.h> 8*c383fe9cSSasha Levin #include <stdlib.h> 9*c383fe9cSSasha Levin 10*c383fe9cSSasha Levin static u8 next_pin = 1; 11*c383fe9cSSasha Levin static u8 next_line = 3; 12*c383fe9cSSasha Levin static u8 next_dev = 1; 13*c383fe9cSSasha Levin static struct rb_root pci_tree = RB_ROOT; 14*c383fe9cSSasha Levin 15*c383fe9cSSasha Levin static struct pci_dev *search(struct rb_root *root, u32 id) 16*c383fe9cSSasha Levin { 17*c383fe9cSSasha Levin struct rb_node *node = root->rb_node; 18*c383fe9cSSasha Levin 19*c383fe9cSSasha Levin while (node) { 20*c383fe9cSSasha Levin struct pci_dev *data = container_of(node, struct pci_dev, node); 21*c383fe9cSSasha Levin int result; 22*c383fe9cSSasha Levin 23*c383fe9cSSasha Levin result = id - data->id; 24*c383fe9cSSasha Levin 25*c383fe9cSSasha Levin if (result < 0) 26*c383fe9cSSasha Levin node = node->rb_left; 27*c383fe9cSSasha Levin else if (result > 0) 28*c383fe9cSSasha Levin node = node->rb_right; 29*c383fe9cSSasha Levin else 30*c383fe9cSSasha Levin return data; 31*c383fe9cSSasha Levin } 32*c383fe9cSSasha Levin return NULL; 33*c383fe9cSSasha Levin } 34*c383fe9cSSasha Levin 35*c383fe9cSSasha Levin static int insert(struct rb_root *root, struct pci_dev *data) 36*c383fe9cSSasha Levin { 37*c383fe9cSSasha Levin struct rb_node **new = &(root->rb_node), *parent = NULL; 38*c383fe9cSSasha Levin 39*c383fe9cSSasha Levin /* Figure out where to put new node */ 40*c383fe9cSSasha Levin while (*new) { 41*c383fe9cSSasha Levin struct pci_dev *this = container_of(*new, struct pci_dev, node); 42*c383fe9cSSasha Levin int result = data->id - this->id; 43*c383fe9cSSasha Levin 44*c383fe9cSSasha Levin parent = *new; 45*c383fe9cSSasha Levin if (result < 0) 46*c383fe9cSSasha Levin new = &((*new)->rb_left); 47*c383fe9cSSasha Levin else if (result > 0) 48*c383fe9cSSasha Levin new = &((*new)->rb_right); 49*c383fe9cSSasha Levin else 50*c383fe9cSSasha Levin return 0; 51*c383fe9cSSasha Levin } 52*c383fe9cSSasha Levin 53*c383fe9cSSasha Levin /* Add new node and rebalance tree. */ 54*c383fe9cSSasha Levin rb_link_node(&data->node, parent, new); 55*c383fe9cSSasha Levin rb_insert_color(&data->node, root); 56*c383fe9cSSasha Levin 57*c383fe9cSSasha Levin return 1; 58*c383fe9cSSasha Levin } 59*c383fe9cSSasha Levin 60*c383fe9cSSasha Levin int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line) 61*c383fe9cSSasha Levin { 62*c383fe9cSSasha Levin struct pci_dev *node; 63*c383fe9cSSasha Levin 64*c383fe9cSSasha Levin node = search(&pci_tree, dev); 65*c383fe9cSSasha Levin 66*c383fe9cSSasha Levin if (!node) { 67*c383fe9cSSasha Levin /* We haven't found a node - First device of it's kind */ 68*c383fe9cSSasha Levin node = malloc(sizeof(*node)); 69*c383fe9cSSasha Levin if (node == NULL) 70*c383fe9cSSasha Levin return -1; 71*c383fe9cSSasha Levin 72*c383fe9cSSasha Levin *node = (struct pci_dev) { 73*c383fe9cSSasha Levin .id = dev, 74*c383fe9cSSasha Levin .pin = next_pin++, 75*c383fe9cSSasha Levin }; 76*c383fe9cSSasha Levin 77*c383fe9cSSasha Levin INIT_LIST_HEAD(&node->lines); 78*c383fe9cSSasha Levin 79*c383fe9cSSasha Levin if (insert(&pci_tree, node) != 1) { 80*c383fe9cSSasha Levin free(node); 81*c383fe9cSSasha Levin return -1; 82*c383fe9cSSasha Levin } 83*c383fe9cSSasha Levin } 84*c383fe9cSSasha Levin 85*c383fe9cSSasha Levin if (node) { 86*c383fe9cSSasha Levin /* This device already has a pin assigned, give out a new line and device id */ 87*c383fe9cSSasha Levin struct irq_line *new = malloc(sizeof(*new)); 88*c383fe9cSSasha Levin if (new == NULL) 89*c383fe9cSSasha Levin return -1; 90*c383fe9cSSasha Levin 91*c383fe9cSSasha Levin new->line = next_line++; 92*c383fe9cSSasha Levin *line = new->line; 93*c383fe9cSSasha Levin *pin = node->pin; 94*c383fe9cSSasha Levin *num = next_dev++; 95*c383fe9cSSasha Levin 96*c383fe9cSSasha Levin list_add(&new->node, &node->lines); 97*c383fe9cSSasha Levin 98*c383fe9cSSasha Levin return 0; 99*c383fe9cSSasha Levin } 100*c383fe9cSSasha Levin 101*c383fe9cSSasha Levin return -1; 102*c383fe9cSSasha Levin } 103*c383fe9cSSasha Levin 104*c383fe9cSSasha Levin struct rb_node *irq__get_pci_tree(void) 105*c383fe9cSSasha Levin { 106*c383fe9cSSasha Levin return rb_first(&pci_tree); 107*c383fe9cSSasha Levin } 108