msi.c revision ba698ad4b7e466cbb4a8bde6b9da8080ab06808d
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 233#ifdef CONFIG_PM 234static void __pci_restore_msi_state(struct pci_dev *dev) 235{ 236 int pos; 237 u16 control; 238 struct msi_desc *entry; 239 240 if (!dev->msi_enabled) 241 return; 242 243 entry = get_irq_msi(dev->irq); 244 pos = entry->msi_attrib.pos; 245 246 pci_intx_for_msi(dev, 0); 247 msi_set_enable(dev, 0); 248 write_msi_msg(dev->irq, &entry->msg); 249 if (entry->msi_attrib.maskbit) 250 msi_set_mask_bit(dev->irq, entry->msi_attrib.masked); 251 252 pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); 253 control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE); 254 if (entry->msi_attrib.maskbit || !entry->msi_attrib.masked) 255 control |= PCI_MSI_FLAGS_ENABLE; 256 pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); 257} 258 259static void __pci_restore_msix_state(struct pci_dev *dev) 260{ 261 int pos; 262 struct msi_desc *entry; 263 u16 control; 264 265 if (!dev->msix_enabled) 266 return; 267 268 /* route the table */ 269 pci_intx_for_msi(dev, 0); 270 msix_set_enable(dev, 0); 271 272 list_for_each_entry(entry, &dev->msi_list, list) { 273 write_msi_msg(entry->irq, &entry->msg); 274 msi_set_mask_bit(entry->irq, entry->msi_attrib.masked); 275 } 276 277 BUG_ON(list_empty(&dev->msi_list)); 278 entry = list_entry(dev->msi_list.next, struct msi_desc, list); 279 pos = entry->msi_attrib.pos; 280 pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); 281 control &= ~PCI_MSIX_FLAGS_MASKALL; 282 control |= PCI_MSIX_FLAGS_ENABLE; 283 pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); 284} 285 286void pci_restore_msi_state(struct pci_dev *dev) 287{ 288 __pci_restore_msi_state(dev); 289 __pci_restore_msix_state(dev); 290} 291#endif /* CONFIG_PM */ 292 293/** 294 * msi_capability_init - configure device's MSI capability structure 295 * @dev: pointer to the pci_dev data structure of MSI device function 296 * 297 * Setup the MSI capability structure of device function with a single 298 * MSI irq, regardless of device function is capable of handling 299 * multiple messages. A return of zero indicates the successful setup 300 * of an entry zero with the new MSI irq or non-zero for otherwise. 301 **/ 302static int msi_capability_init(struct pci_dev *dev) 303{ 304 struct msi_desc *entry; 305 int pos, ret; 306 u16 control; 307 308 msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */ 309 310 pos = pci_find_capability(dev, PCI_CAP_ID_MSI); 311 pci_read_config_word(dev, msi_control_reg(pos), &control); 312 /* MSI Entry Initialization */ 313 entry = alloc_msi_entry(); 314 if (!entry) 315 return -ENOMEM; 316 317 entry->msi_attrib.type = PCI_CAP_ID_MSI; 318 entry->msi_attrib.is_64 = is_64bit_address(control); 319 entry->msi_attrib.entry_nr = 0; 320 entry->msi_attrib.maskbit = is_mask_bit_support(control); 321 entry->msi_attrib.masked = 1; 322 entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ 323 entry->msi_attrib.pos = pos; 324 if (is_mask_bit_support(control)) { 325 entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos, 326 is_64bit_address(control)); 327 } 328 entry->dev = dev; 329 if (entry->msi_attrib.maskbit) { 330 unsigned int maskbits, temp; 331 /* All MSIs are unmasked by default, Mask them all */ 332 pci_read_config_dword(dev, 333 msi_mask_bits_reg(pos, is_64bit_address(control)), 334 &maskbits); 335 temp = (1 << multi_msi_capable(control)); 336 temp = ((temp - 1) & ~temp); 337 maskbits |= temp; 338 pci_write_config_dword(dev, 339 msi_mask_bits_reg(pos, is_64bit_address(control)), 340 maskbits); 341 } 342 list_add_tail(&entry->list, &dev->msi_list); 343 344 /* Configure MSI capability structure */ 345 ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI); 346 if (ret) { 347 msi_free_irqs(dev); 348 return ret; 349 } 350 351 /* Set MSI enabled bits */ 352 pci_intx_for_msi(dev, 0); 353 msi_set_enable(dev, 1); 354 dev->msi_enabled = 1; 355 356 dev->irq = entry->irq; 357 return 0; 358} 359 360/** 361 * msix_capability_init - configure device's MSI-X capability 362 * @dev: pointer to the pci_dev data structure of MSI-X device function 363 * @entries: pointer to an array of struct msix_entry entries 364 * @nvec: number of @entries 365 * 366 * Setup the MSI-X capability structure of device function with a 367 * single MSI-X irq. A return of zero indicates the successful setup of 368 * requested MSI-X entries with allocated irqs or non-zero for otherwise. 369 **/ 370static int msix_capability_init(struct pci_dev *dev, 371 struct msix_entry *entries, int nvec) 372{ 373 struct msi_desc *entry; 374 int pos, i, j, nr_entries, ret; 375 unsigned long phys_addr; 376 u32 table_offset; 377 u16 control; 378 u8 bir; 379 void __iomem *base; 380 381 msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */ 382 383 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); 384 /* Request & Map MSI-X table region */ 385 pci_read_config_word(dev, msi_control_reg(pos), &control); 386 nr_entries = multi_msix_capable(control); 387 388 pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); 389 bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); 390 table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; 391 phys_addr = pci_resource_start (dev, bir) + table_offset; 392 base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); 393 if (base == NULL) 394 return -ENOMEM; 395 396 /* MSI-X Table Initialization */ 397 for (i = 0; i < nvec; i++) { 398 entry = alloc_msi_entry(); 399 if (!entry) 400 break; 401 402 j = entries[i].entry; 403 entry->msi_attrib.type = PCI_CAP_ID_MSIX; 404 entry->msi_attrib.is_64 = 1; 405 entry->msi_attrib.entry_nr = j; 406 entry->msi_attrib.maskbit = 1; 407 entry->msi_attrib.masked = 1; 408 entry->msi_attrib.default_irq = dev->irq; 409 entry->msi_attrib.pos = pos; 410 entry->dev = dev; 411 entry->mask_base = base; 412 413 list_add_tail(&entry->list, &dev->msi_list); 414 } 415 416 ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); 417 if (ret) { 418 int avail = 0; 419 list_for_each_entry(entry, &dev->msi_list, list) { 420 if (entry->irq != 0) { 421 avail++; 422 } 423 } 424 425 msi_free_irqs(dev); 426 427 /* If we had some success report the number of irqs 428 * we succeeded in setting up. 429 */ 430 if (avail == 0) 431 avail = ret; 432 return avail; 433 } 434 435 i = 0; 436 list_for_each_entry(entry, &dev->msi_list, list) { 437 entries[i].vector = entry->irq; 438 set_irq_msi(entry->irq, entry); 439 i++; 440 } 441 /* Set MSI-X enabled bits */ 442 pci_intx_for_msi(dev, 0); 443 msix_set_enable(dev, 1); 444 dev->msix_enabled = 1; 445 446 return 0; 447} 448 449/** 450 * pci_msi_check_device - check whether MSI may be enabled on a device 451 * @dev: pointer to the pci_dev data structure of MSI device function 452 * @nvec: how many MSIs have been requested ? 453 * @type: are we checking for MSI or MSI-X ? 454 * 455 * Look at global flags, the device itself, and its parent busses 456 * to determine if MSI/-X are supported for the device. If MSI/-X is 457 * supported return 0, else return an error code. 458 **/ 459static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type) 460{ 461 struct pci_bus *bus; 462 int ret; 463 464 /* MSI must be globally enabled and supported by the device */ 465 if (!pci_msi_enable || !dev || dev->no_msi) 466 return -EINVAL; 467 468 /* 469 * You can't ask to have 0 or less MSIs configured. 470 * a) it's stupid .. 471 * b) the list manipulation code assumes nvec >= 1. 472 */ 473 if (nvec < 1) 474 return -ERANGE; 475 476 /* Any bridge which does NOT route MSI transactions from it's 477 * secondary bus to it's primary bus must set NO_MSI flag on 478 * the secondary pci_bus. 479 * We expect only arch-specific PCI host bus controller driver 480 * or quirks for specific PCI bridges to be setting NO_MSI. 481 */ 482 for (bus = dev->bus; bus; bus = bus->parent) 483 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) 484 return -EINVAL; 485 486 ret = arch_msi_check_device(dev, nvec, type); 487 if (ret) 488 return ret; 489 490 if (!pci_find_capability(dev, type)) 491 return -EINVAL; 492 493 return 0; 494} 495 496/** 497 * pci_enable_msi - configure device's MSI capability structure 498 * @dev: pointer to the pci_dev data structure of MSI device function 499 * 500 * Setup the MSI capability structure of device function with 501 * a single MSI irq upon its software driver call to request for 502 * MSI mode enabled on its hardware device function. A return of zero 503 * indicates the successful setup of an entry zero with the new MSI 504 * irq or non-zero for otherwise. 505 **/ 506int pci_enable_msi(struct pci_dev* dev) 507{ 508 int status; 509 510 status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI); 511 if (status) 512 return status; 513 514 WARN_ON(!!dev->msi_enabled); 515 516 /* Check whether driver already requested for MSI-X irqs */ 517 if (dev->msix_enabled) { 518 printk(KERN_INFO "PCI: %s: Can't enable MSI. " 519 "Device already has MSI-X enabled\n", 520 pci_name(dev)); 521 return -EINVAL; 522 } 523 status = msi_capability_init(dev); 524 return status; 525} 526EXPORT_SYMBOL(pci_enable_msi); 527 528void pci_disable_msi(struct pci_dev* dev) 529{ 530 struct msi_desc *entry; 531 int default_irq; 532 533 if (!pci_msi_enable || !dev || !dev->msi_enabled) 534 return; 535 536 msi_set_enable(dev, 0); 537 pci_intx_for_msi(dev, 1); 538 dev->msi_enabled = 0; 539 540 BUG_ON(list_empty(&dev->msi_list)); 541 entry = list_entry(dev->msi_list.next, struct msi_desc, list); 542 if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { 543 return; 544 } 545 546 default_irq = entry->msi_attrib.default_irq; 547 msi_free_irqs(dev); 548 549 /* Restore dev->irq to its default pin-assertion irq */ 550 dev->irq = default_irq; 551} 552EXPORT_SYMBOL(pci_disable_msi); 553 554static int msi_free_irqs(struct pci_dev* dev) 555{ 556 struct msi_desc *entry, *tmp; 557 558 list_for_each_entry(entry, &dev->msi_list, list) { 559 if (entry->irq) 560 BUG_ON(irq_has_action(entry->irq)); 561 } 562 563 arch_teardown_msi_irqs(dev); 564 565 list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { 566 if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) { 567 writel(1, entry->mask_base + entry->msi_attrib.entry_nr 568 * PCI_MSIX_ENTRY_SIZE 569 + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); 570 571 if (list_is_last(&entry->list, &dev->msi_list)) 572 iounmap(entry->mask_base); 573 } 574 list_del(&entry->list); 575 kfree(entry); 576 } 577 578 return 0; 579} 580 581/** 582 * pci_enable_msix - configure device's MSI-X capability structure 583 * @dev: pointer to the pci_dev data structure of MSI-X device function 584 * @entries: pointer to an array of MSI-X entries 585 * @nvec: number of MSI-X irqs requested for allocation by device driver 586 * 587 * Setup the MSI-X capability structure of device function with the number 588 * of requested irqs upon its software driver call to request for 589 * MSI-X mode enabled on its hardware device function. A return of zero 590 * indicates the successful configuration of MSI-X capability structure 591 * with new allocated MSI-X irqs. A return of < 0 indicates a failure. 592 * Or a return of > 0 indicates that driver request is exceeding the number 593 * of irqs available. Driver should use the returned value to re-send 594 * its request. 595 **/ 596int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) 597{ 598 int status, pos, nr_entries; 599 int i, j; 600 u16 control; 601 602 if (!entries) 603 return -EINVAL; 604 605 status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX); 606 if (status) 607 return status; 608 609 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); 610 pci_read_config_word(dev, msi_control_reg(pos), &control); 611 nr_entries = multi_msix_capable(control); 612 if (nvec > nr_entries) 613 return -EINVAL; 614 615 /* Check for any invalid entries */ 616 for (i = 0; i < nvec; i++) { 617 if (entries[i].entry >= nr_entries) 618 return -EINVAL; /* invalid entry */ 619 for (j = i + 1; j < nvec; j++) { 620 if (entries[i].entry == entries[j].entry) 621 return -EINVAL; /* duplicate entry */ 622 } 623 } 624 WARN_ON(!!dev->msix_enabled); 625 626 /* Check whether driver already requested for MSI irq */ 627 if (dev->msi_enabled) { 628 printk(KERN_INFO "PCI: %s: Can't enable MSI-X. " 629 "Device already has an MSI irq assigned\n", 630 pci_name(dev)); 631 return -EINVAL; 632 } 633 status = msix_capability_init(dev, entries, nvec); 634 return status; 635} 636EXPORT_SYMBOL(pci_enable_msix); 637 638static void msix_free_all_irqs(struct pci_dev *dev) 639{ 640 msi_free_irqs(dev); 641} 642 643void pci_disable_msix(struct pci_dev* dev) 644{ 645 if (!pci_msi_enable || !dev || !dev->msix_enabled) 646 return; 647 648 msix_set_enable(dev, 0); 649 pci_intx_for_msi(dev, 1); 650 dev->msix_enabled = 0; 651 652 msix_free_all_irqs(dev); 653} 654EXPORT_SYMBOL(pci_disable_msix); 655 656/** 657 * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs to unused state 658 * @dev: pointer to the pci_dev data structure of MSI(X) device function 659 * 660 * Being called during hotplug remove, from which the device function 661 * is hot-removed. All previous assigned MSI/MSI-X irqs, if 662 * allocated for this device function, are reclaimed to unused state, 663 * which may be used later on. 664 **/ 665void msi_remove_pci_irq_vectors(struct pci_dev* dev) 666{ 667 if (!pci_msi_enable || !dev) 668 return; 669 670 if (dev->msi_enabled) 671 msi_free_irqs(dev); 672 673 if (dev->msix_enabled) 674 msix_free_all_irqs(dev); 675} 676 677void pci_no_msi(void) 678{ 679 pci_msi_enable = 0; 680} 681 682void pci_msi_init_pci_dev(struct pci_dev *dev) 683{ 684 INIT_LIST_HEAD(&dev->msi_list); 685} 686 687 688/* Arch hooks */ 689 690int __attribute__ ((weak)) 691arch_msi_check_device(struct pci_dev* dev, int nvec, int type) 692{ 693 return 0; 694} 695 696int __attribute__ ((weak)) 697arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry) 698{ 699 return 0; 700} 701 702int __attribute__ ((weak)) 703arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 704{ 705 struct msi_desc *entry; 706 int ret; 707 708 list_for_each_entry(entry, &dev->msi_list, list) { 709 ret = arch_setup_msi_irq(dev, entry); 710 if (ret) 711 return ret; 712 } 713 714 return 0; 715} 716 717void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq) 718{ 719 return; 720} 721 722void __attribute__ ((weak)) 723arch_teardown_msi_irqs(struct pci_dev *dev) 724{ 725 struct msi_desc *entry; 726 727 list_for_each_entry(entry, &dev->msi_list, list) { 728 if (entry->irq != 0) 729 arch_teardown_msi_irq(entry->irq); 730 } 731} 732