msi.c revision 6a9e7f203187e22e96588fa0156b2652841196bf
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 */ 8 9#include <linux/err.h> 10#include <linux/mm.h> 11#include <linux/irq.h> 12#include <linux/interrupt.h> 13#include <linux/init.h> 14#include <linux/ioport.h> 15#include <linux/pci.h> 16#include <linux/proc_fs.h> 17#include <linux/msi.h> 18#include <linux/smp.h> 19 20#include <asm/errno.h> 21#include <asm/io.h> 22 23#include "pci.h" 24#include "msi.h" 25 26static int pci_msi_enable = 1; 27 28/* Arch hooks */ 29 30int __attribute__ ((weak)) 31arch_msi_check_device(struct pci_dev *dev, int nvec, int type) 32{ 33 return 0; 34} 35 36int __attribute__ ((weak)) 37arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry) 38{ 39 return 0; 40} 41 42int __attribute__ ((weak)) 43arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 44{ 45 struct msi_desc *entry; 46 int ret; 47 48 list_for_each_entry(entry, &dev->msi_list, list) { 49 ret = arch_setup_msi_irq(dev, entry); 50 if (ret) 51 return ret; 52 } 53 54 return 0; 55} 56 57void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq) 58{ 59 return; 60} 61 62void __attribute__ ((weak)) 63arch_teardown_msi_irqs(struct pci_dev *dev) 64{ 65 struct msi_desc *entry; 66 67 list_for_each_entry(entry, &dev->msi_list, list) { 68 if (entry->irq != 0) 69 arch_teardown_msi_irq(entry->irq); 70 } 71} 72 73static void msi_set_enable(struct pci_dev *dev, int enable) 74{ 75 int pos; 76 u16 control; 77 78 pos = pci_find_capability(dev, PCI_CAP_ID_MSI); 79 if (pos) { 80 pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); 81 control &= ~PCI_MSI_FLAGS_ENABLE; 82 if (enable) 83 control |= PCI_MSI_FLAGS_ENABLE; 84 pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); 85 } 86} 87 88static void msix_set_enable(struct pci_dev *dev, int enable) 89{ 90 int pos; 91 u16 control; 92 93 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); 94 if (pos) { 95 pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); 96 control &= ~PCI_MSIX_FLAGS_ENABLE; 97 if (enable) 98 control |= PCI_MSIX_FLAGS_ENABLE; 99 pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); 100 } 101} 102 103static void msix_flush_writes(unsigned int irq) 104{ 105 struct msi_desc *entry; 106 107 entry = get_irq_msi(irq); 108 BUG_ON(!entry || !entry->dev); 109 switch (entry->msi_attrib.type) { 110 case PCI_CAP_ID_MSI: 111 /* nothing to do */ 112 break; 113 case PCI_CAP_ID_MSIX: 114 { 115 int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + 116 PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; 117 readl(entry->mask_base + offset); 118 break; 119 } 120 default: 121 BUG(); 122 break; 123 } 124} 125 126static void msi_set_mask_bit(unsigned int irq, int flag) 127{ 128 struct msi_desc *entry; 129 130 entry = get_irq_msi(irq); 131 BUG_ON(!entry || !entry->dev); 132 switch (entry->msi_attrib.type) { 133 case PCI_CAP_ID_MSI: 134 if (entry->msi_attrib.maskbit) { 135 int pos; 136 u32 mask_bits; 137 138 pos = (long)entry->mask_base; 139 pci_read_config_dword(entry->dev, pos, &mask_bits); 140 mask_bits &= ~(1); 141 mask_bits |= flag; 142 pci_write_config_dword(entry->dev, pos, mask_bits); 143 } else { 144 msi_set_enable(entry->dev, !flag); 145 } 146 break; 147 case PCI_CAP_ID_MSIX: 148 { 149 int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + 150 PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; 151 writel(flag, entry->mask_base + offset); 152 readl(entry->mask_base + offset); 153 break; 154 } 155 default: 156 BUG(); 157 break; 158 } 159 entry->msi_attrib.masked = !!flag; 160} 161 162void read_msi_msg(unsigned int irq, struct msi_msg *msg) 163{ 164 struct msi_desc *entry = get_irq_msi(irq); 165 switch(entry->msi_attrib.type) { 166 case PCI_CAP_ID_MSI: 167 { 168 struct pci_dev *dev = entry->dev; 169 int pos = entry->msi_attrib.pos; 170 u16 data; 171 172 pci_read_config_dword(dev, msi_lower_address_reg(pos), 173 &msg->address_lo); 174 if (entry->msi_attrib.is_64) { 175 pci_read_config_dword(dev, msi_upper_address_reg(pos), 176 &msg->address_hi); 177 pci_read_config_word(dev, msi_data_reg(pos, 1), &data); 178 } else { 179 msg->address_hi = 0; 180 pci_read_config_word(dev, msi_data_reg(pos, 0), &data); 181 } 182 msg->data = data; 183 break; 184 } 185 case PCI_CAP_ID_MSIX: 186 { 187 void __iomem *base; 188 base = entry->mask_base + 189 entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; 190 191 msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); 192 msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); 193 msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET); 194 break; 195 } 196 default: 197 BUG(); 198 } 199} 200 201void write_msi_msg(unsigned int irq, struct msi_msg *msg) 202{ 203 struct msi_desc *entry = get_irq_msi(irq); 204 switch (entry->msi_attrib.type) { 205 case PCI_CAP_ID_MSI: 206 { 207 struct pci_dev *dev = entry->dev; 208 int pos = entry->msi_attrib.pos; 209 210 pci_write_config_dword(dev, msi_lower_address_reg(pos), 211 msg->address_lo); 212 if (entry->msi_attrib.is_64) { 213 pci_write_config_dword(dev, msi_upper_address_reg(pos), 214 msg->address_hi); 215 pci_write_config_word(dev, msi_data_reg(pos, 1), 216 msg->data); 217 } else { 218 pci_write_config_word(dev, msi_data_reg(pos, 0), 219 msg->data); 220 } 221 break; 222 } 223 case PCI_CAP_ID_MSIX: 224 { 225 void __iomem *base; 226 base = entry->mask_base + 227 entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; 228 229 writel(msg->address_lo, 230 base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); 231 writel(msg->address_hi, 232 base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); 233 writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET); 234 break; 235 } 236 default: 237 BUG(); 238 } 239 entry->msg = *msg; 240} 241 242void mask_msi_irq(unsigned int irq) 243{ 244 msi_set_mask_bit(irq, 1); 245 msix_flush_writes(irq); 246} 247 248void unmask_msi_irq(unsigned int irq) 249{ 250 msi_set_mask_bit(irq, 0); 251 msix_flush_writes(irq); 252} 253 254static int msi_free_irqs(struct pci_dev* dev); 255 256 257static struct msi_desc* alloc_msi_entry(void) 258{ 259 struct msi_desc *entry; 260 261 entry = kzalloc(sizeof(struct msi_desc), GFP_KERNEL); 262 if (!entry) 263 return NULL; 264 265 INIT_LIST_HEAD(&entry->list); 266 entry->irq = 0; 267 entry->dev = NULL; 268 269 return entry; 270} 271 272static void pci_intx_for_msi(struct pci_dev *dev, int enable) 273{ 274 if (!(dev->dev_flags & PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG)) 275 pci_intx(dev, enable); 276} 277 278static void __pci_restore_msi_state(struct pci_dev *dev) 279{ 280 int pos; 281 u16 control; 282 struct msi_desc *entry; 283 284 if (!dev->msi_enabled) 285 return; 286 287 entry = get_irq_msi(dev->irq); 288 pos = entry->msi_attrib.pos; 289 290 pci_intx_for_msi(dev, 0); 291 msi_set_enable(dev, 0); 292 write_msi_msg(dev->irq, &entry->msg); 293 if (entry->msi_attrib.maskbit) 294 msi_set_mask_bit(dev->irq, entry->msi_attrib.masked); 295 296 pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); 297 control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE); 298 if (entry->msi_attrib.maskbit || !entry->msi_attrib.masked) 299 control |= PCI_MSI_FLAGS_ENABLE; 300 pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); 301} 302 303static void __pci_restore_msix_state(struct pci_dev *dev) 304{ 305 int pos; 306 struct msi_desc *entry; 307 u16 control; 308 309 if (!dev->msix_enabled) 310 return; 311 312 /* route the table */ 313 pci_intx_for_msi(dev, 0); 314 msix_set_enable(dev, 0); 315 316 list_for_each_entry(entry, &dev->msi_list, list) { 317 write_msi_msg(entry->irq, &entry->msg); 318 msi_set_mask_bit(entry->irq, entry->msi_attrib.masked); 319 } 320 321 BUG_ON(list_empty(&dev->msi_list)); 322 entry = list_entry(dev->msi_list.next, struct msi_desc, list); 323 pos = entry->msi_attrib.pos; 324 pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); 325 control &= ~PCI_MSIX_FLAGS_MASKALL; 326 control |= PCI_MSIX_FLAGS_ENABLE; 327 pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); 328} 329 330void pci_restore_msi_state(struct pci_dev *dev) 331{ 332 __pci_restore_msi_state(dev); 333 __pci_restore_msix_state(dev); 334} 335EXPORT_SYMBOL_GPL(pci_restore_msi_state); 336 337/** 338 * msi_capability_init - configure device's MSI capability structure 339 * @dev: pointer to the pci_dev data structure of MSI device function 340 * 341 * Setup the MSI capability structure of device function with a single 342 * MSI irq, regardless of device function is capable of handling 343 * multiple messages. A return of zero indicates the successful setup 344 * of an entry zero with the new MSI irq or non-zero for otherwise. 345 **/ 346static int msi_capability_init(struct pci_dev *dev) 347{ 348 struct msi_desc *entry; 349 int pos, ret; 350 u16 control; 351 352 msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */ 353 354 pos = pci_find_capability(dev, PCI_CAP_ID_MSI); 355 pci_read_config_word(dev, msi_control_reg(pos), &control); 356 /* MSI Entry Initialization */ 357 entry = alloc_msi_entry(); 358 if (!entry) 359 return -ENOMEM; 360 361 entry->msi_attrib.type = PCI_CAP_ID_MSI; 362 entry->msi_attrib.is_64 = is_64bit_address(control); 363 entry->msi_attrib.entry_nr = 0; 364 entry->msi_attrib.maskbit = is_mask_bit_support(control); 365 entry->msi_attrib.masked = 1; 366 entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ 367 entry->msi_attrib.pos = pos; 368 if (is_mask_bit_support(control)) { 369 entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos, 370 is_64bit_address(control)); 371 } 372 entry->dev = dev; 373 if (entry->msi_attrib.maskbit) { 374 unsigned int maskbits, temp; 375 /* All MSIs are unmasked by default, Mask them all */ 376 pci_read_config_dword(dev, 377 msi_mask_bits_reg(pos, is_64bit_address(control)), 378 &maskbits); 379 temp = (1 << multi_msi_capable(control)); 380 temp = ((temp - 1) & ~temp); 381 maskbits |= temp; 382 pci_write_config_dword(dev, 383 msi_mask_bits_reg(pos, is_64bit_address(control)), 384 maskbits); 385 } 386 list_add_tail(&entry->list, &dev->msi_list); 387 388 /* Configure MSI capability structure */ 389 ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI); 390 if (ret) { 391 msi_free_irqs(dev); 392 return ret; 393 } 394 395 /* Set MSI enabled bits */ 396 pci_intx_for_msi(dev, 0); 397 msi_set_enable(dev, 1); 398 dev->msi_enabled = 1; 399 400 dev->irq = entry->irq; 401 return 0; 402} 403 404/** 405 * msix_capability_init - configure device's MSI-X capability 406 * @dev: pointer to the pci_dev data structure of MSI-X device function 407 * @entries: pointer to an array of struct msix_entry entries 408 * @nvec: number of @entries 409 * 410 * Setup the MSI-X capability structure of device function with a 411 * single MSI-X irq. A return of zero indicates the successful setup of 412 * requested MSI-X entries with allocated irqs or non-zero for otherwise. 413 **/ 414static int msix_capability_init(struct pci_dev *dev, 415 struct msix_entry *entries, int nvec) 416{ 417 struct msi_desc *entry; 418 int pos, i, j, nr_entries, ret; 419 unsigned long phys_addr; 420 u32 table_offset; 421 u16 control; 422 u8 bir; 423 void __iomem *base; 424 425 msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */ 426 427 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); 428 /* Request & Map MSI-X table region */ 429 pci_read_config_word(dev, msi_control_reg(pos), &control); 430 nr_entries = multi_msix_capable(control); 431 432 pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); 433 bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); 434 table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; 435 phys_addr = pci_resource_start (dev, bir) + table_offset; 436 base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); 437 if (base == NULL) 438 return -ENOMEM; 439 440 /* MSI-X Table Initialization */ 441 for (i = 0; i < nvec; i++) { 442 entry = alloc_msi_entry(); 443 if (!entry) 444 break; 445 446 j = entries[i].entry; 447 entry->msi_attrib.type = PCI_CAP_ID_MSIX; 448 entry->msi_attrib.is_64 = 1; 449 entry->msi_attrib.entry_nr = j; 450 entry->msi_attrib.maskbit = 1; 451 entry->msi_attrib.masked = 1; 452 entry->msi_attrib.default_irq = dev->irq; 453 entry->msi_attrib.pos = pos; 454 entry->dev = dev; 455 entry->mask_base = base; 456 457 list_add_tail(&entry->list, &dev->msi_list); 458 } 459 460 ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); 461 if (ret) { 462 int avail = 0; 463 list_for_each_entry(entry, &dev->msi_list, list) { 464 if (entry->irq != 0) { 465 avail++; 466 } 467 } 468 469 msi_free_irqs(dev); 470 471 /* If we had some success report the number of irqs 472 * we succeeded in setting up. 473 */ 474 if (avail == 0) 475 avail = ret; 476 return avail; 477 } 478 479 i = 0; 480 list_for_each_entry(entry, &dev->msi_list, list) { 481 entries[i].vector = entry->irq; 482 set_irq_msi(entry->irq, entry); 483 i++; 484 } 485 /* Set MSI-X enabled bits */ 486 pci_intx_for_msi(dev, 0); 487 msix_set_enable(dev, 1); 488 dev->msix_enabled = 1; 489 490 return 0; 491} 492 493/** 494 * pci_msi_check_device - check whether MSI may be enabled on a device 495 * @dev: pointer to the pci_dev data structure of MSI device function 496 * @nvec: how many MSIs have been requested ? 497 * @type: are we checking for MSI or MSI-X ? 498 * 499 * Look at global flags, the device itself, and its parent busses 500 * to determine if MSI/-X are supported for the device. If MSI/-X is 501 * supported return 0, else return an error code. 502 **/ 503static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type) 504{ 505 struct pci_bus *bus; 506 int ret; 507 508 /* MSI must be globally enabled and supported by the device */ 509 if (!pci_msi_enable || !dev || dev->no_msi) 510 return -EINVAL; 511 512 /* 513 * You can't ask to have 0 or less MSIs configured. 514 * a) it's stupid .. 515 * b) the list manipulation code assumes nvec >= 1. 516 */ 517 if (nvec < 1) 518 return -ERANGE; 519 520 /* Any bridge which does NOT route MSI transactions from it's 521 * secondary bus to it's primary bus must set NO_MSI flag on 522 * the secondary pci_bus. 523 * We expect only arch-specific PCI host bus controller driver 524 * or quirks for specific PCI bridges to be setting NO_MSI. 525 */ 526 for (bus = dev->bus; bus; bus = bus->parent) 527 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) 528 return -EINVAL; 529 530 ret = arch_msi_check_device(dev, nvec, type); 531 if (ret) 532 return ret; 533 534 if (!pci_find_capability(dev, type)) 535 return -EINVAL; 536 537 return 0; 538} 539 540/** 541 * pci_enable_msi - configure device's MSI capability structure 542 * @dev: pointer to the pci_dev data structure of MSI device function 543 * 544 * Setup the MSI capability structure of device function with 545 * a single MSI irq upon its software driver call to request for 546 * MSI mode enabled on its hardware device function. A return of zero 547 * indicates the successful setup of an entry zero with the new MSI 548 * irq or non-zero for otherwise. 549 **/ 550int pci_enable_msi(struct pci_dev* dev) 551{ 552 int status; 553 554 status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI); 555 if (status) 556 return status; 557 558 WARN_ON(!!dev->msi_enabled); 559 560 /* Check whether driver already requested for MSI-X irqs */ 561 if (dev->msix_enabled) { 562 printk(KERN_INFO "PCI: %s: Can't enable MSI. " 563 "Device already has MSI-X enabled\n", 564 pci_name(dev)); 565 return -EINVAL; 566 } 567 status = msi_capability_init(dev); 568 return status; 569} 570EXPORT_SYMBOL(pci_enable_msi); 571 572void pci_disable_msi(struct pci_dev* dev) 573{ 574 struct msi_desc *entry; 575 int default_irq; 576 577 if (!pci_msi_enable || !dev || !dev->msi_enabled) 578 return; 579 580 msi_set_enable(dev, 0); 581 pci_intx_for_msi(dev, 1); 582 dev->msi_enabled = 0; 583 584 BUG_ON(list_empty(&dev->msi_list)); 585 entry = list_entry(dev->msi_list.next, struct msi_desc, list); 586 if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { 587 return; 588 } 589 590 default_irq = entry->msi_attrib.default_irq; 591 msi_free_irqs(dev); 592 593 /* Restore dev->irq to its default pin-assertion irq */ 594 dev->irq = default_irq; 595} 596EXPORT_SYMBOL(pci_disable_msi); 597 598static int msi_free_irqs(struct pci_dev* dev) 599{ 600 struct msi_desc *entry, *tmp; 601 602 list_for_each_entry(entry, &dev->msi_list, list) { 603 if (entry->irq) 604 BUG_ON(irq_has_action(entry->irq)); 605 } 606 607 arch_teardown_msi_irqs(dev); 608 609 list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { 610 if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) { 611 writel(1, entry->mask_base + entry->msi_attrib.entry_nr 612 * PCI_MSIX_ENTRY_SIZE 613 + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); 614 615 if (list_is_last(&entry->list, &dev->msi_list)) 616 iounmap(entry->mask_base); 617 } 618 list_del(&entry->list); 619 kfree(entry); 620 } 621 622 return 0; 623} 624 625/** 626 * pci_enable_msix - configure device's MSI-X capability structure 627 * @dev: pointer to the pci_dev data structure of MSI-X device function 628 * @entries: pointer to an array of MSI-X entries 629 * @nvec: number of MSI-X irqs requested for allocation by device driver 630 * 631 * Setup the MSI-X capability structure of device function with the number 632 * of requested irqs upon its software driver call to request for 633 * MSI-X mode enabled on its hardware device function. A return of zero 634 * indicates the successful configuration of MSI-X capability structure 635 * with new allocated MSI-X irqs. A return of < 0 indicates a failure. 636 * Or a return of > 0 indicates that driver request is exceeding the number 637 * of irqs available. Driver should use the returned value to re-send 638 * its request. 639 **/ 640int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) 641{ 642 int status, pos, nr_entries; 643 int i, j; 644 u16 control; 645 646 if (!entries) 647 return -EINVAL; 648 649 status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX); 650 if (status) 651 return status; 652 653 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); 654 pci_read_config_word(dev, msi_control_reg(pos), &control); 655 nr_entries = multi_msix_capable(control); 656 if (nvec > nr_entries) 657 return -EINVAL; 658 659 /* Check for any invalid entries */ 660 for (i = 0; i < nvec; i++) { 661 if (entries[i].entry >= nr_entries) 662 return -EINVAL; /* invalid entry */ 663 for (j = i + 1; j < nvec; j++) { 664 if (entries[i].entry == entries[j].entry) 665 return -EINVAL; /* duplicate entry */ 666 } 667 } 668 WARN_ON(!!dev->msix_enabled); 669 670 /* Check whether driver already requested for MSI irq */ 671 if (dev->msi_enabled) { 672 printk(KERN_INFO "PCI: %s: Can't enable MSI-X. " 673 "Device already has an MSI irq assigned\n", 674 pci_name(dev)); 675 return -EINVAL; 676 } 677 status = msix_capability_init(dev, entries, nvec); 678 return status; 679} 680EXPORT_SYMBOL(pci_enable_msix); 681 682static void msix_free_all_irqs(struct pci_dev *dev) 683{ 684 msi_free_irqs(dev); 685} 686 687void pci_disable_msix(struct pci_dev* dev) 688{ 689 if (!pci_msi_enable || !dev || !dev->msix_enabled) 690 return; 691 692 msix_set_enable(dev, 0); 693 pci_intx_for_msi(dev, 1); 694 dev->msix_enabled = 0; 695 696 msix_free_all_irqs(dev); 697} 698EXPORT_SYMBOL(pci_disable_msix); 699 700/** 701 * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs to unused state 702 * @dev: pointer to the pci_dev data structure of MSI(X) device function 703 * 704 * Being called during hotplug remove, from which the device function 705 * is hot-removed. All previous assigned MSI/MSI-X irqs, if 706 * allocated for this device function, are reclaimed to unused state, 707 * which may be used later on. 708 **/ 709void msi_remove_pci_irq_vectors(struct pci_dev* dev) 710{ 711 if (!pci_msi_enable || !dev) 712 return; 713 714 if (dev->msi_enabled) 715 msi_free_irqs(dev); 716 717 if (dev->msix_enabled) 718 msix_free_all_irqs(dev); 719} 720 721void pci_no_msi(void) 722{ 723 pci_msi_enable = 0; 724} 725 726void pci_msi_init_pci_dev(struct pci_dev *dev) 727{ 728 INIT_LIST_HEAD(&dev->msi_list); 729} 730