diff options
author | Jayamohan Kallickal <jayamohan.kallickal@emulex.com> | 2014-05-05 21:41:26 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-05-28 12:13:15 -0400 |
commit | 73af08e11c6638e2abd6b1fa13cdab58c2bbdbf8 (patch) | |
tree | f0e8c962e78abbe22c5fe034022368dc8453d2ea /drivers/scsi/be2iscsi | |
parent | 0598b8afd65d6b0893d217f7cf77ea315cdfcb5b (diff) |
be2iscsi: Fix interrupt Coalescing mechanism.
Signed-off-by: Minh Tran <minhduc.tran@emulex.com>
Signed-off-by: John Soni Jose <sony.john-n@emulex.com>
Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/be2iscsi')
-rw-r--r-- | drivers/scsi/be2iscsi/be.h | 11 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.h | 10 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 58 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.h | 5 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.c | 37 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.h | 2 |
6 files changed, 118 insertions, 5 deletions
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index 1bfb0bd01198..860f527d8f26 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h | |||
@@ -83,9 +83,20 @@ static inline void queue_tail_inc(struct be_queue_info *q) | |||
83 | 83 | ||
84 | /*ISCSI */ | 84 | /*ISCSI */ |
85 | 85 | ||
86 | struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */ | ||
87 | bool enable; | ||
88 | u32 min_eqd; /* in usecs */ | ||
89 | u32 max_eqd; /* in usecs */ | ||
90 | u32 prev_eqd; /* in usecs */ | ||
91 | u32 et_eqd; /* configured val when aic is off */ | ||
92 | ulong jiffs; | ||
93 | u64 eq_prev; /* Used to calculate eqe */ | ||
94 | }; | ||
95 | |||
86 | struct be_eq_obj { | 96 | struct be_eq_obj { |
87 | bool todo_mcc_cq; | 97 | bool todo_mcc_cq; |
88 | bool todo_cq; | 98 | bool todo_cq; |
99 | u32 cq_count; | ||
89 | struct be_queue_info q; | 100 | struct be_queue_info q; |
90 | struct beiscsi_hba *phba; | 101 | struct beiscsi_hba *phba; |
91 | struct be_queue_info *cq; | 102 | struct be_queue_info *cq; |
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 7cf7f99ee442..cd4410f934c7 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h | |||
@@ -271,6 +271,12 @@ struct be_cmd_resp_eq_create { | |||
271 | u16 rsvd0; /* sword */ | 271 | u16 rsvd0; /* sword */ |
272 | } __packed; | 272 | } __packed; |
273 | 273 | ||
274 | struct be_set_eqd { | ||
275 | u32 eq_id; | ||
276 | u32 phase; | ||
277 | u32 delay_multiplier; | ||
278 | } __packed; | ||
279 | |||
274 | struct mgmt_chap_format { | 280 | struct mgmt_chap_format { |
275 | u32 flags; | 281 | u32 flags; |
276 | u8 intr_chap_name[256]; | 282 | u8 intr_chap_name[256]; |
@@ -622,7 +628,7 @@ struct be_cmd_req_modify_eq_delay { | |||
622 | u32 eq_id; | 628 | u32 eq_id; |
623 | u32 phase; | 629 | u32 phase; |
624 | u32 delay_multiplier; | 630 | u32 delay_multiplier; |
625 | } delay[8]; | 631 | } delay[MAX_CPUS]; |
626 | } __packed; | 632 | } __packed; |
627 | 633 | ||
628 | /******************** Get MAC ADDR *******************/ | 634 | /******************** Get MAC ADDR *******************/ |
@@ -708,6 +714,8 @@ unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba); | |||
708 | 714 | ||
709 | void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); | 715 | void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); |
710 | 716 | ||
717 | int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, struct be_set_eqd *, | ||
718 | int num); | ||
711 | int beiscsi_mccq_compl(struct beiscsi_hba *phba, | 719 | int beiscsi_mccq_compl(struct beiscsi_hba *phba, |
712 | uint32_t tag, struct be_mcc_wrb **wrb, | 720 | uint32_t tag, struct be_mcc_wrb **wrb, |
713 | struct be_dma_mem *mbx_cmd_mem); | 721 | struct be_dma_mem *mbx_cmd_mem); |
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index a73af296b29d..e9f01a5f360b 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
@@ -2271,6 +2271,7 @@ static int be_iopoll(struct blk_iopoll *iop, int budget) | |||
2271 | 2271 | ||
2272 | pbe_eq = container_of(iop, struct be_eq_obj, iopoll); | 2272 | pbe_eq = container_of(iop, struct be_eq_obj, iopoll); |
2273 | ret = beiscsi_process_cq(pbe_eq); | 2273 | ret = beiscsi_process_cq(pbe_eq); |
2274 | pbe_eq->cq_count += ret; | ||
2274 | if (ret < budget) { | 2275 | if (ret < budget) { |
2275 | phba = pbe_eq->phba; | 2276 | phba = pbe_eq->phba; |
2276 | blk_iopoll_complete(iop); | 2277 | blk_iopoll_complete(iop); |
@@ -3825,9 +3826,9 @@ static int hwi_init_port(struct beiscsi_hba *phba) | |||
3825 | 3826 | ||
3826 | phwi_ctrlr = phba->phwi_ctrlr; | 3827 | phwi_ctrlr = phba->phwi_ctrlr; |
3827 | phwi_context = phwi_ctrlr->phwi_ctxt; | 3828 | phwi_context = phwi_ctrlr->phwi_ctxt; |
3828 | phwi_context->max_eqd = 0; | 3829 | phwi_context->max_eqd = 128; |
3829 | phwi_context->min_eqd = 0; | 3830 | phwi_context->min_eqd = 0; |
3830 | phwi_context->cur_eqd = 64; | 3831 | phwi_context->cur_eqd = 0; |
3831 | be_cmd_fw_initialize(&phba->ctrl); | 3832 | be_cmd_fw_initialize(&phba->ctrl); |
3832 | 3833 | ||
3833 | status = beiscsi_create_eqs(phba, phwi_context); | 3834 | status = beiscsi_create_eqs(phba, phwi_context); |
@@ -5282,6 +5283,57 @@ static void beiscsi_msix_enable(struct beiscsi_hba *phba) | |||
5282 | return; | 5283 | return; |
5283 | } | 5284 | } |
5284 | 5285 | ||
5286 | static void be_eqd_update(struct beiscsi_hba *phba) | ||
5287 | { | ||
5288 | struct be_set_eqd set_eqd[MAX_CPUS]; | ||
5289 | struct be_aic_obj *aic; | ||
5290 | struct be_eq_obj *pbe_eq; | ||
5291 | struct hwi_controller *phwi_ctrlr; | ||
5292 | struct hwi_context_memory *phwi_context; | ||
5293 | int eqd, i, num = 0; | ||
5294 | ulong now; | ||
5295 | u32 pps, delta; | ||
5296 | unsigned int tag; | ||
5297 | |||
5298 | phwi_ctrlr = phba->phwi_ctrlr; | ||
5299 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
5300 | |||
5301 | for (i = 0; i <= phba->num_cpus; i++) { | ||
5302 | aic = &phba->aic_obj[i]; | ||
5303 | pbe_eq = &phwi_context->be_eq[i]; | ||
5304 | now = jiffies; | ||
5305 | if (!aic->jiffs || time_before(now, aic->jiffs) || | ||
5306 | pbe_eq->cq_count < aic->eq_prev) { | ||
5307 | aic->jiffs = now; | ||
5308 | aic->eq_prev = pbe_eq->cq_count; | ||
5309 | continue; | ||
5310 | } | ||
5311 | delta = jiffies_to_msecs(now - aic->jiffs); | ||
5312 | pps = (((u32)(pbe_eq->cq_count - aic->eq_prev) * 1000) / delta); | ||
5313 | eqd = (pps / 1500) << 2; | ||
5314 | |||
5315 | if (eqd < 8) | ||
5316 | eqd = 0; | ||
5317 | eqd = min_t(u32, eqd, phwi_context->max_eqd); | ||
5318 | eqd = max_t(u32, eqd, phwi_context->min_eqd); | ||
5319 | |||
5320 | aic->jiffs = now; | ||
5321 | aic->eq_prev = pbe_eq->cq_count; | ||
5322 | |||
5323 | if (eqd != aic->prev_eqd) { | ||
5324 | set_eqd[num].delay_multiplier = (eqd * 65)/100; | ||
5325 | set_eqd[num].eq_id = pbe_eq->q.id; | ||
5326 | aic->prev_eqd = eqd; | ||
5327 | num++; | ||
5328 | } | ||
5329 | } | ||
5330 | if (num) { | ||
5331 | tag = be_cmd_modify_eq_delay(phba, set_eqd, num); | ||
5332 | if (tag) | ||
5333 | beiscsi_mccq_compl(phba, tag, NULL, NULL); | ||
5334 | } | ||
5335 | } | ||
5336 | |||
5285 | /* | 5337 | /* |
5286 | * beiscsi_hw_health_check()- Check adapter health | 5338 | * beiscsi_hw_health_check()- Check adapter health |
5287 | * @work: work item to check HW health | 5339 | * @work: work item to check HW health |
@@ -5295,6 +5347,8 @@ beiscsi_hw_health_check(struct work_struct *work) | |||
5295 | container_of(work, struct beiscsi_hba, | 5347 | container_of(work, struct beiscsi_hba, |
5296 | beiscsi_hw_check_task.work); | 5348 | beiscsi_hw_check_task.work); |
5297 | 5349 | ||
5350 | be_eqd_update(phba); | ||
5351 | |||
5298 | beiscsi_ue_detect(phba); | 5352 | beiscsi_ue_detect(phba); |
5299 | 5353 | ||
5300 | schedule_delayed_work(&phba->beiscsi_hw_check_task, | 5354 | schedule_delayed_work(&phba->beiscsi_hw_check_task, |
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 9380b55bdeaf..dc56ea91facb 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h | |||
@@ -71,8 +71,8 @@ | |||
71 | 71 | ||
72 | #define BEISCSI_SGLIST_ELEMENTS 30 | 72 | #define BEISCSI_SGLIST_ELEMENTS 30 |
73 | 73 | ||
74 | #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ | 74 | #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ |
75 | #define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */ | 75 | #define BEISCSI_MAX_SECTORS 1024 /* scsi_host->max_sectors */ |
76 | #define BEISCSI_TEMPLATE_HDR_PER_CXN_SIZE 128 /* Template size per cxn */ | 76 | #define BEISCSI_TEMPLATE_HDR_PER_CXN_SIZE 128 /* Template size per cxn */ |
77 | 77 | ||
78 | #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ | 78 | #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ |
@@ -427,6 +427,7 @@ struct beiscsi_hba { | |||
427 | struct mgmt_session_info boot_sess; | 427 | struct mgmt_session_info boot_sess; |
428 | struct invalidate_command_table inv_tbl[128]; | 428 | struct invalidate_command_table inv_tbl[128]; |
429 | 429 | ||
430 | struct be_aic_obj aic_obj[MAX_CPUS]; | ||
430 | unsigned int attr_log_enable; | 431 | unsigned int attr_log_enable; |
431 | int (*iotask_fn)(struct iscsi_task *, | 432 | int (*iotask_fn)(struct iscsi_task *, |
432 | struct scatterlist *sg, | 433 | struct scatterlist *sg, |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 712911fba075..52a36fba1e2b 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
@@ -155,6 +155,43 @@ void beiscsi_ue_detect(struct beiscsi_hba *phba) | |||
155 | } | 155 | } |
156 | } | 156 | } |
157 | 157 | ||
158 | int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, | ||
159 | struct be_set_eqd *set_eqd, int num) | ||
160 | { | ||
161 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
162 | struct be_mcc_wrb *wrb; | ||
163 | struct be_cmd_req_modify_eq_delay *req; | ||
164 | unsigned int tag = 0; | ||
165 | int i; | ||
166 | |||
167 | spin_lock(&ctrl->mbox_lock); | ||
168 | tag = alloc_mcc_tag(phba); | ||
169 | if (!tag) { | ||
170 | spin_unlock(&ctrl->mbox_lock); | ||
171 | return tag; | ||
172 | } | ||
173 | |||
174 | wrb = wrb_from_mccq(phba); | ||
175 | req = embedded_payload(wrb); | ||
176 | |||
177 | wrb->tag0 |= tag; | ||
178 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
179 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
180 | OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req)); | ||
181 | |||
182 | req->num_eq = cpu_to_le32(num); | ||
183 | for (i = 0; i < num; i++) { | ||
184 | req->delay[i].eq_id = cpu_to_le32(set_eqd[i].eq_id); | ||
185 | req->delay[i].phase = 0; | ||
186 | req->delay[i].delay_multiplier = | ||
187 | cpu_to_le32(set_eqd[i].delay_multiplier); | ||
188 | } | ||
189 | |||
190 | be_mcc_notify(phba); | ||
191 | spin_unlock(&ctrl->mbox_lock); | ||
192 | return tag; | ||
193 | } | ||
194 | |||
158 | /** | 195 | /** |
159 | * mgmt_reopen_session()- Reopen a session based on reopen_type | 196 | * mgmt_reopen_session()- Reopen a session based on reopen_type |
160 | * @phba: Device priv structure instance | 197 | * @phba: Device priv structure instance |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index 01b8c97284c0..24a8fc577477 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h | |||
@@ -335,5 +335,7 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, | |||
335 | void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, | 335 | void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, |
336 | struct wrb_handle *pwrb_handle); | 336 | struct wrb_handle *pwrb_handle); |
337 | void beiscsi_ue_detect(struct beiscsi_hba *phba); | 337 | void beiscsi_ue_detect(struct beiscsi_hba *phba); |
338 | int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, | ||
339 | struct be_set_eqd *, int num); | ||
338 | 340 | ||
339 | #endif | 341 | #endif |