be2iscsi: Fix interrupt Coalescing mechanism.
authorJayamohan Kallickal <jayamohan.kallickal@emulex.com>
Tue, 6 May 2014 01:41:26 +0000 (21:41 -0400)
committerChristoph Hellwig <hch@lst.de>
Wed, 28 May 2014 16:13:15 +0000 (18:13 +0200)
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>
drivers/scsi/be2iscsi/be.h
drivers/scsi/be2iscsi/be_cmds.h
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/be2iscsi/be_main.h
drivers/scsi/be2iscsi/be_mgmt.c
drivers/scsi/be2iscsi/be_mgmt.h

index 1bfb0bd01198679fac77fb0c2c73a6e8d4ef57e9..860f527d8f26bd4e3302e5e77ab02cb5ba74f8b8 100644 (file)
@@ -83,9 +83,20 @@ static inline void queue_tail_inc(struct be_queue_info *q)
 
 /*ISCSI */
 
+struct be_aic_obj {            /* Adaptive interrupt coalescing (AIC) info */
+       bool enable;
+       u32 min_eqd;            /* in usecs */
+       u32 max_eqd;            /* in usecs */
+       u32 prev_eqd;           /* in usecs */
+       u32 et_eqd;             /* configured val when aic is off */
+       ulong jiffs;
+       u64 eq_prev;            /* Used to calculate eqe */
+};
+
 struct be_eq_obj {
        bool todo_mcc_cq;
        bool todo_cq;
+       u32 cq_count;
        struct be_queue_info q;
        struct beiscsi_hba *phba;
        struct be_queue_info *cq;
index 7cf7f99ee44238a874e193a09d24d13f69db759b..cd4410f934c7b611c86cd78d4f6550af83b60c02 100644 (file)
@@ -271,6 +271,12 @@ struct be_cmd_resp_eq_create {
        u16 rsvd0;              /* sword */
 } __packed;
 
+struct be_set_eqd {
+       u32 eq_id;
+       u32 phase;
+       u32 delay_multiplier;
+} __packed;
+
 struct mgmt_chap_format {
        u32 flags;
        u8  intr_chap_name[256];
@@ -622,7 +628,7 @@ struct be_cmd_req_modify_eq_delay {
                u32 eq_id;
                u32 phase;
                u32 delay_multiplier;
-       } delay[8];
+       } delay[MAX_CPUS];
 } __packed;
 
 /******************** Get MAC ADDR *******************/
@@ -708,6 +714,8 @@ unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba);
 
 void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag);
 
+int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, struct be_set_eqd *,
+                           int num);
 int beiscsi_mccq_compl(struct beiscsi_hba *phba,
                        uint32_t tag, struct be_mcc_wrb **wrb,
                        struct be_dma_mem *mbx_cmd_mem);
index a73af296b29dbf5f2920586ee8991902cf214fe4..e9f01a5f360b56f8f53b99ec27cea2212e3524d6 100644 (file)
@@ -2271,6 +2271,7 @@ static int be_iopoll(struct blk_iopoll *iop, int budget)
 
        pbe_eq = container_of(iop, struct be_eq_obj, iopoll);
        ret = beiscsi_process_cq(pbe_eq);
+       pbe_eq->cq_count += ret;
        if (ret < budget) {
                phba = pbe_eq->phba;
                blk_iopoll_complete(iop);
@@ -3825,9 +3826,9 @@ static int hwi_init_port(struct beiscsi_hba *phba)
 
        phwi_ctrlr = phba->phwi_ctrlr;
        phwi_context = phwi_ctrlr->phwi_ctxt;
-       phwi_context->max_eqd = 0;
+       phwi_context->max_eqd = 128;
        phwi_context->min_eqd = 0;
-       phwi_context->cur_eqd = 64;
+       phwi_context->cur_eqd = 0;
        be_cmd_fw_initialize(&phba->ctrl);
 
        status = beiscsi_create_eqs(phba, phwi_context);
@@ -5282,6 +5283,57 @@ static void beiscsi_msix_enable(struct beiscsi_hba *phba)
        return;
 }
 
