aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2013-04-15 17:23:21 -0400
committerAlexander Graf <agraf@suse.de>2013-04-26 14:27:18 -0400
commite8cde0939d8ebe9c8ebe5a4bdf71af51a0d56053 (patch)
tree94d17c8818957e916cba928103a6a8bcdb4d6d6d /virt
parent1c9f8520bda73c07fed9bcdb307854b45a3a60c4 (diff)
KVM: Move irq routing setup to irqchip.c
Setting up IRQ routes is nothing IOAPIC specific. Extract everything that really is generic code into irqchip.c and only leave the ioapic specific bits to irq_comm.c. Signed-off-by: Alexander Graf <agraf@suse.de> Acked-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/irq_comm.c76
-rw-r--r--virt/kvm/irqchip.c85
2 files changed, 88 insertions, 73 deletions
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index d5008f4aade7..e2e6b4473a96 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -271,27 +271,14 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
271 rcu_read_unlock(); 271 rcu_read_unlock();
272} 272}
273 273
274static int setup_routing_entry(struct kvm_irq_routing_table *rt, 274int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
275 struct kvm_kernel_irq_routing_entry *e, 275 struct kvm_kernel_irq_routing_entry *e,
276 const struct kvm_irq_routing_entry *ue) 276 const struct kvm_irq_routing_entry *ue)
277{ 277{
278 int r = -EINVAL; 278 int r = -EINVAL;
279 int delta; 279 int delta;
280 unsigned max_pin; 280 unsigned max_pin;
281 struct kvm_kernel_irq_routing_entry *ei;
282 281
283 /*
284 * Do not allow GSI to be mapped to the same irqchip more than once.
285 * Allow only one to one mapping between GSI and MSI.
286 */
287 hlist_for_each_entry(ei, &rt->map[ue->gsi], link)
288 if (ei->type == KVM_IRQ_ROUTING_MSI ||
289 ue->type == KVM_IRQ_ROUTING_MSI ||
290 ue->u.irqchip.irqchip == ei->irqchip.irqchip)
291 return r;
292
293 e->gsi = ue->gsi;
294 e->type = ue->type;
295 switch (ue->type) { 282 switch (ue->type) {
296 case KVM_IRQ_ROUTING_IRQCHIP: 283 case KVM_IRQ_ROUTING_IRQCHIP:
297 delta = 0; 284 delta = 0;
@@ -328,68 +315,11 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt,
328 goto out; 315 goto out;
329 } 316 }
330 317
331 hlist_add_head(&e->link, &rt->map[e->gsi]);
332 r = 0; 318 r = 0;
333out: 319out:
334 return r; 320 return r;
335} 321}
336 322
337int kvm_set_irq_routing(struct kvm *kvm,
338 const struct kvm_irq_routing_entry *ue,
339 unsigned nr,
340 unsigned flags)
341{
342 struct kvm_irq_routing_table *new, *old;
343 u32 i, j, nr_rt_entries = 0;
344 int r;
345
346 for (i = 0; i < nr; ++i) {
347 if (ue[i].gsi >= KVM_MAX_IRQ_ROUTES)
348 return -EINVAL;
349 nr_rt_entries = max(nr_rt_entries, ue[i].gsi);
350 }
351
352 nr_rt_entries += 1;
353
354 new = kzalloc(sizeof(*new) + (nr_rt_entries * sizeof(struct hlist_head))
355 + (nr * sizeof(struct kvm_kernel_irq_routing_entry)),
356 GFP_KERNEL);
357
358 if (!new)
359 return -ENOMEM;
360
361 new->rt_entries = (void *)&new->map[nr_rt_entries];
362
363 new->nr_rt_entries = nr_rt_entries;
364 for (i = 0; i < 3; i++)
365 for (j = 0; j < KVM_IRQCHIP_NUM_PINS; j++)
366 new->chip[i][j] = -1;
367
368 for (i = 0; i < nr; ++i) {
369 r = -EINVAL;
370 if (ue->flags)
371 goto out;
372 r = setup_routing_entry(new, &new->rt_entries[i], ue);
373 if (r)
374 goto out;
375 ++ue;
376 }
377
378 mutex_lock(&kvm->irq_lock);
379 old = kvm->irq_routing;
380 kvm_irq_routing_update(kvm, new);
381 mutex_unlock(&kvm->irq_lock);
382
383 synchronize_rcu();
384
385 new = old;
386 r = 0;
387
388out:
389 kfree(new);
390 return r;
391}
392
393#define IOAPIC_ROUTING_ENTRY(irq) \ 323#define IOAPIC_ROUTING_ENTRY(irq) \
394 { .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP, \ 324 { .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP, \
395 .u.irqchip.irqchip = KVM_IRQCHIP_IOAPIC, .u.irqchip.pin = (irq) } 325 .u.irqchip.irqchip = KVM_IRQCHIP_IOAPIC, .u.irqchip.pin = (irq) }
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index 12f7f26af4f8..20dc9e4a8f6c 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -150,3 +150,88 @@ void kvm_free_irq_routing(struct kvm *kvm)
150 at this stage */ 150 at this stage */
151 kfree(kvm->irq_routing); 151 kfree(kvm->irq_routing);
152} 152}
153
154static int setup_routing_entry(struct kvm_irq_routing_table *rt,
155 struct kvm_kernel_irq_routing_entry *e,
156 const struct kvm_irq_routing_entry *ue)
157{
158 int r = -EINVAL;
159 struct kvm_kernel_irq_routing_entry *ei;
160
161 /*
162 * Do not allow GSI to be mapped to the same irqchip more than once.
163 * Allow only one to one mapping between GSI and MSI.
164 */
165 hlist_for_each_entry(ei, &rt->map[ue->gsi], link)
166 if (ei->type == KVM_IRQ_ROUTING_MSI ||
167 ue->type == KVM_IRQ_ROUTING_MSI ||
168 ue->u.irqchip.irqchip == ei->irqchip.irqchip)
169 return r;
170
171 e->gsi = ue->gsi;
172 e->type = ue->type;
173 r = kvm_set_routing_entry(rt, e, ue);
174 if (r)
175 goto out;
176
177 hlist_add_head(&e->link, &rt->map[e->gsi]);
178 r = 0;
179out:
180 return r;
181}
182
183int kvm_set_irq_routing(struct kvm *kvm,
184 const struct kvm_irq_routing_entry *ue,
185 unsigned nr,
186 unsigned flags)
187{
188 struct kvm_irq_routing_table *new, *old;
189 u32 i, j, nr_rt_entries = 0;
190 int r;
191
192 for (i = 0; i < nr; ++i) {
193 if (ue[i].gsi >= KVM_MAX_IRQ_ROUTES)
194 return -EINVAL;
195 nr_rt_entries = max(nr_rt_entries, ue[i].gsi);
196 }
197
198 nr_rt_entries += 1;
199
200 new = kzalloc(sizeof(*new) + (nr_rt_entries * sizeof(struct hlist_head))
201 + (nr * sizeof(struct kvm_kernel_irq_routing_entry)),
202 GFP_KERNEL);
203
204 if (!new)
205 return -ENOMEM;
206
207 new->rt_entries = (void *)&new->map[nr_rt_entries];
208
209 new->nr_rt_entries = nr_rt_entries;
210 for (i = 0; i < KVM_NR_IRQCHIPS; i++)
211 for (j = 0; j < KVM_IRQCHIP_NUM_PINS; j++)
212 new->chip[i][j] = -1;
213
214 for (i = 0; i < nr; ++i) {
215 r = -EINVAL;
216 if (ue->flags)
217 goto out;
218 r = setup_routing_entry(new, &new->rt_entries[i], ue);
219 if (r)
220 goto out;
221 ++ue;
222 }
223
224 mutex_lock(&kvm->irq_lock);
225 old = kvm->irq_routing;
226 kvm_irq_routing_update(kvm, new);
227 mutex_unlock(&kvm->irq_lock);
228
229 synchronize_rcu();
230
231 new = old;
232 r = 0;
233
234out:
235 kfree(new);
236 return r;
237}