[SCSI] bfa: Fix Command Queue (CPE) full condition check and ack CPE interrupt.
authorKrishna Gudipati <kgudipat@brocade.com>
Sat, 6 Mar 2010 03:37:09 +0000 (19:37 -0800)
committerJames Bottomley <James.Bottomley@suse.de>
Sun, 7 Mar 2010 07:32:14 +0000 (13:02 +0530)
Fixed the issue of not acknowledging the command queue
full-to-non-full interrupt.  Implemented separate acknowledging
functions for different ASIC and interrupt mode.

Fixed the case of missing CPE interrupt by always processing the
pending requests in the completion path.

Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/bfa/bfa_hw_cb.c
drivers/scsi/bfa/bfa_hw_ct.c
drivers/scsi/bfa/bfa_intr.c
drivers/scsi/bfa/bfa_iocfc.c
drivers/scsi/bfa/bfa_iocfc.h

index ede1438619e2d0394cb755731d75b0fddb101e1f..871a4e28575c9781b8504d5a59e771e5d9dd31ec 100644 (file)
@@ -52,6 +52,18 @@ bfa_hwcb_reginit(struct bfa_s *bfa)
        }
 }
 
+void
+bfa_hwcb_reqq_ack(struct bfa_s *bfa, int reqq)
+{
+}
+
+static void
+bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq)
+{
+       bfa_reg_write(bfa->iocfc.bfa_regs.intr_status,
+               __HFN_INT_CPE_Q0 << CPE_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), reqq));
+}
+
 void
 bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq)
 {
@@ -136,6 +148,7 @@ bfa_hwcb_msix_uninstall(struct bfa_s *bfa)
 void
 bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
 {
+       bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix;
        bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix;
 }
 
index 51ae5740e6e99be8c50c6c9eb44960943651de99..76ceb9a4bf2fab7eb062525538db3aa5786de7cc 100644 (file)
@@ -84,6 +84,15 @@ bfa_hwct_reginit(struct bfa_s *bfa)
        }
 }
 
+void
+bfa_hwct_reqq_ack(struct bfa_s *bfa, int reqq)
+{
+       u32 r32;
+
+       r32 = bfa_reg_read(bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq]);
+       bfa_reg_write(bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq], r32);
+}
+
 void
 bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq)
 {
index c42254613f7343c816e7dcfa5fcd6e2c35196cca..0eba3f930d5b8fb5c9906921454b3bbff95f449b 100644 (file)
@@ -34,6 +34,26 @@ bfa_msix_lpu(struct bfa_s *bfa)
        bfa_ioc_mbox_isr(&bfa->ioc);
 }
 
+static void
+bfa_reqq_resume(struct bfa_s *bfa, int qid)
+{
+       struct list_head *waitq, *qe, *qen;
+       struct bfa_reqq_wait_s *wqe;
+
+       waitq = bfa_reqq(bfa, qid);
+       list_for_each_safe(qe, qen, waitq) {
+               /**
+                * Callback only as long as there is room in request queue
+                */
+               if (bfa_reqq_full(bfa, qid))
+                       break;
+
+               list_del(qe);
+               wqe = (struct bfa_reqq_wait_s *) qe;
+               wqe->qresume(wqe->cbarg);
+       }
+}
+
 void
 bfa_msix_all(struct bfa_s *bfa, int vec)
 {
@@ -128,23 +148,18 @@ bfa_isr_disable(struct bfa_s *bfa)
 void
 bfa_msix_reqq(struct bfa_s *bfa, int qid)
 {
-       struct list_head                *waitq, *qe, *qen;
-       struct bfa_reqq_wait_s  *wqe;
+       struct list_head *waitq;
 
        qid &= (BFI_IOC_MAX_CQS - 1);
 
-       waitq = bfa_reqq(bfa, qid);
-       list_for_each_safe(qe, qen, waitq) {
-               /**
-                * Callback only as long as there is room in request queue
-                */
-               if (bfa_reqq_full(bfa, qid))
-                       break;
+       bfa->iocfc.hwif.hw_reqq_ack(bfa, qid);
 
-               list_del(qe);
-               wqe = (struct bfa_reqq_wait_s *) qe;
-               wqe->qresume(wqe->cbarg);
-       }
+       /**
+        * Resume any pending requests in the corresponding reqq.
+        */
+       waitq = bfa_reqq(bfa, qid);
+       if (!list_empty(waitq))
+               bfa_reqq_resume(bfa, qid);
 }
 
 void
@@ -158,26 +173,27 @@ bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
 }
 
 void
