public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Gage Eads <gage.eads@intel.com>
To: linux-kernel@vger.kernel.org, arnd@arndb.de, gregkh@linuxfoundation.org
Cc: magnus.karlsson@intel.com, bjorn.topel@intel.com
Subject: [PATCH 17/20] dlb2: add cos bandwidth get/set ioctls
Date: Sun, 12 Jul 2020 08:43:28 -0500	[thread overview]
Message-ID: <20200712134331.8169-18-gage.eads@intel.com> (raw)
In-Reply-To: <20200712134331.8169-1-gage.eads@intel.com>

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 <gage.eads@intel.com>
Reviewed-by: Björn Töpel <bjorn.topel@intel.com>
---
 drivers/misc/dlb2/dlb2_ioctl.c    | 76 +++++++++++++++++++++++++++++++++++++++
 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    | 54 ++++++++++++++++++++++++++++
 6 files changed, 233 insertions(+)

diff --git a/drivers/misc/dlb2/dlb2_ioctl.c b/drivers/misc/dlb2/dlb2_ioctl.c
index 8701643fc1f1..ce80cdd71af8 100644
--- a/drivers/misc/dlb2/dlb2_ioctl.c
+++ b/drivers/misc/dlb2/dlb2_ioctl.c
@@ -1049,6 +1049,80 @@ static int dlb2_ioctl_get_sn_allocation(struct dlb2_dev *dev,
 	return ret;
 }
 
+static int dlb2_ioctl_set_cos_bw(struct dlb2_dev *dev,
+				 unsigned long user_arg,
+				 u16 size)
+{
+	struct dlb2_cmd_response response = {0};
+	struct dlb2_set_cos_bw_args arg;
+	int ret;
+
+	dev_dbg(dev->dlb2_device, "Entering %s()\n", __func__);
+
+	ret = dlb2_copy_from_user(dev, user_arg, size, &arg, sizeof(arg));
+	if (ret)
+		return ret;
+
+	/* Copy zeroes to verify the user-provided response pointer */
+	ret = dlb2_copy_resp_to_user(dev, arg.response, &response);
+	if (ret)
+		return ret;
+
+	mutex_lock(&dev->resource_mutex);
+
+	ret = dev->ops->set_cos_bw(&dev->hw, arg.cos_id, arg.bandwidth);
+
+	mutex_unlock(&dev->resource_mutex);
+
+	if (copy_to_user((void __user *)arg.response,
+			 &response,
+			 sizeof(response)))
+		return -EFAULT;
+
+	dev_dbg(dev->dlb2_device, "Exiting %s()\n", __func__);
+
+	return ret;
+}
+
+static int dlb2_ioctl_get_cos_bw(struct dlb2_dev *dev,
+				 unsigned long user_arg,
+				 u16 size)
+{
+	struct dlb2_cmd_response response = {0};
+	struct dlb2_get_cos_bw_args arg;
+	int ret;
+
+	dev_dbg(dev->dlb2_device, "Entering %s()\n", __func__);
+
+	ret = dlb2_copy_from_user(dev, user_arg, size, &arg, sizeof(arg));
+	if (ret)
+		return ret;
+
+	/* Copy zeroes to verify the user-provided response pointer */
+	ret = dlb2_copy_resp_to_user(dev, arg.response, &response);
+	if (ret)
+		return ret;
+
+	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);
+
+	if (copy_to_user((void __user *)arg.response,
+			 &response,
+			 sizeof(response)))
+		return -EFAULT;
+
+	dev_dbg(dev->dlb2_device, "Exiting %s()\n", __func__);
+
+	return ret;
+}
+
 static int dlb2_ioctl_get_sn_occupancy(struct dlb2_dev *dev,
 				       unsigned long user_arg,
 				       u16 size)
@@ -1131,6 +1205,8 @@ static dlb2_ioctl_callback_fn_t dlb2_ioctl_callback_fns[NUM_DLB2_CMD] = {
 	dlb2_ioctl_get_driver_version,
 	dlb2_ioctl_set_sn_allocation,
 	dlb2_ioctl_get_sn_allocation,
+	dlb2_ioctl_set_cos_bw,
+	dlb2_ioctl_get_cos_bw,
 	dlb2_ioctl_get_sn_occupancy,
 	dlb2_ioctl_query_cq_poll_mode,
 };
