Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

genirq: Allow the PM device to originate from irq domain

As a preparation to moving the reference to the device used for
runtime power management, add a new 'dev' field to the irqdomain
structure for that exact purpose.

The irq_chip_pm_{get,put}() helpers are made aware of the dual
location via a new private helper.

No functional change intended.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
Tested-by: Tony Lindgren <tony@atomide.com>
Acked-by: Bartosz Golaszewski <brgl@bgdev.pl>
Link: https://lore.kernel.org/r/20220201120310.878267-2-maz@kernel.org

+28 -5
+10
include/linux/irqdomain.h
··· 151 151 * @gc: Pointer to a list of generic chips. There is a helper function for 152 152 * setting up one or more generic chips for interrupt controllers 153 153 * drivers using the generic chip library which uses this pointer. 154 + * @dev: Pointer to a device that the domain represent, and that will be 155 + * used for power management purposes. 154 156 * @parent: Pointer to parent irq_domain to support hierarchy irq_domains 155 157 * 156 158 * Revmap data, used internally by irq_domain ··· 173 171 struct fwnode_handle *fwnode; 174 172 enum irq_domain_bus_token bus_token; 175 173 struct irq_domain_chip_generic *gc; 174 + struct device *dev; 176 175 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY 177 176 struct irq_domain *parent; 178 177 #endif ··· 227 224 static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d) 228 225 { 229 226 return to_of_node(d->fwnode); 227 + } 228 + 229 + static inline void irq_domain_set_pm_device(struct irq_domain *d, 230 + struct device *dev) 231 + { 232 + if (d) 233 + d->dev = dev; 230 234 } 231 235 232 236 #ifdef CONFIG_IRQ_DOMAIN
+18 -5
kernel/irq/chip.c
··· 1558 1558 return 0; 1559 1559 } 1560 1560 1561 + static struct device *irq_get_parent_device(struct irq_data *data) 1562 + { 1563 + if (data->chip->parent_device) 1564 + return data->chip->parent_device; 1565 + 1566 + if (data->domain) 1567 + return data->domain->dev; 1568 + 1569 + return NULL; 1570 + } 1571 + 1561 1572 /** 1562 1573 * irq_chip_pm_get - Enable power for an IRQ chip 1563 1574 * @data: Pointer to interrupt specific data ··· 1578 1567 */ 1579 1568 int irq_chip_pm_get(struct irq_data *data) 1580 1569 { 1570 + struct device *dev = irq_get_parent_device(data); 1581 1571 int retval; 1582 1572 1583 - if (IS_ENABLED(CONFIG_PM) && data->chip->parent_device) { 1584 - retval = pm_runtime_get_sync(data->chip->parent_device); 1573 + if (IS_ENABLED(CONFIG_PM) && dev) { 1574 + retval = pm_runtime_get_sync(dev); 1585 1575 if (retval < 0) { 1586 - pm_runtime_put_noidle(data->chip->parent_device); 1576 + pm_runtime_put_noidle(dev); 1587 1577 return retval; 1588 1578 } 1589 1579 } ··· 1602 1590 */ 1603 1591 int irq_chip_pm_put(struct irq_data *data) 1604 1592 { 1593 + struct device *dev = irq_get_parent_device(data); 1605 1594 int retval = 0; 1606 1595 1607 - if (IS_ENABLED(CONFIG_PM) && data->chip->parent_device) 1608 - retval = pm_runtime_put(data->chip->parent_device); 1596 + if (IS_ENABLED(CONFIG_PM) && dev) 1597 + retval = pm_runtime_put(dev); 1609 1598 1610 1599 return (retval < 0) ? retval : 0; 1611 1600 }