Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */
2 : : #ifndef LINUX_MSI_H
3 : : #define LINUX_MSI_H
4 : :
5 : : #include <linux/kobject.h>
6 : : #include <linux/list.h>
7 : :
8 : : struct msi_msg {
9 : : u32 address_lo; /* low 32 bits of msi message address */
10 : : u32 address_hi; /* high 32 bits of msi message address */
11 : : u32 data; /* 16 bits of msi message data */
12 : : };
13 : :
14 : : extern int pci_msi_ignore_mask;
15 : : /* Helper functions */
16 : : struct irq_data;
17 : : struct msi_desc;
18 : : struct pci_dev;
19 : : struct platform_msi_priv_data;
20 : : void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
21 : : #ifdef CONFIG_GENERIC_MSI_IRQ
22 : : void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
23 : : #else
24 : : static inline void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
25 : : {
26 : : }
27 : : #endif
28 : :
29 : : typedef void (*irq_write_msi_msg_t)(struct msi_desc *desc,
30 : : struct msi_msg *msg);
31 : :
32 : : /**
33 : : * platform_msi_desc - Platform device specific msi descriptor data
34 : : * @msi_priv_data: Pointer to platform private data
35 : : * @msi_index: The index of the MSI descriptor for multi MSI
36 : : */
37 : : struct platform_msi_desc {
38 : : struct platform_msi_priv_data *msi_priv_data;
39 : : u16 msi_index;
40 : : };
41 : :
42 : : /**
43 : : * fsl_mc_msi_desc - FSL-MC device specific msi descriptor data
44 : : * @msi_index: The index of the MSI descriptor
45 : : */
46 : : struct fsl_mc_msi_desc {
47 : : u16 msi_index;
48 : : };
49 : :
50 : : /**
51 : : * ti_sci_inta_msi_desc - TISCI based INTA specific msi descriptor data
52 : : * @dev_index: TISCI device index
53 : : */
54 : : struct ti_sci_inta_msi_desc {
55 : : u16 dev_index;
56 : : };
57 : :
58 : : /**
59 : : * struct msi_desc - Descriptor structure for MSI based interrupts
60 : : * @list: List head for management
61 : : * @irq: The base interrupt number
62 : : * @nvec_used: The number of vectors used
63 : : * @dev: Pointer to the device which uses this descriptor
64 : : * @msg: The last set MSI message cached for reuse
65 : : * @affinity: Optional pointer to a cpu affinity mask for this descriptor
66 : : *
67 : : * @write_msi_msg: Callback that may be called when the MSI message
68 : : * address or data changes
69 : : * @write_msi_msg_data: Data parameter for the callback.
70 : : *
71 : : * @masked: [PCI MSI/X] Mask bits
72 : : * @is_msix: [PCI MSI/X] True if MSI-X
73 : : * @multiple: [PCI MSI/X] log2 num of messages allocated
74 : : * @multi_cap: [PCI MSI/X] log2 num of messages supported
75 : : * @maskbit: [PCI MSI/X] Mask-Pending bit supported?
76 : : * @is_64: [PCI MSI/X] Address size: 0=32bit 1=64bit
77 : : * @entry_nr: [PCI MSI/X] Entry which is described by this descriptor
78 : : * @default_irq:[PCI MSI/X] The default pre-assigned non-MSI irq
79 : : * @mask_pos: [PCI MSI] Mask register position
80 : : * @mask_base: [PCI MSI-X] Mask register base address
81 : : * @platform: [platform] Platform device specific msi descriptor data
82 : : * @fsl_mc: [fsl-mc] FSL MC device specific msi descriptor data
83 : : * @inta: [INTA] TISCI based INTA specific msi descriptor data
84 : : */
85 : : struct msi_desc {
86 : : /* Shared device/bus type independent data */
87 : : struct list_head list;
88 : : unsigned int irq;
89 : : unsigned int nvec_used;
90 : : struct device *dev;
91 : : struct msi_msg msg;
92 : : struct irq_affinity_desc *affinity;
93 : : #ifdef CONFIG_IRQ_MSI_IOMMU
94 : : const void *iommu_cookie;
95 : : #endif
96 : :
97 : : void (*write_msi_msg)(struct msi_desc *entry, void *data);
98 : : void *write_msi_msg_data;
99 : :
100 : : union {
101 : : /* PCI MSI/X specific data */
102 : : struct {
103 : : u32 masked;
104 : : struct {
105 : : u8 is_msix : 1;
106 : : u8 multiple : 3;
107 : : u8 multi_cap : 3;
108 : : u8 maskbit : 1;
109 : : u8 is_64 : 1;
110 : : u8 is_virtual : 1;
111 : : u16 entry_nr;
112 : : unsigned default_irq;
113 : : } msi_attrib;
114 : : union {
115 : : u8 mask_pos;
116 : : void __iomem *mask_base;
117 : : };
118 : : };
119 : :
120 : : /*
121 : : * Non PCI variants add their data structure here. New
122 : : * entries need to use a named structure. We want
123 : : * proper name spaces for this. The PCI part is
124 : : * anonymous for now as it would require an immediate
125 : : * tree wide cleanup.
126 : : */
127 : : struct platform_msi_desc platform;
128 : : struct fsl_mc_msi_desc fsl_mc;
129 : : struct ti_sci_inta_msi_desc inta;
130 : : };
131 : : };
132 : :
133 : : /* Helpers to hide struct msi_desc implementation details */
134 : : #define msi_desc_to_dev(desc) ((desc)->dev)
135 : : #define dev_to_msi_list(dev) (&(dev)->msi_list)
136 : : #define first_msi_entry(dev) \
137 : : list_first_entry(dev_to_msi_list((dev)), struct msi_desc, list)
138 : : #define for_each_msi_entry(desc, dev) \
139 : : list_for_each_entry((desc), dev_to_msi_list((dev)), list)
140 : : #define for_each_msi_entry_safe(desc, tmp, dev) \
141 : : list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list)
142 : :
143 : : #ifdef CONFIG_IRQ_MSI_IOMMU
144 : 0 : static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
145 : : {
146 [ # # ]: 0 : return desc->iommu_cookie;
147 : : }
148 : :
149 : 0 : static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
150 : : const void *iommu_cookie)
151 : : {
152 [ # # ]: 0 : desc->iommu_cookie = iommu_cookie;
153 : : }
154 : : #else
155 : : static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
156 : : {
157 : : return NULL;
158 : : }
159 : :
160 : : static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
161 : : const void *iommu_cookie)
162 : : {
163 : : }
164 : : #endif
165 : :
166 : : #ifdef CONFIG_PCI_MSI
167 : : #define first_pci_msi_entry(pdev) first_msi_entry(&(pdev)->dev)
168 : : #define for_each_pci_msi_entry(desc, pdev) \
169 : : for_each_msi_entry((desc), &(pdev)->dev)
170 : :
171 : : struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc);
172 : : void *msi_desc_to_pci_sysdata(struct msi_desc *desc);
173 : : void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg);
174 : : #else /* CONFIG_PCI_MSI */
175 : : static inline void *msi_desc_to_pci_sysdata(struct msi_desc *desc)
176 : : {
177 : : return NULL;
178 : : }
179 : : static inline void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg)
180 : : {
181 : : }
182 : : #endif /* CONFIG_PCI_MSI */
183 : :
184 : : struct msi_desc *alloc_msi_entry(struct device *dev, int nvec,
185 : : const struct irq_affinity_desc *affinity);
186 : : void free_msi_entry(struct msi_desc *entry);
187 : : void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
188 : : void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
189 : :
190 : : u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag);
191 : : u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag);
192 : : void pci_msi_mask_irq(struct irq_data *data);
193 : : void pci_msi_unmask_irq(struct irq_data *data);
194 : :
195 : : /*
196 : : * The arch hooks to setup up msi irqs. Those functions are
197 : : * implemented as weak symbols so that they /can/ be overriden by
198 : : * architecture specific code if needed.
199 : : */
200 : : int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
201 : : void arch_teardown_msi_irq(unsigned int irq);
202 : : int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
203 : : void arch_teardown_msi_irqs(struct pci_dev *dev);
204 : : void arch_restore_msi_irqs(struct pci_dev *dev);
205 : :
206 : : void default_teardown_msi_irqs(struct pci_dev *dev);
207 : : void default_restore_msi_irqs(struct pci_dev *dev);
208 : :
209 : : struct msi_controller {
210 : : struct module *owner;
211 : : struct device *dev;
212 : : struct device_node *of_node;
213 : : struct list_head list;
214 : :
215 : : int (*setup_irq)(struct msi_controller *chip, struct pci_dev *dev,
216 : : struct msi_desc *desc);
217 : : int (*setup_irqs)(struct msi_controller *chip, struct pci_dev *dev,
218 : : int nvec, int type);
219 : : void (*teardown_irq)(struct msi_controller *chip, unsigned int irq);
220 : : };
221 : :
222 : : #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
223 : :
224 : : #include <linux/irqhandler.h>
225 : : #include <asm/msi.h>
226 : :
227 : : struct irq_domain;
228 : : struct irq_domain_ops;
229 : : struct irq_chip;
230 : : struct device_node;
231 : : struct fwnode_handle;
232 : : struct msi_domain_info;
233 : :
234 : : /**
235 : : * struct msi_domain_ops - MSI interrupt domain callbacks
236 : : * @get_hwirq: Retrieve the resulting hw irq number
237 : : * @msi_init: Domain specific init function for MSI interrupts
238 : : * @msi_free: Domain specific function to free a MSI interrupts
239 : : * @msi_check: Callback for verification of the domain/info/dev data
240 : : * @msi_prepare: Prepare the allocation of the interrupts in the domain
241 : : * @msi_finish: Optional callback to finalize the allocation
242 : : * @set_desc: Set the msi descriptor for an interrupt
243 : : * @handle_error: Optional error handler if the allocation fails
244 : : *
245 : : * @get_hwirq, @msi_init and @msi_free are callbacks used by
246 : : * msi_create_irq_domain() and related interfaces
247 : : *
248 : : * @msi_check, @msi_prepare, @msi_finish, @set_desc and @handle_error
249 : : * are callbacks used by msi_domain_alloc_irqs() and related
250 : : * interfaces which are based on msi_desc.
251 : : */
252 : : struct msi_domain_ops {
253 : : irq_hw_number_t (*get_hwirq)(struct msi_domain_info *info,
254 : : msi_alloc_info_t *arg);
255 : : int (*msi_init)(struct irq_domain *domain,
256 : : struct msi_domain_info *info,
257 : : unsigned int virq, irq_hw_number_t hwirq,
258 : : msi_alloc_info_t *arg);
259 : : void (*msi_free)(struct irq_domain *domain,
260 : : struct msi_domain_info *info,
261 : : unsigned int virq);
262 : : int (*msi_check)(struct irq_domain *domain,
263 : : struct msi_domain_info *info,
264 : : struct device *dev);
265 : : int (*msi_prepare)(struct irq_domain *domain,
266 : : struct device *dev, int nvec,
267 : : msi_alloc_info_t *arg);
268 : : void (*msi_finish)(msi_alloc_info_t *arg, int retval);
269 : : void (*set_desc)(msi_alloc_info_t *arg,
270 : : struct msi_desc *desc);
271 : : int (*handle_error)(struct irq_domain *domain,
272 : : struct msi_desc *desc, int error);
273 : : };
274 : :
275 : : /**
276 : : * struct msi_domain_info - MSI interrupt domain data
277 : : * @flags: Flags to decribe features and capabilities
278 : : * @ops: The callback data structure
279 : : * @chip: Optional: associated interrupt chip
280 : : * @chip_data: Optional: associated interrupt chip data
281 : : * @handler: Optional: associated interrupt flow handler
282 : : * @handler_data: Optional: associated interrupt flow handler data
283 : : * @handler_name: Optional: associated interrupt flow handler name
284 : : * @data: Optional: domain specific data
285 : : */
286 : : struct msi_domain_info {
287 : : u32 flags;
288 : : struct msi_domain_ops *ops;
289 : : struct irq_chip *chip;
290 : : void *chip_data;
291 : : irq_flow_handler_t handler;
292 : : void *handler_data;
293 : : const char *handler_name;
294 : : void *data;
295 : : };
296 : :
297 : : /* Flags for msi_domain_info */
298 : : enum {
299 : : /*
300 : : * Init non implemented ops callbacks with default MSI domain
301 : : * callbacks.
302 : : */
303 : : MSI_FLAG_USE_DEF_DOM_OPS = (1 << 0),
304 : : /*
305 : : * Init non implemented chip callbacks with default MSI chip
306 : : * callbacks.
307 : : */
308 : : MSI_FLAG_USE_DEF_CHIP_OPS = (1 << 1),
309 : : /* Support multiple PCI MSI interrupts */
310 : : MSI_FLAG_MULTI_PCI_MSI = (1 << 2),
311 : : /* Support PCI MSIX interrupts */
312 : : MSI_FLAG_PCI_MSIX = (1 << 3),
313 : : /* Needs early activate, required for PCI */
314 : : MSI_FLAG_ACTIVATE_EARLY = (1 << 4),
315 : : /*
316 : : * Must reactivate when irq is started even when
317 : : * MSI_FLAG_ACTIVATE_EARLY has been set.
318 : : */
319 : : MSI_FLAG_MUST_REACTIVATE = (1 << 5),
320 : : /* Is level-triggered capable, using two messages */
321 : : MSI_FLAG_LEVEL_CAPABLE = (1 << 6),
322 : : };
323 : :
324 : : int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
325 : : bool force);
326 : :
327 : : struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode,
328 : : struct msi_domain_info *info,
329 : : struct irq_domain *parent);
330 : : int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
331 : : int nvec);
332 : : void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev);
333 : : struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain);
334 : :
335 : : struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
336 : : struct msi_domain_info *info,
337 : : struct irq_domain *parent);
338 : : int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
339 : : irq_write_msi_msg_t write_msi_msg);
340 : : void platform_msi_domain_free_irqs(struct device *dev);
341 : :
342 : : /* When an MSI domain is used as an intermediate domain */
343 : : int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
344 : : int nvec, msi_alloc_info_t *args);
345 : : int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
346 : : int virq, int nvec, msi_alloc_info_t *args);
347 : : struct irq_domain *
348 : : __platform_msi_create_device_domain(struct device *dev,
349 : : unsigned int nvec,
350 : : bool is_tree,
351 : : irq_write_msi_msg_t write_msi_msg,
352 : : const struct irq_domain_ops *ops,
353 : : void *host_data);
354 : :
355 : : #define platform_msi_create_device_domain(dev, nvec, write, ops, data) \
356 : : __platform_msi_create_device_domain(dev, nvec, false, write, ops, data)
357 : : #define platform_msi_create_device_tree_domain(dev, nvec, write, ops, data) \
358 : : __platform_msi_create_device_domain(dev, nvec, true, write, ops, data)
359 : :
360 : : int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
361 : : unsigned int nr_irqs);
362 : : void platform_msi_domain_free(struct irq_domain *domain, unsigned int virq,
363 : : unsigned int nvec);
364 : : void *platform_msi_get_host_data(struct irq_domain *domain);
365 : : #endif /* CONFIG_GENERIC_MSI_IRQ_DOMAIN */
366 : :
367 : : #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
368 : : void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg);
369 : : struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
370 : : struct msi_domain_info *info,
371 : : struct irq_domain *parent);
372 : : irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev,
373 : : struct msi_desc *desc);
374 : : int pci_msi_domain_check_cap(struct irq_domain *domain,
375 : : struct msi_domain_info *info, struct device *dev);
376 : : u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev);
377 : : struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev);
378 : : #else
379 : : static inline struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev)
380 : : {
381 : : return NULL;
382 : : }
383 : : #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */
384 : :
385 : : #endif /* LINUX_MSI_H */
|