Skip to content

Commit 2796ca5

Browse files
bjking1James Bottomley
authored andcommitted
ipr: Reset in task context
The pci_set_pcie_reset_state has changed semantics to not be callable from interrupt context, so change ipr's usage of the API to comply with this change by ensuring this occurs from a workqueue. Signed-off-by: Brian King <brking@linux.vnet.ibm.com> Reviewed-by: Wen Xiong <wenxiong@linux.vnet.ibm.com> Reviewed-by: Daniel Kreling <kreling@linux.vnet.ibm.com> Signed-off-by: James Bottomley <JBottomley@Odin.com>
1 parent 4fdd7c7 commit 2796ca5

File tree

2 files changed

+67
-26
lines changed

2 files changed

+67
-26
lines changed

drivers/scsi/ipr.c

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8319,13 +8319,38 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
83198319
static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd)
83208320
{
83218321
ENTER;
8322-
pci_set_pcie_reset_state(ipr_cmd->ioa_cfg->pdev, pcie_deassert_reset);
83238322
ipr_cmd->job_step = ipr_reset_bist_done;
83248323
ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT);
83258324
LEAVE;
83268325
return IPR_RC_JOB_RETURN;
83278326
}
83288327

8328+
/**
8329+
* ipr_reset_reset_work - Pulse a PCIe fundamental reset
8330+
* @work: work struct
8331+
*
8332+
* Description: This pulses warm reset to a slot.
8333+
*
8334+
**/
8335+
static void ipr_reset_reset_work(struct work_struct *work)
8336+
{
8337+
struct ipr_cmnd *ipr_cmd = container_of(work, struct ipr_cmnd, work);
8338+
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
8339+
struct pci_dev *pdev = ioa_cfg->pdev;
8340+
unsigned long lock_flags = 0;
8341+
8342+
ENTER;
8343+
pci_set_pcie_reset_state(pdev, pcie_warm_reset);
8344+
msleep(jiffies_to_msecs(IPR_PCI_RESET_TIMEOUT));
8345+
pci_set_pcie_reset_state(pdev, pcie_deassert_reset);
8346+
8347+
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
8348+
if (ioa_cfg->reset_cmd == ipr_cmd)
8349+
ipr_reset_ioa_job(ipr_cmd);
8350+
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
8351+
LEAVE;
8352+
}
8353+
83298354
/**
83308355
* ipr_reset_slot_reset - Reset the PCI slot of the adapter.
83318356
* @ipr_cmd: ipr command struct
@@ -8338,12 +8363,11 @@ static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd)
83388363
static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
83398364
{
83408365
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
8341-
struct pci_dev *pdev = ioa_cfg->pdev;
83428366

83438367
ENTER;
8344-
pci_set_pcie_reset_state(pdev, pcie_warm_reset);
8368+
INIT_WORK(&ipr_cmd->work, ipr_reset_reset_work);
8369+
queue_work(ioa_cfg->reset_work_q, &ipr_cmd->work);
83458370
ipr_cmd->job_step = ipr_reset_slot_reset_done;
8346-
ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT);
83478371
LEAVE;
83488372
return IPR_RC_JOB_RETURN;
83498373
}
@@ -9092,26 +9116,25 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg)
90929116
}
90939117

90949118
/**
9095-
* ipr_free_all_resources - Free all allocated resources for an adapter.
9096-
* @ipr_cmd: ipr command struct
9119+
* ipr_free_irqs - Free all allocated IRQs for the adapter.
9120+
* @ioa_cfg: ipr cfg struct
90979121
*
9098-
* This function frees all allocated resources for the
9122+
* This function frees all allocated IRQs for the
90999123
* specified adapter.
91009124
*
91019125
* Return value:
91029126
* none
91039127
**/
9104-
static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg)
9128+
static void ipr_free_irqs(struct ipr_ioa_cfg *ioa_cfg)
91059129
{
91069130
struct pci_dev *pdev = ioa_cfg->pdev;
91079131

9108-
ENTER;
91099132
if (ioa_cfg->intr_flag == IPR_USE_MSI ||
91109133
ioa_cfg->intr_flag == IPR_USE_MSIX) {
91119134
int i;
91129135
for (i = 0; i < ioa_cfg->nvectors; i++)
91139136
free_irq(ioa_cfg->vectors_info[i].vec,
9114-
&ioa_cfg->hrrq[i]);
9137+
&ioa_cfg->hrrq[i]);
91159138
} else
91169139
free_irq(pdev->irq, &ioa_cfg->hrrq[0]);
91179140

