Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[sfrench/cifs-2.6.git] / drivers / scsi / lpfc / lpfc_sli.c
index 8b119f87b51d67382b89aa60500d9ffe6f18ab19..aecd2399005d1ed57b87ea78eb7946147d96b137 100644 (file)
@@ -80,8 +80,8 @@ static int lpfc_sli4_fp_handle_cqe(struct lpfc_hba *, struct lpfc_queue *,
                                    struct lpfc_cqe *);
 static int lpfc_sli4_post_sgl_list(struct lpfc_hba *, struct list_head *,
                                       int);
-static int lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba,
-                                   struct lpfc_eqe *eqe, uint32_t qidx);
+static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba,
+                                    struct lpfc_eqe *eqe, uint32_t qidx);
 static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba);
 static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba);
 static int lpfc_sli4_abort_nvme_io(struct lpfc_hba *phba,
@@ -2732,7 +2732,8 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
  *
  * This function looks up the iocb_lookup table to get the command iocb
  * corresponding to the given response iocb using the iotag of the
- * response iocb. This function is called with the hbalock held.
+ * response iocb. This function is called with the hbalock held
+ * for sli3 devices or the ring_lock for sli4 devices.
  * This function returns the command iocb object if it finds the command
  * iocb else returns NULL.
  **/
@@ -2828,9 +2829,15 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
        unsigned long iflag;
 
        /* Based on the iotag field, get the cmd IOCB from the txcmplq */
-       spin_lock_irqsave(&phba->hbalock, iflag);
+       if (phba->sli_rev == LPFC_SLI_REV4)
+               spin_lock_irqsave(&pring->ring_lock, iflag);
+       else
+               spin_lock_irqsave(&phba->hbalock, iflag);
        cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
-       spin_unlock_irqrestore(&phba->hbalock, iflag);
+       if (phba->sli_rev == LPFC_SLI_REV4)
+               spin_unlock_irqrestore(&pring->ring_lock, iflag);
+       else
+               spin_unlock_irqrestore(&phba->hbalock, iflag);
 
        if (cmdiocbp) {
                if (cmdiocbp->iocb_cmpl) {
@@ -3004,13 +3011,13 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
  * and wake up worker thread to process it. Otherwise, it will set up the
  * Error Attention polling timer for the next poll.
  **/
-void lpfc_poll_eratt(unsigned long ptr)
+void lpfc_poll_eratt(struct timer_list *t)
 {
        struct lpfc_hba *phba;
        uint32_t eratt = 0;
        uint64_t sli_intr, cnt;
 
-       phba = (struct lpfc_hba *)ptr;
+       phba = from_timer(phba, t, eratt_poll);
 
        /* Here we will also keep track of interrupts per sec of the hba */
        sli_intr = phba->sli.slistat.sli_intr;
@@ -7167,9 +7174,9 @@ out_free_mbox:
  * done by the worker thread function lpfc_mbox_timeout_handler.
  **/
 void
-lpfc_mbox_timeout(unsigned long ptr)
+lpfc_mbox_timeout(struct timer_list *t)
 {
-       struct lpfc_hba  *phba = (struct lpfc_hba *) ptr;
+       struct lpfc_hba  *phba = from_timer(phba, t, sli.mbox_tmo);
        unsigned long iflag;
        uint32_t tmo_posted;
 
@@ -9396,10 +9403,13 @@ lpfc_sli4_calc_ring(struct lpfc_hba *phba, struct lpfc_iocbq *piocb)
                         * for abort iocb hba_wqidx should already
                         * be setup based on what work queue we used.
                         */
-                       if (!(piocb->iocb_flag & LPFC_USE_FCPWQIDX))
+                       if (!(piocb->iocb_flag & LPFC_USE_FCPWQIDX)) {
                                piocb->hba_wqidx =
                                        lpfc_sli4_scmd_to_wqidx_distr(phba,
                                                              piocb->context1);
+                               piocb->hba_wqidx = piocb->hba_wqidx %
+                                       phba->cfg_fcp_io_channel;
+                       }
                        return phba->sli4_hba.fcp_wq[piocb->hba_wqidx]->pring;
                } else {
                        if (unlikely(!phba->sli4_hba.oas_wq))
@@ -10632,6 +10642,14 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
            (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0)
                return 0;
 
+       if (!pring) {
+               if (cmdiocb->iocb_flag & LPFC_IO_FABRIC)
+                       cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl;
+               else
+                       cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl;
+               goto abort_iotag_exit;
+       }
+
        /*
         * If we're unloading, don't abort iocb on the ELS ring, but change
         * the callback so that nothing happens when it finishes.
@@ -12500,6 +12518,8 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
        unsigned long iflags;
 
        pring = lpfc_phba_elsring(phba);
+       if (unlikely(!pring))
+               return NULL;
 
        wcqe = &irspiocbq->cq_event.cqe.wcqe_cmpl;
        spin_lock_irqsave(&pring->ring_lock, iflags);
@@ -12507,19 +12527,21 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
        /* Look up the ELS command IOCB and create pseudo response IOCB */
        cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring,
                                bf_get(lpfc_wcqe_c_request_tag, wcqe));
-       /* Put the iocb back on the txcmplq */
-       lpfc_sli_ringtxcmpl_put(phba, pring, cmdiocbq);
-       spin_unlock_irqrestore(&pring->ring_lock, iflags);
-
        if (unlikely(!cmdiocbq)) {
+               spin_unlock_irqrestore(&pring->ring_lock, iflags);
                lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
                                "0386 ELS complete with no corresponding "
-                               "cmdiocb: iotag (%d)\n",
-                               bf_get(lpfc_wcqe_c_request_tag, wcqe));
+                               "cmdiocb: 0x%x 0x%x 0x%x 0x%x\n",
+                               wcqe->word0, wcqe->total_data_placed,
+                               wcqe->parameter, wcqe->word3);
                lpfc_sli_release_iocbq(phba, irspiocbq);
                return NULL;
        }
 
+       /* Put the iocb back on the txcmplq */
+       lpfc_sli_ringtxcmpl_put(phba, pring, cmdiocbq);
+       spin_unlock_irqrestore(&pring->ring_lock, iflags);
+
        /* Fake the irspiocbq and copy necessary response information */
        lpfc_sli4_iocb_param_transfer(phba, irspiocbq, cmdiocbq, wcqe);
 
@@ -13010,14 +13032,11 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
  * completion queue, and then return.
  *
  **/
-static int
+static void
 lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
        struct lpfc_queue *speq)
 {
        struct lpfc_queue *cq = NULL, *childq;
-       struct lpfc_cqe *cqe;
-       bool workposted = false;
-       int ecount = 0;
        uint16_t cqid;
 
        /* Get the reference to the corresponding CQ */
@@ -13034,48 +13053,84 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
                        lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                        "0365 Slow-path CQ identifier "
                                        "(%d) does not exist\n", cqid);
-               return 0;
+               return;
        }
 
        /* Save EQ associated with this CQ */
        cq->assoc_qp = speq;
 