diff --git a/drivers/misc/dlb2/dlb2_main.h b/drivers/misc/dlb2/dlb2_main.h
index aa73dad1ce77..4b7a430ffd86 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 8bdeb86a1e87..124e097ff979 100644
--- a/drivers/misc/dlb2/dlb2_pf_ops.c
+++ b/drivers/misc/dlb2/dlb2_pf_ops.c
@@ -644,6 +644,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);
@@ -694,6 +706,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 f686b3045a2b..2c04c5164223 100644
--- a/drivers/misc/dlb2/dlb2_resource.c
+++ b/drivers/misc/dlb2/dlb2_resource.c
@@ -6771,6 +6771,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 246d4e303ecf..430175efcd71 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 d86e5a748f16..b6c55174b1c0 100644
--- a/include/uapi/linux/dlb2_user.h
+++ b/include/uapi/linux/dlb2_user.h
@@ -339,6 +339,50 @@ struct dlb2_get_sn_allocation_args {
 };
 
 /*
+ * 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: pointer to a struct dlb2_cmd_response.
+ *	response.status: Detailed error code. In certain cases, such as if the
+ *		response pointer is invalid, the driver won't set status.
+ */
+struct dlb2_set_cos_bw_args {
+	/* Output parameters */
+	__u64 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: pointer to a struct dlb2_cmd_response.
+ *	response.status: Detailed error code. In certain cases, such as if the
+ *		response pointer is invalid, the driver won't set status.
+ *	response.id: Specified class's bandwidth percentage.
+ */
+struct dlb2_get_cos_bw_args {
+	/* Output parameters */
+	__u64 response;
+	/* Input parameters */
+	__u32 cos_id;
+	__u32 padding0;
+};
+
+/*
  * DLB2_CMD_GET_SN_OCCUPANCY: Get a sequence number group's occupancy
  *
  * Each sequence number group has one or more slots, depending on its
@@ -399,6 +443,8 @@ enum dlb2_user_interface_commands {
 	DLB2_CMD_GET_DRIVER_VERSION,
 	DLB2_CMD_SET_SN_ALLOCATION,
 	DLB2_CMD_GET_SN_ALLOCATION,
+	DLB2_CMD_SET_COS_BW,
+	DLB2_CMD_GET_COS_BW,
 	DLB2_CMD_GET_SN_OCCUPANCY,
 	DLB2_CMD_QUERY_CQ_POLL_MODE,
 
@@ -1012,6 +1058,14 @@ enum dlb2_domain_user_interface_commands {
 		_IOWR(DLB2_IOC_MAGIC,				\
 		      DLB2_CMD_GET_SN_ALLOCATION,		\
 		      struct dlb2_get_sn_allocation_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_GET_SN_OCCUPANCY				\
 		_IOWR(DLB2_IOC_MAGIC,				\
 		      DLB2_CMD_GET_SN_OCCUPANCY,		\
-- 
2.13.6


  parent reply	other threads:[~2020-07-12 13:52 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-12 13:43 [PATCH 00/20] dlb2: introduce DLB 2.0 device driver Gage Eads
2020-07-12 13:43 ` [PATCH 01/20] dlb2: add skeleton for DLB 2.0 driver Gage Eads
2020-07-12 15:56   ` Greg KH
2020-07-17 18:19     ` Eads, Gage
2020-07-18  6:46       ` Greg KH
2020-07-12 15:58   ` Greg KH
2020-07-17 18:18     ` Eads, Gage
2020-07-18  6:46       ` Greg KH
2020-07-20 19:02         ` Eads, Gage
2020-07-20 19:19           ` Greg KH
2020-07-24 21:00             ` Eads, Gage
2020-07-12 13:43 ` [PATCH 02/20] dlb2: initialize PF device Gage Eads
2020-07-12 13:43 ` [PATCH 03/20] dlb2: add resource and device initialization Gage Eads
2020-07-12 13:43 ` [PATCH 04/20] dlb2: add device ioctl layer and first 4 ioctls Gage Eads
2020-07-12 14:42   ` Randy Dunlap
2020-07-17 18:20     ` Eads, Gage
2020-07-12 14:53   ` Randy Dunlap
2020-07-17 18:20     ` Eads, Gage
2020-07-12 15:28   ` Arnd Bergmann
2020-07-17 18:19     ` Eads, Gage
2020-07-17 18:56       ` Arnd Bergmann
2020-07-17 20:05         ` Eads, Gage
2020-07-18  6:48           ` gregkh
2020-08-04 22:20     ` Eads, Gage
2020-08-05  6:46       ` gregkh
2020-08-05 15:07         ` Eads, Gage
2020-08-05 15:17           ` gregkh
2020-08-05 15:39             ` Eads, Gage
2020-07-12 13:43 ` [PATCH 05/20] dlb2: add sched domain config and reset support Gage Eads
2020-07-12 13:43 ` [PATCH 06/20] dlb2: add ioctl to get sched domain fd Gage Eads
2020-07-12 13:43 ` [PATCH 07/20] dlb2: add runtime power-management support Gage Eads
2020-07-12 13:43 ` [PATCH 08/20] dlb2: add queue create and queue-depth-get ioctls Gage Eads
2020-07-12 13:43 ` [PATCH 09/20] dlb2: add ioctl to configure ports, query poll mode Gage Eads
2020-07-12 15:34   ` Arnd Bergmann
2020-07-17 18:19     ` Eads, Gage
2020-07-12 13:43 ` [PATCH 10/20] dlb2: add port mmap support Gage Eads
2020-07-12 13:43 ` [PATCH 11/20] dlb2: add start domain ioctl Gage Eads
2020-07-12 13:43 ` [PATCH 12/20] dlb2: add queue map and unmap ioctls Gage Eads
2020-07-12 13:43 ` [PATCH 13/20] dlb2: add port enable/disable ioctls Gage Eads
2020-07-12 13:43 ` [PATCH 14/20] dlb2: add CQ interrupt support Gage Eads
2020-07-12 13:43 ` [PATCH 15/20] dlb2: add domain alert support Gage Eads
2020-07-12 13:43 ` [PATCH 16/20] dlb2: add sequence-number management ioctls Gage Eads
2020-07-12 13:43 ` Gage Eads [this message]
2020-07-12 13:43 ` [PATCH 18/20] dlb2: add device FLR support Gage Eads
2020-07-12 13:43 ` [PATCH 19/20] dlb2: add basic PF sysfs interfaces Gage Eads
2020-07-12 13:43 ` [PATCH 20/20] dlb2: add ingress error handling Gage Eads

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200712134331.8169-18-gage.eads@intel.com \
    --to=gage.eads@intel.com \
    --cc=arnd@arndb.de \
    --cc=bjorn.topel@intel.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=magnus.karlsson@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox