diff options
| -rw-r--r-- | kernel/irq/msi.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index edb987b2c58d..9ba954331171 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c | |||
| @@ -339,6 +339,13 @@ int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev, | |||
| 339 | return ret; | 339 | return ret; |
| 340 | } | 340 | } |
| 341 | 341 | ||
| 342 | static bool msi_check_reservation_mode(struct msi_domain_info *info) | ||
| 343 | { | ||
| 344 | if (!(info->flags & MSI_FLAG_MUST_REACTIVATE)) | ||
| 345 | return false; | ||
| 346 | return true; | ||
| 347 | } | ||
| 348 | |||
| 342 | /** | 349 | /** |
| 343 | * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain | 350 | * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain |
| 344 | * @domain: The domain to allocate from | 351 | * @domain: The domain to allocate from |
| @@ -353,9 +360,11 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, | |||
| 353 | { | 360 | { |
| 354 | struct msi_domain_info *info = domain->host_data; | 361 | struct msi_domain_info *info = domain->host_data; |
| 355 | struct msi_domain_ops *ops = info->ops; | 362 | struct msi_domain_ops *ops = info->ops; |
| 356 | msi_alloc_info_t arg; | 363 | struct irq_data *irq_data; |
| 357 | struct msi_desc *desc; | 364 | struct msi_desc *desc; |
| 365 | msi_alloc_info_t arg; | ||
| 358 | int i, ret, virq; | 366 | int i, ret, virq; |
| 367 | bool can_reserve; | ||
| 359 | 368 | ||
| 360 | ret = msi_domain_prepare_irqs(domain, dev, nvec, &arg); | 369 | ret = msi_domain_prepare_irqs(domain, dev, nvec, &arg); |
| 361 | if (ret) | 370 | if (ret) |
| @@ -385,6 +394,8 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, | |||
| 385 | if (ops->msi_finish) | 394 | if (ops->msi_finish) |
| 386 | ops->msi_finish(&arg, 0); | 395 | ops->msi_finish(&arg, 0); |
| 387 | 396 | ||
| 397 | can_reserve = msi_check_reservation_mode(info); | ||
| 398 | |||
| 388 | for_each_msi_entry(desc, dev) { | 399 | for_each_msi_entry(desc, dev) { |
| 389 | virq = desc->irq; | 400 | virq = desc->irq; |
| 390 | if (desc->nvec_used == 1) | 401 | if (desc->nvec_used == 1) |
| @@ -397,15 +408,23 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, | |||
| 397 | * the MSI entries before the PCI layer enables MSI in the | 408 | * the MSI entries before the PCI layer enables MSI in the |
| 398 | * card. Otherwise the card latches a random msi message. | 409 | * card. Otherwise the card latches a random msi message. |
| 399 | */ | 410 | */ |
| 400 | if (info->flags & MSI_FLAG_ACTIVATE_EARLY) { | 411 | if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY)) |
| 401 | struct irq_data *irq_data; | 412 | continue; |
| 402 | 413 | ||
| 414 | irq_data = irq_domain_get_irq_data(domain, desc->irq); | ||
| 415 | ret = irq_domain_activate_irq(irq_data, true); | ||
| 416 | if (ret) | ||
| 417 | goto cleanup; | ||
| 418 | } | ||
| 419 | |||
| 420 | /* | ||
| 421 | * If these interrupts use reservation mode, clear the activated bit | ||
| 422 | * so request_irq() will assign the final vector. | ||
| 423 | */ | ||
| 424 | if (can_reserve) { | ||
| 425 | for_each_msi_entry(desc, dev) { | ||
| 403 | irq_data = irq_domain_get_irq_data(domain, desc->irq); | 426 | irq_data = irq_domain_get_irq_data(domain, desc->irq); |
| 404 | ret = irq_domain_activate_irq(irq_data, true); | 427 | irqd_clr_activated(irq_data); |
| 405 | if (ret) | ||
| 406 | goto cleanup; | ||
| 407 | if (info->flags & MSI_FLAG_MUST_REACTIVATE) | ||
| 408 | irqd_clr_activated(irq_data); | ||
| 409 | } | 428 | } |
| 410 | } | 429 | } |
| 411 | return 0; | 430 | return 0; |
