diff options
| author | Krishna Gudipati <kgudipat@brocade.com> | 2010-03-05 22:37:09 -0500 |
|---|---|---|
| committer | James Bottomley <James.Bottomley@suse.de> | 2010-03-07 02:32:14 -0500 |
| commit | f5713c5dfb4d61cd77debf61d3873eb36877ff1f (patch) | |
| tree | 486b3ed74ad3584cf414be3997a5d3ba77712fd4 | |
| parent | 816e49b8ed209e5e08d4c43359635cbca17e7196 (diff) | |
[SCSI] bfa: Fix Command Queue (CPE) full condition check and ack CPE interrupt.
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>
| -rw-r--r-- | drivers/scsi/bfa/bfa_hw_cb.c | 13 | ||||
| -rw-r--r-- | drivers/scsi/bfa/bfa_hw_ct.c | 9 | ||||
| -rw-r--r-- | drivers/scsi/bfa/bfa_intr.c | 71 | ||||
| -rw-r--r-- | drivers/scsi/bfa/bfa_iocfc.c | 2 | ||||
| -rw-r--r-- | drivers/scsi/bfa/bfa_iocfc.h | 3 |
5 files changed, 74 insertions, 24 deletions
diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c index ede1438619e2..871a4e28575c 100644 --- a/drivers/scsi/bfa/bfa_hw_cb.c +++ b/drivers/scsi/bfa/bfa_hw_cb.c | |||
| @@ -53,6 +53,18 @@ bfa_hwcb_reginit(struct bfa_s *bfa) | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | void | 55 | void |
| 56 | bfa_hwcb_reqq_ack(struct bfa_s *bfa, int reqq) | ||
| 57 | { | ||
| 58 | } | ||
| 59 | |||
| 60 | static void | ||
| 61 | bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq) | ||
| 62 | { | ||
| 63 | bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, | ||
| 64 | __HFN_INT_CPE_Q0 << CPE_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), reqq)); | ||
| 65 | } | ||
| 66 | |||
| 67 | void | ||
| 56 | bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq) | 68 | bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq) |
| 57 | { | 69 | { |
| 58 | } | 70 | } |
| @@ -136,6 +148,7 @@ bfa_hwcb_msix_uninstall(struct bfa_s *bfa) | |||
| 136 | void | 148 | void |
| 137 | bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix) | 149 | bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix) |
| 138 | { | 150 | { |
| 151 | bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix; | ||
| 139 | bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix; | 152 | bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix; |
| 140 | } | 153 | } |
| 141 | 154 | ||
diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c index 51ae5740e6e9..76ceb9a4bf2f 100644 --- a/drivers/scsi/bfa/bfa_hw_ct.c +++ b/drivers/scsi/bfa/bfa_hw_ct.c | |||
| @@ -85,6 +85,15 @@ bfa_hwct_reginit(struct bfa_s *bfa) | |||
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | void | 87 | void |
| 88 | bfa_hwct_reqq_ack(struct bfa_s *bfa, int reqq) | ||
| 89 | { | ||
| 90 | u32 r32; | ||
| 91 | |||
| 92 | r32 = bfa_reg_read(bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq]); | ||
| 93 | bfa_reg_write(bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq], r32); | ||
| 94 | } | ||
| 95 | |||
| 96 | void | ||
| 88 | bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq) | 97 | bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq) |
| 89 | { | 98 | { |
| 90 | u32 r32; | 99 | u32 r32; |
diff --git a/drivers/scsi/bfa/bfa_intr.c b/drivers/scsi/bfa/bfa_intr.c index c42254613f73..0eba3f930d5b 100644 --- a/drivers/scsi/bfa/bfa_intr.c +++ b/drivers/scsi/bfa/bfa_intr.c | |||
| @@ -34,6 +34,26 @@ bfa_msix_lpu(struct bfa_s *bfa) | |||
| 34 | bfa_ioc_mbox_isr(&bfa->ioc); | 34 | bfa_ioc_mbox_isr(&bfa->ioc); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | static void | ||
| 38 | bfa_reqq_resume(struct bfa_s *bfa, int qid) | ||
| 39 | { | ||
| 40 | struct list_head *waitq, *qe, *qen; | ||
| 41 | struct bfa_reqq_wait_s *wqe; | ||
| 42 | |||
| 43 | waitq = bfa_reqq(bfa, qid); | ||
| 44 | list_for_each_safe(qe, qen, waitq) { | ||
| 45 | /** | ||
| 46 | * Callback only as long as there is room in request queue | ||
| 47 | */ | ||
| 48 | if (bfa_reqq_full(bfa, qid)) | ||
| 49 | break; | ||
| 50 | |||
| 51 | list_del(qe); | ||
| 52 | wqe = (struct bfa_reqq_wait_s *) qe; | ||
| 53 | wqe->qresume(wqe->cbarg); | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 37 | void | 57 | void |
| 38 | bfa_msix_all(struct bfa_s *bfa, int vec) | 58 | bfa_msix_all(struct bfa_s *bfa, int vec) |
| 39 | { | 59 | { |
| @@ -128,23 +148,18 @@ bfa_isr_disable(struct bfa_s *bfa) | |||
| 128 | void | 148 | void |
| 129 | bfa_msix_reqq(struct bfa_s *bfa, int qid) | 149 | bfa_msix_reqq(struct bfa_s *bfa, int qid) |
| 130 | { | 150 | { |
| 131 | struct list_head *waitq, *qe, *qen; | 151 | struct list_head *waitq; |
| 132 | struct bfa_reqq_wait_s *wqe; | ||
| 133 | 152 | ||
| 134 | qid &= (BFI_IOC_MAX_CQS - 1); | 153 | qid &= (BFI_IOC_MAX_CQS - 1); |
| 135 | 154 | ||
| 136 | waitq = bfa_reqq(bfa, qid); | 155 | bfa->iocfc.hwif.hw_reqq_ack(bfa, qid); |
| 137 | list_for_each_safe(qe, qen, waitq) { | ||
| 138 | /** | ||
| 139 | * Callback only as long as there is room in request queue | ||
| 140 | */ | ||
| 141 | if (bfa_reqq_full(bfa, qid)) | ||
| 142 | break; | ||
| 143 | 156 | ||
| 144 | list_del(qe); | 157 | /** |
| 145 | wqe = (struct bfa_reqq_wait_s *) qe; | 158 | * Resume any pending requests in the corresponding reqq. |
| 146 | wqe->qresume(wqe->cbarg); | 159 | */ |
| 147 | } | 160 | waitq = bfa_reqq(bfa, qid); |
| 161 | if (!list_empty(waitq)) | ||
| 162 | bfa_reqq_resume(bfa, qid); | ||
| 148 | } | 163 | } |
| 149 | 164 | ||
| 150 | void | 165 | void |
| @@ -158,26 +173,27 @@ bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m) | |||
| 158 | } | 173 | } |
| 159 | 174 | ||
| 160 | void | 175 | void |
| 161 | bfa_msix_rspq(struct bfa_s *bfa, int rsp_qid) | 176 | bfa_msix_rspq(struct bfa_s *bfa, int qid) |
| 162 | { | 177 | { |
| 163 | struct bfi_msg_s *m; | 178 | struct bfi_msg_s *m; |
| 164 | u32 pi, ci; | 179 | u32 pi, ci; |
| 180 | struct list_head *waitq; | ||
| 165 | 181 | ||
| 166 | bfa_trc_fp(bfa, rsp_qid); | 182 | bfa_trc_fp(bfa, qid); |
| 167 | 183 | ||
| 168 | rsp_qid &= (BFI_IOC_MAX_CQS - 1); | 184 | qid &= (BFI_IOC_MAX_CQS - 1); |
| 169 | 185 | ||
| 170 | bfa->iocfc.hwif.hw_rspq_ack(bfa, rsp_qid); | 186 | bfa->iocfc.hwif.hw_rspq_ack(bfa, qid); |
| 171 | 187 | ||
| 172 | ci = bfa_rspq_ci(bfa, rsp_qid); | 188 | ci = bfa_rspq_ci(bfa, qid); |
| 173 | pi = bfa_rspq_pi(bfa, rsp_qid); | 189 | pi = bfa_rspq_pi(bfa, qid); |
| 174 | 190 | ||
| 175 | bfa_trc_fp(bfa, ci); | 191 | bfa_trc_fp(bfa, ci); |
| 176 | bfa_trc_fp(bfa, pi); | 192 | bfa_trc_fp(bfa, pi); |
| 177 | 193 | ||
| 178 | if (bfa->rme_process) { | 194 | if (bfa->rme_process) { |
| 179 | while (ci != pi) { | 195 | while (ci != pi) { |
| 180 | m = bfa_rspq_elem(bfa, rsp_qid, ci); | 196 | m = bfa_rspq_elem(bfa, qid, ci); |
| 181 | bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX); | 197 | bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX); |
| 182 | 198 | ||
| 183 | bfa_isrs[m->mhdr.msg_class] (bfa, m); | 199 | bfa_isrs[m->mhdr.msg_class] (bfa, m); |
| @@ -189,9 +205,16 @@ bfa_msix_rspq(struct bfa_s *bfa, int rsp_qid) | |||
| 189 | /** | 205 | /** |
| 190 | * update CI | 206 | * update CI |
| 191 | */ | 207 | */ |
| 192 | bfa_rspq_ci(bfa, rsp_qid) = pi; | 208 | bfa_rspq_ci(bfa, qid) = pi; |
| 193 | bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[rsp_qid], pi); | 209 | bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[qid], pi); |
| 194 | bfa_os_mmiowb(); | 210 | bfa_os_mmiowb(); |
| 211 | |||
| 212 | /** | ||
| 213 | * Resume any pending requests in the corresponding reqq. | ||
| 214 | */ | ||
| 215 | waitq = bfa_reqq(bfa, qid); | ||
| 216 | if (!list_empty(waitq)) | ||
| 217 | bfa_reqq_resume(bfa, qid); | ||
| 195 | } | 218 | } |
| 196 | 219 | ||
| 197 | void | 220 | void |
diff --git a/drivers/scsi/bfa/bfa_iocfc.c b/drivers/scsi/bfa/bfa_iocfc.c index 137591c984d7..a5551db6dba6 100644 --- a/drivers/scsi/bfa/bfa_iocfc.c +++ b/drivers/scsi/bfa/bfa_iocfc.c | |||
| @@ -172,6 +172,7 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | |||
| 172 | */ | 172 | */ |
| 173 | if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT) { | 173 | if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT) { |
| 174 | iocfc->hwif.hw_reginit = bfa_hwct_reginit; | 174 | iocfc->hwif.hw_reginit = bfa_hwct_reginit; |
| 175 | iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack; | ||
| 175 | iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack; | 176 | iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack; |
| 176 | iocfc->hwif.hw_msix_init = bfa_hwct_msix_init; | 177 | iocfc->hwif.hw_msix_init = bfa_hwct_msix_init; |
| 177 | iocfc->hwif.hw_msix_install = bfa_hwct_msix_install; | 178 | 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, | |||
| 180 | iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs; | 181 | iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs; |
| 181 | } else { | 182 | } else { |
| 182 | iocfc->hwif.hw_reginit = bfa_hwcb_reginit; | 183 | iocfc->hwif.hw_reginit = bfa_hwcb_reginit; |
| 184 | iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack; | ||
| 183 | iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack; | 185 | iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack; |
| 184 | iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init; | 186 | iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init; |
| 185 | iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install; | 187 | iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install; |
diff --git a/drivers/scsi/bfa/bfa_iocfc.h b/drivers/scsi/bfa/bfa_iocfc.h index ce9a830a4207..fbb4bdc9d600 100644 --- a/drivers/scsi/bfa/bfa_iocfc.h +++ b/drivers/scsi/bfa/bfa_iocfc.h | |||
| @@ -54,6 +54,7 @@ struct bfa_msix_s { | |||
| 54 | */ | 54 | */ |
| 55 | struct bfa_hwif_s { | 55 | struct bfa_hwif_s { |
| 56 | void (*hw_reginit)(struct bfa_s *bfa); | 56 | void (*hw_reginit)(struct bfa_s *bfa); |
| 57 | void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq); | ||
| 57 | void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq); | 58 | void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq); |
| 58 | void (*hw_msix_init)(struct bfa_s *bfa, int nvecs); | 59 | void (*hw_msix_init)(struct bfa_s *bfa, int nvecs); |
| 59 | void (*hw_msix_install)(struct bfa_s *bfa); | 60 | void (*hw_msix_install)(struct bfa_s *bfa); |
| @@ -143,6 +144,7 @@ void bfa_msix_rspq(struct bfa_s *bfa, int vec); | |||
| 143 | void bfa_msix_lpu_err(struct bfa_s *bfa, int vec); | 144 | void bfa_msix_lpu_err(struct bfa_s *bfa, int vec); |
| 144 | 145 | ||
| 145 | void bfa_hwcb_reginit(struct bfa_s *bfa); | 146 | void bfa_hwcb_reginit(struct bfa_s *bfa); |
| 147 | void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq); | ||
| 146 | void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq); | 148 | void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq); |
| 147 | void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs); | 149 | void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs); |
| 148 | void bfa_hwcb_msix_install(struct bfa_s *bfa); | 150 | 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); | |||
| 151 | void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, | 153 | void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, |
| 152 | u32 *nvecs, u32 *maxvec); | 154 | u32 *nvecs, u32 *maxvec); |
| 153 | void bfa_hwct_reginit(struct bfa_s *bfa); | 155 | void bfa_hwct_reginit(struct bfa_s *bfa); |
| 156 | void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq); | ||
| 154 | void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq); | 157 | void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq); |
| 155 | void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs); | 158 | void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs); |
| 156 | void bfa_hwct_msix_install(struct bfa_s *bfa); | 159 | void bfa_hwct_msix_install(struct bfa_s *bfa); |
