diff options
author | James Smart <jsmart2021@gmail.com> | 2019-01-28 14:14:32 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2019-02-05 22:29:49 -0500 |
commit | cb733e358787b7386bd1aeec088a35e03c53da3b (patch) | |
tree | d210860145ebd78544aa0e4b997581b932bda23d /drivers/scsi/lpfc | |
parent | 6a828b0f6192b4930894925d1c1d0dc1f1d99e6e (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/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 8 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 9 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 126 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 4 |
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 | **/ |
14445 | int | 14450 | void |
14446 | lpfc_modify_hba_eq_delay(struct lpfc_hba *phba, uint32_t startq, | 14451 | lpfc_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, ®_data, | ||
14487 | eq->queue_id); | ||
14488 | bf_set(lpfc_sliport_eqdelay_delay, ®_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); |
957 | void lpfc_sli4_queue_free(struct lpfc_queue *); | 957 | void lpfc_sli4_queue_free(struct lpfc_queue *); |
958 | int lpfc_eq_create(struct lpfc_hba *, struct lpfc_queue *, uint32_t); | 958 | int lpfc_eq_create(struct lpfc_hba *, struct lpfc_queue *, uint32_t); |
959 | int lpfc_modify_hba_eq_delay(struct lpfc_hba *phba, uint32_t startq, | 959 | void 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); |
961 | int lpfc_cq_create(struct lpfc_hba *, struct lpfc_queue *, | 961 | int 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); |
963 | int lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, | 963 | int lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, |