diff options
author | James Smart <james.smart@emulex.com> | 2012-08-03 12:36:52 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-09-14 09:44:39 -0400 |
commit | ba20c8536fa039ac3bfc32e0a0f0450134dee8c1 (patch) | |
tree | 0293b8915bce3638fc9095857bc230f76c6c80ee /drivers/scsi/lpfc | |
parent | 49aa143da98cac07f56096de0d099cb00ccd1582 (diff) |
[SCSI] lpfc 8.3.33: Add lpfc_fcp_look_ahead module parameter
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 11 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 88 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 1 |
6 files changed, 102 insertions, 4 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 26bcbfb2a18b..a184c2443a64 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -73,6 +73,8 @@ struct lpfc_sli2_slim; | |||
73 | #define LPFC_HB_MBOX_INTERVAL 5 /* Heart beat interval in seconds. */ | 73 | #define LPFC_HB_MBOX_INTERVAL 5 /* Heart beat interval in seconds. */ |
74 | #define LPFC_HB_MBOX_TIMEOUT 30 /* Heart beat timeout in seconds. */ | 74 | #define LPFC_HB_MBOX_TIMEOUT 30 /* Heart beat timeout in seconds. */ |
75 | 75 | ||
76 | #define LPFC_LOOK_AHEAD_OFF 0 /* Look ahead logic is turned off */ | ||
77 | |||
76 | /* Error Attention event polling interval */ | 78 | /* Error Attention event polling interval */ |
77 | #define LPFC_ERATT_POLL_INTERVAL 5 /* EATT poll interval in seconds */ | 79 | #define LPFC_ERATT_POLL_INTERVAL 5 /* EATT poll interval in seconds */ |
78 | 80 | ||
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 2ab2b9f2bff5..b032562aa0d9 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -3918,6 +3918,17 @@ LPFC_ATTR_R(enable_hba_heartbeat, 0, 0, 1, "Enable HBA Heartbeat."); | |||
3918 | LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support"); | 3918 | LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support"); |
3919 | 3919 | ||
3920 | /* | 3920 | /* |
3921 | # lpfc_fcp_look_ahead: Look ahead for completions in FCP start routine | ||
3922 | # 0 = disabled (default) | ||
3923 | # 1 = enabled | ||
3924 | # Value range is [0,1]. Default value is 0. | ||
3925 | */ | ||
3926 | unsigned int lpfc_fcp_look_ahead = LPFC_LOOK_AHEAD_OFF; | ||
3927 | |||
3928 | module_param(lpfc_fcp_look_ahead, uint, S_IRUGO); | ||
3929 | MODULE_PARM_DESC(lpfc_fcp_look_ahead, "Look ahead for completions"); | ||
3930 | |||
3931 | /* | ||
3921 | # lpfc_prot_mask: i | 3932 | # lpfc_prot_mask: i |
3922 | # - Bit mask of host protection capabilities used to register with the | 3933 | # - Bit mask of host protection capabilities used to register with the |
3923 | # SCSI mid-layer | 3934 | # SCSI mid-layer |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 08e3a9b60e45..10429149f785 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -390,6 +390,7 @@ extern spinlock_t pgcnt_lock; | |||
390 | extern unsigned int pgcnt; | 390 | extern unsigned int pgcnt; |
391 | extern unsigned int lpfc_prot_mask; | 391 | extern unsigned int lpfc_prot_mask; |
392 | extern unsigned char lpfc_prot_guard; | 392 | extern unsigned char lpfc_prot_guard; |
393 | extern unsigned int lpfc_fcp_look_ahead; | ||
393 | 394 | ||
394 | /* Interface exported by fabric iocb scheduler */ | 395 | /* Interface exported by fabric iocb scheduler */ |
395 | void lpfc_fabric_abort_nport(struct lpfc_nodelist *); | 396 | void lpfc_fabric_abort_nport(struct lpfc_nodelist *); |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 538124b39767..cb2749a67c69 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -8111,6 +8111,7 @@ enable_msix_vectors: | |||
8111 | 8111 | ||
8112 | phba->sli4_hba.fcp_eq_hdl[index].idx = index; | 8112 | phba->sli4_hba.fcp_eq_hdl[index].idx = index; |
8113 | phba->sli4_hba.fcp_eq_hdl[index].phba = phba; | 8113 | phba->sli4_hba.fcp_eq_hdl[index].phba = phba; |
8114 | atomic_set(&phba->sli4_hba.fcp_eq_hdl[index].fcp_eq_in_use, 1); | ||
8114 | rc = request_irq(phba->sli4_hba.msix_entries[index].vector, | 8115 | rc = request_irq(phba->sli4_hba.msix_entries[index].vector, |
8115 | &lpfc_sli4_hba_intr_handler, IRQF_SHARED, | 8116 | &lpfc_sli4_hba_intr_handler, IRQF_SHARED, |
8116 | (char *)&phba->sli4_hba.handler_name[index], | 8117 | (char *)&phba->sli4_hba.handler_name[index], |
@@ -8283,6 +8284,8 @@ lpfc_sli4_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode) | |||
8283 | index++) { | 8284 | index++) { |
8284 | phba->sli4_hba.fcp_eq_hdl[index].idx = index; | 8285 | phba->sli4_hba.fcp_eq_hdl[index].idx = index; |
8285 | phba->sli4_hba.fcp_eq_hdl[index].phba = phba; | 8286 | phba->sli4_hba.fcp_eq_hdl[index].phba = phba; |
8287 | atomic_set(&phba->sli4_hba.fcp_eq_hdl[index]. | ||
8288 | fcp_eq_in_use, 1); | ||
8286 | } | 8289 | } |
8287 | } | 8290 | } |
8288 | } | 8291 | } |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index d8dbe403c37e..b0fe153452aa 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -69,6 +69,8 @@ static int lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *, struct lpfc_queue *, | |||
69 | struct lpfc_cqe *); | 69 | struct lpfc_cqe *); |
70 | static int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *, struct list_head *, | 70 | static int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *, struct list_head *, |
71 | int); | 71 | int); |
72 | static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *, struct lpfc_eqe *, | ||
73 | uint32_t); | ||
72 | 74 | ||
73 | static IOCB_t * | 75 | static IOCB_t * |
74 | lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) | 76 | lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) |
@@ -258,6 +260,25 @@ lpfc_sli4_eq_get(struct lpfc_queue *q) | |||
258 | } | 260 | } |
259 | 261 | ||
260 | /** | 262 | /** |
263 | * lpfc_sli4_eq_clr_intr - Turn off interrupts from this EQ | ||
264 | * @q: The Event Queue to disable interrupts | ||
265 | * | ||
266 | **/ | ||
267 | static inline void | ||
268 | lpfc_sli4_eq_clr_intr(struct lpfc_queue *q) | ||
269 | { | ||
270 | struct lpfc_register doorbell; | ||
271 | |||
272 | doorbell.word0 = 0; | ||
273 | bf_set(lpfc_eqcq_doorbell_eqci, &doorbell, 1); | ||
274 | bf_set(lpfc_eqcq_doorbell_qt, &doorbell, LPFC_QUEUE_TYPE_EVENT); | ||
275 | bf_set(lpfc_eqcq_doorbell_eqid_hi, &doorbell, | ||
276 | (q->queue_id >> LPFC_EQID_HI_FIELD_SHIFT)); | ||
277 | bf_set(lpfc_eqcq_doorbell_eqid_lo, &doorbell, q->queue_id); | ||
278 | writel(doorbell.word0, q->phba->sli4_hba.EQCQDBregaddr); | ||
279 | } | ||
280 | |||
281 | /** | ||
261 | * lpfc_sli4_eq_release - Indicates the host has finished processing an EQ | 282 | * lpfc_sli4_eq_release - Indicates the host has finished processing an EQ |
262 | * @q: The Event Queue that the host has completed processing for. | 283 | * @q: The Event Queue that the host has completed processing for. |
263 | * @arm: Indicates whether the host wants to arms this CQ. | 284 | * @arm: Indicates whether the host wants to arms this CQ. |
@@ -8422,7 +8443,10 @@ int | |||
8422 | lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, | 8443 | lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, |
8423 | struct lpfc_iocbq *piocb, uint32_t flag) | 8444 | struct lpfc_iocbq *piocb, uint32_t flag) |
8424 | { | 8445 | { |
8446 | struct lpfc_fcp_eq_hdl *fcp_eq_hdl; | ||
8425 | struct lpfc_sli_ring *pring; | 8447 | struct lpfc_sli_ring *pring; |
8448 | struct lpfc_queue *fpeq; | ||
8449 | struct lpfc_eqe *eqe; | ||
8426 | unsigned long iflags; | 8450 | unsigned long iflags; |
8427 | int rc, idx; | 8451 | int rc, idx; |
8428 | 8452 | ||
@@ -8433,11 +8457,48 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, | |||
8433 | idx = lpfc_sli4_scmd_to_wqidx_distr(phba); | 8457 | idx = lpfc_sli4_scmd_to_wqidx_distr(phba); |
8434 | piocb->fcp_wqidx = idx; | 8458 | piocb->fcp_wqidx = idx; |
8435 | ring_number = MAX_SLI3_CONFIGURED_RINGS + idx; | 8459 | ring_number = MAX_SLI3_CONFIGURED_RINGS + idx; |
8460 | |||
8461 | pring = &phba->sli.ring[ring_number]; | ||
8462 | spin_lock_irqsave(&pring->ring_lock, iflags); | ||
8463 | rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, | ||
8464 | flag); | ||
8465 | spin_unlock_irqrestore(&pring->ring_lock, iflags); | ||
8466 | |||
8467 | if (lpfc_fcp_look_ahead) { | ||
8468 | fcp_eq_hdl = &phba->sli4_hba.fcp_eq_hdl[idx]; | ||
8469 | |||
8470 | if (atomic_dec_and_test(&fcp_eq_hdl-> | ||
8471 | fcp_eq_in_use)) { | ||
8472 | |||
8473 | /* Get associated EQ with this index */ | ||
8474 | fpeq = phba->sli4_hba.hba_eq[idx]; | ||
8475 | |||
8476 | /* Turn off interrupts from this EQ */ | ||
8477 | lpfc_sli4_eq_clr_intr(fpeq); | ||
8478 | |||
8479 | /* | ||
8480 | * Process all the events on FCP EQ | ||
8481 | */ | ||
8482 | while ((eqe = lpfc_sli4_eq_get(fpeq))) { | ||
8483 | lpfc_sli4_hba_handle_eqe(phba, | ||
8484 | eqe, idx); | ||
8485 | fpeq->EQ_processed++; | ||
8486 | } | ||
8487 | |||
8488 | /* Always clear and re-arm the EQ */ | ||
8489 | lpfc_sli4_eq_release(fpeq, | ||
8490 | LPFC_QUEUE_REARM); | ||
8491 | } | ||
8492 | atomic_inc(&fcp_eq_hdl->fcp_eq_in_use); | ||
8493 | } | ||
8494 | } else { | ||
8495 | pring = &phba->sli.ring[ring_number]; | ||
8496 | spin_lock_irqsave(&pring->ring_lock, iflags); | ||
8497 | rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, | ||
8498 | flag); | ||
8499 | spin_unlock_irqrestore(&pring->ring_lock, iflags); | ||
8500 | |||
8436 | } | 8501 | } |
8437 | pring = &phba->sli.ring[ring_number]; | ||
8438 | spin_lock_irqsave(&pring->ring_lock, iflags); | ||
8439 | rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, flag); | ||
8440 | spin_unlock_irqrestore(&pring->ring_lock, iflags); | ||
8441 | } else { | 8502 | } else { |
8442 | /* For now, SLI2/3 will still use hbalock */ | 8503 | /* For now, SLI2/3 will still use hbalock */ |
8443 | spin_lock_irqsave(&phba->hbalock, iflags); | 8504 | spin_lock_irqsave(&phba->hbalock, iflags); |
@@ -11854,6 +11915,15 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id) | |||
11854 | if (unlikely(!fpeq)) | 11915 | if (unlikely(!fpeq)) |
11855 | return IRQ_NONE; | 11916 | return IRQ_NONE; |
11856 | 11917 | ||
11918 | if (lpfc_fcp_look_ahead) { | ||
11919 | if (atomic_dec_and_test(&fcp_eq_hdl->fcp_eq_in_use)) | ||
11920 | lpfc_sli4_eq_clr_intr(fpeq); | ||
11921 | else { | ||
11922 | atomic_inc(&fcp_eq_hdl->fcp_eq_in_use); | ||
11923 | return IRQ_NONE; | ||
11924 | } | ||
11925 | } | ||
11926 | |||
11857 | /* Check device state for handling interrupt */ | 11927 | /* Check device state for handling interrupt */ |
11858 | if (unlikely(lpfc_intr_state_check(phba))) { | 11928 | if (unlikely(lpfc_intr_state_check(phba))) { |
11859 | fpeq->EQ_badstate++; | 11929 | fpeq->EQ_badstate++; |
@@ -11863,6 +11933,8 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id) | |||
11863 | /* Flush, clear interrupt, and rearm the EQ */ | 11933 | /* Flush, clear interrupt, and rearm the EQ */ |
11864 | lpfc_sli4_eq_flush(phba, fpeq); | 11934 | lpfc_sli4_eq_flush(phba, fpeq); |
11865 | spin_unlock_irqrestore(&phba->hbalock, iflag); | 11935 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
11936 | if (lpfc_fcp_look_ahead) | ||
11937 | atomic_inc(&fcp_eq_hdl->fcp_eq_in_use); | ||
11866 | return IRQ_NONE; | 11938 | return IRQ_NONE; |
11867 | } | 11939 | } |
11868 | 11940 | ||
@@ -11885,6 +11957,12 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id) | |||
11885 | 11957 | ||
11886 | if (unlikely(ecount == 0)) { | 11958 | if (unlikely(ecount == 0)) { |
11887 | fpeq->EQ_no_entry++; | 11959 | fpeq->EQ_no_entry++; |
11960 | |||
11961 | if (lpfc_fcp_look_ahead) { | ||
11962 | atomic_inc(&fcp_eq_hdl->fcp_eq_in_use); | ||
11963 | return IRQ_NONE; | ||
11964 | } | ||
11965 | |||
11888 | if (phba->intr_type == MSIX) | 11966 | if (phba->intr_type == MSIX) |
11889 | /* MSI-X treated interrupt served as no EQ share INT */ | 11967 | /* MSI-X treated interrupt served as no EQ share INT */ |
11890 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, | 11968 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, |
@@ -11894,6 +11972,8 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id) | |||
11894 | return IRQ_NONE; | 11972 | return IRQ_NONE; |
11895 | } | 11973 | } |
11896 | 11974 | ||
11975 | if (lpfc_fcp_look_ahead) | ||
11976 | atomic_inc(&fcp_eq_hdl->fcp_eq_in_use); | ||
11897 | return IRQ_HANDLED; | 11977 | return IRQ_HANDLED; |
11898 | } /* lpfc_sli4_fp_intr_handler */ | 11978 | } /* lpfc_sli4_fp_intr_handler */ |
11899 | 11979 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index c806e66be55b..bd4bc4342ae2 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
@@ -373,6 +373,7 @@ struct lpfc_hba; | |||
373 | struct lpfc_fcp_eq_hdl { | 373 | struct lpfc_fcp_eq_hdl { |
374 | uint32_t idx; | 374 | uint32_t idx; |
375 | struct lpfc_hba *phba; | 375 | struct lpfc_hba *phba; |
376 | atomic_t fcp_eq_in_use; | ||
376 | }; | 377 | }; |
377 | 378 | ||
378 | /* Port Capabilities for SLI4 Parameters */ | 379 | /* Port Capabilities for SLI4 Parameters */ |