+       if (!queue_work(phba->wq, &cq->spwork))
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "0390 Cannot schedule soft IRQ "
+                               "for CQ eqcqid=%d, cqid=%d on CPU %d\n",
+                               cqid, cq->queue_id, smp_processor_id());
+}
+
+/**
+ * lpfc_sli4_sp_process_cq - Process a slow-path event queue entry
+ * @phba: Pointer to HBA context object.
+ *
+ * This routine process a event queue entry from the slow-path event queue.
+ * It will check the MajorCode and MinorCode to determine this is for a
+ * completion event on a completion queue, if not, an error shall be logged
+ * and just return. Otherwise, it will get to the corresponding completion
+ * queue and process all the entries on that completion queue, rearm the
+ * completion queue, and then return.
+ *
+ **/
+static void
+lpfc_sli4_sp_process_cq(struct work_struct *work)
+{
+       struct lpfc_queue *cq =
+               container_of(work, struct lpfc_queue, spwork);
+       struct lpfc_hba *phba = cq->phba;
+       struct lpfc_cqe *cqe;
+       bool workposted = false;
+       int ccount = 0;
+
        /* Process all the entries to the CQ */
        switch (cq->type) {
        case LPFC_MCQ:
                while ((cqe = lpfc_sli4_cq_get(cq))) {
                        workposted |= lpfc_sli4_sp_handle_mcqe(phba, cqe);
-                       if (!(++ecount % cq->entry_repost))
+                       if (!(++ccount % cq->entry_repost))
                                break;
                        cq->CQ_mbox++;
                }
                break;
        case LPFC_WCQ:
                while ((cqe = lpfc_sli4_cq_get(cq))) {
-                       if ((cq->subtype == LPFC_FCP) ||
-                           (cq->subtype == LPFC_NVME))
+                       if (cq->subtype == LPFC_FCP ||
+                           cq->subtype == LPFC_NVME) {
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+                               if (phba->ktime_on)
+                                       cq->isr_timestamp = ktime_get_ns();
+                               else
+                                       cq->isr_timestamp = 0;
+#endif
                                workposted |= lpfc_sli4_fp_handle_cqe(phba, cq,
                                                                       cqe);
-                       else
+                       } else {
                                workposted |= lpfc_sli4_sp_handle_cqe(phba, cq,
                                                                      cqe);
-                       if (!(++ecount % cq->entry_repost))
+                       }
+                       if (!(++ccount % cq->entry_repost))
                                break;
                }
 
                /* Track the max number of CQEs processed in 1 EQ */
-               if (ecount > cq->CQ_max_cqe)
-                       cq->CQ_max_cqe = ecount;
+               if (ccount > cq->CQ_max_cqe)
+                       cq->CQ_max_cqe = ccount;
                break;
        default:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "0370 Invalid completion queue type (%d)\n",
                                cq->type);
-               return 0;
+               return;
        }
 
        /* Catch the no cq entry condition, log an error */
-       if (unlikely(ecount == 0))
+       if (unlikely(ccount == 0))
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "0371 No entry from the CQ: identifier "
                                "(x%x), type (%d)\n", cq->queue_id, cq->type);
@@ -13086,8 +13141,6 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
        /* wake up worker thread if there are works to be done */
        if (workposted)
                lpfc_worker_wake_up(phba);
-
-       return ecount;
 }
 
 /**
@@ -13143,11 +13196,9 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
                                bf_get(lpfc_wcqe_c_request_tag, wcqe));
                return;
        }
-
-       if (cq->assoc_qp)
-               cmdiocbq->isr_timestamp =
-                       cq->assoc_qp->isr_timestamp;
-
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+       cmdiocbq->isr_timestamp = cq->isr_timestamp;
+#endif
        if (cmdiocbq->iocb_cmpl == NULL) {
                if (cmdiocbq->wqe_cmpl) {
                        if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) {
@@ -13292,7 +13343,7 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
                        dma_buf->bytes_recv = bf_get(lpfc_rcqe_length,  rcqe);
                        lpfc_nvmet_unsol_fcp_event(
                                phba, idx, dma_buf,
-                               cq->assoc_qp->isr_timestamp);
+                               cq->isr_timestamp);
                        return false;
                }
 drop:
@@ -13395,15 +13446,12 @@ lpfc_sli4_fp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
  * queue and process all the entries on the completion queue, rearm the
  * completion queue, and then return.
  **/
-static int
+static void
 lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
                        uint32_t qidx)
 {
        struct lpfc_queue *cq = NULL;
-       struct lpfc_cqe *cqe;
-       bool workposted = false;
        uint16_t cqid, id;
-       int ecount = 0;
 
        if (unlikely(bf_get_le32(lpfc_eqe_major_code, eqe) != 0)) {
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
@@ -13411,7 +13459,7 @@ lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
                                "event: majorcode=x%x, minorcode=x%x\n",
                                bf_get_le32(lpfc_eqe_major_code, eqe),
                                bf_get_le32(lpfc_eqe_minor_code, eqe));
-               return 0;
+               return;
        }
 
        /* Get the reference to the corresponding CQ */
@@ -13448,9 +13496,8 @@ lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
 
        /* Otherwise this is a Slow path event */
        if (cq == NULL) {
-               ecount = lpfc_sli4_sp_handle_eqe(phba, eqe,
-                                                phba->sli4_hba.hba_eq[qidx]);
-               return ecount;
+               lpfc_sli4_sp_handle_eqe(phba, eqe, phba->sli4_hba.hba_eq[qidx]);
+               return;
        }
 
 process_cq:
@@ -13459,26 +13506,61 @@ process_cq:
                                "0368 Miss-matched fast-path completion "
                                "queue identifier: eqcqid=%d, fcpcqid=%d\n",
                                cqid, cq->queue_id);
-               return 0;
+               return;
        }
 
        /* Save EQ associated with this CQ */
        cq->assoc_qp = phba->sli4_hba.hba_eq[qidx];
 
+       if (!queue_work(phba->wq, &cq->irqwork))
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "0363 Cannot schedule soft IRQ "
+                               "for CQ eqcqid=%d, cqid=%d on CPU %d\n",
+                               cqid, cq->queue_id, smp_processor_id());
+}
+
+/**
+ * lpfc_sli4_hba_process_cq - Process a fast-path event queue entry
+ * @phba: Pointer to HBA context object.
+ * @eqe: Pointer to fast-path event queue entry.
+ *
+ * This routine process a event queue entry from the fast-path event queue.
+ * It will check the MajorCode and MinorCode to determine this is for a
+ * completion event on a completion queue, if not, an error shall be logged
+ * and just return. Otherwise, it will get to the corresponding completion
+ * queue and process all the entries on the completion queue, rearm the
+ * completion queue, and then return.
+ **/
+static void
+lpfc_sli4_hba_process_cq(struct work_struct *work)
+{
+       struct lpfc_queue *cq =
+               container_of(work, struct lpfc_queue, irqwork);
+       struct lpfc_hba *phba = cq->phba;
+       struct lpfc_cqe *cqe;
+       bool workposted = false;
+       int ccount = 0;
+
        /* Process all the entries to the CQ */
        while ((cqe = lpfc_sli4_cq_get(cq))) {
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+               if (phba->ktime_on)
+                       cq->isr_timestamp = ktime_get_ns();
+               else
+                       cq->isr_timestamp = 0;
+#endif
                workposted |= lpfc_sli4_fp_handle_cqe(phba, cq, cqe);
-               if (!(++ecount % cq->entry_repost))
+               if (!(++ccount % cq->entry_repost))
                        break;
        }
 
        /* Track the max number of CQEs processed in 1 EQ */
-       if (ecount > cq->CQ_max_cqe)
-               cq->CQ_max_cqe = ecount;
-       cq->assoc_qp->EQ_cqe_cnt += ecount;
+       if (ccount > cq->CQ_max_cqe)
+               cq->CQ_max_cqe = ccount;
+       cq->assoc_qp->EQ_cqe_cnt += ccount;
 
        /* Catch the no cq entry condition */
-       if (unlikely(ecount == 0))
+       if (unlikely(ccount == 0))
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "0369 No entry from fast-path completion "
                                "queue fcpcqid=%d\n", cq->queue_id);
@@ -13489,8 +13571,6 @@ process_cq:
        /* wake up worker thread if there are works to be done */
        if (workposted)
                lpfc_worker_wake_up(phba);
-
-       return ecount;
 }
 
 static void