-bfa_msix_rspq(struct bfa_s *bfa, int rsp_qid)
+bfa_msix_rspq(struct bfa_s *bfa, int qid)
 {
-       struct bfi_msg_s      *m;
-       u32        pi, ci;
+       struct bfi_msg_s *m;
+       u32 pi, ci;
+       struct list_head *waitq;
 
-       bfa_trc_fp(bfa, rsp_qid);
+       bfa_trc_fp(bfa, qid);
 
-       rsp_qid &= (BFI_IOC_MAX_CQS - 1);
+       qid &= (BFI_IOC_MAX_CQS - 1);
 
-       bfa->iocfc.hwif.hw_rspq_ack(bfa, rsp_qid);
+       bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);
 
-       ci = bfa_rspq_ci(bfa, rsp_qid);
-       pi = bfa_rspq_pi(bfa, rsp_qid);
+       ci = bfa_rspq_ci(bfa, qid);
+       pi = bfa_rspq_pi(bfa, qid);
 
        bfa_trc_fp(bfa, ci);
        bfa_trc_fp(bfa, pi);
 
        if (bfa->rme_process) {
                while (ci != pi) {
-                       m = bfa_rspq_elem(bfa, rsp_qid, ci);
+                       m = bfa_rspq_elem(bfa, qid, ci);
                        bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX);
 
                        bfa_isrs[m->mhdr.msg_class] (bfa, m);
@@ -189,9 +205,16 @@ bfa_msix_rspq(struct bfa_s *bfa, int rsp_qid)
        /**
         * update CI
         */
-       bfa_rspq_ci(bfa, rsp_qid) = pi;
-       bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[rsp_qid], pi);
+       bfa_rspq_ci(bfa, qid) = pi;
+       bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[qid], pi);
        bfa_os_mmiowb();
+
+       /**
+        * Resume any pending requests in the corresponding reqq.
+        */
+       waitq = bfa_reqq(bfa, qid);
+       if (!list_empty(waitq))
+               bfa_reqq_resume(bfa, qid);
 }
 
 void
index 137591c984d78df4cd630e1dfa1cfd261bdc76bf..a5551db6dba67563c325e109f9fa8257891dcc54 100644 (file)
@@ -172,6 +172,7 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
         */
        if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT) {
                iocfc->hwif.hw_reginit = bfa_hwct_reginit;
+               iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack;
                iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
                iocfc->hwif.hw_msix_init = bfa_hwct_msix_init;
                iocfc->hwif.hw_msix_install = bfa_hwct_msix_install;
@@ -180,6 +181,7 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
                iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
        } else {
                iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
+               iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack;
                iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
                iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
                iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install;
index ce9a830a420749957d31f56983a64f2d6ffe2b51..fbb4bdc9d600af9da34114602151781856dc3ce1 100644 (file)
@@ -54,6 +54,7 @@ struct bfa_msix_s {
  */
 struct bfa_hwif_s {
        void (*hw_reginit)(struct bfa_s *bfa);
+       void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq);
        void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
        void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
        void (*hw_msix_install)(struct bfa_s *bfa);
@@ -143,6 +144,7 @@ void bfa_msix_rspq(struct bfa_s *bfa, int vec);
 void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
 
 void bfa_hwcb_reginit(struct bfa_s *bfa);
+void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq);
 void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
 void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
 void bfa_hwcb_msix_install(struct bfa_s *bfa);
@@ -151,6 +153,7 @@ void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
 void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap,
                        u32 *nvecs, u32 *maxvec);
 void bfa_hwct_reginit(struct bfa_s *bfa);
+void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
 void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
 void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
 void bfa_hwct_msix_install(struct bfa_s *bfa);