From patchwork Thu Dec 18 08:43:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devesh Sharma X-Patchwork-Id: 5512061 Return-Path: X-Original-To: patchwork-linux-rdma@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id DB8FC9F30B for ; Thu, 18 Dec 2014 09:29:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C1634209DE for ; Thu, 18 Dec 2014 09:29:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A5B8D209C7 for ; Thu, 18 Dec 2014 09:29:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752078AbaLRJ3K (ORCPT ); Thu, 18 Dec 2014 04:29:10 -0500 Received: from cmexedge1.emulex.com ([138.239.224.99]:46010 "EHLO CMEXEDGE1.ext.emulex.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750981AbaLRJ3F (ORCPT ); Thu, 18 Dec 2014 04:29:05 -0500 Received: from CMEXHTCAS1.ad.emulex.com (138.239.115.217) by CMEXEDGE1.ext.emulex.com (138.239.224.99) with Microsoft SMTP Server (TLS) id 14.3.174.1; Thu, 18 Dec 2014 01:29:11 -0800 Received: from neo01-el64.lab.bg.emulex.com (10.192.204.8) by smtp.emulex.com (138.239.115.207) with Microsoft SMTP Server id 14.3.174.1; Thu, 18 Dec 2014 01:29:01 -0800 From: Devesh Sharma To: CC: Mitesh Ahuja , Devesh Sharma , Selvin Xavier Subject: [PATCH 11/14] RDMA/ocrdma: Add support for interrupt moderation. Date: Thu, 18 Dec 2014 14:13:05 +0530 X-Mailer: git-send-email 1.7.1 In-Reply-To: <1418892188-6623-1-git-send-email-devesh.sharma@emulex.com> References: <1418892188-6623-1-git-send-email-devesh.sharma@emulex.com> MIME-Version: 1.0 Message-ID: <5686e2bc-2d9f-490b-9b37-434b572bff35@CMEXHTCAS1.ad.emulex.com> Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Mitesh Ahuja Add support for interrupt moderation for ocrdma device. Thresholds for high interrupt rates are static values derived based on experimental results. Signed-off-by: Mitesh Ahuja Signed-off-by: Devesh Sharma Signed-off-by: Selvin Xavier --- drivers/infiniband/hw/ocrdma/ocrdma.h | 14 +++++ drivers/infiniband/hw/ocrdma/ocrdma_hw.c | 77 ++++++++++++++++++++++++++++ drivers/infiniband/hw/ocrdma/ocrdma_main.c | 4 ++ drivers/infiniband/hw/ocrdma/ocrdma_sli.h | 24 +++++++++ 4 files changed, 119 insertions(+), 0 deletions(-) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h index 933b38a..b9fee0e 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma.h @@ -55,6 +55,12 @@ #define OCRDMA_UVERBS(CMD_NAME) (1ull << IB_USER_VERBS_CMD_##CMD_NAME) #define convert_to_64bit(lo, hi) ((u64)hi << 32 | (u64)lo) +#define EQ_INTR_PER_SEC_THRSH_HI 150000 +#define EQ_INTR_PER_SEC_THRSH_LOW 100000 +#define EQ_AIC_MAX_EQD 20 +#define EQ_AIC_MIN_EQD 0 + +void ocrdma_eqd_set_task(struct work_struct *work); struct ocrdma_dev_attr { u8 fw_ver[32]; @@ -117,12 +123,19 @@ struct ocrdma_queue_info { bool created; }; +struct ocrdma_aic_obj { /* Adaptive interrupt coalescing (AIC) info */ + u32 prev_eqd; + u64 eq_intr_cnt; + u64 prev_eq_intr_cnt; +}; + struct ocrdma_eq { struct ocrdma_queue_info q; u32 vector; int cq_cnt; struct ocrdma_dev *dev; char irq_name[32]; + struct ocrdma_aic_obj aic_obj; }; struct ocrdma_mq { @@ -214,6 +227,7 @@ struct ocrdma_dev { struct ocrdma_eq *eq_tbl; int eq_cnt; + struct delayed_work eqd_work; u16 base_eqid; u16 max_eq; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c index 8176bd6..dc1e3d7 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c @@ -960,6 +960,7 @@ static irqreturn_t ocrdma_irq_handler(int irq, void *handle) } while (budget); + eq->aic_obj.eq_intr_cnt++; ocrdma_ring_eq_db(dev, eq->q.id, true, true, 0); return IRQ_HANDLED; } @@ -3017,6 +3018,82 @@ done: return status; } +static int ocrdma_mbx_modify_eqd(struct ocrdma_dev *dev, struct ocrdma_eq *eq, + int num) +{ + int i, status = -ENOMEM; + struct ocrdma_modify_eqd_req *cmd; + + cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_MODIFY_EQ_DELAY, sizeof(*cmd)); + if (!cmd) + return status; + + ocrdma_init_mch(&cmd->cmd.req, OCRDMA_CMD_MODIFY_EQ_DELAY, + OCRDMA_SUBSYS_COMMON, sizeof(*cmd)); + + cmd->cmd.num_eq = num; + for (i = 0; i < num; i++) { + cmd->cmd.set_eqd[i].eq_id = eq[i].q.id; + cmd->cmd.set_eqd[i].phase = 0; + cmd->cmd.set_eqd[i].delay_multiplier = + (eq[i].aic_obj.prev_eqd * 65)/100; + } + status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd); + if (status) + goto mbx_err; +mbx_err: + kfree(cmd); + return status; +} + +static int ocrdma_modify_eqd(struct ocrdma_dev *dev, struct ocrdma_eq *eq, + int num) +{ + int num_eqs, i = 0; + if (num > 8) { + while (num) { + num_eqs = min(num, 8); + ocrdma_mbx_modify_eqd(dev, &eq[i], num_eqs); + i += num_eqs; + num -= num_eqs; + } + } else { + ocrdma_mbx_modify_eqd(dev, eq, num); + } + return 0; +} + +void ocrdma_eqd_set_task(struct work_struct *work) +{ + struct ocrdma_dev *dev = + container_of(work, struct ocrdma_dev, eqd_work.work); + struct ocrdma_eq *eq = 0; + int i, num = 0, status = -EINVAL; + u64 eq_intr; + + for (i = 0; i < dev->eq_cnt; i++) { + eq = &dev->eq_tbl[i]; + if (eq->aic_obj.eq_intr_cnt > eq->aic_obj.prev_eq_intr_cnt) { + eq_intr = eq->aic_obj.eq_intr_cnt - + eq->aic_obj.prev_eq_intr_cnt; + if ((eq_intr > EQ_INTR_PER_SEC_THRSH_HI) && + (eq->aic_obj.prev_eqd == EQ_AIC_MIN_EQD)) { + eq->aic_obj.prev_eqd = EQ_AIC_MAX_EQD; + num++; + } else if ((eq_intr < EQ_INTR_PER_SEC_THRSH_LOW) && + (eq->aic_obj.prev_eqd == EQ_AIC_MAX_EQD)) { + eq->aic_obj.prev_eqd = EQ_AIC_MIN_EQD; + num++; + } + } + eq->aic_obj.prev_eq_intr_cnt = eq->aic_obj.eq_intr_cnt; + } + + if (num) + status = ocrdma_modify_eqd(dev, &dev->eq_tbl[0], num); + schedule_delayed_work(&dev->eqd_work, msecs_to_jiffies(1000)); +} + int ocrdma_init_hw(struct ocrdma_dev *dev) { int status; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index 0083360..7a2b59a 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -493,6 +493,9 @@ static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info) spin_unlock(&ocrdma_devlist_lock); /* Init stats */ ocrdma_add_port_stats(dev); + /* Interrupt Moderation */ + INIT_DELAYED_WORK(&dev->eqd_work, ocrdma_eqd_set_task); + schedule_delayed_work(&dev->eqd_work, msecs_to_jiffies(1000)); pr_info("%s %s: %s \"%s\" port %d\n", dev_name(&dev->nic_info.pdev->dev), hca_name(dev), @@ -530,6 +533,7 @@ static void ocrdma_remove(struct ocrdma_dev *dev) /* first unregister with stack to stop all the active traffic * of the registered clients. */ + cancel_delayed_work_sync(&dev->eqd_work); ocrdma_remove_sysfiles(dev); ib_unregister_device(&dev->ibdev); diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h index 6ba9939..801883a 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h @@ -89,6 +89,7 @@ enum { OCRDMA_CMD_CREATE_MQ = 21, OCRDMA_CMD_GET_CTRL_ATTRIBUTES = 32, OCRDMA_CMD_GET_FW_VER = 35, + OCRDMA_CMD_MODIFY_EQ_DELAY = 41, OCRDMA_CMD_DELETE_MQ = 53, OCRDMA_CMD_DELETE_CQ = 54, OCRDMA_CMD_DELETE_EQ = 55, @@ -316,6 +317,29 @@ struct ocrdma_create_eq_rsp { #define OCRDMA_EQ_MINOR_OTHER 0x1 +struct ocrmda_set_eqd { + u32 eq_id; + u32 phase; + u32 delay_multiplier; +}; + +struct ocrdma_modify_eqd_cmd { + struct ocrdma_mbx_hdr req; + u32 num_eq; + struct ocrmda_set_eqd set_eqd[8]; +} __packed; + +struct ocrdma_modify_eqd_req { + struct ocrdma_mqe_hdr hdr; + struct ocrdma_modify_eqd_cmd cmd; +}; + + +struct ocrdma_modify_eq_delay_rsp { + struct ocrdma_mbx_rsp hdr; + u32 rsvd0; +} __packed; + enum { OCRDMA_MCQE_STATUS_SHIFT = 0, OCRDMA_MCQE_STATUS_MASK = 0xFFFF,