diff options
Diffstat (limited to 'drivers/gpio/gpiolib.c')
| -rw-r--r-- | drivers/gpio/gpiolib.c | 51 | 
1 files changed, 24 insertions, 27 deletions
| diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 9535f48e18d1..68d9f95d7799 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1107,7 +1107,7 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d,  	irq_hw_number_t hwirq;  	unsigned int type = IRQ_TYPE_NONE;  	struct irq_fwspec *fwspec = data; -	void *parent_arg; +	union gpio_irq_fwspec gpio_parent_fwspec = {};  	unsigned int parent_hwirq;  	unsigned int parent_type;  	struct gpio_irq_chip *girq = &gc->irq; @@ -1147,14 +1147,15 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d,  	irq_set_probe(irq);  	/* This parent only handles asserted level IRQs */ -	parent_arg = girq->populate_parent_alloc_arg(gc, parent_hwirq, parent_type); -	if (!parent_arg) -		return -ENOMEM; +	ret = girq->populate_parent_alloc_arg(gc, &gpio_parent_fwspec, +					      parent_hwirq, parent_type); +	if (ret) +		return ret;  	chip_dbg(gc, "alloc_irqs_parent for %d parent hwirq %d\n",  		  irq, parent_hwirq);  	irq_set_lockdep_class(irq, gc->irq.lock_key, gc->irq.request_key); -	ret = irq_domain_alloc_irqs_parent(d, irq, 1, parent_arg); +	ret = irq_domain_alloc_irqs_parent(d, irq, 1, &gpio_parent_fwspec);  	/*  	 * If the parent irqdomain is msi, the interrupts have already  	 * been allocated, so the EEXIST is good. @@ -1166,7 +1167,6 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d,  			 "failed to allocate parent hwirq %d for hwirq %lu\n",  			 parent_hwirq, hwirq); -	kfree(parent_arg);  	return ret;  } @@ -1181,15 +1181,18 @@ static void gpiochip_hierarchy_setup_domain_ops(struct irq_domain_ops *ops)  	ops->activate = gpiochip_irq_domain_activate;  	ops->deactivate = gpiochip_irq_domain_deactivate;  	ops->alloc = gpiochip_hierarchy_irq_domain_alloc; -	ops->free = irq_domain_free_irqs_common;  	/* -	 * We only allow overriding the translate() function for +	 * We only allow overriding the translate() and free() functions for  	 * hierarchical chips, and this should only be done if the user -	 * really need something other than 1:1 translation. +	 * really need something other than 1:1 translation for translate() +	 * callback and free if user wants to free up any resources which +	 * were allocated during callbacks, for example populate_parent_alloc_arg.  	 */  	if (!ops->translate)  		ops->translate = gpiochip_hierarchy_irq_domain_translate; +	if (!ops->free) +		ops->free = irq_domain_free_irqs_common;  }  static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc) @@ -1230,34 +1233,28 @@ static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc)  	return !!gc->irq.parent_domain;  } -void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *gc, -					     unsigned int parent_hwirq, -					     unsigned int parent_type) +int gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *gc, +					    union gpio_irq_fwspec *gfwspec, +					    unsigned int parent_hwirq, +					    unsigned int parent_type)  { -	struct irq_fwspec *fwspec; - -	fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); -	if (!fwspec) -		return NULL; +	struct irq_fwspec *fwspec = &gfwspec->fwspec;  	fwspec->fwnode = gc->irq.parent_domain->fwnode;  	fwspec->param_count = 2;  	fwspec->param[0] = parent_hwirq;  	fwspec->param[1] = parent_type; -	return fwspec; +	return 0;  }  EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_twocell); -void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc, -					      unsigned int parent_hwirq, -					      unsigned int parent_type) +int gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc, +					     union gpio_irq_fwspec *gfwspec, +					     unsigned int parent_hwirq, +					     unsigned int parent_type)  { -	struct irq_fwspec *fwspec; - -	fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); -	if (!fwspec) -		return NULL; +	struct irq_fwspec *fwspec = &gfwspec->fwspec;  	fwspec->fwnode = gc->irq.parent_domain->fwnode;  	fwspec->param_count = 4; @@ -1266,7 +1263,7 @@ void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc,  	fwspec->param[2] = 0;  	fwspec->param[3] = parent_type; -	return fwspec; +	return 0;  }  EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_fourcell); |