aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ipr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r--drivers/scsi/ipr.c138
1 files changed, 117 insertions, 21 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 0f8bc772b112..5f045505a1f4 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -131,13 +131,13 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
131}; 131};
132 132
133static const struct ipr_chip_t ipr_chip[] = { 133static const struct ipr_chip_t ipr_chip[] = {
134 { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, &ipr_chip_cfg[0] }, 134 { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, IPR_USE_LSI, &ipr_chip_cfg[0] },
135 { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, &ipr_chip_cfg[0] }, 135 { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, IPR_USE_LSI, &ipr_chip_cfg[0] },
136 { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, &ipr_chip_cfg[0] }, 136 { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, IPR_USE_LSI, &ipr_chip_cfg[0] },
137 { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, &ipr_chip_cfg[0] }, 137 { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, IPR_USE_LSI, &ipr_chip_cfg[0] },
138 { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, &ipr_chip_cfg[0] }, 138 { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, IPR_USE_MSI, &ipr_chip_cfg[0] },
139 { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, &ipr_chip_cfg[1] }, 139 { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, IPR_USE_LSI, &ipr_chip_cfg[1] },
140 { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, &ipr_chip_cfg[1] } 140 { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, IPR_USE_LSI, &ipr_chip_cfg[1] }
141}; 141};
142 142
143static int ipr_max_bus_speeds [] = { 143static int ipr_max_bus_speeds [] = {
@@ -7367,6 +7367,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
7367 INIT_LIST_HEAD(&ioa_cfg->used_res_q); 7367 INIT_LIST_HEAD(&ioa_cfg->used_res_q);
7368 INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread); 7368 INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread);
7369 init_waitqueue_head(&ioa_cfg->reset_wait_q); 7369 init_waitqueue_head(&ioa_cfg->reset_wait_q);
7370 init_waitqueue_head(&ioa_cfg->msi_wait_q);
7370 ioa_cfg->sdt_state = INACTIVE; 7371 ioa_cfg->sdt_state = INACTIVE;
7371 if (ipr_enable_cache) 7372 if (ipr_enable_cache)
7372 ioa_cfg->cache_state = CACHE_ENABLED; 7373 ioa_cfg->cache_state = CACHE_ENABLED;
@@ -7398,25 +7399,108 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
7398} 7399}
7399 7400
7400/** 7401/**
7401 * ipr_get_chip_cfg - Find adapter chip configuration 7402 * ipr_get_chip_info - Find adapter chip information
7402 * @dev_id: PCI device id struct 7403 * @dev_id: PCI device id struct
7403 * 7404 *
7404 * Return value: 7405 * Return value:
7405 * ptr to chip config on success / NULL on failure 7406 * ptr to chip information on success / NULL on failure
7406 **/ 7407 **/
7407static const struct ipr_chip_cfg_t * __devinit 7408static const struct ipr_chip_t * __devinit
7408ipr_get_chip_cfg(const struct pci_device_id *dev_id) 7409ipr_get_chip_info(const struct pci_device_id *dev_id)
7409{ 7410{
7410 int i; 7411 int i;
7411 7412
7412 for (i = 0; i < ARRAY_SIZE(ipr_chip); i++) 7413 for (i = 0; i < ARRAY_SIZE(ipr_chip); i++)
7413 if (ipr_chip[i].vendor == dev_id->vendor && 7414 if (ipr_chip[i].vendor == dev_id->vendor &&
7414 ipr_chip[i].device == dev_id->device) 7415 ipr_chip[i].device == dev_id->device)
7415 return ipr_chip[i].cfg; 7416 return &ipr_chip[i];
7416 return NULL; 7417 return NULL;
7417} 7418}
7418 7419
7419/** 7420/**
7421 * ipr_test_intr - Handle the interrupt generated in ipr_test_msi().
7422 * @pdev: PCI device struct
7423 *
7424 * Description: Simply set the msi_received flag to 1 indicating that
7425 * Message Signaled Interrupts are supported.
7426 *
7427 * Return value:
7428 * 0 on success / non-zero on failure
7429 **/
7430static irqreturn_t __devinit ipr_test_intr(int irq, void *devp)
7431{
7432 struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
7433 unsigned long lock_flags = 0;
7434 irqreturn_t rc = IRQ_HANDLED;
7435
7436 spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
7437
7438 ioa_cfg->msi_received = 1;
7439 wake_up(&ioa_cfg->msi_wait_q);
7440
7441 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
7442 return rc;
7443}
7444
7445/**
7446 * ipr_test_msi - Test for Message Signaled Interrupt (MSI) support.
7447 * @pdev: PCI device struct
7448 *
7449 * Description: The return value from pci_enable_msi() can not always be
7450 * trusted. This routine sets up and initiates a test interrupt to determine
7451 * if the interrupt is received via the ipr_test_intr() service routine.
7452 * If the tests fails, the driver will fall back to LSI.
7453 *
7454 * Return value:
7455 * 0 on success / non-zero on failure
7456 **/
7457static int __devinit ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg,
7458 struct pci_dev *pdev)
7459{
7460 int rc;
7461 volatile u32 int_reg;
7462 unsigned long lock_flags = 0;
7463
7464 ENTER;
7465
7466 spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
7467 init_waitqueue_head(&ioa_cfg->msi_wait_q);
7468 ioa_cfg->msi_received = 0;
7469 ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
7470 writel(IPR_PCII_IO_DEBUG_ACKNOWLEDGE, ioa_cfg->regs.clr_interrupt_mask_reg);
7471 int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
7472 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
7473
7474 rc = request_irq(pdev->irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg);
7475 if (rc) {
7476 dev_err(&pdev->dev, "Can not assign irq %d\n", pdev->irq);
7477 return rc;
7478 } else if (ipr_debug)
7479 dev_info(&pdev->dev, "IRQ assigned: %d\n", pdev->irq);
7480
7481 writel(IPR_PCII_IO_DEBUG_ACKNOWLEDGE, ioa_cfg->regs.sense_interrupt_reg);
7482 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);
7483 wait_event_timeout(ioa_cfg->msi_wait_q, ioa_cfg->msi_received, HZ);
7484 ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
7485
7486 spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
7487 if (!ioa_cfg->msi_received) {
7488 /* MSI test failed */
7489 dev_info(&pdev->dev, "MSI test failed. Falling back to LSI.\n");
7490 rc = -EOPNOTSUPP;
7491 } else if (ipr_debug)
7492 dev_info(&pdev->dev, "MSI test succeeded.\n");
7493
7494 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
7495
7496 free_irq(pdev->irq, ioa_cfg);
7497
7498 LEAVE;
7499
7500 return rc;
7501}
7502
7503/**
7420 * ipr_probe_ioa - Allocates memory and does first stage of initialization 7504 * ipr_probe_ioa - Allocates memory and does first stage of initialization
7421 * @pdev: PCI device struct 7505 * @pdev: PCI device struct
7422 * @dev_id: PCI device id struct 7506 * @dev_id: PCI device id struct
@@ -7441,11 +7525,6 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
7441 goto out; 7525 goto out;
7442 } 7526 }
7443 7527
7444 if (!(rc = pci_enable_msi(pdev)))
7445 dev_info(&pdev->dev, "MSI enabled\n");
7446 else if (ipr_debug)
7447 dev_info(&pdev->dev, "Cannot enable MSI\n");
7448
7449 dev_info(&pdev->dev, "Found IOA with IRQ: %d\n", pdev->irq); 7528 dev_info(&pdev->dev, "Found IOA with IRQ: %d\n", pdev->irq);
7450 7529
7451 host = scsi_host_alloc(&driver_template, sizeof(*ioa_cfg)); 7530 host = scsi_host_alloc(&driver_template, sizeof(*ioa_cfg));
@@ -7461,14 +7540,16 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
7461 ata_host_init(&ioa_cfg->ata_host, &pdev->dev, 7540 ata_host_init(&ioa_cfg->ata_host, &pdev->dev,
7462 sata_port_info.flags, &ipr_sata_ops); 7541 sata_port_info.flags, &ipr_sata_ops);
7463 7542
7464 ioa_cfg->chip_cfg = ipr_get_chip_cfg(dev_id); 7543 ioa_cfg->ipr_chip = ipr_get_chip_info(dev_id);
7465 7544
7466 if (!ioa_cfg->chip_cfg) { 7545 if (!ioa_cfg->ipr_chip) {
7467 dev_err(&pdev->dev, "Unknown adapter chipset 0x%04X 0x%04X\n", 7546 dev_err(&pdev->dev, "Unknown adapter chipset 0x%04X 0x%04X\n",
7468 dev_id->vendor, dev_id->device); 7547 dev_id->vendor, dev_id->device);
7469 goto out_scsi_host_put; 7548 goto out_scsi_host_put;
7470 } 7549 }
7471 7550
7551 ioa_cfg->chip_cfg = ioa_cfg->ipr_chip->cfg;
7552
7472 if (ipr_transop_timeout) 7553 if (ipr_transop_timeout)
7473 ioa_cfg->transop_timeout = ipr_transop_timeout; 7554 ioa_cfg->transop_timeout = ipr_transop_timeout;
7474 else if (dev_id->driver_data & IPR_USE_LONG_TRANSOP_TIMEOUT) 7555 else if (dev_id->driver_data & IPR_USE_LONG_TRANSOP_TIMEOUT)
@@ -7519,6 +7600,18 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
7519 goto cleanup_nomem; 7600 goto cleanup_nomem;
7520 } 7601 }
7521 7602
7603 /* Enable MSI style interrupts if they are supported. */
7604 if (ioa_cfg->ipr_chip->intr_type == IPR_USE_MSI && !pci_enable_msi(pdev)) {
7605 rc = ipr_test_msi(ioa_cfg, pdev);
7606 if (rc == -EOPNOTSUPP)
7607 pci_disable_msi(pdev);
7608 else if (rc)
7609 goto out_msi_disable;
7610 else
7611 dev_info(&pdev->dev, "MSI enabled with IRQ: %d\n", pdev->irq);
7612 } else if (ipr_debug)
7613 dev_info(&pdev->dev, "Cannot enable MSI.\n");
7614
7522 /* Save away PCI config space for use following IOA reset */ 7615 /* Save away PCI config space for use following IOA reset */
7523 rc = pci_save_state(pdev); 7616 rc = pci_save_state(pdev);
7524 7617
@@ -7556,7 +7649,9 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
7556 ioa_cfg->ioa_unit_checked = 1; 7649 ioa_cfg->ioa_unit_checked = 1;
7557 7650
7558 ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER); 7651 ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
7559 rc = request_irq(pdev->irq, ipr_isr, IRQF_SHARED, IPR_NAME, ioa_cfg); 7652 rc = request_irq(pdev->irq, ipr_isr,
7653 ioa_cfg->msi_received ? 0 : IRQF_SHARED,
7654 IPR_NAME, ioa_cfg);
7560 7655
7561 if (rc) { 7656 if (rc) {
7562 dev_err(&pdev->dev, "Couldn't register IRQ %d! rc=%d\n", 7657 dev_err(&pdev->dev, "Couldn't register IRQ %d! rc=%d\n",
@@ -7583,12 +7678,13 @@ cleanup_nolog:
7583 ipr_free_mem(ioa_cfg); 7678 ipr_free_mem(ioa_cfg);
7584cleanup_nomem: 7679cleanup_nomem:
7585 iounmap(ipr_regs); 7680 iounmap(ipr_regs);
7681out_msi_disable:
7682 pci_disable_msi(pdev);
7586out_release_regions: 7683out_release_regions:
7587 pci_release_regions(pdev); 7684 pci_release_regions(pdev);
7588out_scsi_host_put: 7685out_scsi_host_put:
7589 scsi_host_put(host); 7686 scsi_host_put(host);
7590out_disable: 7687out_disable:
7591 pci_disable_msi(pdev);
7592 pci_disable_device(pdev); 7688 pci_disable_device(pdev);
7593 goto out; 7689 goto out;
7594} 7690}