aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2012-08-03 12:36:52 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-09-14 09:44:39 -0400
commitba20c8536fa039ac3bfc32e0a0f0450134dee8c1 (patch)
tree0293b8915bce3638fc9095857bc230f76c6c80ee /drivers/scsi/lpfc
parent49aa143da98cac07f56096de0d099cb00ccd1582 (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.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c11
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c3
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c88
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h1
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.");
3918LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support"); 3918LPFC_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*/
3926unsigned int lpfc_fcp_look_ahead = LPFC_LOOK_AHEAD_OFF;
3927
3928module_param(lpfc_fcp_look_ahead, uint, S_IRUGO);
3929MODULE_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;
390extern unsigned int pgcnt; 390extern unsigned int pgcnt;
391extern unsigned int lpfc_prot_mask; 391extern unsigned int lpfc_prot_mask;
392extern unsigned char lpfc_prot_guard; 392extern unsigned char lpfc_prot_guard;
393extern unsigned int lpfc_fcp_look_ahead;
393 394
394/* Interface exported by fabric iocb scheduler */ 395/* Interface exported by fabric iocb scheduler */
395void lpfc_fabric_abort_nport(struct lpfc_nodelist *); 396void 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 *);
70static int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *, struct list_head *, 70static int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *, struct list_head *,
71 int); 71 int);
72static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *, struct lpfc_eqe *,
73 uint32_t);
72 74
73static IOCB_t * 75static IOCB_t *
74lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) 76lpfc_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 **/
267static inline void
268lpfc_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
8422lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, 8443lpfc_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;
373struct lpfc_fcp_eq_hdl { 373struct 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 */