aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/events.c
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2011-05-06 07:27:50 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-05-10 12:47:40 -0400
commit7e186bdd0098b34c69fb8067c67340ae610ea499 (patch)
treedd648a0f57ba6adf798fca78ff08df6be94848f7 /drivers/xen/events.c
parent693d92a1bbc9e42681c42ed190bd42b636ca876f (diff)
xen: do not clear and mask evtchns in __xen_evtchn_do_upcall
Change the irq handler of evtchns and pirqs that don't need EOI (pirqs that correspond to physical edge interrupts) to handle_edge_irq. Use handle_fasteoi_irq for pirqs that need eoi (they generally correspond to level triggered irqs), no risk in loosing interrupts because we have to EOI the irq anyway. This change has the following benefits: - it uses the very same handlers that Linux would use on native for the same irqs (handle_edge_irq for edge irqs and msis, and handle_fasteoi_irq for everything else); - it uses these handlers in the same way native code would use them: it let Linux mask\unmask and ack the irq when Linux want to mask\unmask and ack the irq; - it fixes a problem occurring when a driver calls disable_irq() in its handler: the old code was unconditionally unmasking the evtchn even if the irq is disabled when irq_eoi was called. See Documentation/DocBook/genericirq.tmpl for more informations. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> [v1: Fixed space/tab issues] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen/events.c')
-rw-r--r--drivers/xen/events.c113
1 files changed, 73 insertions, 40 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 33167b43ac7e..0ae1d4d7e18c 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -118,6 +118,8 @@ static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG],
118static struct irq_chip xen_dynamic_chip; 118static struct irq_chip xen_dynamic_chip;
119static struct irq_chip xen_percpu_chip; 119static struct irq_chip xen_percpu_chip;
120static struct irq_chip xen_pirq_chip; 120static struct irq_chip xen_pirq_chip;
121static void enable_dynirq(struct irq_data *data);
122static void disable_dynirq(struct irq_data *data);
121 123
122/* Get info for IRQ */ 124/* Get info for IRQ */
123static struct irq_info *info_for_irq(unsigned irq) 125static struct irq_info *info_for_irq(unsigned irq)
@@ -473,16 +475,6 @@ static void xen_free_irq(unsigned irq)
473 irq_free_desc(irq); 475 irq_free_desc(irq);
474} 476}
475 477
476static void pirq_unmask_notify(int irq)
477{
478 struct physdev_eoi eoi = { .irq = pirq_from_irq(irq) };
479
480 if (unlikely(pirq_needs_eoi(irq))) {
481 int rc = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi);
482 WARN_ON(rc);
483 }
484}
485
486static void pirq_query_unmask(int irq) 478static void pirq_query_unmask(int irq)
487{ 479{
488 struct physdev_irq_status_query irq_status; 480 struct physdev_irq_status_query irq_status;
@@ -506,6 +498,29 @@ static bool probing_irq(int irq)
506 return desc && desc->action == NULL; 498 return desc && desc->action == NULL;
507} 499}
508 500
501static void eoi_pirq(struct irq_data *data)
502{
503 int evtchn = evtchn_from_irq(data->irq);
504 struct physdev_eoi eoi = { .irq = pirq_from_irq(data->irq) };
505 int rc = 0;
506
507 irq_move_irq(data);
508
509 if (VALID_EVTCHN(evtchn))
510 clear_evtchn(evtchn);
511
512 if (pirq_needs_eoi(data->irq)) {
513 rc = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi);
514 WARN_ON(rc);
515 }
516}
517
518static void mask_ack_pirq(struct irq_data *data)
519{
520 disable_dynirq(data);
521 eoi_pirq(data);
522}
523
509static unsigned int __startup_pirq(unsigned int irq) 524static unsigned int __startup_pirq(unsigned int irq)
510{ 525{
511 struct evtchn_bind_pirq bind_pirq; 526 struct evtchn_bind_pirq bind_pirq;
@@ -539,7 +554,7 @@ static unsigned int __startup_pirq(unsigned int irq)
539 554
540out: 555out:
541 unmask_evtchn(evtchn); 556 unmask_evtchn(evtchn);
542 pirq_unmask_notify(irq); 557 eoi_pirq(irq_get_irq_data(irq));
543 558
544 return 0; 559 return 0;
545} 560}
@@ -579,18 +594,7 @@ static void enable_pirq(struct irq_data *data)
579 594
580static void disable_pirq(struct irq_data *data) 595static void disable_pirq(struct irq_data *data)
581{ 596{
582} 597 disable_dynirq(data);
583
584static void ack_pirq(struct irq_data *data)
585{
586 int evtchn = evtchn_from_irq(data->irq);
587
588 irq_move_irq(data);
589
590 if (VALID_EVTCHN(evtchn)) {
591 mask_evtchn(evtchn);
592 clear_evtchn(evtchn);
593 }
594} 598}
595 599
596static int find_irq_by_gsi(unsigned gsi) 600static int find_irq_by_gsi(unsigned gsi)
@@ -639,9 +643,6 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
639 if (irq < 0) 643 if (irq < 0)
640 goto out; 644 goto out;
641 645
642 irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_level_irq,
643 name);
644
645 irq_op.irq = irq; 646 irq_op.irq = irq;
646 irq_op.vector = 0; 647 irq_op.vector = 0;
647 648
@@ -658,6 +659,32 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
658 xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, 659 xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector,
659 shareable ? PIRQ_SHAREABLE : 0); 660 shareable ? PIRQ_SHAREABLE : 0);
660 661
662 pirq_query_unmask(irq);
663 /* We try to use the handler with the appropriate semantic for the
664 * type of interrupt: if the interrupt doesn't need an eoi
665 * (pirq_needs_eoi returns false), we treat it like an edge
666 * triggered interrupt so we use handle_edge_irq.
667 * As a matter of fact this only happens when the corresponding
668 * physical interrupt is edge triggered or an msi.
669 *
670 * On the other hand if the interrupt needs an eoi (pirq_needs_eoi
671 * returns true) we treat it like a level triggered interrupt so we
672 * use handle_fasteoi_irq like the native code does for this kind of
673 * interrupts.
674 * Depending on the Xen version, pirq_needs_eoi might return true
675 * not only for level triggered interrupts but for edge triggered
676 * interrupts too. In any case Xen always honors the eoi mechanism,
677 * not injecting any more pirqs of the same kind if the first one
678 * hasn't received an eoi yet. Therefore using the fasteoi handler
679 * is the right choice either way.
680 */
681 if (pirq_needs_eoi(irq))
682 irq_set_chip_and_handler_name(irq, &xen_pirq_chip,
683 handle_fasteoi_irq, name);
684 else
685 irq_set_chip_and_handler_name(irq, &xen_pirq_chip,
686 handle_edge_irq, name);
687
661out: 688out:
662 spin_unlock(&irq_mapping_update_lock); 689 spin_unlock(&irq_mapping_update_lock);
663 690
@@ -690,8 +717,8 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
690 if (irq == -1) 717 if (irq == -1)
691 goto out; 718 goto out;
692 719
693 irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_level_irq, 720 irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq,
694 name); 721 name);
695 722
696 xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, 0); 723 xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, 0);
697 ret = irq_set_msi_desc(irq, msidesc); 724 ret = irq_set_msi_desc(irq, msidesc);
@@ -773,7 +800,7 @@ int bind_evtchn_to_irq(unsigned int evtchn)
773 goto out; 800 goto out;
774 801
775 irq_set_chip_and_handler_name(irq, &xen_dynamic_chip, 802 irq_set_chip_and_handler_name(irq, &xen_dynamic_chip,
776 handle_fasteoi_irq, "event"); 803 handle_edge_irq, "event");
777 804
778 xen_irq_info_evtchn_init(irq, evtchn); 805 xen_irq_info_evtchn_init(irq, evtchn);
779 } 806 }
@@ -1179,9 +1206,6 @@ static void __xen_evtchn_do_upcall(void)
1179 port = (word_idx * BITS_PER_LONG) + bit_idx; 1206 port = (word_idx * BITS_PER_LONG) + bit_idx;
1180 irq = evtchn_to_irq[port]; 1207 irq = evtchn_to_irq[port];
1181 1208
1182 mask_evtchn(port);
1183 clear_evtchn(port);
1184
1185 if (irq != -1) { 1209 if (irq != -1) {
1186 desc = irq_to_desc(irq); 1210 desc = irq_to_desc(irq);
1187 if (desc) 1211 if (desc)
@@ -1337,10 +1361,16 @@ static void ack_dynirq(struct irq_data *data)
1337{ 1361{
1338 int evtchn = evtchn_from_irq(data->irq); 1362 int evtchn = evtchn_from_irq(data->irq);
1339 1363
1340 irq_move_masked_irq(data); 1364 irq_move_irq(data);
1341 1365
1342 if (VALID_EVTCHN(evtchn)) 1366 if (VALID_EVTCHN(evtchn))
1343 unmask_evtchn(evtchn); 1367 clear_evtchn(evtchn);
1368}
1369
1370static void mask_ack_dynirq(struct irq_data *data)
1371{
1372 disable_dynirq(data);
1373 ack_dynirq(data);
1344} 1374}
1345 1375
1346static int retrigger_dynirq(struct irq_data *data) 1376static int retrigger_dynirq(struct irq_data *data)
@@ -1535,7 +1565,9 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
1535 .irq_mask = disable_dynirq, 1565 .irq_mask = disable_dynirq,
1536 .irq_unmask = enable_dynirq, 1566 .irq_unmask = enable_dynirq,
1537 1567
1538 .irq_eoi = ack_dynirq, 1568 .irq_ack = ack_dynirq,
1569 .irq_mask_ack = mask_ack_dynirq,
1570
1539 .irq_set_affinity = set_affinity_irq, 1571 .irq_set_affinity = set_affinity_irq,
1540 .irq_retrigger = retrigger_dynirq, 1572 .irq_retrigger = retrigger_dynirq,
1541}; 1573};
@@ -1545,14 +1577,15 @@ static struct irq_chip xen_pirq_chip __read_mostly = {
1545 1577
1546 .irq_startup = startup_pirq, 1578 .irq_startup = startup_pirq,
1547 .irq_shutdown = shutdown_pirq, 1579 .irq_shutdown = shutdown_pirq,
1548
1549 .irq_enable = enable_pirq, 1580 .irq_enable = enable_pirq,
1550 .irq_unmask = enable_pirq,
1551
1552 .irq_disable = disable_pirq, 1581 .irq_disable = disable_pirq,
1553 .irq_mask = disable_pirq,
1554 1582
1555 .irq_ack = ack_pirq, 1583 .irq_mask = disable_dynirq,
1584 .irq_unmask = enable_dynirq,
1585
1586 .irq_ack = eoi_pirq,
1587 .irq_eoi = eoi_pirq,
1588 .irq_mask_ack = mask_ack_pirq,
1556 1589
1557 .irq_set_affinity = set_affinity_irq, 1590 .irq_set_affinity = set_affinity_irq,
1558 1591