mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
[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>
This commit is contained in:
parent
84774a4d0a
commit
a8e497d51e
5 changed files with 103 additions and 3 deletions
|
@ -199,6 +199,7 @@ int lpfc_sli_issue_iocb(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||||
struct lpfc_iocbq *, uint32_t);
|
struct lpfc_iocbq *, uint32_t);
|
||||||
void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
|
void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
|
||||||
void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
|
void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
|
||||||
|
void lpfc_sli_flush_fcp_rings(struct lpfc_hba *);
|
||||||
int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
|
int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||||
struct lpfc_dmabuf *);
|
struct lpfc_dmabuf *);
|
||||||
struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
|
struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
|
||||||
|
@ -290,6 +291,7 @@ void lpfc_unblock_fabric_iocbs(struct lpfc_hba *);
|
||||||
void lpfc_adjust_queue_depth(struct lpfc_hba *);
|
void lpfc_adjust_queue_depth(struct lpfc_hba *);
|
||||||
void lpfc_ramp_down_queue_handler(struct lpfc_hba *);
|
void lpfc_ramp_down_queue_handler(struct lpfc_hba *);
|
||||||
void lpfc_ramp_up_queue_handler(struct lpfc_hba *);
|
void lpfc_ramp_up_queue_handler(struct lpfc_hba *);
|
||||||
|
void lpfc_scsi_dev_block(struct lpfc_hba *);
|
||||||
|
|
||||||
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
|
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
|
||||||
#define HBA_EVENT_RSCN 5
|
#define HBA_EVENT_RSCN 5
|
||||||
|
|
|
@ -237,8 +237,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
|
||||||
lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
|
lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
|
||||||
ndlp->nlp_sid, 0, LPFC_CTX_TGT);
|
ndlp->nlp_sid, 0, LPFC_CTX_TGT);
|
||||||
}
|
}
|
||||||
if (vport->load_flag & FC_UNLOADING)
|
|
||||||
warn_on = 0;
|
|
||||||
|
|
||||||
if (warn_on) {
|
if (warn_on) {
|
||||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
|
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
|
||||||
|
|
|
@ -2661,8 +2661,15 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
|
||||||
struct lpfc_sli *psli = &phba->sli;
|
struct lpfc_sli *psli = &phba->sli;
|
||||||
struct lpfc_sli_ring *pring;
|
struct lpfc_sli_ring *pring;
|
||||||
|
|
||||||
if (state == pci_channel_io_perm_failure)
|
if (state == pci_channel_io_perm_failure) {
|
||||||
|
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||||
|
"0472 PCI channel I/O permanent failure\n");
|
||||||
|
/* Block all SCSI devices' I/Os on the host */
|
||||||
|
lpfc_scsi_dev_block(phba);
|
||||||
|
/* Clean up all driver's outstanding SCSI I/Os */
|
||||||
|
lpfc_sli_flush_fcp_rings(phba);
|
||||||
return PCI_ERS_RESULT_DISCONNECT;
|
return PCI_ERS_RESULT_DISCONNECT;
|
||||||
|
}
|
||||||
|
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -183,6 +183,35 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
|
||||||
atomic_set(&phba->num_cmd_success, 0);
|
atomic_set(&phba->num_cmd_success, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lpfc_scsi_dev_block: set all scsi hosts to block state.
|
||||||
|
* @phba: Pointer to HBA context object.
|
||||||
|
*
|
||||||
|
* This function walks vport list and set each SCSI host to block state
|
||||||
|
* by invoking fc_remote_port_delete() routine. This function is invoked
|
||||||
|
* with EEH when device's PCI slot has been permanently disabled.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
lpfc_scsi_dev_block(struct lpfc_hba *phba)
|
||||||
|
{
|
||||||
|
struct lpfc_vport **vports;
|
||||||
|
struct Scsi_Host *shost;
|
||||||
|
struct scsi_device *sdev;
|
||||||
|
struct fc_rport *rport;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
vports = lpfc_create_vport_work_array(phba);
|
||||||
|
if (vports != NULL)
|
||||||
|
for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
|
||||||
|
shost = lpfc_shost_from_vport(vports[i]);
|
||||||
|
shost_for_each_device(sdev, shost) {
|
||||||
|
rport = starget_to_rport(scsi_target(sdev));
|
||||||
|
fc_remote_port_delete(rport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lpfc_destroy_vport_work_array(phba, vports);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This routine allocates a scsi buffer, which contains all the necessary
|
* This routine allocates a scsi buffer, which contains all the necessary
|
||||||
* information needed to initiate a SCSI I/O. The non-DMAable buffer region
|
* information needed to initiate a SCSI I/O. The non-DMAable buffer region
|
||||||
|
|
|
@ -2376,6 +2376,70 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lpfc_sli_flush_fcp_rings: flush all iocbs in the fcp ring.
|
||||||
|
* @phba: Pointer to HBA context object.
|
||||||
|
*
|
||||||
|
* This function flushes all iocbs in the fcp ring and frees all the iocb
|
||||||
|
* objects in txq and txcmplq. This function will not issue abort iocbs
|
||||||
|
* for all the iocb commands in txcmplq, they will just be returned with
|
||||||
|
* IOERR_SLI_DOWN. This function is invoked with EEH when device's PCI
|
||||||
|
* slot has been permanently disabled.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba)
|
||||||
|
{
|
||||||
|
LIST_HEAD(txq);
|
||||||
|
LIST_HEAD(txcmplq);
|
||||||
|
struct lpfc_iocbq *iocb;
|
||||||
|
IOCB_t *cmd = NULL;
|
||||||
|
struct lpfc_sli *psli = &phba->sli;
|
||||||
|
struct lpfc_sli_ring *pring;
|
||||||
|
|
||||||
|
/* Currently, only one fcp ring */
|
||||||
|
pring = &psli->ring[psli->fcp_ring];
|
||||||
|
|
||||||
|
spin_lock_irq(&phba->hbalock);
|
||||||
|
/* Retrieve everything on txq */
|
||||||
|
list_splice_init(&pring->txq, &txq);
|
||||||
|
pring->txq_cnt = 0;
|
||||||
|
|
||||||
|
/* Retrieve everything on the txcmplq */
|
||||||
|
list_splice_init(&pring->txcmplq, &txcmplq);
|
||||||
|
pring->txcmplq_cnt = 0;
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
|
||||||
|
/* Flush the txq */
|
||||||
|
while (!list_empty(&txq)) {
|
||||||
|
iocb = list_get_first(&txq, struct lpfc_iocbq, list);
|
||||||
|
cmd = &iocb->iocb;
|
||||||
|
list_del_init(&iocb->list);
|
||||||
|
|
||||||
|
if (!iocb->iocb_cmpl)
|
||||||
|
lpfc_sli_release_iocbq(phba, iocb);
|
||||||
|
else {
|
||||||
|
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||||
|
cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
|
||||||
|
(iocb->iocb_cmpl) (phba, iocb, iocb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flush the txcmpq */
|
||||||
|
while (!list_empty(&txcmplq)) {
|
||||||
|
iocb = list_get_first(&txcmplq, struct lpfc_iocbq, list);
|
||||||
|
cmd = &iocb->iocb;
|
||||||
|
list_del_init(&iocb->list);
|
||||||
|
|
||||||
|
if (!iocb->iocb_cmpl)
|
||||||
|
lpfc_sli_release_iocbq(phba, iocb);
|
||||||
|
else {
|
||||||
|
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||||
|
cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
|
||||||
|
(iocb->iocb_cmpl) (phba, iocb, iocb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lpfc_sli_brdready: Check for host status bits.
|
* lpfc_sli_brdready: Check for host status bits.
|
||||||
* @phba: Pointer to HBA context object.
|
* @phba: Pointer to HBA context object.
|
||||||
|
|
Loading…
Reference in a new issue