Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 154031
b: refs/heads/master
c: 95fecd9
h: refs/heads/master
i:
  154029: 241a7e0
  154027: 46cd350
  154023: 77a8d8c
  154015: 40da598
v: v3
  • Loading branch information
Wayne Boyer authored and James Bottomley committed Jun 21, 2009
1 parent 62fbbcc commit e9d0624
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 10 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a9e0edb687151617fe89cc5ab0086ebfc73ffccb
refs/heads/master: 95fecd90397ec1f85eb31ede955d846a86d2077b
108 changes: 101 additions & 7 deletions trunk/drivers/scsi/ipr.c
Original file line number Diff line number Diff line change
Expand Up @@ -7367,6 +7367,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
INIT_LIST_HEAD(&ioa_cfg->used_res_q);
INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread);
init_waitqueue_head(&ioa_cfg->reset_wait_q);
init_waitqueue_head(&ioa_cfg->msi_wait_q);
ioa_cfg->sdt_state = INACTIVE;
if (ipr_enable_cache)
ioa_cfg->cache_state = CACHE_ENABLED;
Expand Down Expand Up @@ -7416,6 +7417,89 @@ ipr_get_chip_cfg(const struct pci_device_id *dev_id)
return NULL;
}

/**
* ipr_test_intr - Handle the interrupt generated in ipr_test_msi().
* @pdev: PCI device struct
*
* Description: Simply set the msi_received flag to 1 indicating that
* Message Signaled Interrupts are supported.
*
* Return value:
* 0 on success / non-zero on failure
**/
static irqreturn_t __devinit ipr_test_intr(int irq, void *devp)
{
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
unsigned long lock_flags = 0;
irqreturn_t rc = IRQ_HANDLED;

spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);

ioa_cfg->msi_received = 1;
wake_up(&ioa_cfg->msi_wait_q);

spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return rc;
}

/**
* ipr_test_msi - Test for Message Signaled Interrupt (MSI) support.
* @pdev: PCI device struct
*
* Description: The return value from pci_enable_msi() can not always be
* trusted. This routine sets up and initiates a test interrupt to determine
* if the interrupt is received via the ipr_test_intr() service routine.
* If the tests fails, the driver will fall back to LSI.
*
* Return value:
* 0 on success / non-zero on failure
**/
static int __devinit ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg,
struct pci_dev *pdev)
{
int rc;
volatile u32 int_reg;
unsigned long lock_flags = 0;

ENTER;

spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
init_waitqueue_head(&ioa_cfg->msi_wait_q);
ioa_cfg->msi_received = 0;
ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
writel(IPR_PCII_IO_DEBUG_ACKNOWLEDGE, ioa_cfg->regs.clr_interrupt_mask_reg);
int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);

rc = request_irq(pdev->irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg);
if (rc) {
dev_err(&pdev->dev, "Can not assign irq %d\n", pdev->irq);
return rc;
} else if (ipr_debug)
dev_info(&pdev->dev, "IRQ assigned: %d\n", pdev->irq);

writel(IPR_PCII_IO_DEBUG_ACKNOWLEDGE, ioa_cfg->regs.sense_interrupt_reg);
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);
wait_event_timeout(ioa_cfg->msi_wait_q, ioa_cfg->msi_received, HZ);
ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);

spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
if (!ioa_cfg->msi_received) {
/* MSI test failed */
dev_info(&pdev->dev, "MSI test failed. Falling back to LSI.\n");
rc = -EOPNOTSUPP;
} else if (ipr_debug)
dev_info(&pdev->dev, "MSI test succeeded.\n");

spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);

free_irq(pdev->irq, ioa_cfg);

LEAVE;

return rc;
}

/**
* ipr_probe_ioa - Allocates memory and does first stage of initialization
* @pdev: PCI device struct
Expand All @@ -7441,11 +7525,6 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
goto out;
}

if (!(rc = pci_enable_msi(pdev)))
dev_info(&pdev->dev, "MSI enabled\n");
else if (ipr_debug)
dev_info(&pdev->dev, "Cannot enable MSI\n");

dev_info(&pdev->dev, "Found IOA with IRQ: %d\n", pdev->irq);

host = scsi_host_alloc(&driver_template, sizeof(*ioa_cfg));
Expand Down Expand Up @@ -7519,6 +7598,18 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
goto cleanup_nomem;
}

/* Enable MSI style interrupts if they are supported. */
if (!(rc = pci_enable_msi(pdev))) {
rc = ipr_test_msi(ioa_cfg, pdev);
if (rc == -EOPNOTSUPP)
pci_disable_msi(pdev);
else if (rc)
goto out_msi_disable;
else
dev_info(&pdev->dev, "MSI enabled with IRQ: %d\n", pdev->irq);
} else if (ipr_debug)
dev_info(&pdev->dev, "Cannot enable MSI.\n");

/* Save away PCI config space for use following IOA reset */
rc = pci_save_state(pdev);

Expand Down Expand Up @@ -7556,7 +7647,9 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
ioa_cfg->ioa_unit_checked = 1;

ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
rc = request_irq(pdev->irq, ipr_isr, IRQF_SHARED, IPR_NAME, ioa_cfg);
rc = request_irq(pdev->irq, ipr_isr,
ioa_cfg->msi_received ? 0 : IRQF_SHARED,
IPR_NAME, ioa_cfg);

if (rc) {
dev_err(&pdev->dev, "Couldn't register IRQ %d! rc=%d\n",
Expand All @@ -7583,12 +7676,13 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
ipr_free_mem(ioa_cfg);
cleanup_nomem:
iounmap(ipr_regs);
out_msi_disable:
pci_disable_msi(pdev);
out_release_regions:
pci_release_regions(pdev);
out_scsi_host_put:
scsi_host_put(host);
out_disable:
pci_disable_msi(pdev);
pci_disable_device(pdev);
goto out;
}
Expand Down
6 changes: 4 additions & 2 deletions trunk/drivers/scsi/ipr.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
/*
* Literals
*/
#define IPR_DRIVER_VERSION "2.4.2"
#define IPR_DRIVER_DATE "(January 21, 2009)"
#define IPR_DRIVER_VERSION "2.4.3"
#define IPR_DRIVER_DATE "(June 10, 2009)"

/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
Expand Down Expand Up @@ -1094,6 +1094,7 @@ struct ipr_ioa_cfg {
u8 needs_hard_reset:1;
u8 dual_raid:1;
u8 needs_warm_reset:1;
u8 msi_received:1;

u8 revid;

Expand Down Expand Up @@ -1179,6 +1180,7 @@ struct ipr_ioa_cfg {
struct work_struct work_q;

wait_queue_head_t reset_wait_q;
wait_queue_head_t msi_wait_q;

struct ipr_dump *dump;
enum ipr_sdt_state sdt_state;
Expand Down

0 comments on commit e9d0624

Please sign in to comment.