aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2012-06-12 13:54:50 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-07-20 03:58:29 -0400
commit173edbb2c326ce4839bae8caa868fe83ce46dda3 (patch)
tree5d307e89546f9745346b04978ab9821e2d2aaab9 /drivers/scsi/lpfc
parent3a70730aa06c37d46086ecdbca7107531fe2d2c5 (diff)
[SCSI] lpfc 8.3.32: Fix ability to change FCP EQ delay multiplier
Fix fcp_imax module parameter to dynamically change FCP EQ delay multiplier Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com> 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_attr.c93
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h22
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c77
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h1
4 files changed, 185 insertions, 8 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 5eb2bc116183..adef5bb2100e 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -3617,6 +3617,91 @@ lpfc_sriov_nr_virtfn_init(struct lpfc_hba *phba, int val)
3617static DEVICE_ATTR(lpfc_sriov_nr_virtfn, S_IRUGO | S_IWUSR, 3617static DEVICE_ATTR(lpfc_sriov_nr_virtfn, S_IRUGO | S_IWUSR,
3618 lpfc_sriov_nr_virtfn_show, lpfc_sriov_nr_virtfn_store); 3618 lpfc_sriov_nr_virtfn_show, lpfc_sriov_nr_virtfn_store);
3619 3619
3620/**
3621 * lpfc_fcp_imax_store
3622 *
3623 * @dev: class device that is converted into a Scsi_host.
3624 * @attr: device attribute, not used.
3625 * @buf: string with the number of fast-path FCP interrupts per second.
3626 * @count: unused variable.
3627 *
3628 * Description:
3629 * If val is in a valid range [636,651042], then set the adapter's
3630 * maximum number of fast-path FCP interrupts per second.
3631 *
3632 * Returns:
3633 * length of the buf on success if val is in range the intended mode
3634 * is supported.
3635 * -EINVAL if val out of range or intended mode is not supported.
3636 **/
3637static ssize_t
3638lpfc_fcp_imax_store(struct device *dev, struct device_attribute *attr,
3639 const char *buf, size_t count)
3640{
3641 struct Scsi_Host *shost = class_to_shost(dev);
3642 struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
3643 struct lpfc_hba *phba = vport->phba;
3644 int val = 0, i;
3645
3646 /* Sanity check on user data */
3647 if (!isdigit(buf[0]))
3648 return -EINVAL;
3649 if (sscanf(buf, "%i", &val) != 1)
3650 return -EINVAL;
3651
3652 /* Value range is [636,651042] */
3653 if (val < LPFC_MIM_IMAX || val > LPFC_DMULT_CONST)
3654 return -EINVAL;
3655
3656 phba->cfg_fcp_imax = (uint32_t)val;
3657 for (i = 0; i < phba->cfg_fcp_eq_count; i += LPFC_MAX_EQ_DELAY)
3658 lpfc_modify_fcp_eq_delay(phba, i);
3659
3660 return strlen(buf);
3661}
3662
3663/*
3664# lpfc_fcp_imax: The maximum number of fast-path FCP interrupts per second
3665#
3666# Value range is [636,651042]. Default value is 10000.
3667*/
3668static int lpfc_fcp_imax = LPFC_FP_DEF_IMAX;
3669module_param(lpfc_fcp_imax, int, S_IRUGO|S_IWUSR);
3670MODULE_PARM_DESC(lpfc_fcp_imax,
3671 "Set the maximum number of fast-path FCP interrupts per second");
3672lpfc_param_show(fcp_imax)
3673
3674/**
3675 * lpfc_fcp_imax_init - Set the initial sr-iov virtual function enable
3676 * @phba: lpfc_hba pointer.
3677 * @val: link speed value.
3678 *
3679 * Description:
3680 * If val is in a valid range [636,651042], then initialize the adapter's
3681 * maximum number of fast-path FCP interrupts per second.
3682 *
3683 * Returns:
3684 * zero if val saved.
3685 * -EINVAL val out of range
3686 **/
3687static int
3688lpfc_fcp_imax_init(struct lpfc_hba *phba, int val)
3689{
3690 if (val >= LPFC_MIM_IMAX && val <= LPFC_DMULT_CONST) {
3691 phba->cfg_fcp_imax = val;
3692 return 0;
3693 }
3694
3695 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
3696 "3016 fcp_imax: %d out of range, using default\n", val);
3697 phba->cfg_fcp_imax = LPFC_FP_DEF_IMAX;
3698
3699 return 0;
3700}
3701
3702static DEVICE_ATTR(lpfc_fcp_imax, S_IRUGO | S_IWUSR,
3703 lpfc_fcp_imax_show, lpfc_fcp_imax_store);
3704
3620/* 3705/*
3621# lpfc_fcp_class: Determines FC class to use for the FCP protocol. 3706# lpfc_fcp_class: Determines FC class to use for the FCP protocol.
3622# Value range is [2,3]. Default value is 3. 3707# Value range is [2,3]. Default value is 3.
@@ -3758,14 +3843,6 @@ LPFC_ATTR_R(use_msi, 2, 0, 2, "Use Message Signaled Interrupts (1) or "
3758 "MSI-X (2), if possible"); 3843 "MSI-X (2), if possible");
3759 3844
3760/* 3845/*
3761# lpfc_fcp_imax: Set the maximum number of fast-path FCP interrupts per second
3762#
3763# Value range is [636,651042]. Default value is 10000.
3764*/
3765LPFC_ATTR_R(fcp_imax, LPFC_FP_DEF_IMAX, LPFC_MIM_IMAX, LPFC_DMULT_CONST,
3766 "Set the maximum number of fast-path FCP interrupts per second");
3767
3768/*
3769# lpfc_fcp_wq_count: Set the number of fast-path FCP work queues 3846# lpfc_fcp_wq_count: Set the number of fast-path FCP work queues
3770# 3847#
3771# Value range is [1,31]. Default value is 4. 3848# Value range is [1,31]. Default value is 4.
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index f1946dfda5b4..a631ebf4158d 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -874,6 +874,7 @@ struct mbox_header {
874#define LPFC_MBOX_OPCODE_MQ_CREATE 0x15 874#define LPFC_MBOX_OPCODE_MQ_CREATE 0x15
875#define LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES 0x20 875#define LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES 0x20
876#define LPFC_MBOX_OPCODE_NOP 0x21 876#define LPFC_MBOX_OPCODE_NOP 0x21
877#define LPFC_MBOX_OPCODE_MODIFY_EQ_DELAY 0x29
877#define LPFC_MBOX_OPCODE_MQ_DESTROY 0x35 878#define LPFC_MBOX_OPCODE_MQ_DESTROY 0x35
878#define LPFC_MBOX_OPCODE_CQ_DESTROY 0x36 879#define LPFC_MBOX_OPCODE_CQ_DESTROY 0x36
879#define LPFC_MBOX_OPCODE_EQ_DESTROY 0x37 880#define LPFC_MBOX_OPCODE_EQ_DESTROY 0x37
@@ -940,6 +941,13 @@ struct eq_context {
940 uint32_t reserved3; 941 uint32_t reserved3;
941}; 942};
942 943
944struct eq_delay_info {
945 uint32_t eq_id;
946 uint32_t phase;
947 uint32_t delay_multi;
948};
949#define LPFC_MAX_EQ_DELAY 8
950
943struct sgl_page_pairs { 951struct sgl_page_pairs {
944 uint32_t sgl_pg0_addr_lo; 952 uint32_t sgl_pg0_addr_lo;
945 uint32_t sgl_pg0_addr_hi; 953 uint32_t sgl_pg0_addr_hi;
@@ -1002,6 +1010,19 @@ struct lpfc_mbx_eq_create {
1002 } u; 1010 } u;
1003}; 1011};
1004 1012
1013struct lpfc_mbx_modify_eq_delay {
1014 struct mbox_header header;
1015 union {
1016 struct {
1017 uint32_t num_eq;
1018 struct eq_delay_info eq[LPFC_MAX_EQ_DELAY];
1019 } request;
1020 struct {
1021 uint32_t word0;
1022 } response;
1023 } u;
1024};
1025
1005struct lpfc_mbx_eq_destroy { 1026struct lpfc_mbx_eq_destroy {
1006 struct mbox_header header; 1027 struct mbox_header header;
1007 union { 1028 union {
@@ -2875,6 +2896,7 @@ struct lpfc_mqe {
2875 struct lpfc_mbx_mq_create mq_create; 2896 struct lpfc_mbx_mq_create mq_create;
2876 struct lpfc_mbx_mq_create_ext mq_create_ext; 2897 struct lpfc_mbx_mq_create_ext mq_create_ext;
2877 struct lpfc_mbx_eq_create eq_create; 2898 struct lpfc_mbx_eq_create eq_create;
2899 struct lpfc_mbx_modify_eq_delay eq_delay;
2878 struct lpfc_mbx_cq_create cq_create; 2900 struct lpfc_mbx_cq_create cq_create;
2879 struct lpfc_mbx_wq_create wq_create; 2901 struct lpfc_mbx_wq_create wq_create;
2880 struct lpfc_mbx_rq_create rq_create; 2902 struct lpfc_mbx_rq_create rq_create;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 3333e64703a3..9cbd20b1328b 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -12048,6 +12048,83 @@ out_fail:
12048} 12048}
12049 12049
12050/** 12050/**
12051 * lpfc_modify_fcp_eq_delay - Modify Delay Multiplier on FCP EQs
12052 * @phba: HBA structure that indicates port to create a queue on.
12053 * @startq: The starting FCP EQ to modify
12054 *
12055 * This function sends an MODIFY_EQ_DELAY mailbox command to the HBA.
12056 *
12057 * The @phba struct is used to send mailbox command to HBA. The @startq
12058 * is used to get the starting FCP EQ to change.
12059 * This function is asynchronous and will wait for the mailbox
12060 * command to finish before continuing.
12061 *
12062 * On success this function will return a zero. If unable to allocate enough
12063 * memory this function will return -ENOMEM. If the queue create mailbox command
12064 * fails this function will return -ENXIO.
12065 **/
12066uint32_t
12067lpfc_modify_fcp_eq_delay(struct lpfc_hba *phba, uint16_t startq)
12068{
12069 struct lpfc_mbx_modify_eq_delay *eq_delay;
12070 LPFC_MBOXQ_t *mbox;
12071 struct lpfc_queue *eq;
12072 int cnt, rc, length, status = 0;
12073 uint32_t shdr_status, shdr_add_status;
12074 int fcp_eqidx;
12075 union lpfc_sli4_cfg_shdr *shdr;
12076 uint16_t dmult;
12077
12078 if (startq >= phba->cfg_fcp_eq_count)
12079 return 0;
12080
12081 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
12082 if (!mbox)
12083 return -ENOMEM;
12084 length = (sizeof(struct lpfc_mbx_modify_eq_delay) -
12085 sizeof(struct lpfc_sli4_cfg_mhdr));
12086 lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
12087 LPFC_MBOX_OPCODE_MODIFY_EQ_DELAY,
12088 length, LPFC_SLI4_MBX_EMBED);
12089 eq_delay = &mbox->u.mqe.un.eq_delay;
12090
12091 /* Calculate delay multiper from maximum interrupt per second */
12092 dmult = LPFC_DMULT_CONST/phba->cfg_fcp_imax - 1;
12093
12094 cnt = 0;
12095 for (fcp_eqidx = startq; fcp_eqidx < phba->cfg_fcp_eq_count;
12096 fcp_eqidx++) {
12097 eq = phba->sli4_hba.fp_eq[fcp_eqidx];
12098 if (!eq)
12099 continue;
12100 eq_delay->u.request.eq[cnt].eq_id = eq->queue_id;
12101 eq_delay->u.request.eq[cnt].phase = 0;
12102 eq_delay->u.request.eq[cnt].delay_multi = dmult;
12103 cnt++;
12104 if (cnt >= LPFC_MAX_EQ_DELAY)
12105 break;
12106 }
12107 eq_delay->u.request.num_eq = cnt;
12108
12109 mbox->vport = phba->pport;
12110 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
12111 mbox->context1 = NULL;
12112 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
12113 shdr = (union lpfc_sli4_cfg_shdr *) &eq_delay->header.cfg_shdr;
12114 shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
12115 shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
12116 if (shdr_status || shdr_add_status || rc) {
12117 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
12118 "2512 MODIFY_EQ_DELAY mailbox failed with "
12119 "status x%x add_status x%x, mbx status x%x\n",
12120 shdr_status, shdr_add_status, rc);
12121 status = -ENXIO;
12122 }
12123 mempool_free(mbox, phba->mbox_mem_pool);
12124 return status;
12125}
12126
12127/**
12051 * lpfc_eq_create - Create an Event Queue on the HBA 12128 * lpfc_eq_create - Create an Event Queue on the HBA
12052 * @phba: HBA structure that indicates port to create a queue on. 12129 * @phba: HBA structure that indicates port to create a queue on.
12053 * @eq: The queue structure to use to create the event queue. 12130 * @eq: The queue structure to use to create the event queue.
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index a4a77080091b..ec756118c5c1 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -598,6 +598,7 @@ struct lpfc_queue *lpfc_sli4_queue_alloc(struct lpfc_hba *, uint32_t,
598 uint32_t); 598 uint32_t);
599void lpfc_sli4_queue_free(struct lpfc_queue *); 599void lpfc_sli4_queue_free(struct lpfc_queue *);
600uint32_t lpfc_eq_create(struct lpfc_hba *, struct lpfc_queue *, uint16_t); 600uint32_t lpfc_eq_create(struct lpfc_hba *, struct lpfc_queue *, uint16_t);
601uint32_t lpfc_modify_fcp_eq_delay(struct lpfc_hba *, uint16_t);
601uint32_t lpfc_cq_create(struct lpfc_hba *, struct lpfc_queue *, 602uint32_t lpfc_cq_create(struct lpfc_hba *, struct lpfc_queue *,
602 struct lpfc_queue *, uint32_t, uint32_t); 603 struct lpfc_queue *, uint32_t, uint32_t);
603int32_t lpfc_mq_create(struct lpfc_hba *, struct lpfc_queue *, 604int32_t lpfc_mq_create(struct lpfc_hba *, struct lpfc_queue *,