[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] xen/arm: Implement dynamic allocation of irq descriptors
On 19/02/15 07:17, vijay.kilari@xxxxxxxxx wrote: > From: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> > > For arm memory for 1024 irq descriptors are allocated > statically irrespective of number of interrupt supported > by the platform. > > With this patch, irq descriptors are allocated at run time > and managed using red-black tree. Functions to insert, search > and delete irq descriptor are implemented in xen/common/irq.c. I think we may want to allocate SPIs/SGIs/PPIs at boot time. This number will never change. We can avoid to always to allocate 1024 IRQs by using the number provided by the GIC. [..] > void __cpuinit init_secondary_IRQ(void) > @@ -265,6 +269,7 @@ void release_irq(unsigned int irq, const void *dev_id) > > desc = irq_to_desc(irq); > > + ASSERT(desc != NULL); What happen if the code decides to try to free a non-existing IRQ on non-debug mode? It will just segfault... and bring a possible security issue. > spin_lock_irqsave(&desc->lock,flags); > > action_ptr = &desc->action; > @@ -301,6 +306,11 @@ void release_irq(unsigned int irq, const void *dev_id) > > if ( action->free_on_release ) > xfree(action); > + > + spin_lock(&rb_tree_desc_lock); > + delete_irq_desc(&desc_root, irq); > + xfree(desc); > + spin_unlock(&rb_tree_desc_lock); > } > > static int __setup_irq(struct irq_desc *desc, unsigned int irqflags, > @@ -339,6 +349,8 @@ int setup_irq(unsigned int irq, unsigned int irqflags, > struct irqaction *new) > > desc = irq_to_desc(irq); > > + ASSERT(desc != NULL); > + > spin_lock_irqsave(&desc->lock, flags); > > if ( test_bit(_IRQ_GUEST, &desc->status) ) > @@ -382,7 +394,7 @@ int route_irq_to_guest(struct domain *d, unsigned int irq, > const char * devname) > { > struct irqaction *action; > - struct irq_desc *desc = irq_to_desc(irq); > + struct irq_desc *desc = NULL; Pointless initialization. > unsigned long flags; > int retval = 0; > > @@ -394,6 +406,23 @@ int route_irq_to_guest(struct domain *d, unsigned int > irq, > action->name = devname; > action->free_on_release = 1; > > + spin_lock(&rb_tree_desc_lock); > + desc = find_irq_desc(&desc_root, irq); > + > + if ( desc == NULL ) > + { > + /* Allocate descriptor and add to rb tree */ > + desc = xzalloc(struct irq_desc); > + if ( desc == NULL ) > + { > + spin_unlock(&rb_tree_desc_lock); > + return -ENOMEM; > + } > + init_irq_data(irq, desc); > + insert_irq_desc(&desc_root, irq, desc); > + } > + spin_unlock(&rb_tree_desc_lock); > + Why do you need this in route_irq_to_guest? > spin_lock_irqsave(&desc->lock, flags); > > /* If the IRQ is already used by someone > @@ -470,13 +499,16 @@ static bool_t irq_validate_new_type(unsigned int curr, > unsigned new) > int irq_set_spi_type(unsigned int spi, unsigned int type) > { > unsigned long flags; > - struct irq_desc *desc = irq_to_desc(spi); > + struct irq_desc *desc = NULL; > int ret = -EBUSY; > > /* This function should not be used for other than SPIs */ > if ( spi < NR_LOCAL_IRQS ) > return -EINVAL; > > + desc = irq_to_desc(spi); > + ASSERT(desc != NULL); > + > spin_lock_irqsave(&desc->lock, flags); > > if ( !irq_validate_new_type(desc->arch.type, type) ) > @@ -532,6 +564,7 @@ int platform_get_irq(const struct dt_device_node *device, > int index) > { > struct dt_irq dt_irq; > unsigned int type, irq; > + struct irq_desc *desc; > int res; > > res = dt_device_get_irq(device, index, &dt_irq); > @@ -541,6 +574,22 @@ int platform_get_irq(const struct dt_device_node > *device, int index) > irq = dt_irq.irq; > type = dt_irq.type; > > + spin_lock(&rb_tree_desc_lock); > + desc = find_irq_desc(&desc_root, irq); > + if ( desc == NULL ) > + { > + /* Allocate descriptor for this irq */ > + desc = xzalloc(struct irq_desc); > + if ( desc == NULL ) > + { > + spin_unlock(&rb_tree_desc_lock); > + return -ENOMEM; > + } > + init_irq_data(irq, desc); > + insert_irq_desc(&desc_root, irq, desc); > + } > + spin_unlock(&rb_tree_desc_lock); > + > /* Setup the IRQ type */ > if ( irq < NR_LOCAL_IRQS ) > res = irq_local_set_type(irq, type); > diff --git a/xen/common/irq.c b/xen/common/irq.c > index 3e55dfa..ddf85c5 100644 > --- a/xen/common/irq.c > +++ b/xen/common/irq.c > @@ -40,3 +40,61 @@ unsigned int irq_startup_none(struct irq_desc *desc) > { > return 0; > } > + > +irq_desc_t * find_irq_desc( struct rb_root *root_node, int irq) > +{ > + struct rb_node *node = root_node->rb_node; > + > + while ( node ) > + { > + irq_desc_t *this; > + > + this = container_of(node, irq_desc_t, node); > + > + if ( irq < this->irq ) > + node = node->rb_left; > + else if (irq > this->irq) > + node = node->rb_right; > + else > + return this; > + } > + > + return NULL; > +} > + > +int insert_irq_desc(struct rb_root *root_node, int irq, struct irq_desc > *desc) > +{ > + struct rb_node **new, *parent; > + > + new = &root_node->rb_node; > + parent = NULL; > + > + while ( *new ) > + { > + irq_desc_t *this; > + > + this = container_of(*new, irq_desc_t, node); > + > + parent = *new; > + if ( desc->irq < this->irq ) > + new = &((*new)->rb_left); > + else if (desc->irq > this->irq) > + new = &((*new)->rb_right); > + else > + return -EEXIST; > + } > + > + rb_link_node(&desc->node, parent, new); > + rb_insert_color(&desc->node, root_node); > + > + return 0; > +} > + > +void delete_irq_desc(struct rb_root *root_node, int irq) > +{ > + struct irq_desc *desc; > + > + desc = find_irq_desc(root_node, irq); > + if ( desc ) > + rb_erase(&desc->node, root_node); > +} What's the matter to put this function on the common code when the variable itself lives in the architecture code? > diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h > index 9e0155c..d623ce3 100644 > --- a/xen/include/xen/irq.h > +++ b/xen/include/xen/irq.h > @@ -6,6 +6,7 @@ > #include <xen/spinlock.h> > #include <xen/time.h> > #include <xen/list.h> > +#include <xen/rbtree.h> > #include <asm/regs.h> > #include <asm/hardirq.h> > > @@ -83,6 +84,7 @@ struct msi_desc; > * first field. > */ > typedef struct irq_desc { > + struct rb_node node; Please move this after the field status. So code on ARM rely on the alignment to access this field without lock (via bit_* manipulation). > unsigned int status; /* IRQ status */ > hw_irq_controller *handler; > struct msi_desc *msi_desc; > @@ -168,6 +170,10 @@ static inline void set_native_irq_info(unsigned int irq, > const cpumask_t *mask) > > unsigned int set_desc_affinity(struct irq_desc *, const cpumask_t *); > > +irq_desc_t * find_irq_desc(struct rb_root *root_node, int irq); > +int insert_irq_desc(struct rb_root *root_node, int irq, struct irq_desc > *desc); > +void delete_irq_desc(struct rb_root *root_node, int irq); > + > #ifndef arch_hwdom_irqs > unsigned int arch_hwdom_irqs(domid_t); > #endif > Regards, -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |