direct-io.hg

view linux-2.6-xen-sparse/arch/ia64/xen/drivers/evtchn_ia64.c @ 7530:813e504dc716

Necessary change to make ia64 dom0 rework:
- All even channels on xen/ia64 shares one common interrupt vector
- xen_start_info is initialized only after xen_init, so adjust
sequence to avoid access before initialization

Signed-off-by Kevin Tian <kevin.tian@intel.com>
author djm@kirby.fc.hp.com
date Mon Oct 24 09:15:53 2005 -0600 (2005-10-24)
parents ba9706473941
children 4ef1a7322bf4
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 256
11 #define VALID_EVTCHN(_chn) ((_chn) >= 0)
13 static struct {
14 irqreturn_t (*handler)(int, void *, struct pt_regs *);
15 void *dev_id;
16 } evtchns[MAX_EVTCHN];
18 int virq_to_evtchn[NR_VIRQS] = {-1};
19 unsigned int bind_virq_to_evtchn(int virq)
20 {
21 evtchn_op_t op;
23 op.cmd = EVTCHNOP_bind_virq;
24 op.u.bind_virq.virq = virq;
25 if ( HYPERVISOR_event_channel_op(&op) != 0 )
26 BUG();
28 virq_to_evtchn[virq] = op.u.bind_virq.port;
29 return op.u.bind_virq.port;
30 }
32 int bind_virq_to_irq(int virq, int cpu)
33 {
34 printk("bind_virq_to_irq called... FIXME??\n");
35 while(1);
36 }
38 #if 0
39 void notify_remote_via_irq(int virq)
40 {
41 printk("notify_remote_via_irq called... FIXME??\n");
42 while(1);
43 }
44 #endif
46 void unbind_virq_from_evtchn(int virq)
47 {
48 evtchn_op_t op;
50 op.cmd = EVTCHNOP_close;
51 // op.u.close.dom = DOMID_SELF;
52 op.u.close.port = virq_to_evtchn[virq];
53 if ( HYPERVISOR_event_channel_op(&op) != 0 )
54 BUG();
56 virq_to_evtchn[virq] = -1;
57 }
59 int bind_evtchn_to_irqhandler(unsigned int evtchn,
60 irqreturn_t (*handler)(int, void *, struct pt_regs *),
61 unsigned long irqflags, const char * devname, void *dev_id)
62 {
63 if (evtchn >= MAX_EVTCHN)
64 return -EINVAL;
66 evtchns[evtchn].handler = handler;
67 evtchns[evtchn].dev_id = dev_id;
68 unmask_evtchn(evtchn);
69 //return 0;
70 /* On ia64, there's only one irq vector allocated for all event channels,
71 * so let's just return evtchn as handle for later communication
72 */
73 return evtchn;
74 }
76 void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id)
77 {
78 if (evtchn >= MAX_EVTCHN)
79 return;
81 mask_evtchn(evtchn);
82 evtchns[evtchn].handler = NULL;
83 }
85 void unbind_evtchn_from_irq(unsigned int evtchn)
86 {
87 printk("unbind_evtchn_from_irq called... FIXME??\n");
88 while(1);
89 }
91 void notify_remote_via_irq(int irq)
92 {
93 int evtchn = virq_to_evtchn[irq]; // FIXME... is this right??
95 if (VALID_EVTCHN(evtchn))
96 notify_remote_via_evtchn(evtchn);
97 }
99 irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
100 {
101 unsigned long l1, l2;
102 unsigned int l1i, l2i, port;
103 irqreturn_t (*handler)(int, void *, struct pt_regs *);
104 shared_info_t *s = HYPERVISOR_shared_info;
105 vcpu_info_t *vcpu_info = &s->vcpu_data[smp_processor_id()];
107 vcpu_info->evtchn_upcall_mask = 1;
108 vcpu_info->evtchn_upcall_pending = 0;
110 /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
111 l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
112 while ( l1 != 0 )
113 {
114 l1i = __ffs(l1);
115 l1 &= ~(1UL << l1i);
117 while ( (l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i]) != 0 )
118 {
119 l2i = __ffs(l2);
120 l2 &= ~(1UL << l2i);
122 port = (l1i * BITS_PER_LONG) + l2i;
123 if ( (handler = evtchns[port].handler) != NULL )
124 {
125 clear_evtchn(port);
126 handler(port, evtchns[port].dev_id, regs);
127 }
128 else
129 {
130 evtchn_device_upcall(port);
131 }
132 }
133 }
134 vcpu_info->evtchn_upcall_mask = 0;
135 return IRQ_HANDLED;
136 }
138 void force_evtchn_callback(void)
139 {
140 //(void)HYPERVISOR_xen_version(0, NULL);
141 }
143 static struct irqaction evtchn_irqaction = {
144 .handler = evtchn_interrupt,
145 .flags = SA_INTERRUPT,
146 .name = "xen-event-channel"
147 };
149 int evtchn_irq = 0xe9;
150 void __init evtchn_init(void)
151 {
152 shared_info_t *s = HYPERVISOR_shared_info;
153 vcpu_info_t *vcpu_info = &s->vcpu_data[smp_processor_id()];
155 #if 0
156 int ret;
157 irq = assign_irq_vector(AUTO_ASSIGN);
158 ret = request_irq(irq, evtchn_interrupt, 0, "xen-event-channel", NULL);
159 if (ret < 0)
160 {
161 printk("xen-event-channel unable to get irq %d (%d)\n", irq, ret);
162 return;
163 }
164 #endif
165 register_percpu_irq(evtchn_irq, &evtchn_irqaction);
167 vcpu_info->arch.evtchn_vector = evtchn_irq;
168 printk("xen-event-channel using irq %d\n", evtchn_irq);
169 }
171 /* Following are set of interfaces unused on IA64/XEN, just keep it here */
173 void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) {}
174 int teardown_irq(unsigned int irq, struct irqaction * old) {return 0;}