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