ia64/xen-unstable

view xen/arch/x86/msi.c @ 19835:edfdeb150f27

Fix buildsystem to detect udev > version 124

udev removed the udevinfo symlink from versions higher than 123 and
xen's build-system could not detect if udev is in place and has the
required version.

Signed-off-by: Marc-A. Dahlhaus <mad@wol.de>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 25 13:02:37 2009 +0100 (2009-06-25)
parents 78962f85c562
children
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 <xen/config.h>
10 #include <xen/lib.h>
11 #include <xen/init.h>
12 #include <xen/irq.h>
13 #include <xen/delay.h>
14 #include <xen/sched.h>
15 #include <xen/acpi.h>
16 #include <xen/errno.h>
17 #include <xen/pci.h>
18 #include <xen/pci_regs.h>
19 #include <xen/keyhandler.h>
20 #include <asm/io.h>
21 #include <asm/smp.h>
22 #include <asm/desc.h>
23 #include <asm/msi.h>
24 #include <asm/fixmap.h>
25 #include <mach_apic.h>
26 #include <io_ports.h>
27 #include <public/physdev.h>
28 #include <xen/iommu.h>
30 /* bitmap indicate which fixed map is free */
31 DEFINE_SPINLOCK(msix_fixmap_lock);
32 DECLARE_BITMAP(msix_fixmap_pages, FIX_MSIX_MAX_PAGES);
34 static int msix_fixmap_alloc(void)
35 {
36 int i, rc = -ENOMEM;
38 spin_lock(&msix_fixmap_lock);
39 for ( i = 0; i < FIX_MSIX_MAX_PAGES; i++ )
40 if ( !test_bit(i, &msix_fixmap_pages) )
41 break;
42 if ( i == FIX_MSIX_MAX_PAGES )
43 goto out;
44 rc = FIX_MSIX_IO_RESERV_BASE + i;
45 set_bit(i, &msix_fixmap_pages);
47 out:
48 spin_unlock(&msix_fixmap_lock);
49 return rc;
50 }
52 static void msix_fixmap_free(int idx)
53 {
54 spin_lock(&msix_fixmap_lock);
55 if ( idx >= FIX_MSIX_IO_RESERV_BASE )
56 clear_bit(idx - FIX_MSIX_IO_RESERV_BASE, &msix_fixmap_pages);
57 spin_unlock(&msix_fixmap_lock);
58 }
60 static int msix_get_fixmap(struct pci_dev *dev, unsigned long table_paddr,
61 unsigned long entry_paddr)
62 {
63 int nr_page, idx;
65 nr_page = (entry_paddr >> PAGE_SHIFT) - (table_paddr >> PAGE_SHIFT);
67 if ( nr_page < 0 || nr_page >= MAX_MSIX_TABLE_PAGES )
68 return -EINVAL;
70 spin_lock(&dev->msix_table_lock);
71 if ( dev->msix_table_refcnt[nr_page]++ == 0 )
72 {
73 idx = msix_fixmap_alloc();
74 if ( idx < 0 )
75 {
76 dev->msix_table_refcnt[nr_page]--;
77 goto out;
78 }
79 set_fixmap_nocache(idx, entry_paddr);
80 dev->msix_table_idx[nr_page] = idx;
81 }
82 else
83 idx = dev->msix_table_idx[nr_page];
85 out:
86 spin_unlock(&dev->msix_table_lock);
87 return idx;
88 }
90 static void msix_put_fixmap(struct pci_dev *dev, int idx)
91 {
92 int i;
93 unsigned long start;
95 spin_lock(&dev->msix_table_lock);
96 for ( i = 0; i < MAX_MSIX_TABLE_PAGES; i++ )
97 {
98 if ( dev->msix_table_idx[i] == idx )
99 break;
100 }
101 if ( i == MAX_MSIX_TABLE_PAGES )
102 goto out;
104 if ( --dev->msix_table_refcnt[i] == 0 )
105 {
106 start = fix_to_virt(idx);
107 destroy_xen_mappings(start, start + PAGE_SIZE);
108 msix_fixmap_free(idx);
109 dev->msix_table_idx[i] = 0;
110 }
112 out:
113 spin_unlock(&dev->msix_table_lock);
114 }
116 /*
117 * MSI message composition
118 */
119 void msi_compose_msg(struct pci_dev *pdev, int vector,
120 struct msi_msg *msg)
121 {
122 unsigned dest;
123 cpumask_t tmp;
125 tmp = TARGET_CPUS;
126 if ( vector )
127 {
128 dest = cpu_mask_to_apicid(tmp);
130 msg->address_hi = MSI_ADDR_BASE_HI;
131 msg->address_lo =
132 MSI_ADDR_BASE_LO |
133 ((INT_DEST_MODE == 0) ?
134 MSI_ADDR_DESTMODE_PHYS:
135 MSI_ADDR_DESTMODE_LOGIC) |
136 ((INT_DELIVERY_MODE != dest_LowestPrio) ?
137 MSI_ADDR_REDIRECTION_CPU:
138 MSI_ADDR_REDIRECTION_LOWPRI) |
139 MSI_ADDR_DEST_ID(dest);
141 msg->data =
142 MSI_DATA_TRIGGER_EDGE |
143 MSI_DATA_LEVEL_ASSERT |
144 ((INT_DELIVERY_MODE != dest_LowestPrio) ?
145 MSI_DATA_DELIVERY_FIXED:
146 MSI_DATA_DELIVERY_LOWPRI) |
147 MSI_DATA_VECTOR(vector);
148 }
149 }
151 static void read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
152 {
153 switch ( entry->msi_attrib.type )
154 {
155 case PCI_CAP_ID_MSI:
156 {
157 struct pci_dev *dev = entry->dev;
158 int pos = entry->msi_attrib.pos;
159 u16 data;
160 u8 bus = dev->bus;
161 u8 slot = PCI_SLOT(dev->devfn);
162 u8 func = PCI_FUNC(dev->devfn);
164 msg->address_lo = pci_conf_read32(bus, slot, func,
165 msi_lower_address_reg(pos));
166 if ( entry->msi_attrib.is_64 )
167 {
168 msg->address_hi = pci_conf_read32(bus, slot, func,
169 msi_upper_address_reg(pos));
170 data = pci_conf_read16(bus, slot, func, msi_data_reg(pos, 1));
171 }
172 else
173 {
174 msg->address_hi = 0;
175 data = pci_conf_read16(bus, slot, func, msi_data_reg(pos, 0));
176 }
177 msg->data = data;
178 break;
179 }
180 case PCI_CAP_ID_MSIX:
181 {
182 void __iomem *base;
183 base = entry->mask_base;
185 msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
186 msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
187 msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET);
188 break;
189 }
190 default:
191 BUG();
192 }
194 if ( iommu_enabled )
195 iommu_read_msi_from_ire(entry, msg);
196 }
198 static int set_vector_msi(struct msi_desc *entry)
199 {
200 if ( entry->vector >= NR_VECTORS )
201 {
202 dprintk(XENLOG_ERR, "Trying to install msi data for Vector %d\n",
203 entry->vector);
204 return -EINVAL;
205 }
207 irq_desc[entry->vector].msi_desc = entry;
208 return 0;
209 }
211 static int unset_vector_msi(int vector)
212 {
213 ASSERT(spin_is_locked(&irq_desc[vector].lock));
215 if ( vector >= NR_VECTORS )
216 {
217 dprintk(XENLOG_ERR, "Trying to uninstall msi data for Vector %d\n",
218 vector);
219 return -EINVAL;
220 }
222 irq_desc[vector].msi_desc = NULL;
224 return 0;
225 }
227 static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
228 {
229 if ( iommu_enabled )
230 iommu_update_ire_from_msi(entry, msg);
232 switch ( entry->msi_attrib.type )
233 {
234 case PCI_CAP_ID_MSI:
235 {
236 struct pci_dev *dev = entry->dev;
237 int pos = entry->msi_attrib.pos;
238 u8 bus = dev->bus;
239 u8 slot = PCI_SLOT(dev->devfn);
240 u8 func = PCI_FUNC(dev->devfn);
242 pci_conf_write32(bus, slot, func, msi_lower_address_reg(pos),
243 msg->address_lo);
244 if ( entry->msi_attrib.is_64 )
245 {
246 pci_conf_write32(bus, slot, func, msi_upper_address_reg(pos),
247 msg->address_hi);
248 pci_conf_write16(bus, slot, func, msi_data_reg(pos, 1),
249 msg->data);
250 }
251 else
252 pci_conf_write16(bus, slot, func, msi_data_reg(pos, 0),
253 msg->data);
254 break;
255 }
256 case PCI_CAP_ID_MSIX:
257 {
258 void __iomem *base;
259 base = entry->mask_base;
261 writel(msg->address_lo,
262 base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
263 writel(msg->address_hi,
264 base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
265 writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET);
266 break;
267 }
268 default:
269 BUG();
270 }
271 entry->msg = *msg;
272 }
274 void set_msi_affinity(unsigned int vector, cpumask_t mask)
275 {
276 struct msi_desc *desc = irq_desc[vector].msi_desc;
277 struct msi_msg msg;
278 unsigned int dest;
280 memset(&msg, 0, sizeof(msg));
281 cpus_and(mask, mask, cpu_online_map);
282 if ( cpus_empty(mask) )
283 mask = TARGET_CPUS;
284 dest = cpu_mask_to_apicid(mask);
286 if ( !desc )
287 return;
289 ASSERT(spin_is_locked(&irq_desc[vector].lock));
290 read_msi_msg(desc, &msg);
292 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
293 msg.address_lo |= MSI_ADDR_DEST_ID(dest);
295 write_msi_msg(desc, &msg);
296 }
298 static void msi_set_enable(struct pci_dev *dev, int enable)
299 {
300 int pos;
301 u16 control;
302 u8 bus = dev->bus;
303 u8 slot = PCI_SLOT(dev->devfn);
304 u8 func = PCI_FUNC(dev->devfn);
306 pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSI);
307 if ( pos )
308 {
309 control = pci_conf_read16(bus, slot, func, pos + PCI_MSI_FLAGS);
310 control &= ~PCI_MSI_FLAGS_ENABLE;
311 if ( enable )
312 control |= PCI_MSI_FLAGS_ENABLE;
313 pci_conf_write16(bus, slot, func, pos + PCI_MSI_FLAGS, control);
314 }
315 }
317 static void msix_set_enable(struct pci_dev *dev, int enable)
318 {
319 int pos;
320 u16 control;
321 u8 bus = dev->bus;
322 u8 slot = PCI_SLOT(dev->devfn);
323 u8 func = PCI_FUNC(dev->devfn);
325 pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSIX);
326 if ( pos )
327 {
328 control = pci_conf_read16(bus, slot, func, pos + PCI_MSIX_FLAGS);
329 control &= ~PCI_MSIX_FLAGS_ENABLE;
330 if ( enable )
331 control |= PCI_MSIX_FLAGS_ENABLE;
332 pci_conf_write16(bus, slot, func, pos + PCI_MSIX_FLAGS, control);
333 }
334 }
336 static void msix_flush_writes(unsigned int vector)
337 {
338 struct msi_desc *entry = irq_desc[vector].msi_desc;
340 BUG_ON(!entry || !entry->dev);
341 switch (entry->msi_attrib.type) {
342 case PCI_CAP_ID_MSI:
343 /* nothing to do */
344 break;
345 case PCI_CAP_ID_MSIX:
346 {
347 int offset = PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
348 readl(entry->mask_base + offset);
349 break;
350 }
351 default:
352 BUG();
353 break;
354 }
355 }
357 int msi_maskable_irq(const struct msi_desc *entry)
358 {
359 BUG_ON(!entry);
360 return entry->msi_attrib.type != PCI_CAP_ID_MSI
361 || entry->msi_attrib.maskbit;
362 }
364 static void msi_set_mask_bit(unsigned int vector, int flag)
365 {
366 struct msi_desc *entry = irq_desc[vector].msi_desc;
368 ASSERT(spin_is_locked(&irq_desc[vector].lock));
369 BUG_ON(!entry || !entry->dev);
370 switch (entry->msi_attrib.type) {
371 case PCI_CAP_ID_MSI:
372 if (entry->msi_attrib.maskbit) {
373 int pos;
374 u32 mask_bits;
375 u8 bus = entry->dev->bus;
376 u8 slot = PCI_SLOT(entry->dev->devfn);
377 u8 func = PCI_FUNC(entry->dev->devfn);
379 pos = (long)entry->mask_base;
380 mask_bits = pci_conf_read32(bus, slot, func, pos);
381 mask_bits &= ~(1);
382 mask_bits |= flag;
383 pci_conf_write32(bus, slot, func, pos, mask_bits);
384 }
385 break;
386 case PCI_CAP_ID_MSIX:
387 {
388 int offset = PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
389 writel(flag, entry->mask_base + offset);
390 readl(entry->mask_base + offset);
391 break;
392 }
393 default:
394 BUG();
395 break;
396 }
397 entry->msi_attrib.masked = !!flag;
398 }
400 void mask_msi_vector(unsigned int vector)
401 {
402 msi_set_mask_bit(vector, 1);
403 msix_flush_writes(vector);
404 }
406 void unmask_msi_vector(unsigned int vector)
407 {
408 msi_set_mask_bit(vector, 0);
409 msix_flush_writes(vector);
410 }
412 static struct msi_desc* alloc_msi_entry(void)
413 {
414 struct msi_desc *entry;
416 entry = xmalloc(struct msi_desc);
417 if ( !entry )
418 return NULL;
420 INIT_LIST_HEAD(&entry->list);
421 entry->dev = NULL;
422 entry->remap_index = -1;
424 return entry;
425 }
427 int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
428 {
429 struct msi_msg msg;
431 msi_compose_msg(dev, desc->vector, &msg);
432 set_vector_msi(desc);
433 write_msi_msg(irq_desc[desc->vector].msi_desc, &msg);
435 return 0;
436 }
438 void teardown_msi_vector(int vector)
439 {
440 unset_vector_msi(vector);
441 }
443 int msi_free_vector(struct msi_desc *entry)
444 {
445 if ( entry->msi_attrib.type == PCI_CAP_ID_MSIX )
446 {
447 unsigned long start;
449 writel(1, entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
451 start = (unsigned long)entry->mask_base & ~(PAGE_SIZE - 1);
452 msix_put_fixmap(entry->dev, virt_to_fix(start));
453 }
454 list_del(&entry->list);
455 xfree(entry);
456 return 0;
457 }
459 static struct msi_desc *find_msi_entry(struct pci_dev *dev,
460 int vector, int cap_id)
461 {
462 struct msi_desc *entry;
464 list_for_each_entry( entry, &dev->msi_list, list )
465 {
466 if ( entry->msi_attrib.type == cap_id &&
467 (vector == -1 || entry->vector == vector) )
468 return entry;
469 }
471 return NULL;
472 }
474 /**
475 * msi_capability_init - configure device's MSI capability structure
476 * @dev: pointer to the pci_dev data structure of MSI device function
477 *
478 * Setup the MSI capability structure of device function with a single
479 * MSI irq, regardless of device function is capable of handling
480 * multiple messages. A return of zero indicates the successful setup
481 * of an entry zero with the new MSI irq or non-zero for otherwise.
482 **/
483 static int msi_capability_init(struct pci_dev *dev,
484 int vector,
485 struct msi_desc **desc)
486 {
487 struct msi_desc *entry;
488 int pos;
489 u16 control;
490 u8 bus = dev->bus;
491 u8 slot = PCI_SLOT(dev->devfn);
492 u8 func = PCI_FUNC(dev->devfn);
494 ASSERT(spin_is_locked(&pcidevs_lock));
495 pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSI);
496 control = pci_conf_read16(bus, slot, func, msi_control_reg(pos));
497 /* MSI Entry Initialization */
498 msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */
500 entry = alloc_msi_entry();
501 if ( !entry )
502 return -ENOMEM;
504 entry->msi_attrib.type = PCI_CAP_ID_MSI;
505 entry->msi_attrib.is_64 = is_64bit_address(control);
506 entry->msi_attrib.entry_nr = 0;
507 entry->msi_attrib.maskbit = is_mask_bit_support(control);
508 entry->msi_attrib.masked = 1;
509 entry->msi_attrib.pos = pos;
510 entry->vector = vector;
511 if ( is_mask_bit_support(control) )
512 entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
513 is_64bit_address(control));
514 entry->dev = dev;
515 if ( entry->msi_attrib.maskbit )
516 {
517 unsigned int maskbits, temp;
518 /* All MSIs are unmasked by default, Mask them all */
519 maskbits = pci_conf_read32(bus, slot, func,
520 msi_mask_bits_reg(pos, is_64bit_address(control)));
521 temp = (1 << multi_msi_capable(control));
522 temp = ((temp - 1) & ~temp);
523 maskbits |= temp;
524 pci_conf_write32(bus, slot, func,
525 msi_mask_bits_reg(pos, is_64bit_address(control)),
526 maskbits);
527 }
528 list_add_tail(&entry->list, &dev->msi_list);
530 *desc = entry;
531 /* Restore the original MSI enabled bits */
532 pci_conf_write16(bus, slot, func, msi_control_reg(pos), control);
534 return 0;
535 }
537 /**
538 * msix_capability_init - configure device's MSI-X capability
539 * @dev: pointer to the pci_dev data structure of MSI-X device function
540 * @entries: pointer to an array of struct msix_entry entries
541 * @nvec: number of @entries
542 *
543 * Setup the MSI-X capability structure of device function with a
544 * single MSI-X irq. A return of zero indicates the successful setup of
545 * requested MSI-X entries with allocated irqs or non-zero for otherwise.
546 **/
547 static int msix_capability_init(struct pci_dev *dev,
548 struct msi_info *msi,
549 struct msi_desc **desc)
550 {
551 struct msi_desc *entry;
552 int pos;
553 u16 control;
554 unsigned long table_paddr, entry_paddr;
555 u32 table_offset, entry_offset;
556 u8 bir;
557 void __iomem *base;
558 int idx;
559 u8 bus = dev->bus;
560 u8 slot = PCI_SLOT(dev->devfn);
561 u8 func = PCI_FUNC(dev->devfn);
563 ASSERT(spin_is_locked(&pcidevs_lock));
564 ASSERT(desc);
566 pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSIX);
567 control = pci_conf_read16(bus, slot, func, msix_control_reg(pos));
568 msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */
570 /* MSI-X Table Initialization */
571 entry = alloc_msi_entry();
572 if ( !entry )
573 return -ENOMEM;
575 /* Request & Map MSI-X table region */
576 table_offset = pci_conf_read32(bus, slot, func, msix_table_offset_reg(pos));
577 bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
578 table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
579 entry_offset = msi->entry_nr * PCI_MSIX_ENTRY_SIZE;
581 table_paddr = msi->table_base + table_offset;
582 entry_paddr = table_paddr + entry_offset;
583 idx = msix_get_fixmap(dev, table_paddr, entry_paddr);
584 if ( idx < 0 )
585 {
586 xfree(entry);
587 return idx;
588 }
589 base = (void *)(fix_to_virt(idx) + (entry_paddr & ((1UL << PAGE_SHIFT) - 1)));
591 entry->msi_attrib.type = PCI_CAP_ID_MSIX;
592 entry->msi_attrib.is_64 = 1;
593 entry->msi_attrib.entry_nr = msi->entry_nr;
594 entry->msi_attrib.maskbit = 1;
595 entry->msi_attrib.masked = 1;
596 entry->msi_attrib.pos = pos;
597 entry->vector = msi->vector;
598 entry->dev = dev;
599 entry->mask_base = base;
601 list_add_tail(&entry->list, &dev->msi_list);
603 /* Mask interrupt here */
604 writel(1, entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
606 *desc = entry;
607 /* Restore MSI-X enabled bits */
608 pci_conf_write16(bus, slot, func, msix_control_reg(pos), control);
610 return 0;
611 }
613 /**
614 * pci_enable_msi - configure device's MSI capability structure
615 * @dev: pointer to the pci_dev data structure of MSI device function
616 *
617 * Setup the MSI capability structure of device function with
618 * a single MSI irq upon its software driver call to request for
619 * MSI mode enabled on its hardware device function. A return of zero
620 * indicates the successful setup of an entry zero with the new MSI
621 * irq or non-zero for otherwise.
622 **/
623 static int __pci_enable_msi(struct msi_info *msi, struct msi_desc **desc)
624 {
625 int status;
626 struct pci_dev *pdev;
628 ASSERT(spin_is_locked(&pcidevs_lock));
629 pdev = pci_get_pdev(msi->bus, msi->devfn);
630 if ( !pdev )
631 return -ENODEV;
633 if ( find_msi_entry(pdev, msi->vector, PCI_CAP_ID_MSI) )
634 {
635 dprintk(XENLOG_WARNING, "vector %d has already mapped to MSI on "
636 "device %02x:%02x.%01x.\n", msi->vector, msi->bus,
637 PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
638 return 0;
639 }
641 status = msi_capability_init(pdev, msi->vector, desc);
642 return status;
643 }
645 static void __pci_disable_msi(struct msi_desc *entry)
646 {
647 struct pci_dev *dev;
648 int pos;
649 u16 control;
650 u8 bus, slot, func;
652 dev = entry->dev;
653 bus = dev->bus;
654 slot = PCI_SLOT(dev->devfn);
655 func = PCI_FUNC(dev->devfn);
657 pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSI);
658 control = pci_conf_read16(bus, slot, func, msi_control_reg(pos));
659 msi_set_enable(dev, 0);
661 BUG_ON(list_empty(&dev->msi_list));
663 }
665 /**
666 * pci_enable_msix - configure device's MSI-X capability structure
667 * @dev: pointer to the pci_dev data structure of MSI-X device function
668 * @entries: pointer to an array of MSI-X entries
669 * @nvec: number of MSI-X irqs requested for allocation by device driver
670 *
671 * Setup the MSI-X capability structure of device function with the number
672 * of requested irqs upon its software driver call to request for
673 * MSI-X mode enabled on its hardware device function. A return of zero
674 * indicates the successful configuration of MSI-X capability structure
675 * with new allocated MSI-X irqs. A return of < 0 indicates a failure.
676 * Or a return of > 0 indicates that driver request is exceeding the number
677 * of irqs available. Driver should use the returned value to re-send
678 * its request.
679 **/
680 static int __pci_enable_msix(struct msi_info *msi, struct msi_desc **desc)
681 {
682 int status, pos, nr_entries;
683 struct pci_dev *pdev;
684 u16 control;
685 u8 slot = PCI_SLOT(msi->devfn);
686 u8 func = PCI_FUNC(msi->devfn);
688 ASSERT(spin_is_locked(&pcidevs_lock));
689 pdev = pci_get_pdev(msi->bus, msi->devfn);
690 if ( !pdev )
691 return -ENODEV;
693 pos = pci_find_cap_offset(msi->bus, slot, func, PCI_CAP_ID_MSIX);
694 control = pci_conf_read16(msi->bus, slot, func, msi_control_reg(pos));
695 nr_entries = multi_msix_capable(control);
696 if (msi->entry_nr >= nr_entries)
697 return -EINVAL;
699 if ( find_msi_entry(pdev, msi->vector, PCI_CAP_ID_MSIX) )
700 {
701 dprintk(XENLOG_WARNING, "vector %d has already mapped to MSIX on "
702 "device %02x:%02x.%01x.\n", msi->vector, msi->bus,
703 PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
704 return 0;
705 }
707 status = msix_capability_init(pdev, msi, desc);
708 return status;
709 }
711 static void __pci_disable_msix(struct msi_desc *entry)
712 {
713 struct pci_dev *dev;
714 int pos;
715 u16 control;
716 u8 bus, slot, func;
718 dev = entry->dev;
719 bus = dev->bus;
720 slot = PCI_SLOT(dev->devfn);
721 func = PCI_FUNC(dev->devfn);
723 pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSIX);
724 control = pci_conf_read16(bus, slot, func, msix_control_reg(pos));
725 msix_set_enable(dev, 0);
727 BUG_ON(list_empty(&dev->msi_list));
729 writel(1, entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
731 pci_conf_write16(bus, slot, func, msix_control_reg(pos), control);
732 }
734 /*
735 * Notice: only construct the msi_desc
736 * no change to irq_desc here, and the interrupt is masked
737 */
738 int pci_enable_msi(struct msi_info *msi, struct msi_desc **desc)
739 {
740 ASSERT(spin_is_locked(&pcidevs_lock));
742 return msi->table_base ? __pci_enable_msix(msi, desc) :
743 __pci_enable_msi(msi, desc);
744 }
746 /*
747 * Device only, no irq_desc
748 */
749 void pci_disable_msi(struct msi_desc *msi_desc)
750 {
751 if ( msi_desc->msi_attrib.type == PCI_CAP_ID_MSI )
752 __pci_disable_msi(msi_desc);
753 else if ( msi_desc->msi_attrib.type == PCI_CAP_ID_MSIX )
754 __pci_disable_msix(msi_desc);
755 }
757 static void msi_free_vectors(struct pci_dev* dev)
758 {
759 struct msi_desc *entry, *tmp;
760 irq_desc_t *desc;
761 unsigned long flags, vector;
763 list_for_each_entry_safe( entry, tmp, &dev->msi_list, list )
764 {
765 vector = entry->vector;
766 desc = &irq_desc[vector];
767 pci_disable_msi(entry);
769 spin_lock_irqsave(&desc->lock, flags);
771 teardown_msi_vector(vector);
773 if ( desc->handler == &pci_msi_type )
774 {
775 /* MSI is not shared, so should be released already */
776 BUG_ON(desc->status & IRQ_GUEST);
777 desc->handler = &no_irq_type;
778 }
780 spin_unlock_irqrestore(&desc->lock, flags);
781 msi_free_vector(entry);
782 }
783 }
785 void pci_cleanup_msi(struct pci_dev *pdev)
786 {
787 /* Disable MSI and/or MSI-X */
788 msi_set_enable(pdev, 0);
789 msix_set_enable(pdev, 0);
790 msi_free_vectors(pdev);
791 }
793 int pci_restore_msi_state(struct pci_dev *pdev)
794 {
795 unsigned long flags;
796 int vector;
797 struct msi_desc *entry, *tmp;
798 irq_desc_t *desc;
800 ASSERT(spin_is_locked(&pcidevs_lock));
802 if (!pdev)
803 return -EINVAL;
805 list_for_each_entry_safe( entry, tmp, &pdev->msi_list, list )
806 {
807 vector = entry->vector;
808 desc = &irq_desc[vector];
810 spin_lock_irqsave(&desc->lock, flags);
812 ASSERT(desc->msi_desc == entry);
814 if (desc->msi_desc != entry)
815 {
816 dprintk(XENLOG_ERR, "Restore MSI for dev %x:%x not set before?\n",
817 pdev->bus, pdev->devfn);
818 spin_unlock_irqrestore(&desc->lock, flags);
819 return -EINVAL;
820 }
822 if ( entry->msi_attrib.type == PCI_CAP_ID_MSI )
823 msi_set_enable(pdev, 0);
824 else if ( entry->msi_attrib.type == PCI_CAP_ID_MSIX )
825 msix_set_enable(pdev, 0);
827 write_msi_msg(entry, &entry->msg);
829 msi_set_mask_bit(vector, entry->msi_attrib.masked);
831 if ( entry->msi_attrib.type == PCI_CAP_ID_MSI )
832 msi_set_enable(pdev, 1);
833 else if ( entry->msi_attrib.type == PCI_CAP_ID_MSIX )
834 msix_set_enable(pdev, 1);
836 spin_unlock_irqrestore(&desc->lock, flags);
837 }
839 return 0;
840 }
842 unsigned int pci_msix_get_table_len(struct pci_dev *pdev)
843 {
844 int pos;
845 u16 control;
846 u8 bus, slot, func;
847 unsigned int len;
849 bus = pdev->bus;
850 slot = PCI_SLOT(pdev->devfn);
851 func = PCI_FUNC(pdev->devfn);
853 pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSIX);
854 if ( !pos )
855 return 0;
857 control = pci_conf_read16(bus, slot, func, msix_control_reg(pos));
858 len = msix_table_size(control) * PCI_MSIX_ENTRY_SIZE;
860 return len;
861 }