.. | .. |
---|
5 | 5 | * |
---|
6 | 6 | * This file is licensed under GPLv2. |
---|
7 | 7 | * |
---|
8 | | - * This file contains common code to support Message Signalled Interrupt for |
---|
| 8 | + * This file contains common code to support Message Signaled Interrupts for |
---|
9 | 9 | * PCI compatible and non PCI compatible devices. |
---|
10 | 10 | */ |
---|
11 | 11 | #include <linux/types.h> |
---|
.. | .. |
---|
23 | 23 | * @nvec: The number of vectors used in this entry |
---|
24 | 24 | * @affinity: Optional pointer to an affinity mask array size of @nvec |
---|
25 | 25 | * |
---|
26 | | - * If @affinity is not NULL then a an affinity array[@nvec] is allocated |
---|
27 | | - * and the affinity masks from @affinity are copied. |
---|
| 26 | + * If @affinity is not NULL then an affinity array[@nvec] is allocated |
---|
| 27 | + * and the affinity masks and flags from @affinity are copied. |
---|
28 | 28 | */ |
---|
29 | | -struct msi_desc * |
---|
30 | | -alloc_msi_entry(struct device *dev, int nvec, const struct cpumask *affinity) |
---|
| 29 | +struct msi_desc *alloc_msi_entry(struct device *dev, int nvec, |
---|
| 30 | + const struct irq_affinity_desc *affinity) |
---|
31 | 31 | { |
---|
32 | 32 | struct msi_desc *desc; |
---|
33 | 33 | |
---|
.. | .. |
---|
187 | 187 | .deactivate = msi_domain_deactivate, |
---|
188 | 188 | }; |
---|
189 | 189 | |
---|
190 | | -#ifdef GENERIC_MSI_DOMAIN_OPS |
---|
191 | 190 | static irq_hw_number_t msi_domain_ops_get_hwirq(struct msi_domain_info *info, |
---|
192 | 191 | msi_alloc_info_t *arg) |
---|
193 | 192 | { |
---|
.. | .. |
---|
206 | 205 | { |
---|
207 | 206 | arg->desc = desc; |
---|
208 | 207 | } |
---|
209 | | -#else |
---|
210 | | -#define msi_domain_ops_get_hwirq NULL |
---|
211 | | -#define msi_domain_ops_prepare NULL |
---|
212 | | -#define msi_domain_ops_set_desc NULL |
---|
213 | | -#endif /* !GENERIC_MSI_DOMAIN_OPS */ |
---|
214 | 208 | |
---|
215 | 209 | static int msi_domain_ops_init(struct irq_domain *domain, |
---|
216 | 210 | struct msi_domain_info *info, |
---|
.. | .. |
---|
235 | 229 | } |
---|
236 | 230 | |
---|
237 | 231 | static struct msi_domain_ops msi_domain_ops_default = { |
---|
238 | | - .get_hwirq = msi_domain_ops_get_hwirq, |
---|
239 | | - .msi_init = msi_domain_ops_init, |
---|
240 | | - .msi_check = msi_domain_ops_check, |
---|
241 | | - .msi_prepare = msi_domain_ops_prepare, |
---|
242 | | - .set_desc = msi_domain_ops_set_desc, |
---|
| 232 | + .get_hwirq = msi_domain_ops_get_hwirq, |
---|
| 233 | + .msi_init = msi_domain_ops_init, |
---|
| 234 | + .msi_check = msi_domain_ops_check, |
---|
| 235 | + .msi_prepare = msi_domain_ops_prepare, |
---|
| 236 | + .set_desc = msi_domain_ops_set_desc, |
---|
| 237 | + .domain_alloc_irqs = __msi_domain_alloc_irqs, |
---|
| 238 | + .domain_free_irqs = __msi_domain_free_irqs, |
---|
243 | 239 | }; |
---|
244 | 240 | |
---|
245 | 241 | static void msi_domain_update_dom_ops(struct msi_domain_info *info) |
---|
.. | .. |
---|
250 | 246 | info->ops = &msi_domain_ops_default; |
---|
251 | 247 | return; |
---|
252 | 248 | } |
---|
| 249 | + |
---|
| 250 | + if (ops->domain_alloc_irqs == NULL) |
---|
| 251 | + ops->domain_alloc_irqs = msi_domain_ops_default.domain_alloc_irqs; |
---|
| 252 | + if (ops->domain_free_irqs == NULL) |
---|
| 253 | + ops->domain_free_irqs = msi_domain_ops_default.domain_free_irqs; |
---|
| 254 | + |
---|
| 255 | + if (!(info->flags & MSI_FLAG_USE_DEF_DOM_OPS)) |
---|
| 256 | + return; |
---|
253 | 257 | |
---|
254 | 258 | if (ops->get_hwirq == NULL) |
---|
255 | 259 | ops->get_hwirq = msi_domain_ops_default.get_hwirq; |
---|
.. | .. |
---|
284 | 288 | { |
---|
285 | 289 | struct irq_domain *domain; |
---|
286 | 290 | |
---|
287 | | - if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) |
---|
288 | | - msi_domain_update_dom_ops(info); |
---|
| 291 | + msi_domain_update_dom_ops(info); |
---|
289 | 292 | if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) |
---|
290 | 293 | msi_domain_update_chip_ops(info); |
---|
291 | 294 | |
---|
.. | .. |
---|
370 | 373 | { |
---|
371 | 374 | struct msi_desc *desc; |
---|
372 | 375 | |
---|
373 | | - if (domain->bus_token != DOMAIN_BUS_PCI_MSI) |
---|
| 376 | + switch(domain->bus_token) { |
---|
| 377 | + case DOMAIN_BUS_PCI_MSI: |
---|
| 378 | + case DOMAIN_BUS_VMD_MSI: |
---|
| 379 | + break; |
---|
| 380 | + default: |
---|
374 | 381 | return false; |
---|
| 382 | + } |
---|
375 | 383 | |
---|
376 | 384 | if (!(info->flags & MSI_FLAG_MUST_REACTIVATE)) |
---|
377 | 385 | return false; |
---|
.. | .. |
---|
387 | 395 | return desc->msi_attrib.is_msix || desc->msi_attrib.maskbit; |
---|
388 | 396 | } |
---|
389 | 397 | |
---|
390 | | -/** |
---|
391 | | - * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain |
---|
392 | | - * @domain: The domain to allocate from |
---|
393 | | - * @dev: Pointer to device struct of the device for which the interrupts |
---|
394 | | - * are allocated |
---|
395 | | - * @nvec: The number of interrupts to allocate |
---|
396 | | - * |
---|
397 | | - * Returns 0 on success or an error code. |
---|
398 | | - */ |
---|
399 | | -int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, |
---|
400 | | - int nvec) |
---|
| 398 | +int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, |
---|
| 399 | + int nvec) |
---|
401 | 400 | { |
---|
402 | 401 | struct msi_domain_info *info = domain->host_data; |
---|
403 | 402 | struct msi_domain_ops *ops = info->ops; |
---|
.. | .. |
---|
457 | 456 | irqd_clr_can_reserve(irq_data); |
---|
458 | 457 | if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK) |
---|
459 | 458 | irqd_set_msi_nomask_quirk(irq_data); |
---|
| 459 | + if ((info->flags & MSI_FLAG_ACTIVATE_EARLY) && |
---|
| 460 | + irqd_affinity_is_managed(irq_data) && |
---|
| 461 | + !cpumask_intersects(irq_data_get_affinity_mask(irq_data), |
---|
| 462 | + cpu_online_mask)) { |
---|
| 463 | + irqd_set_managed_shutdown(irq_data); |
---|
| 464 | + continue; |
---|
| 465 | + } |
---|
460 | 466 | } |
---|
461 | 467 | ret = irq_domain_activate_irq(irq_data, can_reserve); |
---|
462 | 468 | if (ret) |
---|
.. | .. |
---|
482 | 488 | } |
---|
483 | 489 | |
---|
484 | 490 | /** |
---|
485 | | - * msi_domain_free_irqs - Free interrupts from a MSI interrupt @domain associated tp @dev |
---|
486 | | - * @domain: The domain to managing the interrupts |
---|
| 491 | + * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain |
---|
| 492 | + * @domain: The domain to allocate from |
---|
487 | 493 | * @dev: Pointer to device struct of the device for which the interrupts |
---|
488 | | - * are free |
---|
| 494 | + * are allocated |
---|
| 495 | + * @nvec: The number of interrupts to allocate |
---|
| 496 | + * |
---|
| 497 | + * Returns 0 on success or an error code. |
---|
489 | 498 | */ |
---|
490 | | -void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) |
---|
| 499 | +int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, |
---|
| 500 | + int nvec) |
---|
| 501 | +{ |
---|
| 502 | + struct msi_domain_info *info = domain->host_data; |
---|
| 503 | + struct msi_domain_ops *ops = info->ops; |
---|
| 504 | + |
---|
| 505 | + return ops->domain_alloc_irqs(domain, dev, nvec); |
---|
| 506 | +} |
---|
| 507 | + |
---|
| 508 | +void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) |
---|
491 | 509 | { |
---|
492 | 510 | struct irq_data *irq_data; |
---|
493 | 511 | struct msi_desc *desc; |
---|
.. | .. |
---|
513 | 531 | } |
---|
514 | 532 | |
---|
515 | 533 | /** |
---|
| 534 | + * __msi_domain_free_irqs - Free interrupts from a MSI interrupt @domain associated tp @dev |
---|
| 535 | + * @domain: The domain to managing the interrupts |
---|
| 536 | + * @dev: Pointer to device struct of the device for which the interrupts |
---|
| 537 | + * are free |
---|
| 538 | + */ |
---|
| 539 | +void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) |
---|
| 540 | +{ |
---|
| 541 | + struct msi_domain_info *info = domain->host_data; |
---|
| 542 | + struct msi_domain_ops *ops = info->ops; |
---|
| 543 | + |
---|
| 544 | + return ops->domain_free_irqs(domain, dev); |
---|
| 545 | +} |
---|
| 546 | + |
---|
| 547 | +/** |
---|
516 | 548 | * msi_get_domain_info - Get the MSI interrupt domain info for @domain |
---|
517 | 549 | * @domain: The interrupt domain to retrieve data from |
---|
518 | 550 | * |
---|