summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJames Smart <jsmart2021@gmail.com>2019-01-28 14:14:32 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2019-02-05 22:29:49 -0500
commitcb733e358787b7386bd1aeec088a35e03c53da3b (patch)
treed210860145ebd78544aa0e4b997581b932bda23d /drivers
parent6a828b0f6192b4930894925d1c1d0dc1f1d99e6e (diff)
scsi: lpfc: cleanup: convert eq_delay to usdelay
Review of the eq coalescing logic showed the code was a bit fragmented. Sometimes it would save/set via an interrupt max value, while in others it would do so via a usdelay. There were also two places changing eq delay, one place that issued mailbox commands, and another that changed via register writes if supported. Clean this up by: - Standardizing the operation of lpfc_modify_hba_eq_delay() routine so that it is always told of a us delay to impose. The routine then chooses the best way to set that - via register or via mbx. - Rather than two value types stored in eq->q_mode (usdelay if change via register, imax if change via mbox) - q_mode always contains usdelay. Before any value change, old vs new value is compared and only if different is a change done. - Revised the dmult calculation. dmult is not set based on overall imax divided by hardware queues - instead imax applies to a single cpu and the value will be replicated to all cpus. Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <jsmart2021@gmail.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c9
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c126
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h4
4 files changed, 89 insertions, 58 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index fc7f80d68638..ed8caeefe3a2 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -4935,6 +4935,7 @@ lpfc_fcp_imax_store(struct device *dev, struct device_attribute *attr,
4935 struct Scsi_Host *shost = class_to_shost(dev); 4935 struct Scsi_Host *shost = class_to_shost(dev);
4936 struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; 4936 struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
4937 struct lpfc_hba *phba = vport->phba; 4937 struct lpfc_hba *phba = vport->phba;
4938 uint32_t usdelay;
4938 int val = 0, i; 4939 int val = 0, i;
4939 4940
4940 /* fcp_imax is only valid for SLI4 */ 4941 /* fcp_imax is only valid for SLI4 */
@@ -4958,9 +4959,14 @@ lpfc_fcp_imax_store(struct device *dev, struct device_attribute *attr,
4958 phba->cfg_fcp_imax = (uint32_t)val; 4959 phba->cfg_fcp_imax = (uint32_t)val;
4959 phba->initial_imax = phba->cfg_fcp_imax; 4960 phba->initial_imax = phba->cfg_fcp_imax;
4960 4961
4962 if (phba->cfg_fcp_imax)
4963 usdelay = LPFC_SEC_TO_USEC / phba->cfg_fcp_imax;
4964 else
4965 usdelay = 0;
4966
4961 for (i = 0; i < phba->cfg_irq_chann; i += LPFC_MAX_EQ_DELAY_EQID_CNT) 4967 for (i = 0; i < phba->cfg_irq_chann; i += LPFC_MAX_EQ_DELAY_EQID_CNT)
4962 lpfc_modify_hba_eq_delay(phba, i, LPFC_MAX_EQ_DELAY_EQID_CNT, 4968 lpfc_modify_hba_eq_delay(phba, i, LPFC_MAX_EQ_DELAY_EQID_CNT,
4963 val); 4969 usdelay);
4964 4970
4965 return strlen(buf); 4971 return strlen(buf);
4966} 4972}
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 145c08f112a3..22aec1a9b689 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -9336,7 +9336,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
9336 struct lpfc_sli4_hdw_queue *qp; 9336 struct lpfc_sli4_hdw_queue *qp;
9337 LPFC_MBOXQ_t *mboxq; 9337 LPFC_MBOXQ_t *mboxq;
9338 int qidx; 9338 int qidx;
9339 uint32_t length; 9339 uint32_t length, usdelay;
9340 int rc = -ENOMEM; 9340 int rc = -ENOMEM;
9341 9341
9342 /* Check for dual-ULP support */ 9342 /* Check for dual-ULP support */
@@ -9643,10 +9643,15 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
9643 phba->sli4_hba.dat_rq->queue_id, 9643 phba->sli4_hba.dat_rq->queue_id,
9644 phba->sli4_hba.els_cq->queue_id); 9644 phba->sli4_hba.els_cq->queue_id);
9645 9645
9646 if (phba->cfg_fcp_imax)
9647 usdelay = LPFC_SEC_TO_USEC / phba->cfg_fcp_imax;
9648 else
9649 usdelay = 0;
9650
9646 for (qidx = 0; qidx < phba->cfg_irq_chann; 9651 for (qidx = 0; qidx < phba->cfg_irq_chann;
9647 qidx += LPFC_MAX_EQ_DELAY_EQID_CNT) 9652 qidx += LPFC_MAX_EQ_DELAY_EQID_CNT)
9648 lpfc_modify_hba_eq_delay(phba, qidx, LPFC_MAX_EQ_DELAY_EQID_CNT, 9653 lpfc_modify_hba_eq_delay(phba, qidx, LPFC_MAX_EQ_DELAY_EQID_CNT,
9649 phba->cfg_fcp_imax); 9654 usdelay);
9650 9655
9651 if (phba->sli4_hba.cq_max) { 9656 if (phba->sli4_hba.cq_max) {
9652 kfree(phba->sli4_hba.cq_lookup); 9657 kfree(phba->sli4_hba.cq_lookup);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 0cc81321643d..a3477cecb0c9 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -14425,43 +14425,86 @@ lpfc_dual_chute_pci_bar_map(struct lpfc_hba *phba, uint16_t pci_barset)
14425} 14425}
14426 14426
14427/** 14427/**
14428 * lpfc_modify_hba_eq_delay - Modify Delay Multiplier on FCP EQs 14428 * lpfc_modify_hba_eq_delay - Modify Delay Multiplier on EQs
14429 * @phba: HBA structure that indicates port to create a queue on. 14429 * @phba: HBA structure that EQs are on.
14430 * @startq: The starting FCP EQ to modify 14430 * @startq: The starting EQ index to modify
14431 * 14431 * @numq: The number of EQs (consecutive indexes) to modify
14432 * This function sends an MODIFY_EQ_DELAY mailbox command to the HBA. 14432 * @usdelay: amount of delay
14433 * The command allows up to LPFC_MAX_EQ_DELAY_EQID_CNT EQ ID's to be 14433 *
14434 * updated in one mailbox command. 14434 * This function revises the EQ delay on 1 or more EQs. The EQ delay
14435 * 14435 * is set either by writing to a register (if supported by the SLI Port)
14436 * The @phba struct is used to send mailbox command to HBA. The @startq 14436 * or by mailbox command. The mailbox command allows several EQs to be
14437 * is used to get the starting FCP EQ to change. 14437 * updated at once.
14438 * This function is asynchronous and will wait for the mailbox 14438 *
14439 * command to finish before continuing. 14439 * The @phba struct is used to send a mailbox command to HBA. The @startq
14440 * 14440 * is used to get the starting EQ index to change. The @numq value is
14441 * On success this function will return a zero. If unable to allocate enough 14441 * used to specify how many consecutive EQ indexes, starting at EQ index,
14442 * memory this function will return -ENOMEM. If the queue create mailbox command 14442 * are to be changed. This function is asynchronous and will wait for any
14443 * fails this function will return -ENXIO. 14443 * mailbox commands to finish before returning.
14444 *
14445 * On success this function will return a zero. If unable to allocate
14446 * enough memory this function will return -ENOMEM. If a mailbox command
14447 * fails this function will return -ENXIO. Note: on ENXIO, some EQs may
14448 * have had their delay multipler changed.
14444 **/ 14449 **/
14445int 14450void
14446lpfc_modify_hba_eq_delay(struct lpfc_hba *phba, uint32_t startq, 14451lpfc_modify_hba_eq_delay(struct lpfc_hba *phba, uint32_t startq,
14447 uint32_t numq, uint32_t imax) 14452 uint32_t numq, uint32_t usdelay)
14448{ 14453{
14449 struct lpfc_mbx_modify_eq_delay *eq_delay; 14454 struct lpfc_mbx_modify_eq_delay *eq_delay;
14450 LPFC_MBOXQ_t *mbox; 14455 LPFC_MBOXQ_t *mbox;
14451 struct lpfc_queue *eq; 14456 struct lpfc_queue *eq;
14452 int cnt, rc, length, status = 0; 14457 int cnt = 0, rc, length;
14453 uint32_t shdr_status, shdr_add_status; 14458 uint32_t shdr_status, shdr_add_status;
14454 uint32_t result, val; 14459 uint32_t dmult;
14460 struct lpfc_register reg_data;
14455 int qidx; 14461 int qidx;
14456 union lpfc_sli4_cfg_shdr *shdr; 14462 union lpfc_sli4_cfg_shdr *shdr;
14457 uint16_t dmult;
14458 14463
14459 if (startq >= phba->cfg_irq_chann) 14464 if (startq >= phba->cfg_irq_chann)
14460 return 0; 14465 return;
14466
14467 if (usdelay > 0xFFFF) {
14468 lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP | LOG_NVME,
14469 "6429 usdelay %d too large. Scaled down to "
14470 "0xFFFF.\n", usdelay);
14471 usdelay = 0xFFFF;
14472 }
14473
14474 /* set values by EQ_DELAY register if supported */
14475 if (phba->sli.sli_flag & LPFC_SLI_USE_EQDR) {
14476 for (qidx = startq; qidx < phba->cfg_irq_chann; qidx++) {
14477 eq = phba->sli4_hba.hdwq[qidx].hba_eq;
14478 if (!eq)
14479 continue;
14480
14481 /* save value last set */
14482 eq->q_mode = usdelay;
14483
14484 /* write register */
14485 reg_data.word0 = 0;
14486 bf_set(lpfc_sliport_eqdelay_id, &reg_data,
14487 eq->queue_id);
14488 bf_set(lpfc_sliport_eqdelay_delay, &reg_data, usdelay);
14489 writel(reg_data.word0,
14490 phba->sli4_hba.u.if_type2.EQDregaddr);
14491
14492 if (++cnt >= numq)
14493 break;
14494 }
14495
14496 return;
14497 }
14498
14499 /* Otherwise, set values by mailbox cmd */
14461 14500
14462 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); 14501 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
14463 if (!mbox) 14502 if (!mbox) {
14464 return -ENOMEM; 14503 lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_FCP | LOG_NVME,
14504 "6428 Failed allocating mailbox cmd buffer."
14505 " EQ delay was not set.\n");
14506 return;
14507 }
14465 length = (sizeof(struct lpfc_mbx_modify_eq_delay) - 14508 length = (sizeof(struct lpfc_mbx_modify_eq_delay) -
14466 sizeof(struct lpfc_sli4_cfg_mhdr)); 14509 sizeof(struct lpfc_sli4_cfg_mhdr));
14467 lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, 14510 lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
@@ -14470,44 +14513,22 @@ lpfc_modify_hba_eq_delay(struct lpfc_hba *phba, uint32_t startq,
14470 eq_delay = &mbox->u.mqe.un.eq_delay; 14513 eq_delay = &mbox->u.mqe.un.eq_delay;
14471 14514
14472 /* Calculate delay multiper from maximum interrupt per second */ 14515 /* Calculate delay multiper from maximum interrupt per second */
14473 result = imax / phba->cfg_irq_chann; 14516 dmult = (usdelay * LPFC_DMULT_CONST) / LPFC_SEC_TO_USEC;
14474 if (result > LPFC_DMULT_CONST || result == 0) 14517 if (dmult)
14475 dmult = 0; 14518 dmult--;
14476 else
14477 dmult = LPFC_DMULT_CONST/result - 1;
14478 if (dmult > LPFC_DMULT_MAX) 14519 if (dmult > LPFC_DMULT_MAX)
14479 dmult = LPFC_DMULT_MAX; 14520 dmult = LPFC_DMULT_MAX;
14480 14521
14481 cnt = 0;
14482 for (qidx = startq; qidx < phba->cfg_irq_chann; qidx++) { 14522 for (qidx = startq; qidx < phba->cfg_irq_chann; qidx++) {
14483 eq = phba->sli4_hba.hdwq[qidx].hba_eq; 14523 eq = phba->sli4_hba.hdwq[qidx].hba_eq;
14484 if (!eq) 14524 if (!eq)
14485 continue; 14525 continue;
14486 eq->q_mode = imax; 14526 eq->q_mode = usdelay;
14487 eq_delay->u.request.eq[cnt].eq_id = eq->queue_id; 14527 eq_delay->u.request.eq[cnt].eq_id = eq->queue_id;
14488 eq_delay->u.request.eq[cnt].phase = 0; 14528 eq_delay->u.request.eq[cnt].phase = 0;
14489 eq_delay->u.request.eq[cnt].delay_multi = dmult; 14529 eq_delay->u.request.eq[cnt].delay_multi = dmult;
14490 cnt++;
14491
14492 /* q_mode is only used for auto_imax */
14493 if (phba->sli.sli_flag & LPFC_SLI_USE_EQDR) {
14494 /* Use EQ Delay Register method for q_mode */
14495
14496 /* Convert for EQ Delay register */
14497 val = phba->cfg_fcp_imax;
14498 if (val) {
14499 /* First, interrupts per sec per EQ */
14500 val = phba->cfg_fcp_imax / phba->cfg_irq_chann;
14501
14502 /* us delay between each interrupt */
14503 val = LPFC_SEC_TO_USEC / val;
14504 }
14505 eq->q_mode = val;
14506 } else {
14507 eq->q_mode = imax;
14508 }
14509 14530
14510 if (cnt >= numq) 14531 if (++cnt >= numq)
14511 break; 14532 break;
14512 } 14533 }
14513 eq_delay->u.request.num_eq = cnt; 14534 eq_delay->u.request.num_eq = cnt;
@@ -14525,10 +14546,9 @@ lpfc_modify_hba_eq_delay(struct lpfc_hba *phba, uint32_t startq,
14525 "2512 MODIFY_EQ_DELAY mailbox failed with " 14546 "2512 MODIFY_EQ_DELAY mailbox failed with "
14526 "status x%x add_status x%x, mbx status x%x\n", 14547 "status x%x add_status x%x, mbx status x%x\n",
14527 shdr_status, shdr_add_status, rc); 14548 shdr_status, shdr_add_status, rc);
14528 status = -ENXIO;
14529 } 14549 }
14530 mempool_free(mbox, phba->mbox_mem_pool); 14550 mempool_free(mbox, phba->mbox_mem_pool);
14531 return status; 14551 return;
14532} 14552}
14533 14553
14534/** 14554/**
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index c381f2cb4909..accccca3a027 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -956,8 +956,8 @@ struct lpfc_queue *lpfc_sli4_queue_alloc(struct lpfc_hba *, uint32_t,
956 uint32_t, uint32_t); 956 uint32_t, uint32_t);
957void lpfc_sli4_queue_free(struct lpfc_queue *); 957void lpfc_sli4_queue_free(struct lpfc_queue *);
958int lpfc_eq_create(struct lpfc_hba *, struct lpfc_queue *, uint32_t); 958int lpfc_eq_create(struct lpfc_hba *, struct lpfc_queue *, uint32_t);
959int lpfc_modify_hba_eq_delay(struct lpfc_hba *phba, uint32_t startq, 959void lpfc_modify_hba_eq_delay(struct lpfc_hba *phba, uint32_t startq,
960 uint32_t numq, uint32_t imax); 960 uint32_t numq, uint32_t usdelay);
961int lpfc_cq_create(struct lpfc_hba *, struct lpfc_queue *, 961int lpfc_cq_create(struct lpfc_hba *, struct lpfc_queue *,
962 struct lpfc_queue *, uint32_t, uint32_t); 962 struct lpfc_queue *, uint32_t, uint32_t);
963int lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, 963int lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,