Loading drivers/scsi/lpfc/lpfc_sli.c +112 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,8 @@ static int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *, struct list_head *, int); static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *, struct lpfc_eqe *, uint32_t); static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba); static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba); static IOCB_t * lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) Loading Loading @@ -6566,6 +6568,108 @@ lpfc_mbox_timeout(unsigned long ptr) return; } /** * lpfc_sli4_mbox_completions_pending - check to see if any mailbox completions * are pending * @phba: Pointer to HBA context object. * * This function checks if any mailbox completions are present on the mailbox * completion queue. **/ bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba) { uint32_t idx; struct lpfc_queue *mcq; struct lpfc_mcqe *mcqe; bool pending_completions = false; if (unlikely(!phba) || (phba->sli_rev != LPFC_SLI_REV4)) return false; /* Check for completions on mailbox completion queue */ mcq = phba->sli4_hba.mbx_cq; idx = mcq->hba_index; while (bf_get_le32(lpfc_cqe_valid, mcq->qe[idx].cqe)) { mcqe = (struct lpfc_mcqe *)mcq->qe[idx].cqe; if (bf_get_le32(lpfc_trailer_completed, mcqe) && (!bf_get_le32(lpfc_trailer_async, mcqe))) { pending_completions = true; break; } idx = (idx + 1) % mcq->entry_count; if (mcq->hba_index == idx) break; } return pending_completions; } /** * lpfc_sli4_process_missed_mbox_completions - process mbox completions * that were missed. * @phba: Pointer to HBA context object. * * For sli4, it is possible to miss an interrupt. As such mbox completions * maybe missed causing erroneous mailbox timeouts to occur. This function * checks to see if mbox completions are on the mailbox completion queue * and will process all the completions associated with the eq for the * mailbox completion queue. **/ bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba) { uint32_t eqidx; struct lpfc_queue *fpeq = NULL; struct lpfc_eqe *eqe; bool mbox_pending; if (unlikely(!phba) || (phba->sli_rev != LPFC_SLI_REV4)) return false; /* Find the eq associated with the mcq */ if (phba->sli4_hba.hba_eq) for (eqidx = 0; eqidx < phba->cfg_fcp_io_channel; eqidx++) if (phba->sli4_hba.hba_eq[eqidx]->queue_id == phba->sli4_hba.mbx_cq->assoc_qid) { fpeq = phba->sli4_hba.hba_eq[eqidx]; break; } if (!fpeq) return false; /* Turn off interrupts from this EQ */ lpfc_sli4_eq_clr_intr(fpeq); /* Check to see if a mbox completion is pending */ mbox_pending = lpfc_sli4_mbox_completions_pending(phba); /* * If a mbox completion is pending, process all the events on EQ * associated with the mbox completion queue (this could include * mailbox commands, async events, els commands, receive queue data * and fcp commands) */ if (mbox_pending) while ((eqe = lpfc_sli4_eq_get(fpeq))) { lpfc_sli4_hba_handle_eqe(phba, eqe, eqidx); fpeq->EQ_processed++; } /* Always clear and re-arm the EQ */ lpfc_sli4_eq_release(fpeq, LPFC_QUEUE_REARM); return mbox_pending; } /** * lpfc_mbox_timeout_handler - Worker thread function to handle mailbox timeout Loading @@ -6583,6 +6687,10 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; /* If the mailbox completed, process the completion and return */ if (lpfc_sli4_process_missed_mbox_completions(phba)) return; /* Check the pmbox pointer first. There is a race condition * between the mbox timeout handler getting executed in the * worklist and the mailbox actually completing. When this Loading Loading @@ -7077,6 +7185,10 @@ lpfc_sli4_async_mbox_block(struct lpfc_hba *phba) 1000) + jiffies; spin_unlock_irq(&phba->hbalock); /* Make sure the mailbox is really active */ if (timeout) lpfc_sli4_process_missed_mbox_completions(phba); /* Wait for the outstnading mailbox command to complete */ while (phba->sli.mbox_active) { /* Check active mailbox complete status every 2ms */ Loading Loading
drivers/scsi/lpfc/lpfc_sli.c +112 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,8 @@ static int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *, struct list_head *, int); static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *, struct lpfc_eqe *, uint32_t); static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba); static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba); static IOCB_t * lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) Loading Loading @@ -6566,6 +6568,108 @@ lpfc_mbox_timeout(unsigned long ptr) return; } /** * lpfc_sli4_mbox_completions_pending - check to see if any mailbox completions * are pending * @phba: Pointer to HBA context object. * * This function checks if any mailbox completions are present on the mailbox * completion queue. **/ bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba) { uint32_t idx; struct lpfc_queue *mcq; struct lpfc_mcqe *mcqe; bool pending_completions = false; if (unlikely(!phba) || (phba->sli_rev != LPFC_SLI_REV4)) return false; /* Check for completions on mailbox completion queue */ mcq = phba->sli4_hba.mbx_cq; idx = mcq->hba_index; while (bf_get_le32(lpfc_cqe_valid, mcq->qe[idx].cqe)) { mcqe = (struct lpfc_mcqe *)mcq->qe[idx].cqe; if (bf_get_le32(lpfc_trailer_completed, mcqe) && (!bf_get_le32(lpfc_trailer_async, mcqe))) { pending_completions = true; break; } idx = (idx + 1) % mcq->entry_count; if (mcq->hba_index == idx) break; } return pending_completions; } /** * lpfc_sli4_process_missed_mbox_completions - process mbox completions * that were missed. * @phba: Pointer to HBA context object. * * For sli4, it is possible to miss an interrupt. As such mbox completions * maybe missed causing erroneous mailbox timeouts to occur. This function * checks to see if mbox completions are on the mailbox completion queue * and will process all the completions associated with the eq for the * mailbox completion queue. **/ bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba) { uint32_t eqidx; struct lpfc_queue *fpeq = NULL; struct lpfc_eqe *eqe; bool mbox_pending; if (unlikely(!phba) || (phba->sli_rev != LPFC_SLI_REV4)) return false; /* Find the eq associated with the mcq */ if (phba->sli4_hba.hba_eq) for (eqidx = 0; eqidx < phba->cfg_fcp_io_channel; eqidx++) if (phba->sli4_hba.hba_eq[eqidx]->queue_id == phba->sli4_hba.mbx_cq->assoc_qid) { fpeq = phba->sli4_hba.hba_eq[eqidx]; break; } if (!fpeq) return false; /* Turn off interrupts from this EQ */ lpfc_sli4_eq_clr_intr(fpeq); /* Check to see if a mbox completion is pending */ mbox_pending = lpfc_sli4_mbox_completions_pending(phba); /* * If a mbox completion is pending, process all the events on EQ * associated with the mbox completion queue (this could include * mailbox commands, async events, els commands, receive queue data * and fcp commands) */ if (mbox_pending) while ((eqe = lpfc_sli4_eq_get(fpeq))) { lpfc_sli4_hba_handle_eqe(phba, eqe, eqidx); fpeq->EQ_processed++; } /* Always clear and re-arm the EQ */ lpfc_sli4_eq_release(fpeq, LPFC_QUEUE_REARM); return mbox_pending; } /** * lpfc_mbox_timeout_handler - Worker thread function to handle mailbox timeout Loading @@ -6583,6 +6687,10 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; /* If the mailbox completed, process the completion and return */ if (lpfc_sli4_process_missed_mbox_completions(phba)) return; /* Check the pmbox pointer first. There is a race condition * between the mbox timeout handler getting executed in the * worklist and the mailbox actually completing. When this Loading Loading @@ -7077,6 +7185,10 @@ lpfc_sli4_async_mbox_block(struct lpfc_hba *phba) 1000) + jiffies; spin_unlock_irq(&phba->hbalock); /* Make sure the mailbox is really active */ if (timeout) lpfc_sli4_process_missed_mbox_completions(phba); /* Wait for the outstnading mailbox command to complete */ while (phba->sli.mbox_active) { /* Check active mailbox complete status every 2ms */ Loading