@@ -9122,7 +9145,26 @@ static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg)
91229145
pci_disable_msix(pdev);
91239146
ioa_cfg->intr_flag &= ~IPR_USE_MSIX;
91249147
}
9148+
}
9149+
9150+
/**
9151+
* ipr_free_all_resources - Free all allocated resources for an adapter.
9152+
* @ipr_cmd: ipr command struct
9153+
*
9154+
* This function frees all allocated resources for the
9155+
* specified adapter.
9156+
*
9157+
* Return value:
9158+
* none
9159+
**/
9160+
static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg)
9161+
{
9162+
struct pci_dev *pdev = ioa_cfg->pdev;
91259163

9164+
ENTER;
9165+
ipr_free_irqs(ioa_cfg);
9166+
if (ioa_cfg->reset_work_q)
9167+
destroy_workqueue(ioa_cfg->reset_work_q);
91269168
iounmap(ioa_cfg->hdw_dma_regs);
91279169
pci_release_regions(pdev);
91289170
ipr_free_mem(ioa_cfg);
@@ -9942,6 +9984,14 @@ static int ipr_probe_ioa(struct pci_dev *pdev,
99429984
(dev_id->device == PCI_DEVICE_ID_IBM_OBSIDIAN_E && !ioa_cfg->revid)) {
99439985
ioa_cfg->needs_warm_reset = 1;
99449986
ioa_cfg->reset = ipr_reset_slot_reset;
9987+
9988+
ioa_cfg->reset_work_q = alloc_ordered_workqueue("ipr_reset_%d",
9989+
WQ_MEM_RECLAIM, host->host_no);
9990+
9991+
if (!ioa_cfg->reset_work_q) {
9992+
dev_err(&pdev->dev, "Couldn't register reset workqueue\n");
9993+
goto out_free_irq;
9994+
}
99459995
} else
99469996
ioa_cfg->reset = ipr_reset_start_bist;
99479997

@@ -9953,6 +10003,8 @@ static int ipr_probe_ioa(struct pci_dev *pdev,
995310003
out:
995410004
return rc;
995510005

10006+
out_free_irq:
10007+
ipr_free_irqs(ioa_cfg);
995610008
cleanup_nolog:
995710009
ipr_free_mem(ioa_cfg);
995810010
out_msi_disable:
@@ -10033,6 +10085,8 @@ static void __ipr_remove(struct pci_dev *pdev)
1003310085
spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
1003410086
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
1003510087
flush_work(&ioa_cfg->work_q);
10088+
if (ioa_cfg->reset_work_q)
10089+
flush_workqueue(ioa_cfg->reset_work_q);
1003610090
INIT_LIST_HEAD(&ioa_cfg->used_res_q);
1003710091
spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
1003810092

@@ -10178,22 +10232,7 @@ static void ipr_shutdown(struct pci_dev *pdev)
1017810232
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
1017910233
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
1018010234
if (ipr_fast_reboot && system_state == SYSTEM_RESTART && ioa_cfg->sis64) {
10181-
if (ioa_cfg->intr_flag == IPR_USE_MSI ||
10182-
ioa_cfg->intr_flag == IPR_USE_MSIX) {
10183-
int i;
10184-
for (i = 0; i < ioa_cfg->nvectors; i++)
10185-
free_irq(ioa_cfg->vectors_info[i].vec,
10186-
&ioa_cfg->hrrq[i]);
10187-
}
10188-
10189-
if (ioa_cfg->intr_flag == IPR_USE_MSI) {
10190-
pci_disable_msi(ioa_cfg->pdev);
10191-
ioa_cfg->intr_flag &= ~IPR_USE_MSI;
10192-
} else if (ioa_cfg->intr_flag == IPR_USE_MSIX) {
10193-
pci_disable_msix(ioa_cfg->pdev);
10194-
ioa_cfg->intr_flag &= ~IPR_USE_MSIX;
10195-
}
10196-
10235+
ipr_free_irqs(ioa_cfg);
1019710236
pci_disable_device(ioa_cfg->pdev);
1019810237
}
1019910238
}

drivers/scsi/ipr.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,7 @@ struct ipr_ioa_cfg {
15401540
u8 saved_mode_page_len;
15411541

15421542
struct work_struct work_q;
1543+
struct workqueue_struct *reset_work_q;
15431544

15441545
wait_queue_head_t reset_wait_q;
15451546
wait_queue_head_t msi_wait_q;
@@ -1591,6 +1592,7 @@ struct ipr_cmnd {
15911592
struct ata_queued_cmd *qc;
15921593
struct completion completion;
15931594
struct timer_list timer;
1595+
struct work_struct work;
15941596
void (*fast_done) (struct ipr_cmnd *);
15951597
void (*done) (struct ipr_cmnd *);
15961598
int (*job_step) (struct ipr_cmnd *);

0 commit comments

Comments
 (0)