aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/irq/msi.c35
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
342static 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;