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

irqchip/gic-its: Rework platform MSI deviceID detection

Current code retrieving platform devices MSI devID in the GIC ITS MSI
parent helpers suffers from some minor issues:

- It leaks a struct device_node reference
- It is duplicated between GICv3 and GICv5 for no good reason
- It does not use the OF phandle iterator code that simplifies
the msi-parent property parsing

Consolidate GIC v3 and v5 deviceID retrieval in a function that addresses
the full set of issues in one go by merging GIC v3 and v5 code and
converting the msi-parent parsing loop to the more modern OF phandle
iterator API, fixing the struct device_node reference leak in the process.

Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://patch.msgid.link/20251021124103.198419-6-lpieralisi@kernel.org

authored by

Lorenzo Pieralisi and committed by
Thomas Gleixner
9c1fbc56 4f32612f

+23 -68
+23 -68
drivers/irqchip/irq-gic-its-msi-parent.c
··· 142 142 #define its_v5_pci_msi_prepare NULL 143 143 #endif /* !CONFIG_PCI_MSI */ 144 144 145 - static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev, 146 - u32 *dev_id) 145 + static int of_pmsi_get_msi_info(struct irq_domain *domain, struct device *dev, u32 *dev_id, 146 + phys_addr_t *pa) 147 147 { 148 - int ret, index = 0; 148 + struct of_phandle_iterator it; 149 + int ret; 149 150 150 151 /* Suck the DeviceID out of the msi-parent property */ 151 - do { 152 - struct of_phandle_args args; 152 + of_for_each_phandle(&it, ret, dev->of_node, "msi-parent", "#msi-cells", -1) { 153 + /* GICv5 ITS domain matches the MSI controller node parent */ 154 + struct device_node *np __free(device_node) = pa ? of_get_parent(it.node) 155 + : of_node_get(it.node); 153 156 154 - ret = of_parse_phandle_with_args(dev->of_node, 155 - "msi-parent", "#msi-cells", 156 - index, &args); 157 - if (args.np == irq_domain_get_of_node(domain)) { 158 - if (WARN_ON(args.args_count != 1)) 159 - return -EINVAL; 160 - *dev_id = args.args[0]; 161 - break; 162 - } 163 - index++; 164 - } while (!ret); 157 + if (np == irq_domain_get_of_node(domain)) { 158 + u32 args; 165 159 166 - if (ret) { 167 - struct device_node *np = NULL; 160 + if (WARN_ON(of_phandle_iterator_args(&it, &args, 1) != 1)) 161 + ret = -EINVAL; 168 162 169 - ret = of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &np, dev_id); 170 - if (np) 171 - of_node_put(np); 172 - } 163 + if (!ret && pa) 164 + ret = its_translate_frame_address(it.node, pa); 173 165 174 - return ret; 175 - } 166 + if (!ret) 167 + *dev_id = args; 176 168 177 - static int of_v5_pmsi_get_msi_info(struct irq_domain *domain, struct device *dev, 178 - u32 *dev_id, phys_addr_t *pa) 179 - { 180 - int ret, index = 0; 181 - /* 182 - * Retrieve the DeviceID and the ITS translate frame node pointer 183 - * out of the msi-parent property. 184 - */ 185 - do { 186 - struct of_phandle_args args; 187 - 188 - ret = of_parse_phandle_with_args(dev->of_node, 189 - "msi-parent", "#msi-cells", 190 - index, &args); 191 - if (ret) 192 - break; 193 - /* 194 - * The IRQ domain fwnode is the msi controller parent 195 - * in GICv5 (where the msi controller nodes are the 196 - * ITS translate frames). 197 - */ 198 - if (args.np->parent == irq_domain_get_of_node(domain)) { 199 - if (WARN_ON(args.args_count != 1)) 200 - return -EINVAL; 201 - *dev_id = args.args[0]; 202 - 203 - ret = its_translate_frame_address(args.np, pa); 204 - if (ret) 205 - return -ENODEV; 206 - break; 207 - } 208 - index++; 209 - } while (!ret); 210 - 211 - if (ret) { 212 - struct device_node *np = NULL; 213 - 214 - ret = of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &np, dev_id); 215 - if (np) { 216 - ret = its_translate_frame_address(np, pa); 217 - of_node_put(np); 169 + of_node_put(it.node); 170 + return ret; 218 171 } 219 172 } 220 173 221 - return ret; 174 + struct device_node *msi_ctrl __free(device_node) = NULL; 175 + 176 + return of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &msi_ctrl, dev_id); 222 177 } 223 178 224 179 int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id) ··· 189 234 int ret; 190 235 191 236 if (dev->of_node) 192 - ret = of_pmsi_get_dev_id(domain->parent, dev, &dev_id); 237 + ret = of_pmsi_get_msi_info(domain->parent, dev, &dev_id, NULL); 193 238 else 194 239 ret = iort_pmsi_get_dev_id(dev, &dev_id); 195 240 if (ret) ··· 217 262 if (!dev->of_node) 218 263 return -ENODEV; 219 264 220 - ret = of_v5_pmsi_get_msi_info(domain->parent, dev, &dev_id, &pa); 265 + ret = of_pmsi_get_msi_info(domain->parent, dev, &dev_id, &pa); 221 266 if (ret) 222 267 return ret; 223 268