ia64/linux-2.6.18-xen.hg

view drivers/pci/msi-xen.c @ 661:7886619f623e

linux/pci-msi: translate Xen-provided PIRQs (take 2)

Previously, the kernel depended upon Xen's NR_IRQS to be no larger
than the kernel's NR_PIRQS.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Sep 08 13:13:35 2008 +0100 (2008-09-08)
parents ad374a7a9f3e
children 583086d5cd26
line source
1 /*
2 * File: msi.c
3 * Purpose: PCI Message Signaled Interrupt (MSI)
4 *
5 * Copyright (C) 2003-2004 Intel
6 * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
7 */
9 #include <linux/mm.h>
10 #include <linux/irq.h>
11 #include <linux/interrupt.h>
12 #include <linux/init.h>
13 #include <linux/ioport.h>
14 #include <linux/smp_lock.h>
15 #include <linux/pci.h>
16 #include <linux/proc_fs.h>
18 #include <xen/evtchn.h>
20 #include <asm/errno.h>
21 #include <asm/io.h>
22 #include <asm/smp.h>
24 #include "pci.h"
25 #include "msi.h"
27 static int pci_msi_enable = 1;
29 static struct msi_ops *msi_ops;
31 int msi_register(struct msi_ops *ops)
32 {
33 msi_ops = ops;
34 return 0;
35 }
37 static LIST_HEAD(msi_dev_head);
38 DEFINE_SPINLOCK(msi_dev_lock);
40 struct msi_dev_list {
41 struct pci_dev *dev;
42 struct list_head list;
43 spinlock_t pirq_list_lock;
44 struct list_head pirq_list_head;
45 };
47 struct msi_pirq_entry {
48 struct list_head list;
49 int pirq;
50 int entry_nr;
51 };
53 static struct msi_dev_list *get_msi_dev_pirq_list(struct pci_dev *dev)
54 {
55 struct msi_dev_list *msi_dev_list, *ret = NULL;
56 unsigned long flags;
58 spin_lock_irqsave(&msi_dev_lock, flags);
60 list_for_each_entry(msi_dev_list, &msi_dev_head, list)
61 if ( msi_dev_list->dev == dev )
62 ret = msi_dev_list;
64 if ( ret ) {
65 spin_unlock_irqrestore(&msi_dev_lock, flags);
66 return ret;
67 }
69 /* Has not allocate msi_dev until now. */
70 ret = kmalloc(sizeof(struct msi_dev_list), GFP_ATOMIC);
72 /* Failed to allocate msi_dev structure */
73 if ( !ret ) {
74 spin_unlock_irqrestore(&msi_dev_lock, flags);
75 return NULL;
76 }
78 spin_lock_init(&ret->pirq_list_lock);
79 INIT_LIST_HEAD(&ret->pirq_list_head);
80 list_add_tail(&ret->list, &msi_dev_head);
81 spin_unlock_irqrestore(&msi_dev_lock, flags);
82 return ret;
83 }
85 static int attach_pirq_entry(int pirq, int entry_nr,
86 struct msi_dev_list *msi_dev_entry)
87 {
88 struct msi_pirq_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
89 unsigned long flags;
91 if (!entry)
92 return -ENOMEM;
93 entry->pirq = pirq;
94 entry->entry_nr = entry_nr;
95 spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
96 list_add_tail(&entry->list, &msi_dev_entry->pirq_list_head);
97 spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
98 return 0;
99 }
101 static void detach_pirq_entry(int entry_nr,
102 struct msi_dev_list *msi_dev_entry)
103 {
104 unsigned long flags;
105 struct msi_pirq_entry *pirq_entry;
107 list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
108 if (pirq_entry->entry_nr == entry_nr) {
109 spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
110 list_del(&pirq_entry->list);
111 spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
112 kfree(pirq_entry);
113 return;
114 }
115 }
116 }
118 /*
119 * pciback will provide device's owner
120 */
121 static int (*get_owner)(struct pci_dev *dev);
123 int register_msi_get_owner(int (*func)(struct pci_dev *dev))
124 {
125 if (get_owner) {
126 printk(KERN_WARNING "register msi_get_owner again\n");
127 return -EEXIST;
128 }
129 get_owner = func;
130 return 0;
131 }
133 int unregister_msi_get_owner(int (*func)(struct pci_dev *dev))
134 {
135 if (get_owner != func)
136 return -EINVAL;
137 get_owner = NULL;
138 return 0;
139 }
141 static int msi_get_dev_owner(struct pci_dev *dev)
142 {
143 int owner;
145 BUG_ON(!is_initial_xendomain());
146 if (get_owner && (owner = get_owner(dev)) >= 0) {
147 printk(KERN_INFO "get owner for dev %x get %x \n",
148 dev->devfn, owner);
149 return owner;
150 }
152 return DOMID_SELF;
153 }
155 static int msi_unmap_pirq(struct pci_dev *dev, int pirq)
156 {
157 struct physdev_unmap_pirq unmap;
158 int rc;
160 unmap.domid = msi_get_dev_owner(dev);
161 unmap.pirq = evtchn_get_xen_pirq(pirq);
163 if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap)))
164 printk(KERN_WARNING "unmap irq %x failed\n", pirq);
166 if (rc < 0)
167 return rc;
169 evtchn_map_pirq(pirq, 0);
170 return 0;
171 }
173 static u64 find_table_base(struct pci_dev *dev, int pos)
174 {
175 u8 bar;
176 u32 reg;
177 unsigned long flags;
179 pci_read_config_dword(dev, msix_table_offset_reg(pos), &reg);
180 bar = reg & PCI_MSIX_FLAGS_BIRMASK;
182 flags = pci_resource_flags(dev, bar);
183 if (flags & (IORESOURCE_DISABLED | IORESOURCE_UNSET | IORESOURCE_BUSY))
184 return 0;
186 return pci_resource_start(dev, bar);
187 }
189 /*
190 * Protected by msi_lock
191 */
192 static int msi_map_pirq_to_vector(struct pci_dev *dev, int pirq,
193 int entry_nr, u64 table_base)
194 {
195 struct physdev_map_pirq map_irq;
196 int rc;
197 domid_t domid = DOMID_SELF;
199 domid = msi_get_dev_owner(dev);
201 map_irq.domid = domid;
202 map_irq.type = MAP_PIRQ_TYPE_MSI;
203 map_irq.index = -1;
204 map_irq.pirq = pirq < 0 ? -1 : evtchn_get_xen_pirq(pirq);
205 map_irq.bus = dev->bus->number;
206 map_irq.devfn = dev->devfn;
207 map_irq.entry_nr = entry_nr;
208 map_irq.table_base = table_base;
210 if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq)))
211 printk(KERN_WARNING "map irq failed\n");
213 if (rc < 0)
214 return rc;
215 /* This happens when MSI support is not enabled in Xen. */
216 if (rc == 0 && map_irq.pirq < 0)
217 return -ENOSYS;
219 BUG_ON(map_irq.pirq <= 0);
220 return evtchn_map_pirq(pirq, map_irq.pirq);
221 }
223 static int msi_map_vector(struct pci_dev *dev, int entry_nr, u64 table_base)
224 {
225 return msi_map_pirq_to_vector(dev, -1, entry_nr, table_base);
226 }
228 static int msi_init(void)
229 {
230 static int status = 0;
232 if (pci_msi_quirk) {
233 pci_msi_enable = 0;
234 printk(KERN_WARNING "PCI: MSI quirk detected. MSI disabled.\n");
235 status = -EINVAL;
236 }
238 return status;
239 }
241 void pci_scan_msi_device(struct pci_dev *dev) { }
243 void disable_msi_mode(struct pci_dev *dev, int pos, int type)
244 {
245 u16 control;
247 pci_read_config_word(dev, msi_control_reg(pos), &control);
248 if (type == PCI_CAP_ID_MSI) {
249 /* Set enabled bits to single MSI & enable MSI_enable bit */
250 msi_disable(control);
251 pci_write_config_word(dev, msi_control_reg(pos), control);
252 dev->msi_enabled = 0;
253 } else {
254 msix_disable(control);
255 pci_write_config_word(dev, msi_control_reg(pos), control);
256 dev->msix_enabled = 0;
257 }
258 if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
259 /* PCI Express Endpoint device detected */
260 pci_intx(dev, 1); /* enable intx */
261 }
262 }
264 static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
265 {
266 u16 control;
268 pci_read_config_word(dev, msi_control_reg(pos), &control);
269 if (type == PCI_CAP_ID_MSI) {
270 /* Set enabled bits to single MSI & enable MSI_enable bit */
271 msi_enable(control, 1);
272 pci_write_config_word(dev, msi_control_reg(pos), control);
273 dev->msi_enabled = 1;
274 } else {
275 msix_enable(control);
276 pci_write_config_word(dev, msi_control_reg(pos), control);
277 dev->msix_enabled = 1;
278 }
279 if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
280 /* PCI Express Endpoint device detected */
281 pci_intx(dev, 0); /* disable intx */
282 }
283 }
285 #ifdef CONFIG_PM
286 int pci_save_msi_state(struct pci_dev *dev)
287 {
288 int pos;
290 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
291 if (pos <= 0 || dev->no_msi)
292 return 0;
294 if (!dev->msi_enabled)
295 return 0;
297 /* Restore dev->irq to its default pin-assertion vector */
298 msi_unmap_pirq(dev, dev->irq);
299 /* Disable MSI mode */
300 disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
301 /* Set the flags for use of restore */
302 dev->msi_enabled = 1;
303 return 0;
304 }
306 void pci_restore_msi_state(struct pci_dev *dev)
307 {
308 int pos, pirq;
310 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
311 if (pos <= 0)
312 return;
314 if (!dev->msi_enabled)
315 return;
317 pirq = msi_map_pirq_to_vector(dev, dev->irq, 0, 0);
318 if (pirq < 0)
319 return;
320 enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
321 }
323 int pci_save_msix_state(struct pci_dev *dev)
324 {
325 int pos;
326 unsigned long flags;
327 struct msi_dev_list *msi_dev_entry;
328 struct msi_pirq_entry *pirq_entry, *tmp;
330 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
331 if (pos <= 0 || dev->no_msi)
332 return 0;
334 /* save the capability */
335 if (!dev->msix_enabled)
336 return 0;
338 msi_dev_entry = get_msi_dev_pirq_list(dev);
340 spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
341 list_for_each_entry_safe(pirq_entry, tmp,
342 &msi_dev_entry->pirq_list_head, list)
343 msi_unmap_pirq(dev, pirq_entry->pirq);
344 spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
346 disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
347 /* Set the flags for use of restore */
348 dev->msix_enabled = 1;
350 return 0;
351 }
353 void pci_restore_msix_state(struct pci_dev *dev)
354 {
355 int pos;
356 unsigned long flags;
357 u64 table_base;
358 struct msi_dev_list *msi_dev_entry;
359 struct msi_pirq_entry *pirq_entry, *tmp;
361 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
362 if (pos <= 0)
363 return;
365 if (!dev->msix_enabled)
366 return;
368 msi_dev_entry = get_msi_dev_pirq_list(dev);
369 table_base = find_table_base(dev, pos);
370 if (!table_base)
371 return;
373 spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
374 list_for_each_entry_safe(pirq_entry, tmp,
375 &msi_dev_entry->pirq_list_head, list) {
376 int rc = msi_map_pirq_to_vector(dev, pirq_entry->pirq,
377 pirq_entry->entry_nr, table_base);
378 if (rc < 0)
379 printk(KERN_WARNING
380 "%s: re-mapping irq #%d (pirq%d) failed: %d\n",
381 pci_name(dev), pirq_entry->entry_nr,
382 pirq_entry->pirq, rc);
383 }
384 spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
386 enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
387 }
388 #endif
390 /**
391 * msi_capability_init - configure device's MSI capability structure
392 * @dev: pointer to the pci_dev data structure of MSI device function
393 *
394 * Setup the MSI capability structure of device function with a single
395 * MSI vector, regardless of device function is capable of handling
396 * multiple messages. A return of zero indicates the successful setup
397 * of an entry zero with the new MSI vector or non-zero for otherwise.
398 **/
399 static int msi_capability_init(struct pci_dev *dev)
400 {
401 int pos, pirq;
402 u16 control;
404 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
405 pci_read_config_word(dev, msi_control_reg(pos), &control);
407 pirq = msi_map_vector(dev, 0, 0);
408 if (pirq < 0)
409 return -EBUSY;
411 dev->irq = pirq;
412 /* Set MSI enabled bits */
413 enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
414 dev->msi_enabled = 1;
416 return 0;
417 }
419 /**
420 * msix_capability_init - configure device's MSI-X capability
421 * @dev: pointer to the pci_dev data structure of MSI-X device function
422 * @entries: pointer to an array of struct msix_entry entries
423 * @nvec: number of @entries
424 *
425 * Setup the MSI-X capability structure of device function with a
426 * single MSI-X vector. A return of zero indicates the successful setup of
427 * requested MSI-X entries with allocated vectors or non-zero for otherwise.
428 **/
429 static int msix_capability_init(struct pci_dev *dev,
430 struct msix_entry *entries, int nvec)
431 {
432 u64 table_base;
433 int pirq, i, j, mapped, pos;
434 struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
435 struct msi_pirq_entry *pirq_entry;
437 if (!msi_dev_entry)
438 return -ENOMEM;
440 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
441 table_base = find_table_base(dev, pos);
442 if (!table_base)
443 return -ENODEV;
445 /* MSI-X Table Initialization */
446 for (i = 0; i < nvec; i++) {
447 mapped = 0;
448 list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
449 if (pirq_entry->entry_nr == entries[i].entry) {
450 printk(KERN_WARNING "msix entry %d for dev %02x:%02x:%01x are \
451 not freed before acquire again.\n", entries[i].entry,
452 dev->bus->number, PCI_SLOT(dev->devfn),
453 PCI_FUNC(dev->devfn));
454 (entries + i)->vector = pirq_entry->pirq;
455 mapped = 1;
456 break;
457 }
458 }
459 if (mapped)
460 continue;
461 pirq = msi_map_vector(dev, entries[i].entry, table_base);
462 if (pirq < 0)
463 break;
464 attach_pirq_entry(pirq, entries[i].entry, msi_dev_entry);
465 (entries + i)->vector = pirq;
466 }
468 if (i != nvec) {
469 for (j = --i; j >= 0; j--) {
470 msi_unmap_pirq(dev, entries[j].vector);
471 detach_pirq_entry(entries[j].entry, msi_dev_entry);
472 entries[j].vector = 0;
473 }
474 return -EBUSY;
475 }
477 enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
478 dev->msix_enabled = 1;
480 return 0;
481 }
483 /**
484 * pci_enable_msi - configure device's MSI capability structure
485 * @dev: pointer to the pci_dev data structure of MSI device function
486 *
487 * Setup the MSI capability structure of device function with
488 * a single MSI vector upon its software driver call to request for
489 * MSI mode enabled on its hardware device function. A return of zero
490 * indicates the successful setup of an entry zero with the new MSI
491 * vector or non-zero for otherwise.
492 **/
493 extern int pci_frontend_enable_msi(struct pci_dev *dev);
494 int pci_enable_msi(struct pci_dev* dev)
495 {
496 struct pci_bus *bus;
497 int pos, temp, status = -EINVAL;
499 if (!pci_msi_enable || !dev)
500 return status;
502 if (dev->no_msi)
503 return status;
505 for (bus = dev->bus; bus; bus = bus->parent)
506 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
507 return -EINVAL;
509 status = msi_init();
510 if (status < 0)
511 return status;
513 #ifdef CONFIG_XEN_PCIDEV_FRONTEND
514 if (!is_initial_xendomain())
515 {
516 int ret;
518 temp = dev->irq;
519 ret = pci_frontend_enable_msi(dev);
520 if (ret)
521 return ret;
523 dev->irq_old = temp;
525 return ret;
526 }
527 #endif
529 temp = dev->irq;
531 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
532 if (!pos)
533 return -EINVAL;
535 /* Check whether driver already requested for MSI-X vectors */
536 if (dev->msix_enabled) {
537 printk(KERN_INFO "PCI: %s: Can't enable MSI. "
538 "Device already has MSI-X vectors assigned\n",
539 pci_name(dev));
540 dev->irq = temp;
541 return -EINVAL;
542 }
544 status = msi_capability_init(dev);
545 if ( !status )
546 dev->irq_old = temp;
547 else
548 dev->irq = temp;
550 return status;
551 }
553 extern void pci_frontend_disable_msi(struct pci_dev* dev);
554 void pci_disable_msi(struct pci_dev* dev)
555 {
556 int pos;
557 int pirq;
559 if (!pci_msi_enable)
560 return;
561 if (!dev)
562 return;
564 #ifdef CONFIG_XEN_PCIDEV_FRONTEND
565 if (!is_initial_xendomain()) {
566 pci_frontend_disable_msi(dev);
567 dev->irq = dev->irq_old;
568 return;
569 }
570 #endif
572 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
573 if (!pos)
574 return;
576 pirq = dev->irq;
577 /* Restore dev->irq to its default pin-assertion vector */
578 dev->irq = dev->irq_old;
579 msi_unmap_pirq(dev, pirq);
581 /* Disable MSI mode */
582 disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
583 }
585 /**
586 * pci_enable_msix - configure device's MSI-X capability structure
587 * @dev: pointer to the pci_dev data structure of MSI-X device function
588 * @entries: pointer to an array of MSI-X entries
589 * @nvec: number of MSI-X vectors requested for allocation by device driver
590 *
591 * Setup the MSI-X capability structure of device function with the number
592 * of requested vectors upon its software driver call to request for
593 * MSI-X mode enabled on its hardware device function. A return of zero
594 * indicates the successful configuration of MSI-X capability structure
595 * with new allocated MSI-X vectors. A return of < 0 indicates a failure.
596 * Or a return of > 0 indicates that driver request is exceeding the number
597 * of vectors available. Driver should use the returned value to re-send
598 * its request.
599 **/
600 extern int pci_frontend_enable_msix(struct pci_dev *dev,
601 struct msix_entry *entries, int nvec);
602 int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
603 {
604 struct pci_bus *bus;
605 int status, pos, nr_entries;
606 int i, j, temp;
607 u16 control;
609 if (!pci_msi_enable || !dev || !entries)
610 return -EINVAL;
612 if (dev->no_msi)
613 return -EINVAL;
615 for (bus = dev->bus; bus; bus = bus->parent)
616 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
617 return -EINVAL;
619 #ifdef CONFIG_XEN_PCIDEV_FRONTEND
620 if (!is_initial_xendomain()) {
621 int ret;
623 ret = pci_frontend_enable_msix(dev, entries, nvec);
624 if (ret) {
625 printk("get %x from pci_frontend_enable_msix\n", ret);
626 return ret;
627 }
629 return 0;
630 }
631 #endif
633 status = msi_init();
634 if (status < 0)
635 return status;
637 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
638 if (!pos)
639 return -EINVAL;
641 pci_read_config_word(dev, msi_control_reg(pos), &control);
642 nr_entries = multi_msix_capable(control);
643 if (nvec > nr_entries)
644 return -EINVAL;
646 /* Check for any invalid entries */
647 for (i = 0; i < nvec; i++) {
648 if (entries[i].entry >= nr_entries)
649 return -EINVAL; /* invalid entry */
650 for (j = i + 1; j < nvec; j++) {
651 if (entries[i].entry == entries[j].entry)
652 return -EINVAL; /* duplicate entry */
653 }
654 }
656 temp = dev->irq;
657 /* Check whether driver already requested for MSI vector */
658 if (dev->msi_enabled) {
659 printk(KERN_INFO "PCI: %s: Can't enable MSI-X. "
660 "Device already has an MSI vector assigned\n",
661 pci_name(dev));
662 dev->irq = temp;
663 return -EINVAL;
664 }
666 status = msix_capability_init(dev, entries, nvec);
668 if ( !status )
669 dev->irq_old = temp;
670 else
671 dev->irq = temp;
673 return status;
674 }
676 extern void pci_frontend_disable_msix(struct pci_dev* dev);
677 void pci_disable_msix(struct pci_dev* dev)
678 {
679 int pos;
680 u16 control;
683 if (!pci_msi_enable)
684 return;
685 if (!dev)
686 return;
688 #ifdef CONFIG_XEN_PCIDEV_FRONTEND
689 if (!is_initial_xendomain()) {
690 pci_frontend_disable_msix(dev);
691 dev->irq = dev->irq_old;
692 return;
693 }
694 #endif
696 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
697 if (!pos)
698 return;
700 pci_read_config_word(dev, msi_control_reg(pos), &control);
701 if (!(control & PCI_MSIX_FLAGS_ENABLE))
702 return;
704 msi_remove_pci_irq_vectors(dev);
706 /* Disable MSI mode */
707 disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
708 }
710 /**
711 * msi_remove_pci_irq_vectors - reclaim MSI(X) vectors to unused state
712 * @dev: pointer to the pci_dev data structure of MSI(X) device function
713 *
714 * Being called during hotplug remove, from which the device function
715 * is hot-removed. All previous assigned MSI/MSI-X vectors, if
716 * allocated for this device function, are reclaimed to unused state,
717 * which may be used later on.
718 **/
719 void msi_remove_pci_irq_vectors(struct pci_dev* dev)
720 {
721 unsigned long flags;
722 struct msi_dev_list *msi_dev_entry;
723 struct msi_pirq_entry *pirq_entry, *tmp;
725 if (!pci_msi_enable || !dev)
726 return;
728 msi_dev_entry = get_msi_dev_pirq_list(dev);
730 spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
731 if (!list_empty(&msi_dev_entry->pirq_list_head))
732 {
733 printk(KERN_WARNING "msix pirqs for dev %02x:%02x:%01x are not freed \
734 before acquire again.\n", dev->bus->number, PCI_SLOT(dev->devfn),
735 PCI_FUNC(dev->devfn));
736 list_for_each_entry_safe(pirq_entry, tmp,
737 &msi_dev_entry->pirq_list_head, list) {
738 msi_unmap_pirq(dev, pirq_entry->pirq);
739 list_del(&pirq_entry->list);
740 kfree(pirq_entry);
741 }
742 }
743 spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
744 dev->irq = dev->irq_old;
745 }
747 void pci_no_msi(void)
748 {
749 pci_msi_enable = 0;
750 }
752 EXPORT_SYMBOL(pci_enable_msi);
753 EXPORT_SYMBOL(pci_disable_msi);
754 EXPORT_SYMBOL(pci_enable_msix);
755 EXPORT_SYMBOL(pci_disable_msix);
756 #ifdef CONFIG_XEN
757 EXPORT_SYMBOL(register_msi_get_owner);
758 EXPORT_SYMBOL(unregister_msi_get_owner);
759 #endif