Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp569534pxa; Tue, 11 Aug 2020 09:37:48 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxzISUg375/IUe9Ks67Z+lh2KyTsB5IqGk37VcFhaTImTApkNZBdGRMW2vdljJyJbjfcONd X-Received: by 2002:a17:906:64d7:: with SMTP id p23mr26847982ejn.185.1597163868461; Tue, 11 Aug 2020 09:37:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1597163868; cv=none; d=google.com; s=arc-20160816; b=R7FnSUIGvl6Rai5q99pEMafIxYOMACWwTke3JgyBZmuUPU2GQhMrxAh9obLYmbfPQd B4dsDJ5cXHbi3GyEg0xrZqkztXECr0rmNtyIDRpkZDkOsHVv68KKxh6ihy+a2VfBXgnt FMrzBEO3ttApKnosuKHbWjwF+xta1FxZLb1ne0gnY7bvzmgUhHfEpcUeA6FLh+J/8qUR b7HOw+Qz9FIBrJ+uUupA4uXSgbtX22Zg41ZzmHxAGQY/Mquh5jgU2REKyQ+yvGWYY5g0 nkoIZ+H85Y/ygZIP76Q/HBjoOKYyI/hlgPtKV21L+A6ZH43mGQFjlWmZYSGOxTV6AykW 8HMw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :ironport-sdr:ironport-sdr; bh=lQfc6jPjY3jljse8ju+dY4lv4JoZixLJ1XTVhejmIWs=; b=d4UnTvDLUHF1S7XEAuDZpM0K3sSjXLGB1eQyLwN+qng4e2Gir6jbaBfmUDKSKRTcFj 4caJ5BYOwsT3u/w5kbr32pUeUoR7C93MwBdGKlKNuu4LCOk467/xDMDwC8K9nazTGt3J /Rcse2KbcXXM+RB1yAbf1Y7vFSe6khnfMUEkSfIgZMy4RS0piTUwVtpac43Tmyyel4mM kLFKMk765VvLtdF0phmboNdFgnrw5IBU6Js87NWkHr7slO+oOc++b/A8FcEbTcmBShAp xZTGBsKVfsN5MASyY8ydGwLLnteRupSfslE4hBJNxgVknRMBpAAS9OsSb1NrfSl4igBC VROw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ba10si3099131edb.472.2020.08.11.09.37.24; Tue, 11 Aug 2020 09:37:48 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729121AbgHKQgI (ORCPT + 99 others); Tue, 11 Aug 2020 12:36:08 -0400 Received: from mga14.intel.com ([192.55.52.115]:62150 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729068AbgHKQfp (ORCPT ); Tue, 11 Aug 2020 12:35:45 -0400 IronPort-SDR: R1NlfI9UQY6lFvei2jng2bV+r1MrNNTFbf8PpdiEflMAzmYaaYccmqpcsYNYjUS/Hie+J0zlEX 1kY1MfNxPJYw== X-IronPort-AV: E=McAfee;i="6000,8403,9710"; a="152985417" X-IronPort-AV: E=Sophos;i="5.76,301,1592895600"; d="scan'208";a="152985417" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Aug 2020 09:30:47 -0700 IronPort-SDR: ktceOh/lxyJlut2IBDsISpuDrr5iSIdrelWjfIFJAU7MQjSul9SAQZksDlNyhdMhIjKcEjYTay +jYBvr5VvczQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,301,1592895600"; d="scan'208";a="317786522" Received: from txasoft-yocto.an.intel.com ([10.123.72.192]) by fmsmga004.fm.intel.com with ESMTP; 11 Aug 2020 09:30:46 -0700 From: Gage Eads To: linux-kernel@vger.kernel.org, arnd@arndb.de, gregkh@linuxfoundation.org Cc: magnus.karlsson@intel.com, bjorn.topel@intel.com Subject: [PATCH v2 16/19] dlb2: add cos bandwidth get/set ioctls Date: Tue, 11 Aug 2020 11:27:29 -0500 Message-Id: <20200811162732.1369-17-gage.eads@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20200811162732.1369-1-gage.eads@intel.com> References: <20200811162732.1369-1-gage.eads@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The DLB 2.0 supports four load-balanced port classes of service (CoS). Each CoS receives a guaranteed percentage of the load-balanced scheduler's bandwidth, and any unreserved bandwidth is divided among the four CoS. These two ioctls allow applications to query CoS allocations and adjust them as needed. These allocations are controlled by the PF driver; virtual devices, when support for them is added, will not be able to adjust them. Signed-off-by: Gage Eads Reviewed-by: Björn Töpel --- drivers/misc/dlb2/dlb2_ioctl.c | 54 +++++++++++++++++++++++++++++++++++ drivers/misc/dlb2/dlb2_main.h | 2 ++ drivers/misc/dlb2/dlb2_pf_ops.c | 14 ++++++++++ drivers/misc/dlb2/dlb2_resource.c | 59 +++++++++++++++++++++++++++++++++++++++ drivers/misc/dlb2/dlb2_resource.h | 28 +++++++++++++++++++ include/uapi/linux/dlb2_user.h | 52 ++++++++++++++++++++++++++++++++++ 6 files changed, 209 insertions(+) diff --git a/drivers/misc/dlb2/dlb2_ioctl.c b/drivers/misc/dlb2/dlb2_ioctl.c index 3e5ca65f9feb..3e4fb19dd726 100644 --- a/drivers/misc/dlb2/dlb2_ioctl.c +++ b/drivers/misc/dlb2/dlb2_ioctl.c @@ -761,6 +761,56 @@ static int dlb2_ioctl_get_sn_occupancy(struct dlb2_dev *dev, return ret; } +static int dlb2_ioctl_set_cos_bw(struct dlb2_dev *dev, unsigned long user_arg) +{ + struct dlb2_cmd_response response = {0}; + struct dlb2_set_cos_bw_args arg; + int ret; + + if (copy_from_user(&arg, (void __user *)user_arg, sizeof(arg))) + return -EFAULT; + + mutex_lock(&dev->resource_mutex); + + ret = dev->ops->set_cos_bw(&dev->hw, arg.cos_id, arg.bandwidth); + + mutex_unlock(&dev->resource_mutex); + + BUILD_BUG_ON(offsetof(typeof(arg), response) != 0); + + if (copy_to_user((void __user *)user_arg, &response, sizeof(response))) + return -EFAULT; + + return ret; +} + +static int dlb2_ioctl_get_cos_bw(struct dlb2_dev *dev, unsigned long user_arg) +{ + struct dlb2_cmd_response response = {0}; + struct dlb2_get_cos_bw_args arg; + int ret; + + if (copy_from_user(&arg, (void __user *)user_arg, sizeof(arg))) + return -EFAULT; + + mutex_lock(&dev->resource_mutex); + + ret = dev->ops->get_cos_bw(&dev->hw, arg.cos_id); + + response.id = ret; + + ret = (ret > 0) ? 0 : ret; + + mutex_unlock(&dev->resource_mutex); + + BUILD_BUG_ON(offsetof(typeof(arg), response) != 0); + + if (copy_to_user((void __user *)user_arg, &response, sizeof(response))) + return -EFAULT; + + return ret; +} + long dlb2_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { struct dlb2_dev *dev; @@ -782,6 +832,10 @@ long dlb2_ioctl(struct file *f, unsigned int cmd, unsigned long arg) return dlb2_ioctl_get_sn_allocation(dev, arg); case DLB2_IOC_GET_SN_OCCUPANCY: return dlb2_ioctl_get_sn_occupancy(dev, arg); + case DLB2_IOC_SET_COS_BW: + return dlb2_ioctl_set_cos_bw(dev, arg); + case DLB2_IOC_GET_COS_BW: + return dlb2_ioctl_get_cos_bw(dev, arg); default: return -ENOTTY; } diff --git a/drivers/misc/dlb2/dlb2_main.h b/drivers/misc/dlb2/dlb2_main.h index a7be9399255f..e3d7c9362257 100644 --- a/drivers/misc/dlb2/dlb2_main.h +++ b/drivers/misc/dlb2/dlb2_main.h @@ -146,6 +146,8 @@ struct dlb2_device_ops { u32 domain_id, struct dlb2_get_dir_queue_depth_args *args, struct dlb2_cmd_response *resp); + int (*set_cos_bw)(struct dlb2_hw *hw, u32 cos_id, u8 bandwidth); + int (*get_cos_bw)(struct dlb2_hw *hw, u32 cos_id); void (*init_hardware)(struct dlb2_dev *dev); int (*query_cq_poll_mode)(struct dlb2_dev *dev, struct dlb2_cmd_response *user_resp); diff --git a/drivers/misc/dlb2/dlb2_pf_ops.c b/drivers/misc/dlb2/dlb2_pf_ops.c index 337cc8a72a5c..771fd793870b 100644 --- a/drivers/misc/dlb2/dlb2_pf_ops.c +++ b/drivers/misc/dlb2/dlb2_pf_ops.c @@ -617,6 +617,18 @@ dlb2_pf_set_sn_allocation(struct dlb2_hw *hw, u32 group_id, u32 num) } static int +dlb2_pf_set_cos_bw(struct dlb2_hw *hw, u32 cos_id, u8 bandwidth) +{ + return dlb2_hw_set_cos_bandwidth(hw, cos_id, bandwidth); +} + +static int +dlb2_pf_get_cos_bw(struct dlb2_hw *hw, u32 cos_id) +{ + return dlb2_hw_get_cos_bandwidth(hw, cos_id); +} + +static int dlb2_pf_get_sn_occupancy(struct dlb2_hw *hw, u32 group_id) { return dlb2_get_group_sequence_number_occupancy(hw, group_id); @@ -667,6 +679,8 @@ struct dlb2_device_ops dlb2_pf_ops = { .get_sn_occupancy = dlb2_pf_get_sn_occupancy, .get_ldb_queue_depth = dlb2_pf_get_ldb_queue_depth, .get_dir_queue_depth = dlb2_pf_get_dir_queue_depth, + .set_cos_bw = dlb2_pf_set_cos_bw, + .get_cos_bw = dlb2_pf_get_cos_bw, .init_hardware = dlb2_pf_init_hardware, .query_cq_poll_mode = dlb2_pf_query_cq_poll_mode, }; diff --git a/drivers/misc/dlb2/dlb2_resource.c b/drivers/misc/dlb2/dlb2_resource.c index 646f52a06842..f2f650bc979e 100644 --- a/drivers/misc/dlb2/dlb2_resource.c +++ b/drivers/misc/dlb2/dlb2_resource.c @@ -6769,6 +6769,65 @@ void dlb2_clr_pmcsr_disable(struct dlb2_hw *hw) DLB2_CSR_WR(hw, DLB2_CFG_MSTR_CFG_PM_PMCSR_DISABLE, r0.val); } +int dlb2_hw_get_cos_bandwidth(struct dlb2_hw *hw, u32 cos_id) +{ + if (cos_id >= DLB2_NUM_COS_DOMAINS) + return -EINVAL; + + return hw->cos_reservation[cos_id]; +} + +static void dlb2_log_set_cos_bandwidth(struct dlb2_hw *hw, u32 cos_id, u8 bw) +{ + DLB2_HW_DBG(hw, "DLB2 set port CoS bandwidth:\n"); + DLB2_HW_DBG(hw, "\tCoS ID: %u\n", cos_id); + DLB2_HW_DBG(hw, "\tBandwidth: %u\n", bw); +} + +int dlb2_hw_set_cos_bandwidth(struct dlb2_hw *hw, u32 cos_id, u8 bandwidth) +{ + union dlb2_lsp_cfg_shdw_range_cos r0 = { {0} }; + union dlb2_lsp_cfg_shdw_ctrl r1 = { {0} }; + unsigned int i; + u8 total; + + if (cos_id >= DLB2_NUM_COS_DOMAINS) + return -EINVAL; + + if (bandwidth > 100) + return -EINVAL; + + total = 0; + + for (i = 0; i < DLB2_NUM_COS_DOMAINS; i++) + total += (i == cos_id) ? bandwidth : hw->cos_reservation[i]; + + if (total > 100) + return -EINVAL; + + r0.val = DLB2_CSR_RD(hw, DLB2_LSP_CFG_SHDW_RANGE_COS(cos_id)); + + /* + * Normalize the bandwidth to a value in the range 0-255. Integer + * division may leave unreserved scheduling slots; these will be + * divided among the 4 classes of service. + */ + r0.field.bw_range = (bandwidth * 256) / 100; + + DLB2_CSR_WR(hw, DLB2_LSP_CFG_SHDW_RANGE_COS(cos_id), r0.val); + + r1.field.transfer = 1; + + /* Atomically transfer the newly configured service weight */ + DLB2_CSR_WR(hw, DLB2_LSP_CFG_SHDW_CTRL, r1.val); + + dlb2_log_set_cos_bandwidth(hw, cos_id, bandwidth); + + hw->cos_reservation[cos_id] = bandwidth; + + return 0; +} + void dlb2_hw_enable_sparse_ldb_cq_mode(struct dlb2_hw *hw) { union dlb2_chp_cfg_chp_csr_ctrl r0; diff --git a/drivers/misc/dlb2/dlb2_resource.h b/drivers/misc/dlb2/dlb2_resource.h index c1e1d677b2ae..e325c584cb3f 100644 --- a/drivers/misc/dlb2/dlb2_resource.h +++ b/drivers/misc/dlb2/dlb2_resource.h @@ -823,6 +823,34 @@ int dlb2_hw_pending_port_unmaps(struct dlb2_hw *hw, unsigned int vf_id); /** + * dlb2_hw_get_cos_bandwidth() - returns the percent of bandwidth allocated + * to a port class-of-service. + * @hw: dlb2_hw handle for a particular device. + * @cos_id: class-of-service ID. + * + * Return: + * Returns -EINVAL if cos_id is invalid, else the class' bandwidth allocation. + */ +int dlb2_hw_get_cos_bandwidth(struct dlb2_hw *hw, u32 cos_id); + +/** + * dlb2_hw_set_cos_bandwidth() - set a bandwidth allocation percentage for a + * port class-of-service. + * @hw: dlb2_hw handle for a particular device. + * @cos_id: class-of-service ID. + * @bandwidth: class-of-service bandwidth. + * + * Return: + * Returns 0 upon success, < 0 otherwise. + * + * Errors: + * EINVAL - Invalid cos ID, bandwidth is greater than 100, or bandwidth would + * cause the total bandwidth across all classes of service to exceed + * 100%. + */ +int dlb2_hw_set_cos_bandwidth(struct dlb2_hw *hw, u32 cos_id, u8 bandwidth); + +/** * dlb2_hw_enable_sparse_ldb_cq_mode() - enable sparse mode for load-balanced * ports. * @hw: dlb2_hw handle for a particular device. diff --git a/include/uapi/linux/dlb2_user.h b/include/uapi/linux/dlb2_user.h index a117ca71dbbc..946e01fae63d 100644 --- a/include/uapi/linux/dlb2_user.h +++ b/include/uapi/linux/dlb2_user.h @@ -308,6 +308,48 @@ struct dlb2_get_sn_occupancy_args { __u32 padding0; }; +/* + * DLB2_CMD_SET_COS_BW: Set a bandwidth allocation percentage for a + * load-balanced port class-of-service (PF only). + * + * Input parameters: + * - cos_id: class-of-service ID, between 0 and 3 (inclusive). + * - bandwidth: class-of-service bandwidth percentage. Total bandwidth + * percentages across all 4 classes cannot exceed 100%. + * + * Output parameters: + * - response.status: Detailed error code. In certain cases, such as if the + * ioctl request arg is invalid, the driver won't set status. + */ +struct dlb2_set_cos_bw_args { + /* Output parameters */ + struct dlb2_cmd_response response; + /* Input parameters */ + __u32 cos_id; + __u32 bandwidth; +}; + +/* + * DLB2_CMD_GET_COS_BW: Get the bandwidth allocation percentage for a + * load-balanced port class-of-service. + * + * Input parameters: + * - cos_id: class-of-service ID, between 0 and 3 (inclusive). + * - padding0: Reserved for future use. + * + * Output parameters: + * - response.status: Detailed error code. In certain cases, such as if the + * ioctl request arg is invalid, the driver won't set status. + * - response.id: Specified class's bandwidth percentage. + */ +struct dlb2_get_cos_bw_args { + /* Output parameters */ + struct dlb2_cmd_response response; + /* Input parameters */ + __u32 cos_id; + __u32 padding0; +}; + enum dlb2_user_interface_commands { DLB2_CMD_GET_DEVICE_VERSION, DLB2_CMD_CREATE_SCHED_DOMAIN, @@ -316,6 +358,8 @@ enum dlb2_user_interface_commands { DLB2_CMD_SET_SN_ALLOCATION, DLB2_CMD_GET_SN_ALLOCATION, DLB2_CMD_GET_SN_OCCUPANCY, + DLB2_CMD_SET_COS_BW, + DLB2_CMD_GET_COS_BW, /* NUM_DLB2_CMD must be last */ NUM_DLB2_CMD, @@ -909,6 +953,14 @@ enum dlb2_domain_user_interface_commands { _IOWR(DLB2_IOC_MAGIC, \ DLB2_CMD_GET_SN_OCCUPANCY, \ struct dlb2_get_sn_occupancy_args) +#define DLB2_IOC_SET_COS_BW \ + _IOWR(DLB2_IOC_MAGIC, \ + DLB2_CMD_SET_COS_BW, \ + struct dlb2_set_cos_bw_args) +#define DLB2_IOC_GET_COS_BW \ + _IOWR(DLB2_IOC_MAGIC, \ + DLB2_CMD_GET_COS_BW, \ + struct dlb2_get_cos_bw_args) #define DLB2_IOC_CREATE_LDB_QUEUE \ _IOWR(DLB2_IOC_MAGIC, \ DLB2_DOMAIN_CMD_CREATE_LDB_QUEUE, \ -- 2.13.6