diff options
-rw-r--r-- | arch/s390/include/asm/pci.h | 2 | ||||
-rw-r--r-- | arch/s390/pci/pci.c | 45 |
2 files changed, 18 insertions, 29 deletions
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index 4e3186649578..328142c8fe92 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h | |||
@@ -109,7 +109,7 @@ struct zpci_dev { | |||
109 | u64 msi_addr; /* MSI address */ | 109 | u64 msi_addr; /* MSI address */ |
110 | unsigned int max_msi; /* maximum number of MSI's */ | 110 | unsigned int max_msi; /* maximum number of MSI's */ |
111 | struct airq_iv *aibv; /* adapter interrupt bit vector */ | 111 | struct airq_iv *aibv; /* adapter interrupt bit vector */ |
112 | unsigned int aisb; /* number of the summary bit */ | 112 | unsigned long aisb; /* number of the summary bit */ |
113 | 113 | ||
114 | /* DMA stuff */ | 114 | /* DMA stuff */ |
115 | unsigned long *dma_table; | 115 | unsigned long *dma_table; |
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 8051df109db3..3dd9686c576a 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c | |||
@@ -372,22 +372,21 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
372 | struct msi_msg msg; | 372 | struct msi_msg msg; |
373 | int rc, irq; | 373 | int rc, irq; |
374 | 374 | ||
375 | zdev->aisb = -1UL; | ||
375 | if (type == PCI_CAP_ID_MSI && nvec > 1) | 376 | if (type == PCI_CAP_ID_MSI && nvec > 1) |
376 | return 1; | 377 | return 1; |
377 | msi_vecs = min_t(unsigned int, nvec, zdev->max_msi); | 378 | msi_vecs = min_t(unsigned int, nvec, zdev->max_msi); |
378 | 379 | ||
379 | /* Allocate adapter summary indicator bit */ | 380 | /* Allocate adapter summary indicator bit */ |
380 | rc = -EIO; | ||
381 | aisb = airq_iv_alloc_bit(zpci_aisb_iv); | 381 | aisb = airq_iv_alloc_bit(zpci_aisb_iv); |
382 | if (aisb == -1UL) | 382 | if (aisb == -1UL) |
383 | goto out; | 383 | return -EIO; |
384 | zdev->aisb = aisb; | 384 | zdev->aisb = aisb; |
385 | 385 | ||
386 | /* Create adapter interrupt vector */ | 386 | /* Create adapter interrupt vector */ |
387 | rc = -ENOMEM; | ||
388 | zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK); | 387 | zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK); |
389 | if (!zdev->aibv) | 388 | if (!zdev->aibv) |
390 | goto out_si; | 389 | return -ENOMEM; |
391 | 390 | ||
392 | /* Wire up shortcut pointer */ | 391 | /* Wire up shortcut pointer */ |
393 | zpci_aibv[aisb] = zdev->aibv; | 392 | zpci_aibv[aisb] = zdev->aibv; |
@@ -398,10 +397,10 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
398 | rc = -EIO; | 397 | rc = -EIO; |
399 | irq = irq_alloc_desc(0); /* Alloc irq on node 0 */ | 398 | irq = irq_alloc_desc(0); /* Alloc irq on node 0 */ |
400 | if (irq < 0) | 399 | if (irq < 0) |
401 | goto out_msi; | 400 | return -ENOMEM; |
402 | rc = irq_set_msi_desc(irq, msi); | 401 | rc = irq_set_msi_desc(irq, msi); |
403 | if (rc) | 402 | if (rc) |
404 | goto out_msi; | 403 | return rc; |
405 | irq_set_chip_and_handler(irq, &zpci_irq_chip, | 404 | irq_set_chip_and_handler(irq, &zpci_irq_chip, |
406 | handle_simple_irq); | 405 | handle_simple_irq); |
407 | msg.data = hwirq; | 406 | msg.data = hwirq; |
@@ -415,27 +414,9 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
415 | /* Enable adapter interrupts */ | 414 | /* Enable adapter interrupts */ |
416 | rc = zpci_set_airq(zdev); | 415 | rc = zpci_set_airq(zdev); |
417 | if (rc) | 416 | if (rc) |
418 | goto out_msi; | 417 | return rc; |
419 | 418 | ||
420 | return (msi_vecs == nvec) ? 0 : msi_vecs; | 419 | return (msi_vecs == nvec) ? 0 : msi_vecs; |
421 | |||
422 | out_msi: | ||
423 | for_each_pci_msi_entry(msi, pdev) { | ||
424 | if (hwirq-- == 0) | ||
425 | break; | ||
426 | irq_set_msi_desc(msi->irq, NULL); | ||
427 | irq_free_desc(msi->irq); | ||
428 | msi->msg.address_lo = 0; | ||
429 | msi->msg.address_hi = 0; | ||
430 | msi->msg.data = 0; | ||
431 | msi->irq = 0; | ||
432 | } | ||
433 | zpci_aibv[aisb] = NULL; | ||
434 | airq_iv_release(zdev->aibv); | ||
435 | out_si: | ||
436 | airq_iv_free_bit(zpci_aisb_iv, aisb); | ||
437 | out: | ||
438 | return rc; | ||
439 | } | 420 | } |
440 | 421 | ||
441 | void arch_teardown_msi_irqs(struct pci_dev *pdev) | 422 | void arch_teardown_msi_irqs(struct pci_dev *pdev) |
@@ -451,6 +432,8 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev) | |||
451 | 432 | ||
452 | /* Release MSI interrupts */ | 433 | /* Release MSI interrupts */ |
453 | for_each_pci_msi_entry(msi, pdev) { | 434 | for_each_pci_msi_entry(msi, pdev) { |
435 | if (!msi->irq) | ||
436 | continue; | ||
454 | if (msi->msi_attrib.is_msix) | 437 | if (msi->msi_attrib.is_msix) |
455 | __pci_msix_desc_mask_irq(msi, 1); | 438 | __pci_msix_desc_mask_irq(msi, 1); |
456 | else | 439 | else |
@@ -463,9 +446,15 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev) | |||
463 | msi->irq = 0; | 446 | msi->irq = 0; |
464 | } | 447 | } |
465 | 448 | ||
466 | zpci_aibv[zdev->aisb] = NULL; | 449 | if (zdev->aisb != -1UL) { |
467 | airq_iv_release(zdev->aibv); | 450 | zpci_aibv[zdev->aisb] = NULL; |
468 | airq_iv_free_bit(zpci_aisb_iv, zdev->aisb); | 451 | airq_iv_free_bit(zpci_aisb_iv, zdev->aisb); |
452 | zdev->aisb = -1UL; | ||
453 | } | ||
454 | if (zdev->aibv) { | ||
455 | airq_iv_release(zdev->aibv); | ||
456 | zdev->aibv = NULL; | ||
457 | } | ||
469 | } | 458 | } |
470 | 459 | ||
471 | static void zpci_map_resources(struct pci_dev *pdev) | 460 | static void zpci_map_resources(struct pci_dev *pdev) |