aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-08-24 21:50:11 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-10-13 09:28:54 -0400
commita8e497d51e6adb2dd6ef307ae76f3433a4dbe895 (patch)
tree35c1a66bcd2fc8903cc7f25cfbafb919f5cd7b9a /drivers
parent84774a4d0a4dba8a5767da6c58ea5a8c5b0cfe25 (diff)
[SCSI] lpfc 8.2.8 : Add support for PCI-EEH permanent disabling
Add support for PCI-EEH permanent-disabling a device via lpfc_pci_remove_one() Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c9
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c29
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c64
5 files changed, 103 insertions, 3 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 189ce9f8a7b1..495afd06936b 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -199,6 +199,7 @@ int lpfc_sli_issue_iocb(struct lpfc_hba *, struct lpfc_sli_ring *,
199 struct lpfc_iocbq *, uint32_t); 199 struct lpfc_iocbq *, uint32_t);
200void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t); 200void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
201void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *); 201void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
202void lpfc_sli_flush_fcp_rings(struct lpfc_hba *);
202int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, 203int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
203 struct lpfc_dmabuf *); 204 struct lpfc_dmabuf *);
204struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, 205struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
@@ -290,6 +291,7 @@ void lpfc_unblock_fabric_iocbs(struct lpfc_hba *);
290void lpfc_adjust_queue_depth(struct lpfc_hba *); 291void lpfc_adjust_queue_depth(struct lpfc_hba *);
291void lpfc_ramp_down_queue_handler(struct lpfc_hba *); 292void lpfc_ramp_down_queue_handler(struct lpfc_hba *);
292void lpfc_ramp_up_queue_handler(struct lpfc_hba *); 293void lpfc_ramp_up_queue_handler(struct lpfc_hba *);
294void lpfc_scsi_dev_block(struct lpfc_hba *);
293 295
294#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code) 296#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
295#define HBA_EVENT_RSCN 5 297#define HBA_EVENT_RSCN 5
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index b4ef83623532..897ef7d7a8e9 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -237,8 +237,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
237 lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], 237 lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
238 ndlp->nlp_sid, 0, LPFC_CTX_TGT); 238 ndlp->nlp_sid, 0, LPFC_CTX_TGT);
239 } 239 }
240 if (vport->load_flag & FC_UNLOADING)
241 warn_on = 0;
242 240
243 if (warn_on) { 241 if (warn_on) {
244 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, 242 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 41a8c13e6950..333166b17908 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2661,8 +2661,15 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
2661 struct lpfc_sli *psli = &phba->sli; 2661 struct lpfc_sli *psli = &phba->sli;
2662 struct lpfc_sli_ring *pring; 2662 struct lpfc_sli_ring *pring;
2663 2663
2664 if (state == pci_channel_io_perm_failure) 2664 if (state == pci_channel_io_perm_failure) {
2665 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2666 "0472 PCI channel I/O permanent failure\n");
2667 /* Block all SCSI devices' I/Os on the host */
2668 lpfc_scsi_dev_block(phba);
2669 /* Clean up all driver's outstanding SCSI I/Os */
2670 lpfc_sli_flush_fcp_rings(phba);
2665 return PCI_ERS_RESULT_DISCONNECT; 2671 return PCI_ERS_RESULT_DISCONNECT;
2672 }
2666 2673
2667 pci_disable_device(pdev); 2674 pci_disable_device(pdev);
2668 /* 2675 /*
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index b73968b2b8b4..3606b7098fc1 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -183,6 +183,35 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
183 atomic_set(&phba->num_cmd_success, 0); 183 atomic_set(&phba->num_cmd_success, 0);
184} 184}
185 185
186/**
187 * lpfc_scsi_dev_block: set all scsi hosts to block state.
188 * @phba: Pointer to HBA context object.
189 *
190 * This function walks vport list and set each SCSI host to block state
191 * by invoking fc_remote_port_delete() routine. This function is invoked
192 * with EEH when device's PCI slot has been permanently disabled.
193 **/
194void
195lpfc_scsi_dev_block(struct lpfc_hba *phba)
196{
197 struct lpfc_vport **vports;
198 struct Scsi_Host *shost;
199 struct scsi_device *sdev;
200 struct fc_rport *rport;
201 int i;
202
203 vports = lpfc_create_vport_work_array(phba);
204 if (vports != NULL)
205 for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
206 shost = lpfc_shost_from_vport(vports[i]);
207 shost_for_each_device(sdev, shost) {
208 rport = starget_to_rport(scsi_target(sdev));
209 fc_remote_port_delete(rport);
210 }
211 }
212 lpfc_destroy_vport_work_array(phba, vports);
213}
214
186/* 215/*
187 * This routine allocates a scsi buffer, which contains all the necessary 216 * This routine allocates a scsi buffer, which contains all the necessary
188 * information needed to initiate a SCSI I/O. The non-DMAable buffer region 217 * information needed to initiate a SCSI I/O. The non-DMAable buffer region
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 857bc0a57c47..1812e18246d5 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -2377,6 +2377,70 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
2377} 2377}
2378 2378
2379/** 2379/**
2380 * lpfc_sli_flush_fcp_rings: flush all iocbs in the fcp ring.
2381 * @phba: Pointer to HBA context object.
2382 *
2383 * This function flushes all iocbs in the fcp ring and frees all the iocb
2384 * objects in txq and txcmplq. This function will not issue abort iocbs
2385 * for all the iocb commands in txcmplq, they will just be returned with
2386 * IOERR_SLI_DOWN. This function is invoked with EEH when device's PCI
2387 * slot has been permanently disabled.
2388 **/
2389void
2390lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba)
2391{
2392 LIST_HEAD(txq);
2393 LIST_HEAD(txcmplq);
2394 struct lpfc_iocbq *iocb;
2395 IOCB_t *cmd = NULL;
2396 struct lpfc_sli *psli = &phba->sli;
2397 struct lpfc_sli_ring *pring;
2398
2399 /* Currently, only one fcp ring */
2400 pring = &psli->ring[psli->fcp_ring];
2401
2402 spin_lock_irq(&phba->hbalock);
2403 /* Retrieve everything on txq */
2404 list_splice_init(&pring->txq, &txq);
2405 pring->txq_cnt = 0;
2406
2407 /* Retrieve everything on the txcmplq */
2408 list_splice_init(&pring->txcmplq, &txcmplq);
2409 pring->txcmplq_cnt = 0;
2410 spin_unlock_irq(&phba->hbalock);
2411
2412 /* Flush the txq */
2413 while (!list_empty(&txq)) {
2414 iocb = list_get_first(&txq, struct lpfc_iocbq, list);
2415 cmd = &iocb->iocb;
2416 list_del_init(&iocb->list);
2417
2418 if (!iocb->iocb_cmpl)
2419 lpfc_sli_release_iocbq(phba, iocb);
2420 else {
2421 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
2422 cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
2423 (iocb->iocb_cmpl) (phba, iocb, iocb);
2424 }
2425 }
2426
2427 /* Flush the txcmpq */
2428 while (!list_empty(&txcmplq)) {
2429 iocb = list_get_first(&txcmplq, struct lpfc_iocbq, list);
2430 cmd = &iocb->iocb;
2431 list_del_init(&iocb->list);
2432
2433 if (!iocb->iocb_cmpl)
2434 lpfc_sli_release_iocbq(phba, iocb);
2435 else {
2436 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
2437 cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
2438 (iocb->iocb_cmpl) (phba, iocb, iocb);
2439 }
2440 }
2441}
2442
2443/**
2380 * lpfc_sli_brdready: Check for host status bits. 2444 * lpfc_sli_brdready: Check for host status bits.
2381 * @phba: Pointer to HBA context object. 2445 * @phba: Pointer to HBA context object.
2382 * @mask: Bit mask to be checked. 2446 * @mask: Bit mask to be checked.