Lines Matching +full:msi +full:- +full:parent
1 // SPDX-License-Identifier: GPL-2.0
3 * MSI framework for platform devices
13 #include <linux/msi.h>
17 #define MAX_DEV_MSIS (1 << (32 - DEV_ID_SHIFT))
21 * and the callback to write the MSI message.
36 * Convert an msi_desc to a globaly unique identifier (per-device
43 devid = desc->platform.msi_priv_data->devid; in platform_msi_calc_hwirq()
45 return (devid << (32 - DEV_ID_SHIFT)) | desc->platform.msi_index; in platform_msi_calc_hwirq()
50 arg->desc = desc; in platform_msi_set_desc()
51 arg->hwirq = platform_msi_calc_hwirq(desc); in platform_msi_set_desc()
60 info->chip, info->chip_data); in platform_msi_init()
69 struct msi_domain_ops *ops = info->ops; in platform_msi_update_dom_ops()
73 if (ops->msi_init == NULL) in platform_msi_update_dom_ops()
74 ops->msi_init = platform_msi_init; in platform_msi_update_dom_ops()
75 if (ops->set_desc == NULL) in platform_msi_update_dom_ops()
76 ops->set_desc = platform_msi_set_desc; in platform_msi_update_dom_ops()
84 priv_data = desc->platform.msi_priv_data; in platform_msi_write_msg()
86 priv_data->write_msg(desc, msg); in platform_msi_write_msg()
91 struct irq_chip *chip = info->chip; in platform_msi_update_chip_ops()
94 if (!chip->irq_mask) in platform_msi_update_chip_ops()
95 chip->irq_mask = irq_chip_mask_parent; in platform_msi_update_chip_ops()
96 if (!chip->irq_unmask) in platform_msi_update_chip_ops()
97 chip->irq_unmask = irq_chip_unmask_parent; in platform_msi_update_chip_ops()
98 if (!chip->irq_eoi) in platform_msi_update_chip_ops()
99 chip->irq_eoi = irq_chip_eoi_parent; in platform_msi_update_chip_ops()
100 if (!chip->irq_set_affinity) in platform_msi_update_chip_ops()
101 chip->irq_set_affinity = msi_domain_set_affinity; in platform_msi_update_chip_ops()
102 if (!chip->irq_write_msi_msg) in platform_msi_update_chip_ops()
103 chip->irq_write_msi_msg = platform_msi_write_msg; in platform_msi_update_chip_ops()
104 if (WARN_ON((info->flags & MSI_FLAG_LEVEL_CAPABLE) && in platform_msi_update_chip_ops()
105 !(chip->flags & IRQCHIP_SUPPORTS_LEVEL_MSI))) in platform_msi_update_chip_ops()
106 info->flags &= ~MSI_FLAG_LEVEL_CAPABLE; in platform_msi_update_chip_ops()
114 if (desc->platform.msi_index >= base && in platform_msi_free_descs()
115 desc->platform.msi_index < (base + nvec)) { in platform_msi_free_descs()
116 list_del(&desc->list); in platform_msi_free_descs()
133 base = desc->platform.msi_index + 1; in platform_msi_alloc_descs_with_irq()
141 desc->platform.msi_priv_data = data; in platform_msi_alloc_descs_with_irq()
142 desc->platform.msi_index = base + i; in platform_msi_alloc_descs_with_irq()
143 desc->irq = virq ? virq + i : 0; in platform_msi_alloc_descs_with_irq()
145 list_add_tail(&desc->list, dev_to_msi_list(dev)); in platform_msi_alloc_descs_with_irq()
152 return -ENOMEM; in platform_msi_alloc_descs_with_irq()
166 * platform_msi_create_irq_domain - Create a platform MSI interrupt domain
168 * @info: MSI domain info
169 * @parent: Parent irq domain
171 * Updates the domain and chip ops and creates a platform MSI
179 struct irq_domain *parent) in platform_msi_create_irq_domain() argument
183 if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) in platform_msi_create_irq_domain()
185 if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) in platform_msi_create_irq_domain()
188 domain = msi_create_irq_domain(fwnode, info, parent); in platform_msi_create_irq_domain()
203 * accordingly (which would impact the max number of MSI in platform_msi_alloc_priv_data()
206 if (!dev->msi_domain || !write_msi_msg || !nvec || nvec > MAX_DEV_MSIS) in platform_msi_alloc_priv_data()
207 return ERR_PTR(-EINVAL); in platform_msi_alloc_priv_data()
209 if (dev->msi_domain->bus_token != DOMAIN_BUS_PLATFORM_MSI) { in platform_msi_alloc_priv_data()
211 return ERR_PTR(-EINVAL); in platform_msi_alloc_priv_data()
214 /* Already had a helping of MSI? Greed... */ in platform_msi_alloc_priv_data()
216 return ERR_PTR(-EBUSY); in platform_msi_alloc_priv_data()
220 return ERR_PTR(-ENOMEM); in platform_msi_alloc_priv_data()
222 datap->devid = ida_simple_get(&platform_msi_devid_ida, in platform_msi_alloc_priv_data()
224 if (datap->devid < 0) { in platform_msi_alloc_priv_data()
225 int err = datap->devid; in platform_msi_alloc_priv_data()
230 datap->write_msg = write_msi_msg; in platform_msi_alloc_priv_data()
231 datap->dev = dev; in platform_msi_alloc_priv_data()
238 ida_simple_remove(&platform_msi_devid_ida, data->devid); in platform_msi_free_priv_data()
243 * platform_msi_domain_alloc_irqs - Allocate MSI interrupts for @dev
265 err = msi_domain_alloc_irqs(dev->msi_domain, dev, nvec); in platform_msi_domain_alloc_irqs()
281 * platform_msi_domain_free_irqs - Free MSI interrupts for @dev
290 platform_msi_free_priv_data(desc->platform.msi_priv_data); in platform_msi_domain_free_irqs()
293 msi_domain_free_irqs(dev->msi_domain, dev); in platform_msi_domain_free_irqs()
299 * platform_msi_get_host_data - Query the private data associated with
300 * a platform-msi domain
301 * @domain: The platform-msi domain
308 struct platform_msi_priv_data *data = domain->host_data; in platform_msi_get_host_data()
309 return data->host_data; in platform_msi_get_host_data()
313 * platform_msi_create_device_domain - Create a platform-msi domain
339 data->host_data = host_data; in __platform_msi_create_device_domain()
340 domain = irq_domain_create_hierarchy(dev->msi_domain, 0, in __platform_msi_create_device_domain()
342 dev->fwnode, ops, data); in __platform_msi_create_device_domain()
346 err = msi_domain_prepare_irqs(domain->parent, dev, nvec, &data->arg); in __platform_msi_create_device_domain()
360 * platform_msi_domain_free - Free interrupts associated with a platform-msi
363 * @domain: The platform-msi domain
370 struct platform_msi_priv_data *data = domain->host_data; in platform_msi_domain_free()
372 for_each_msi_entry_safe(desc, tmp, data->dev) { in platform_msi_domain_free()
373 if (WARN_ON(!desc->irq || desc->nvec_used != 1)) in platform_msi_domain_free()
375 if (!(desc->irq >= virq && desc->irq < (virq + nvec))) in platform_msi_domain_free()
378 irq_domain_free_irqs_common(domain, desc->irq, 1); in platform_msi_domain_free()
379 list_del(&desc->list); in platform_msi_domain_free()
385 * platform_msi_domain_alloc - Allocate interrupts associated with
386 * a platform-msi domain
388 * @domain: The platform-msi domain
394 * top-level interrupt allocation).
399 struct platform_msi_priv_data *data = domain->host_data; in platform_msi_domain_alloc()
402 err = platform_msi_alloc_descs_with_irq(data->dev, virq, nr_irqs, data); in platform_msi_domain_alloc()
406 err = msi_domain_populate_irqs(domain->parent, data->dev, in platform_msi_domain_alloc()
407 virq, nr_irqs, &data->arg); in platform_msi_domain_alloc()