+static void be_eqd_update(struct beiscsi_hba *phba)
+{
+       struct be_set_eqd set_eqd[MAX_CPUS];
+       struct be_aic_obj *aic;
+       struct be_eq_obj *pbe_eq;
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_context_memory *phwi_context;
+       int eqd, i, num = 0;
+       ulong now;
+       u32 pps, delta;
+       unsigned int tag;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_context = phwi_ctrlr->phwi_ctxt;
+
+       for (i = 0; i <= phba->num_cpus; i++) {
+               aic = &phba->aic_obj[i];
+               pbe_eq = &phwi_context->be_eq[i];
+               now = jiffies;
+               if (!aic->jiffs || time_before(now, aic->jiffs) ||
+                   pbe_eq->cq_count < aic->eq_prev) {
+                       aic->jiffs = now;
+                       aic->eq_prev = pbe_eq->cq_count;
+                       continue;
+               }
+               delta = jiffies_to_msecs(now - aic->jiffs);
+               pps = (((u32)(pbe_eq->cq_count - aic->eq_prev) * 1000) / delta);
+               eqd = (pps / 1500) << 2;
+
+               if (eqd < 8)
+                       eqd = 0;
+               eqd = min_t(u32, eqd, phwi_context->max_eqd);
+               eqd = max_t(u32, eqd, phwi_context->min_eqd);
+
+               aic->jiffs = now;
+               aic->eq_prev = pbe_eq->cq_count;
+
+               if (eqd != aic->prev_eqd) {
+                       set_eqd[num].delay_multiplier = (eqd * 65)/100;
+                       set_eqd[num].eq_id = pbe_eq->q.id;
+                       aic->prev_eqd = eqd;
+                       num++;
+               }
+       }
+       if (num) {
+               tag = be_cmd_modify_eq_delay(phba, set_eqd, num);
+               if (tag)
+                       beiscsi_mccq_compl(phba, tag, NULL, NULL);
+       }
+}
+
 /*
  * beiscsi_hw_health_check()- Check adapter health
  * @work: work item to check HW health
@@ -5295,6 +5347,8 @@ beiscsi_hw_health_check(struct work_struct *work)
                container_of(work, struct beiscsi_hba,
                             beiscsi_hw_check_task.work);
 
+       be_eqd_update(phba);
+
        beiscsi_ue_detect(phba);
 
        schedule_delayed_work(&phba->beiscsi_hw_check_task,
index 9380b55bdeaf754ec0df495b4db87e2872bc511f..dc56ea91facb71cec570133e42a824073107bcae 100644 (file)
@@ -71,8 +71,8 @@
 
 #define BEISCSI_SGLIST_ELEMENTS        30
 
-#define BEISCSI_CMD_PER_LUN    128     /* scsi_host->cmd_per_lun */
-#define BEISCSI_MAX_SECTORS    2048    /* scsi_host->max_sectors */
+#define BEISCSI_CMD_PER_LUN    128 /* scsi_host->cmd_per_lun */
+#define BEISCSI_MAX_SECTORS    1024 /* scsi_host->max_sectors */
 #define BEISCSI_TEMPLATE_HDR_PER_CXN_SIZE 128 /* Template size per cxn */
 
 #define BEISCSI_MAX_CMD_LEN    16      /* scsi_host->max_cmd_len */
@@ -427,6 +427,7 @@ struct beiscsi_hba {
        struct mgmt_session_info boot_sess;
        struct invalidate_command_table inv_tbl[128];
 
+       struct be_aic_obj aic_obj[MAX_CPUS];
        unsigned int attr_log_enable;
        int (*iotask_fn)(struct iscsi_task *,
                        struct scatterlist *sg,
index 712911fba075595c6ae1e0f1b24d660eeb601f1d..52a36fba1e2b864b18bb32092a14db13e65820f5 100644 (file)
@@ -155,6 +155,43 @@ void beiscsi_ue_detect(struct beiscsi_hba *phba)
        }
 }
 
+int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
+                struct be_set_eqd *set_eqd, int num)
+{
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_modify_eq_delay *req;
+       unsigned int tag = 0;
+       int i;
+
+       spin_lock(&ctrl->mbox_lock);
+       tag = alloc_mcc_tag(phba);
+       if (!tag) {
+               spin_unlock(&ctrl->mbox_lock);
+               return tag;
+       }
+
+       wrb = wrb_from_mccq(phba);
+       req = embedded_payload(wrb);
+
+       wrb->tag0 |= tag;
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+               OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req));
+
+       req->num_eq = cpu_to_le32(num);
+       for (i = 0; i < num; i++) {
+               req->delay[i].eq_id = cpu_to_le32(set_eqd[i].eq_id);
+               req->delay[i].phase = 0;
+               req->delay[i].delay_multiplier =
+                               cpu_to_le32(set_eqd[i].delay_multiplier);
+       }
+
+       be_mcc_notify(phba);
+       spin_unlock(&ctrl->mbox_lock);
+       return tag;
+}
+
 /**
  * mgmt_reopen_session()- Reopen a session based on reopen_type
  * @phba: Device priv structure instance
index 01b8c97284c0653753f6bc8085c47f799ce09f79..24a8fc577477394b2c674905eb3227d12bd9feb1 100644 (file)
@@ -335,5 +335,7 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
 void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
                             struct wrb_handle *pwrb_handle);
 void beiscsi_ue_detect(struct beiscsi_hba *phba);
+int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
+                        struct be_set_eqd *, int num);
 
 #endif