ia64/xen-unstable

view linux-2.6-xen-sparse/arch/ia64/xen/drivers/evtchn_ia64.c @ 7723:9be9bc0b0f11

Fix typo
author djm@kirby.fc.hp.com
date Thu Nov 10 09:07:47 2005 -0600 (2005-11-10)
parents 214bd6a0ed27
children e002282b79c8
line source
1 /* NOTE: This file split off from evtchn.c because there was
2 some discussion that the mechanism is sufficiently different.
3 It may be possible to merge it back in the future... djm */
4 #include <linux/config.h>
5 #include <linux/kernel.h>
6 #include <asm/hw_irq.h>
7 #include <asm-xen/evtchn.h>
9 #define MAX_EVTCHN 1024
11 /* Xen will never allocate port zero for any purpose. */
12 #define VALID_EVTCHN(_chn) (((_chn) != 0) && ((_chn) < MAX_EVTCHN))
14 /* Binding types. Hey, only IRQT_VIRQ and IRQT_EVTCHN are supported now
15 * for XEN/IA64 - ktian1
16 */
17 enum { IRQT_UNBOUND, IRQT_PIRQ, IRQT_VIRQ, IRQT_IPI, IRQT_EVTCHN };
19 /* Constructor for packed IRQ information. */
20 #define mk_irq_info(type, index, evtchn) \
21 (((u32)(type) << 24) | ((u32)(index) << 16) | (u32)(evtchn))
22 /* Convenient shorthand for packed representation of an unbound IRQ. */
23 #define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0)
24 /* Accessor macros for packed IRQ information. */
25 #define evtchn_from_irq(irq) ((u16)(irq_info[irq]))
26 #define index_from_irq(irq) ((u8)(irq_info[irq] >> 16))
27 #define type_from_irq(irq) ((u8)(irq_info[irq] >> 24))
29 /* Packed IRQ information: binding type, sub-type index, and event channel. */
30 static u32 irq_info[NR_IRQS];
32 /* One note for XEN/IA64 is that we have all event channels bound to one
33 * physical irq vector. So we always mean evtchn vector identical to 'irq'
34 * vector in this context. - ktian1
35 */
36 static struct {
37 irqreturn_t (*handler)(int, void *, struct pt_regs *);
38 void *dev_id;
39 char opened; /* Whether allocated */
40 } evtchns[MAX_EVTCHN];
42 /*
43 * This lock protects updates to the following mapping and reference-count
44 * arrays. The lock does not need to be acquired to read the mapping tables.
45 */
46 static spinlock_t irq_mapping_update_lock;
48 #define unbound_irq(e) (VALID_EVTCHN(e) && (!evtchns[(e)].opened))
49 int bind_virq_to_irqhandler(
50 unsigned int virq,
51 unsigned int cpu,
52 irqreturn_t (*handler)(int, void *, struct pt_regs *),
53 unsigned long irqflags,
54 const char *devname,
55 void *dev_id)
56 {
57 evtchn_op_t op;
58 int evtchn;
60 spin_lock(&irq_mapping_update_lock);
62 op.cmd = EVTCHNOP_bind_virq;
63 op.u.bind_virq.virq = virq;
64 op.u.bind_virq.vcpu = cpu;
65 BUG_ON(HYPERVISOR_event_channel_op(&op) != 0 );
66 evtchn = op.u.bind_virq.port;
68 if (!unbound_irq(evtchn))
69 return -EINVAL;
71 evtchns[evtchn].handler = handler;
72 evtchns[evtchn].dev_id = dev_id;
73 evtchns[evtchn].opened = 1;
74 irq_info[evtchn] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
76 unmask_evtchn(evtchn);
77 spin_unlock(&irq_mapping_update_lock);
78 return evtchn;
79 }
81 int bind_evtchn_to_irqhandler(unsigned int evtchn,
82 irqreturn_t (*handler)(int, void *, struct pt_regs *),
83 unsigned long irqflags, const char * devname, void *dev_id)
84 {
85 spin_lock(&irq_mapping_update_lock);
87 if (!unbound_irq(evtchn))
88 return -EINVAL;
90 evtchns[evtchn].handler = handler;
91 evtchns[evtchn].dev_id = dev_id;
92 evtchns[evtchn].opened = 1;
93 irq_info[evtchn] = mk_irq_info(IRQT_EVTCHN, 0, evtchn);
95 unmask_evtchn(evtchn);
96 spin_unlock(&irq_mapping_update_lock);
97 return evtchn;
98 }
100 int bind_ipi_to_irqhandler(
101 unsigned int ipi,
102 unsigned int cpu,
103 irqreturn_t (*handler)(int, void *, struct pt_regs *),
104 unsigned long irqflags,
105 const char *devname,
106 void *dev_id)
107 {
108 printk("%s is called which has not been supported now...?\n", __FUNCTION__);
109 while(1);
110 }
112 void unbind_from_irqhandler(unsigned int irq, void *dev_id)
113 {
114 evtchn_op_t op;
115 int evtchn = evtchn_from_irq(irq);
117 spin_lock(&irq_mapping_update_lock);
119 if (unbound_irq(irq))
120 return;
122 op.cmd = EVTCHNOP_close;
123 op.u.close.port = evtchn;
124 BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
126 switch (type_from_irq(irq)) {
127 case IRQT_VIRQ:
128 /* Add smp stuff later... */
129 break;
130 case IRQT_IPI:
131 /* Add smp stuff later... */
132 break;
133 default:
134 break;
135 }
137 mask_evtchn(evtchn);
138 evtchns[evtchn].handler = NULL;
139 evtchns[evtchn].opened = 0;
141 spin_unlock(&irq_mapping_update_lock);
142 }
144 void notify_remote_via_irq(int irq)
145 {
146 int evtchn = evtchn_from_irq(irq);
148 if (!unbound_irq(evtchn))
149 notify_remote_via_evtchn(evtchn);
150 }
152 irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
153 {
154 unsigned long l1, l2;
155 unsigned int l1i, l2i, port;
156 irqreturn_t (*handler)(int, void *, struct pt_regs *);
157 shared_info_t *s = HYPERVISOR_shared_info;
158 vcpu_info_t *vcpu_info = &s->vcpu_data[smp_processor_id()];
160 vcpu_info->evtchn_upcall_mask = 1;
161 vcpu_info->evtchn_upcall_pending = 0;
163 /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
164 l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
165 while ( l1 != 0 )
166 {
167 l1i = __ffs(l1);
168 l1 &= ~(1UL << l1i);
170 while ( (l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i]) != 0 )
171 {
172 l2i = __ffs(l2);
173 l2 &= ~(1UL << l2i);
175 port = (l1i * BITS_PER_LONG) + l2i;
176 if ( (handler = evtchns[port].handler) != NULL )
177 {
178 clear_evtchn(port);
179 handler(port, evtchns[port].dev_id, regs);
180 }
181 else
182 {
183 evtchn_device_upcall(port);
184 }
185 }
186 }
187 vcpu_info->evtchn_upcall_mask = 0;
188 return IRQ_HANDLED;
189 }
191 void force_evtchn_callback(void)
192 {
193 //(void)HYPERVISOR_xen_version(0, NULL);
194 }
196 static struct irqaction evtchn_irqaction = {
197 .handler = evtchn_interrupt,
198 .flags = SA_INTERRUPT,
199 .name = "xen-event-channel"
200 };
202 int evtchn_irq = 0xe9;
203 void __init evtchn_init(void)
204 {
205 shared_info_t *s = HYPERVISOR_shared_info;
206 vcpu_info_t *vcpu_info = &s->vcpu_data[smp_processor_id()];
208 #if 0
209 int ret;
210 irq = assign_irq_vector(AUTO_ASSIGN);
211 ret = request_irq(irq, evtchn_interrupt, 0, "xen-event-channel", NULL);
212 if (ret < 0)
213 {
214 printk("xen-event-channel unable to get irq %d (%d)\n", irq, ret);
215 return;
216 }
217 #endif
218 register_percpu_irq(evtchn_irq, &evtchn_irqaction);
220 vcpu_info->arch.evtchn_vector = evtchn_irq;
221 printk("xen-event-channel using irq %d\n", evtchn_irq);
223 spin_lock_init(&irq_mapping_update_lock);
224 memset(evtchns, 0, sizeof(evtchns));
225 }