@@ -98,13 +98,18 @@ struct irq_info {
9898 short refcnt ;
9999 u8 spurious_cnt ;
100100 u8 is_accounted ;
101- enum xen_irq_type type ; /* type */
101+ short type ; /* type: IRQT_* */
102+ u8 mask_reason ; /* Why is event channel masked */
103+ #define EVT_MASK_REASON_EXPLICIT 0x01
104+ #define EVT_MASK_REASON_TEMPORARY 0x02
105+ #define EVT_MASK_REASON_EOI_PENDING 0x04
102106 unsigned irq ;
103107 evtchn_port_t evtchn ; /* event channel */
104108 unsigned short cpu ; /* cpu bound */
105109 unsigned short eoi_cpu ; /* EOI must happen on this cpu-1 */
106110 unsigned int irq_epoch ; /* If eoi_cpu valid: irq_epoch of event */
107111 u64 eoi_time ; /* Time in jiffies when to EOI. */
112+ spinlock_t lock ;
108113
109114 union {
110115 unsigned short virq ;
@@ -154,6 +159,7 @@ static DEFINE_RWLOCK(evtchn_rwlock);
154159 * evtchn_rwlock
155160 * IRQ-desc lock
156161 * percpu eoi_list_lock
162+ * irq_info->lock
157163 */
158164
159165static LIST_HEAD (xen_irq_list_head );
@@ -304,6 +310,8 @@ static int xen_irq_info_common_setup(struct irq_info *info,
304310 info -> irq = irq ;
305311 info -> evtchn = evtchn ;
306312 info -> cpu = cpu ;
313+ info -> mask_reason = EVT_MASK_REASON_EXPLICIT ;
314+ spin_lock_init (& info -> lock );
307315
308316 ret = set_evtchn_to_irq (evtchn , irq );
309317 if (ret < 0 )
@@ -459,6 +467,34 @@ unsigned int cpu_from_evtchn(evtchn_port_t evtchn)
459467 return ret ;
460468}
461469
470+ static void do_mask (struct irq_info * info , u8 reason )
471+ {
472+ unsigned long flags ;
473+
474+ spin_lock_irqsave (& info -> lock , flags );
475+
476+ if (!info -> mask_reason )
477+ mask_evtchn (info -> evtchn );
478+
479+ info -> mask_reason |= reason ;
480+
481+ spin_unlock_irqrestore (& info -> lock , flags );
482+ }
483+
484+ static void do_unmask (struct irq_info * info , u8 reason )
485+ {
486+ unsigned long flags ;
487+
488+ spin_lock_irqsave (& info -> lock , flags );
489+
490+ info -> mask_reason &= ~reason ;
491+
492+ if (!info -> mask_reason )
493+ unmask_evtchn (info -> evtchn );
494+
495+ spin_unlock_irqrestore (& info -> lock , flags );
496+ }
497+
462498#ifdef CONFIG_X86
463499static bool pirq_check_eoi_map (unsigned irq )
464500{
@@ -605,7 +641,7 @@ static void xen_irq_lateeoi_locked(struct irq_info *info, bool spurious)
605641 }
606642
607643 info -> eoi_time = 0 ;
608- unmask_evtchn ( evtchn );
644+ do_unmask ( info , EVT_MASK_REASON_EOI_PENDING );
609645}
610646
611647static void xen_irq_lateeoi_worker (struct work_struct * work )
@@ -850,7 +886,8 @@ static unsigned int __startup_pirq(unsigned int irq)
850886 goto err ;
851887
852888out :
853- unmask_evtchn (evtchn );
889+ do_unmask (info , EVT_MASK_REASON_EXPLICIT );
890+
854891 eoi_pirq (irq_get_irq_data (irq ));
855892
856893 return 0 ;
@@ -877,7 +914,7 @@ static void shutdown_pirq(struct irq_data *data)
877914 if (!VALID_EVTCHN (evtchn ))
878915 return ;
879916
880- mask_evtchn ( evtchn );
917+ do_mask ( info , EVT_MASK_REASON_EXPLICIT );
881918 xen_evtchn_close (evtchn );
882919 xen_irq_info_cleanup (info );
883920}
@@ -1721,10 +1758,10 @@ void rebind_evtchn_irq(evtchn_port_t evtchn, int irq)
17211758}
17221759
17231760/* Rebind an evtchn so that it gets delivered to a specific cpu */
1724- static int xen_rebind_evtchn_to_cpu (evtchn_port_t evtchn , unsigned int tcpu )
1761+ static int xen_rebind_evtchn_to_cpu (struct irq_info * info , unsigned int tcpu )
17251762{
17261763 struct evtchn_bind_vcpu bind_vcpu ;
1727- int masked ;
1764+ evtchn_port_t evtchn = info ? info -> evtchn : 0 ;
17281765
17291766 if (!VALID_EVTCHN (evtchn ))
17301767 return -1 ;
@@ -1740,7 +1777,7 @@ static int xen_rebind_evtchn_to_cpu(evtchn_port_t evtchn, unsigned int tcpu)
17401777 * Mask the event while changing the VCPU binding to prevent
17411778 * it being delivered on an unexpected VCPU.
17421779 */
1743- masked = test_and_set_mask ( evtchn );
1780+ do_mask ( info , EVT_MASK_REASON_TEMPORARY );
17441781
17451782 /*
17461783 * If this fails, it usually just indicates that we're dealing with a
@@ -1750,8 +1787,7 @@ static int xen_rebind_evtchn_to_cpu(evtchn_port_t evtchn, unsigned int tcpu)
17501787 if (HYPERVISOR_event_channel_op (EVTCHNOP_bind_vcpu , & bind_vcpu ) >= 0 )
17511788 bind_evtchn_to_cpu (evtchn , tcpu , false);
17521789
1753- if (!masked )
1754- unmask_evtchn (evtchn );
1790+ do_unmask (info , EVT_MASK_REASON_TEMPORARY );
17551791
17561792 return 0 ;
17571793}
@@ -1790,7 +1826,7 @@ static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest,
17901826 unsigned int tcpu = select_target_cpu (dest );
17911827 int ret ;
17921828
1793- ret = xen_rebind_evtchn_to_cpu (evtchn_from_irq (data -> irq ), tcpu );
1829+ ret = xen_rebind_evtchn_to_cpu (info_for_irq (data -> irq ), tcpu );
17941830 if (!ret )
17951831 irq_data_update_effective_affinity (data , cpumask_of (tcpu ));
17961832
@@ -1799,18 +1835,20 @@ static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest,
17991835
18001836static void enable_dynirq (struct irq_data * data )
18011837{
1802- evtchn_port_t evtchn = evtchn_from_irq (data -> irq );
1838+ struct irq_info * info = info_for_irq (data -> irq );
1839+ evtchn_port_t evtchn = info ? info -> evtchn : 0 ;
18031840
18041841 if (VALID_EVTCHN (evtchn ))
1805- unmask_evtchn ( evtchn );
1842+ do_unmask ( info , EVT_MASK_REASON_EXPLICIT );
18061843}
18071844
18081845static void disable_dynirq (struct irq_data * data )
18091846{
1810- evtchn_port_t evtchn = evtchn_from_irq (data -> irq );
1847+ struct irq_info * info = info_for_irq (data -> irq );
1848+ evtchn_port_t evtchn = info ? info -> evtchn : 0 ;
18111849
18121850 if (VALID_EVTCHN (evtchn ))
1813- mask_evtchn ( evtchn );
1851+ do_mask ( info , EVT_MASK_REASON_EXPLICIT );
18141852}
18151853
18161854static void ack_dynirq (struct irq_data * data )
@@ -1829,18 +1867,39 @@ static void mask_ack_dynirq(struct irq_data *data)
18291867 ack_dynirq (data );
18301868}
18311869
1870+ static void lateeoi_ack_dynirq (struct irq_data * data )
1871+ {
1872+ struct irq_info * info = info_for_irq (data -> irq );
1873+ evtchn_port_t evtchn = info ? info -> evtchn : 0 ;
1874+
1875+ if (VALID_EVTCHN (evtchn )) {
1876+ do_mask (info , EVT_MASK_REASON_EOI_PENDING );
1877+ clear_evtchn (evtchn );
1878+ }
1879+ }
1880+
1881+ static void lateeoi_mask_ack_dynirq (struct irq_data * data )
1882+ {
1883+ struct irq_info * info = info_for_irq (data -> irq );
1884+ evtchn_port_t evtchn = info ? info -> evtchn : 0 ;
1885+
1886+ if (VALID_EVTCHN (evtchn )) {
1887+ do_mask (info , EVT_MASK_REASON_EXPLICIT );
1888+ clear_evtchn (evtchn );
1889+ }
1890+ }
1891+
18321892static int retrigger_dynirq (struct irq_data * data )
18331893{
1834- evtchn_port_t evtchn = evtchn_from_irq (data -> irq );
1835- int masked ;
1894+ struct irq_info * info = info_for_irq (data -> irq );
1895+ evtchn_port_t evtchn = info ? info -> evtchn : 0 ;
18361896
18371897 if (!VALID_EVTCHN (evtchn ))
18381898 return 0 ;
18391899
1840- masked = test_and_set_mask ( evtchn );
1900+ do_mask ( info , EVT_MASK_REASON_TEMPORARY );
18411901 set_evtchn (evtchn );
1842- if (!masked )
1843- unmask_evtchn (evtchn );
1902+ do_unmask (info , EVT_MASK_REASON_TEMPORARY );
18441903
18451904 return 1 ;
18461905}
@@ -2054,8 +2113,8 @@ static struct irq_chip xen_lateeoi_chip __read_mostly = {
20542113 .irq_mask = disable_dynirq ,
20552114 .irq_unmask = enable_dynirq ,
20562115
2057- .irq_ack = mask_ack_dynirq ,
2058- .irq_mask_ack = mask_ack_dynirq ,
2116+ .irq_ack = lateeoi_ack_dynirq ,
2117+ .irq_mask_ack = lateeoi_mask_ack_dynirq ,
20592118
20602119 .irq_set_affinity = set_affinity_irq ,
20612120 .irq_retrigger = retrigger_dynirq ,
0 commit comments