@@ -13524,10 +13604,7 @@ static void
 lpfc_sli4_fof_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
 {
        struct lpfc_queue *cq;
-       struct lpfc_cqe *cqe;
-       bool workposted = false;
        uint16_t cqid;
-       int ecount = 0;
 
        if (unlikely(bf_get_le32(lpfc_eqe_major_code, eqe) != 0)) {
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
@@ -13562,30 +13639,12 @@ lpfc_sli4_fof_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
        /* Save EQ associated with this CQ */
        cq->assoc_qp = phba->sli4_hba.fof_eq;
 
-       /* Process all the entries to the OAS CQ */
-       while ((cqe = lpfc_sli4_cq_get(cq))) {
-               workposted |= lpfc_sli4_fp_handle_cqe(phba, cq, cqe);
-               if (!(++ecount % cq->entry_repost))
-                       break;
-       }
-
-       /* Track the max number of CQEs processed in 1 EQ */
-       if (ecount > cq->CQ_max_cqe)
-               cq->CQ_max_cqe = ecount;
-       cq->assoc_qp->EQ_cqe_cnt += ecount;
-
-       /* Catch the no cq entry condition */
-       if (unlikely(ecount == 0))
+       /* CQ work will be processed on CPU affinitized to this IRQ */
+       if (!queue_work(phba->wq, &cq->irqwork))
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                               "9153 No entry from fast-path completion "
-                               "queue fcpcqid=%d\n", cq->queue_id);
-
-       /* In any case, flash and re-arm the CQ */
-       lpfc_sli4_cq_release(cq, LPFC_QUEUE_REARM);
-
-       /* wake up worker thread if there are works to be done */
-       if (workposted)
-               lpfc_worker_wake_up(phba);
+                               "0367 Cannot schedule soft IRQ "
+                               "for CQ eqcqid=%d, cqid=%d on CPU %d\n",
+                               cqid, cq->queue_id, smp_processor_id());
 }
 
 /**
@@ -13711,7 +13770,6 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
        struct lpfc_eqe *eqe;
        unsigned long iflag;
        int ecount = 0;
-       int ccount = 0;
        int hba_eqidx;
 
        /* Get the driver's phba structure from the dev_id */
@@ -13729,11 +13787,6 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
        if (unlikely(!fpeq))
                return IRQ_NONE;
 
-#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
-       if (phba->ktime_on)
-               fpeq->isr_timestamp = ktime_get_ns();
-#endif
-
        if (lpfc_fcp_look_ahead) {
                if (atomic_dec_and_test(&hba_eq_hdl->hba_eq_in_use))
                        lpfc_sli4_eq_clr_intr(fpeq);
@@ -13760,12 +13813,8 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
         * Process all the event on FCP fast-path EQ
         */
        while ((eqe = lpfc_sli4_eq_get(fpeq))) {
-               if (eqe == NULL)
-                       break;
-
-               ccount += lpfc_sli4_hba_handle_eqe(phba, eqe, hba_eqidx);
-               if (!(++ecount % fpeq->entry_repost) ||
-                   ccount > LPFC_MAX_ISR_CQE)
+               lpfc_sli4_hba_handle_eqe(phba, eqe, hba_eqidx);
+               if (!(++ecount % fpeq->entry_repost))
                        break;
                fpeq->EQ_processed++;
        }
@@ -13948,6 +13997,8 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size,
        queue->entry_size = entry_size;
        queue->entry_count = entry_count;
        queue->phba = phba;
+       INIT_WORK(&queue->irqwork, lpfc_sli4_hba_process_cq);
+       INIT_WORK(&queue->spwork, lpfc_sli4_sp_process_cq);
 
        /* entry_repost will be set during q creation */
 
@@ -17137,7 +17188,8 @@ exit:
        if (pcmd && pcmd->virt)
                dma_pool_free(phba->lpfc_drb_pool, pcmd->virt, pcmd->phys);
        kfree(pcmd);
-       lpfc_sli_release_iocbq(phba, iocbq);
+       if (iocbq)
+               lpfc_sli_release_iocbq(phba, iocbq);
        lpfc_in_buf_free(phba, &dmabuf->dbuf);
 }
 
@@ -18691,6 +18743,8 @@ lpfc_drain_txq(struct lpfc_hba *phba)
        uint32_t txq_cnt = 0;
 
        pring = lpfc_phba_elsring(phba);
+       if (unlikely(!pring))
+               return 0;
 
        spin_lock_irqsave(&pring->ring_lock, iflags);
        list_for_each_entry(piocbq, &pring->txq, list) {