diff options
author | Brian King <brking@linux.vnet.ibm.com> | 2015-03-26 12:23:52 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Odin.com> | 2015-04-09 16:43:14 -0400 |
commit | 2796ca5e51737ed0be8ebb6cf73fd56af05da0a7 (patch) | |
tree | 6b6ae274bf930a91025b0b1e18200b8a73ecf310 | |
parent | 4fdd7c7aabbec3aa9e5dc41c129bc9f6aed7e615 (diff) |
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>
-rw-r--r-- | drivers/scsi/ipr.c | 91 | ||||
-rw-r--r-- | drivers/scsi/ipr.h | 2 |
2 files changed, 67 insertions, 26 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 190d0ae0193f..200110caae17 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -8319,7 +8319,6 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) | |||
8319 | static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd) | 8319 | static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd) |
8320 | { | 8320 | { |
8321 | ENTER; | 8321 | ENTER; |
8322 | pci_set_pcie_reset_state(ipr_cmd->ioa_cfg->pdev, pcie_deassert_reset); | ||
8323 | ipr_cmd->job_step = ipr_reset_bist_done; | 8322 | ipr_cmd->job_step = ipr_reset_bist_done; |
8324 | ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT); | 8323 | ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT); |
8325 | LEAVE; | 8324 | LEAVE; |
@@ -8327,6 +8326,32 @@ static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd) | |||
8327 | } | 8326 | } |
8328 | 8327 | ||
8329 | /** | 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 | |||
8354 | /** | ||
8330 | * ipr_reset_slot_reset - Reset the PCI slot of the adapter. | 8355 | * ipr_reset_slot_reset - Reset the PCI slot of the adapter. |
8331 | * @ipr_cmd: ipr command struct | 8356 | * @ipr_cmd: ipr command struct |
8332 | * | 8357 | * |
@@ -8338,12 +8363,11 @@ static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd) | |||
8338 | static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd) | 8363 | static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd) |
8339 | { | 8364 | { |
8340 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 8365 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
8341 | struct pci_dev *pdev = ioa_cfg->pdev; | ||
8342 | 8366 | ||
8343 | ENTER; | 8367 | 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); | ||
8345 | ipr_cmd->job_step = ipr_reset_slot_reset_done; | 8370 | ipr_cmd->job_step = ipr_reset_slot_reset_done; |
8346 | ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT); | ||
8347 | LEAVE; | 8371 | LEAVE; |
8348 | return IPR_RC_JOB_RETURN; | 8372 | return IPR_RC_JOB_RETURN; |
8349 | } | 8373 | } |
@@ -9092,26 +9116,25 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg) | |||
9092 | } | 9116 | } |
9093 | 9117 | ||
9094 | /** | 9118 | /** |
9095 | * ipr_free_all_resources - Free all allocated resources for an adapter. | 9119 | * ipr_free_irqs - Free all allocated IRQs for the adapter. |
9096 | * @ipr_cmd: ipr command struct | 9120 | * @ioa_cfg: ipr cfg struct |
9097 | * | 9121 | * |
9098 | * This function frees all allocated resources for the | 9122 | * This function frees all allocated IRQs for the |
9099 | * specified adapter. | 9123 | * specified adapter. |
9100 | * | 9124 | * |
9101 | * Return value: | 9125 | * Return value: |
9102 | * none | 9126 | * none |
9103 | **/ | 9127 | **/ |
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) |
9105 | { | 9129 | { |
9106 | struct pci_dev *pdev = ioa_cfg->pdev; | 9130 | struct pci_dev *pdev = ioa_cfg->pdev; |
9107 | 9131 | ||
9108 | ENTER; | ||
9109 | if (ioa_cfg->intr_flag == IPR_USE_MSI || | 9132 | if (ioa_cfg->intr_flag == IPR_USE_MSI || |
9110 | ioa_cfg->intr_flag == IPR_USE_MSIX) { | 9133 | ioa_cfg->intr_flag == IPR_USE_MSIX) { |
9111 | int i; | 9134 | int i; |
9112 | for (i = 0; i < ioa_cfg->nvectors; i++) | 9135 | for (i = 0; i < ioa_cfg->nvectors; i++) |
9113 | free_irq(ioa_cfg->vectors_info[i].vec, | 9136 | free_irq(ioa_cfg->vectors_info[i].vec, |
9114 | &ioa_cfg->hrrq[i]); | 9137 | &ioa_cfg->hrrq[i]); |
9115 | } else | 9138 | } else |
9116 | free_irq(pdev->irq, &ioa_cfg->hrrq[0]); | 9139 | free_irq(pdev->irq, &ioa_cfg->hrrq[0]); |
9117 | 9140 | ||
@@ -9122,7 +9145,26 @@ static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg) | |||
9122 | pci_disable_msix(pdev); | 9145 | pci_disable_msix(pdev); |
9123 | ioa_cfg->intr_flag &= ~IPR_USE_MSIX; | 9146 | ioa_cfg->intr_flag &= ~IPR_USE_MSIX; |
9124 | } | 9147 | } |
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; | ||
9125 | 9163 | ||
9164 | ENTER; | ||
9165 | ipr_free_irqs(ioa_cfg); | ||
9166 | if (ioa_cfg->reset_work_q) | ||
9167 | destroy_workqueue(ioa_cfg->reset_work_q); | ||
9126 | iounmap(ioa_cfg->hdw_dma_regs); | 9168 | iounmap(ioa_cfg->hdw_dma_regs); |
9127 | pci_release_regions(pdev); | 9169 | pci_release_regions(pdev); |
9128 | ipr_free_mem(ioa_cfg); | 9170 | ipr_free_mem(ioa_cfg); |
@@ -9942,6 +9984,14 @@ static int ipr_probe_ioa(struct pci_dev *pdev, | |||
9942 | (dev_id->device == PCI_DEVICE_ID_IBM_OBSIDIAN_E && !ioa_cfg->revid)) { | 9984 | (dev_id->device == PCI_DEVICE_ID_IBM_OBSIDIAN_E && !ioa_cfg->revid)) { |
9943 | ioa_cfg->needs_warm_reset = 1; | 9985 | ioa_cfg->needs_warm_reset = 1; |
9944 | ioa_cfg->reset = ipr_reset_slot_reset; | 9986 | 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 | } | ||
9945 | } else | 9995 | } else |
9946 | ioa_cfg->reset = ipr_reset_start_bist; | 9996 | ioa_cfg->reset = ipr_reset_start_bist; |
9947 | 9997 | ||
@@ -9953,6 +10003,8 @@ static int ipr_probe_ioa(struct pci_dev *pdev, | |||
9953 | out: | 10003 | out: |
9954 | return rc; | 10004 | return rc; |
9955 | 10005 | ||
10006 | out_free_irq: | ||
10007 | ipr_free_irqs(ioa_cfg); | ||
9956 | cleanup_nolog: | 10008 | cleanup_nolog: |
9957 | ipr_free_mem(ioa_cfg); | 10009 | ipr_free_mem(ioa_cfg); |
9958 | out_msi_disable: | 10010 | out_msi_disable: |
@@ -10033,6 +10085,8 @@ static void __ipr_remove(struct pci_dev *pdev) | |||
10033 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags); | 10085 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags); |
10034 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); | 10086 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); |
10035 | flush_work(&ioa_cfg->work_q); | 10087 | flush_work(&ioa_cfg->work_q); |
10088 | if (ioa_cfg->reset_work_q) | ||
10089 | flush_workqueue(ioa_cfg->reset_work_q); | ||
10036 | INIT_LIST_HEAD(&ioa_cfg->used_res_q); | 10090 | INIT_LIST_HEAD(&ioa_cfg->used_res_q); |
10037 | spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags); | 10091 | spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags); |
10038 | 10092 | ||
@@ -10178,22 +10232,7 @@ static void ipr_shutdown(struct pci_dev *pdev) | |||
10178 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | 10232 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); |
10179 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); | 10233 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); |
10180 | if (ipr_fast_reboot && system_state == SYSTEM_RESTART && ioa_cfg->sis64) { | 10234 | if (ipr_fast_reboot && system_state == SYSTEM_RESTART && ioa_cfg->sis64) { |
10181 | if (ioa_cfg->intr_flag == IPR_USE_MSI || | 10235 | ipr_free_irqs(ioa_cfg); |
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 | |||
10197 | pci_disable_device(ioa_cfg->pdev); | 10236 | pci_disable_device(ioa_cfg->pdev); |
10198 | } | 10237 | } |
10199 | } | 10238 | } |
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 34eec5bcdce0..f7d0e375e4f6 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h | |||
@@ -1540,6 +1540,7 @@ struct ipr_ioa_cfg { | |||
1540 | u8 saved_mode_page_len; | 1540 | u8 saved_mode_page_len; |
1541 | 1541 | ||
1542 | struct work_struct work_q; | 1542 | struct work_struct work_q; |
1543 | struct workqueue_struct *reset_work_q; | ||
1543 | 1544 | ||
1544 | wait_queue_head_t reset_wait_q; | 1545 | wait_queue_head_t reset_wait_q; |
1545 | wait_queue_head_t msi_wait_q; | 1546 | wait_queue_head_t msi_wait_q; |
@@ -1591,6 +1592,7 @@ struct ipr_cmnd { | |||
1591 | struct ata_queued_cmd *qc; | 1592 | struct ata_queued_cmd *qc; |
1592 | struct completion completion; | 1593 | struct completion completion; |
1593 | struct timer_list timer; | 1594 | struct timer_list timer; |
1595 | struct work_struct work; | ||
1594 | void (*fast_done) (struct ipr_cmnd *); | 1596 | void (*fast_done) (struct ipr_cmnd *); |
1595 | void (*done) (struct ipr_cmnd *); | 1597 | void (*done) (struct ipr_cmnd *); |
1596 | int (*job_step) (struct ipr_cmnd *); | 1598 | int (*job_step) (struct ipr_cmnd *); |