The ioctls can be used to dynamically enable or disable scheduling to a
port. (By default, ports start with their scheduling enabled.) Doing so
allows software to, for example, quickly add/remove cores to/from a worker
pool.

Signed-off-by: Gage Eads <gage.e...@intel.com>
Reviewed-by: Björn Töpel <bjorn.to...@intel.com>
---
 drivers/misc/dlb2/dlb2_ioctl.c    | 112 +++++++++++
 drivers/misc/dlb2/dlb2_main.h     |  16 ++
 drivers/misc/dlb2/dlb2_pf_ops.c   |  40 ++++
 drivers/misc/dlb2/dlb2_resource.c | 382 ++++++++++++++++++++++++++++++++++++++
 drivers/misc/dlb2/dlb2_resource.h | 120 ++++++++++++
 include/uapi/linux/dlb2_user.h    |  92 +++++++++
 6 files changed, 762 insertions(+)

diff --git a/drivers/misc/dlb2/dlb2_ioctl.c b/drivers/misc/dlb2/dlb2_ioctl.c
index 0ab4a95fb34a..490c380670cc 100644
--- a/drivers/misc/dlb2/dlb2_ioctl.c
+++ b/drivers/misc/dlb2/dlb2_ioctl.c
@@ -57,6 +57,110 @@ DLB2_DOMAIN_IOCTL_CALLBACK_TEMPLATE(unmap_qid)
 DLB2_DOMAIN_IOCTL_CALLBACK_TEMPLATE(pending_port_unmaps)
 
 /*
+ * Port enable/disable ioctls don't use the callback template macro because
+ * they have additional CQ interrupt management logic.
+ */
+static int dlb2_domain_ioctl_enable_ldb_port(struct dlb2_dev *dev,
+                                            struct dlb2_domain *domain,
+                                            unsigned long user_arg)
+{
+       struct dlb2_cmd_response response = {0};
+       struct dlb2_enable_ldb_port_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->enable_ldb_port(&dev->hw, domain->id, &arg, &response);
+
+       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_domain_ioctl_enable_dir_port(struct dlb2_dev *dev,
+                                            struct dlb2_domain *domain,
+                                            unsigned long user_arg)
+{
+       struct dlb2_cmd_response response = {0};
+       struct dlb2_enable_dir_port_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->enable_dir_port(&dev->hw, domain->id, &arg, &response);
+
+       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_domain_ioctl_disable_ldb_port(struct dlb2_dev *dev,
+                                             struct dlb2_domain *domain,
+                                             unsigned long user_arg)
+{
+       struct dlb2_cmd_response response = {0};
+       struct dlb2_disable_ldb_port_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->disable_ldb_port(&dev->hw, domain->id, &arg, &response);
+
+       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_domain_ioctl_disable_dir_port(struct dlb2_dev *dev,
+                                             struct dlb2_domain *domain,
+                                             unsigned long user_arg)
+{
+       struct dlb2_cmd_response response = {0};
+       struct dlb2_disable_dir_port_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->disable_dir_port(&dev->hw, domain->id, &arg, &response);
+
+       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;
+}
+
+/*
  * Port creation ioctls don't use the callback template macro because they have
  * a number of OS-dependent memory operations.
  */
@@ -355,6 +459,14 @@ long dlb2_domain_ioctl(struct file *f, unsigned int cmd, 
unsigned long arg)
                return dlb2_domain_ioctl_unmap_qid(dev, dom, arg);
        case DLB2_IOC_PENDING_PORT_UNMAPS:
                return dlb2_domain_ioctl_pending_port_unmaps(dev, dom, arg);
+       case DLB2_IOC_ENABLE_LDB_PORT:
+               return dlb2_domain_ioctl_enable_ldb_port(dev, dom, arg);
+       case DLB2_IOC_ENABLE_DIR_PORT:
+               return dlb2_domain_ioctl_enable_dir_port(dev, dom, arg);
+       case DLB2_IOC_DISABLE_LDB_PORT:
+               return dlb2_domain_ioctl_disable_ldb_port(dev, dom, arg);
+       case DLB2_IOC_DISABLE_DIR_PORT:
+               return dlb2_domain_ioctl_disable_dir_port(dev, dom, arg);
        default:
                return -ENOTTY;
        }
diff --git a/drivers/misc/dlb2/dlb2_main.h b/drivers/misc/dlb2/dlb2_main.h
index 626a3311eb18..92e182603445 100644
--- a/drivers/misc/dlb2/dlb2_main.h
+++ b/drivers/misc/dlb2/dlb2_main.h
@@ -94,6 +94,22 @@ struct dlb2_device_ops {
                                   u32 domain_id,
                                   struct dlb2_pending_port_unmaps_args *args,
                                   struct dlb2_cmd_response *resp);
+       int (*enable_ldb_port)(struct dlb2_hw *hw,
+                              u32 domain_id,
+                              struct dlb2_enable_ldb_port_args *args,
+                              struct dlb2_cmd_response *resp);
+       int (*disable_ldb_port)(struct dlb2_hw *hw,
+                               u32 domain_id,
+                               struct dlb2_disable_ldb_port_args *args,
+                               struct dlb2_cmd_response *resp);
+       int (*enable_dir_port)(struct dlb2_hw *hw,
+                              u32 domain_id,
+                              struct dlb2_enable_dir_port_args *args,
+                              struct dlb2_cmd_response *resp);
+       int (*disable_dir_port)(struct dlb2_hw *hw,
+                               u32 domain_id,
+                               struct dlb2_disable_dir_port_args *args,
+                               struct dlb2_cmd_response *resp);
        int (*get_num_resources)(struct dlb2_hw *hw,
                                 struct dlb2_get_num_resources_args *args);
        int (*reset_domain)(struct dlb2_hw *hw, u32 domain_id);
diff --git a/drivers/misc/dlb2/dlb2_pf_ops.c b/drivers/misc/dlb2/dlb2_pf_ops.c
index b531448d1a25..8b1aac196073 100644
--- a/drivers/misc/dlb2/dlb2_pf_ops.c
+++ b/drivers/misc/dlb2/dlb2_pf_ops.c
@@ -299,6 +299,42 @@ dlb2_pf_pending_port_unmaps(struct dlb2_hw *hw,
 }
 
 static int
+dlb2_pf_enable_ldb_port(struct dlb2_hw *hw,
+                       u32 id,
+                       struct dlb2_enable_ldb_port_args *args,
+                       struct dlb2_cmd_response *resp)
+{
+       return dlb2_hw_enable_ldb_port(hw, id, args, resp, false, 0);
+}
+
+static int
+dlb2_pf_disable_ldb_port(struct dlb2_hw *hw,
+                        u32 id,
+                        struct dlb2_disable_ldb_port_args *args,
+                        struct dlb2_cmd_response *resp)
+{
+       return dlb2_hw_disable_ldb_port(hw, id, args, resp, false, 0);
+}
+
+static int
+dlb2_pf_enable_dir_port(struct dlb2_hw *hw,
+                       u32 id,
+                       struct dlb2_enable_dir_port_args *args,
+                       struct dlb2_cmd_response *resp)
+{
+       return dlb2_hw_enable_dir_port(hw, id, args, resp, false, 0);
+}
+
+static int
+dlb2_pf_disable_dir_port(struct dlb2_hw *hw,
+                        u32 id,
+                        struct dlb2_disable_dir_port_args *args,
+                        struct dlb2_cmd_response *resp)
+{
+       return dlb2_hw_disable_dir_port(hw, id, args, resp, false, 0);
+}
+
+static int
 dlb2_pf_get_num_resources(struct dlb2_hw *hw,
                          struct dlb2_get_num_resources_args *args)
 {
@@ -389,6 +425,10 @@ struct dlb2_device_ops dlb2_pf_ops = {
        .map_qid = dlb2_pf_map_qid,
        .unmap_qid = dlb2_pf_unmap_qid,
        .pending_port_unmaps = dlb2_pf_pending_port_unmaps,
+       .enable_ldb_port = dlb2_pf_enable_ldb_port,
+       .enable_dir_port = dlb2_pf_enable_dir_port,
+       .disable_ldb_port = dlb2_pf_disable_ldb_port,
+       .disable_dir_port = dlb2_pf_disable_dir_port,
        .get_num_resources = dlb2_pf_get_num_resources,
        .reset_domain = dlb2_pf_reset_domain,
        .ldb_port_owned_by_domain = dlb2_pf_ldb_port_owned_by_domain,
diff --git a/drivers/misc/dlb2/dlb2_resource.c 
b/drivers/misc/dlb2/dlb2_resource.c
index 6afac8c99c06..665841ca7919 100644
--- a/drivers/misc/dlb2/dlb2_resource.c
+++ b/drivers/misc/dlb2/dlb2_resource.c
@@ -1707,6 +1707,150 @@ static int dlb2_verify_unmap_qid_args(struct dlb2_hw 
*hw,
        return -EINVAL;
 }
 
+static int
+dlb2_verify_enable_ldb_port_args(struct dlb2_hw *hw,
+                                u32 domain_id,
+                                struct dlb2_enable_ldb_port_args *args,
+                                struct dlb2_cmd_response *resp,
+                                bool vdev_req,
+                                unsigned int vdev_id)
+{
+       struct dlb2_hw_domain *domain;
+       struct dlb2_ldb_port *port;
+       int id;
+
+       domain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);
+
+       if (!domain) {
+               resp->status = DLB2_ST_INVALID_DOMAIN_ID;
+               return -EINVAL;
+       }
+
+       if (!domain->configured) {
+               resp->status = DLB2_ST_DOMAIN_NOT_CONFIGURED;
+               return -EINVAL;
+       }
+
+       id = args->port_id;
+
+       port = dlb2_get_domain_used_ldb_port(id, vdev_req, domain);
+
+       if (!port || !port->configured) {
+               resp->status = DLB2_ST_INVALID_PORT_ID;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+dlb2_verify_enable_dir_port_args(struct dlb2_hw *hw,
+                                u32 domain_id,
+                                struct dlb2_enable_dir_port_args *args,
+                                struct dlb2_cmd_response *resp,
+                                bool vdev_req,
+                                unsigned int vdev_id)
+{
+       struct dlb2_hw_domain *domain;
+       struct dlb2_dir_pq_pair *port;
+       int id;
+
+       domain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);
+
+       if (!domain) {
+               resp->status = DLB2_ST_INVALID_DOMAIN_ID;
+               return -EINVAL;
+       }
+
+       if (!domain->configured) {
+               resp->status = DLB2_ST_DOMAIN_NOT_CONFIGURED;
+               return -EINVAL;
+       }
+
+       id = args->port_id;
+
+       port = dlb2_get_domain_used_dir_pq(id, vdev_req, domain);
+
+       if (!port || !port->port_configured) {
+               resp->status = DLB2_ST_INVALID_PORT_ID;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+dlb2_verify_disable_ldb_port_args(struct dlb2_hw *hw,
+                                 u32 domain_id,
+                                 struct dlb2_disable_ldb_port_args *args,
+                                 struct dlb2_cmd_response *resp,
+                                 bool vdev_req,
+                                 unsigned int vdev_id)
+{
+       struct dlb2_hw_domain *domain;
+       struct dlb2_ldb_port *port;
+       int id;
+
+       domain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);
+
+       if (!domain) {
+               resp->status = DLB2_ST_INVALID_DOMAIN_ID;
+               return -EINVAL;
+       }
+
+       if (!domain->configured) {
+               resp->status = DLB2_ST_DOMAIN_NOT_CONFIGURED;
+               return -EINVAL;
+       }
+
+       id = args->port_id;
+
+       port = dlb2_get_domain_used_ldb_port(id, vdev_req, domain);
+
+       if (!port || !port->configured) {
+               resp->status = DLB2_ST_INVALID_PORT_ID;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+dlb2_verify_disable_dir_port_args(struct dlb2_hw *hw,
+                                 u32 domain_id,
+                                 struct dlb2_disable_dir_port_args *args,
+                                 struct dlb2_cmd_response *resp,
+                                 bool vdev_req,
+                                 unsigned int vdev_id)
+{
+       struct dlb2_hw_domain *domain;
+       struct dlb2_dir_pq_pair *port;
+       int id;
+
+       domain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);
+
+       if (!domain) {
+               resp->status = DLB2_ST_INVALID_DOMAIN_ID;
+               return -EINVAL;
+       }
+
+       if (!domain->configured) {
+               resp->status = DLB2_ST_DOMAIN_NOT_CONFIGURED;
+               return -EINVAL;
+       }
+
+       id = args->port_id;
+
+       port = dlb2_get_domain_used_dir_pq(id, vdev_req, domain);
+
+       if (!port || !port->port_configured) {
+               resp->status = DLB2_ST_INVALID_PORT_ID;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static void dlb2_configure_domain_credits(struct dlb2_hw *hw,
                                          struct dlb2_hw_domain *domain)
 {
@@ -4303,6 +4447,244 @@ int dlb2_hw_unmap_qid(struct dlb2_hw *hw,
        return 0;
 }
 
+static void dlb2_log_enable_port(struct dlb2_hw *hw,
+                                u32 domain_id,
+                                u32 port_id,
+                                bool vdev_req,
+                                unsigned int vdev_id)
+{
+       DLB2_HW_DBG(hw, "DLB2 enable port arguments:\n");
+       if (vdev_req)
+               DLB2_HW_DBG(hw, "(Request from vdev %d)\n", vdev_id);
+       DLB2_HW_DBG(hw, "\tDomain ID: %d\n",
+                   domain_id);
+       DLB2_HW_DBG(hw, "\tPort ID:   %d\n",
+                   port_id);
+}
+
+int dlb2_hw_enable_ldb_port(struct dlb2_hw *hw,
+                           u32 domain_id,
+                           struct dlb2_enable_ldb_port_args *args,
+                           struct dlb2_cmd_response *resp,
+                           bool vdev_req,
+                           unsigned int vdev_id)
+{
+       struct dlb2_hw_domain *domain;
+       struct dlb2_ldb_port *port;
+       int ret, id;
+
+       dlb2_log_enable_port(hw, domain_id, args->port_id, vdev_req, vdev_id);
+
+       /*
+        * Verify that hardware resources are available before attempting to
+        * satisfy the request. This simplifies the error unwinding code.
+        */
+       ret = dlb2_verify_enable_ldb_port_args(hw,
+                                              domain_id,
+                                              args,
+                                              resp,
+                                              vdev_req,
+                                              vdev_id);
+       if (ret)
+               return ret;
+
+       domain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);
+
+       id = args->port_id;
+
+       port = dlb2_get_domain_used_ldb_port(id, vdev_req, domain);
+
+       /* Hardware requires disabling the CQ before unmapping QIDs. */
+       if (!port->enabled) {
+               dlb2_ldb_port_cq_enable(hw, port);
+               port->enabled = true;
+       }
+
+       resp->status = 0;
+
+       return 0;
+}
+
+static void dlb2_log_disable_port(struct dlb2_hw *hw,
+                                 u32 domain_id,
+                                 u32 port_id,
+                                 bool vdev_req,
+                                 unsigned int vdev_id)
+{
+       DLB2_HW_DBG(hw, "DLB2 disable port arguments:\n");
+       if (vdev_req)
+               DLB2_HW_DBG(hw, "(Request from vdev %d)\n", vdev_id);
+       DLB2_HW_DBG(hw, "\tDomain ID: %d\n",
+                   domain_id);
+       DLB2_HW_DBG(hw, "\tPort ID:   %d\n",
+                   port_id);
+}
+
+int dlb2_hw_disable_ldb_port(struct dlb2_hw *hw,
+                            u32 domain_id,
+                            struct dlb2_disable_ldb_port_args *args,
+                            struct dlb2_cmd_response *resp,
+                            bool vdev_req,
+                            unsigned int vdev_id)
+{
+       struct dlb2_hw_domain *domain;
+       struct dlb2_ldb_port *port;
+       int ret, id;
+
+       dlb2_log_disable_port(hw, domain_id, args->port_id, vdev_req, vdev_id);
+
+       /*
+        * Verify that hardware resources are available before attempting to
+        * satisfy the request. This simplifies the error unwinding code.
+        */
+       ret = dlb2_verify_disable_ldb_port_args(hw,
+                                               domain_id,
+                                               args,
+                                               resp,
+                                               vdev_req,
+                                               vdev_id);
+       if (ret)
+               return ret;
+
+       domain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);
+       if (!domain) {
+               DLB2_HW_ERR(hw,
+                           "[%s():%d] Internal error: domain not found\n",
+                           __func__, __LINE__);
+               return -EFAULT;
+       }
+
+       id = args->port_id;
+
+       port = dlb2_get_domain_used_ldb_port(id, vdev_req, domain);
+       if (!port) {
+               DLB2_HW_ERR(hw,
+                           "[%s():%d] Internal error: port not found\n",
+                           __func__, __LINE__);
+               return -EFAULT;
+       }
+
+       /* Hardware requires disabling the CQ before unmapping QIDs. */
+       if (port->enabled) {
+               dlb2_ldb_port_cq_disable(hw, port);
+               port->enabled = false;
+       }
+
+       resp->status = 0;
+
+       return 0;
+}
+
+int dlb2_hw_enable_dir_port(struct dlb2_hw *hw,
+                           u32 domain_id,
+                           struct dlb2_enable_dir_port_args *args,
+                           struct dlb2_cmd_response *resp,
+                           bool vdev_req,
+                           unsigned int vdev_id)
+{
+       struct dlb2_dir_pq_pair *port;
+       struct dlb2_hw_domain *domain;
+       int ret, id;
+
+       dlb2_log_enable_port(hw, domain_id, args->port_id, vdev_req, vdev_id);
+
+       /*
+        * Verify that hardware resources are available before attempting to
+        * satisfy the request. This simplifies the error unwinding code.
+        */
+       ret = dlb2_verify_enable_dir_port_args(hw,
+                                              domain_id,
+                                              args,
+                                              resp,
+                                              vdev_req,
+                                              vdev_id);
+       if (ret)
+               return ret;
+
+       domain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);
+       if (!domain) {
+               DLB2_HW_ERR(hw,
+                           "[%s():%d] Internal error: domain not found\n",
+                           __func__, __LINE__);
+               return -EFAULT;
+       }
+
+       id = args->port_id;
+
+       port = dlb2_get_domain_used_dir_pq(id, vdev_req, domain);
+       if (!port) {
+               DLB2_HW_ERR(hw,
+                           "[%s():%d] Internal error: port not found\n",
+                           __func__, __LINE__);
+               return -EFAULT;
+       }
+
+       /* Hardware requires disabling the CQ before unmapping QIDs. */
+       if (!port->enabled) {
+               dlb2_dir_port_cq_enable(hw, port);
+               port->enabled = true;
+       }
+
+       resp->status = 0;
+
+       return 0;
+}
+
+int dlb2_hw_disable_dir_port(struct dlb2_hw *hw,
+                            u32 domain_id,
+                            struct dlb2_disable_dir_port_args *args,
+                            struct dlb2_cmd_response *resp,
+                            bool vdev_req,
+                            unsigned int vdev_id)
+{
+       struct dlb2_dir_pq_pair *port;
+       struct dlb2_hw_domain *domain;
+       int ret, id;
+
+       dlb2_log_disable_port(hw, domain_id, args->port_id, vdev_req, vdev_id);
+
+       /*
+        * Verify that hardware resources are available before attempting to
+        * satisfy the request. This simplifies the error unwinding code.
+        */
+       ret = dlb2_verify_disable_dir_port_args(hw,
+                                               domain_id,
+                                               args,
+                                               resp,
+                                               vdev_req,
+                                               vdev_id);
+       if (ret)
+               return ret;
+
+       domain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);
+       if (!domain) {
+               DLB2_HW_ERR(hw,
+                           "[%s():%d] Internal error: domain not found\n",
+                           __func__, __LINE__);
+               return -EFAULT;
+       }
+
+       id = args->port_id;
+
+       port = dlb2_get_domain_used_dir_pq(id, vdev_req, domain);
+       if (!port) {
+               DLB2_HW_ERR(hw,
+                           "[%s():%d] Internal error: port not found\n",
+                           __func__, __LINE__);
+               return -EFAULT;
+       }
+
+       /* Hardware requires disabling the CQ before unmapping QIDs. */
+       if (port->enabled) {
+               dlb2_dir_port_cq_disable(hw, port);
+               port->enabled = false;
+       }
+
+       resp->status = 0;
+
+       return 0;
+}
+
 static u32 dlb2_ldb_cq_inflight_count(struct dlb2_hw *hw,
                                      struct dlb2_ldb_port *port)
 {
diff --git a/drivers/misc/dlb2/dlb2_resource.h 
b/drivers/misc/dlb2/dlb2_resource.h
index 4843da49935f..a78a8664eabc 100644
--- a/drivers/misc/dlb2/dlb2_resource.h
+++ b/drivers/misc/dlb2/dlb2_resource.h
@@ -325,6 +325,126 @@ int dlb2_hw_unmap_qid(struct dlb2_hw *hw,
                      unsigned int vdev_id);
 
 /**
+ * dlb2_hw_enable_ldb_port() - enable a load-balanced port for scheduling
+ * @hw: dlb2_hw handle for a particular device.
+ * @domain_id: domain ID.
+ * @args: port enable arguments.
+ * @resp: response structure.
+ * @vdev_request: indicates whether this request came from a vdev.
+ * @vdev_id: If vdev_request is true, this contains the vdev's ID.
+ *
+ * This function configures the DLB to schedule QEs to a load-balanced port.
+ * Ports are enabled by default.
+ *
+ * A vdev can be either an SR-IOV virtual function or a Scalable IOV virtual
+ * device.
+ *
+ * Return:
+ * Returns 0 upon success, < 0 otherwise. If an error occurs, resp->status is
+ * assigned a detailed error code from enum dlb2_error.
+ *
+ * Errors:
+ * EINVAL - The port ID is invalid or the domain is not configured.
+ * EFAULT - Internal error (resp->status not set).
+ */
+int dlb2_hw_enable_ldb_port(struct dlb2_hw *hw,
+                           u32 domain_id,
+                           struct dlb2_enable_ldb_port_args *args,
+                           struct dlb2_cmd_response *resp,
+                           bool vdev_request,
+                           unsigned int vdev_id);
+
+/**
+ * dlb2_hw_disable_ldb_port() - disable a load-balanced port for scheduling
+ * @hw: dlb2_hw handle for a particular device.
+ * @domain_id: domain ID.
+ * @args: port disable arguments.
+ * @resp: response structure.
+ * @vdev_request: indicates whether this request came from a vdev.
+ * @vdev_id: If vdev_request is true, this contains the vdev's ID.
+ *
+ * This function configures the DLB to stop scheduling QEs to a load-balanced
+ * port. Ports are enabled by default.
+ *
+ * A vdev can be either an SR-IOV virtual function or a Scalable IOV virtual
+ * device.
+ *
+ * Return:
+ * Returns 0 upon success, < 0 otherwise. If an error occurs, resp->status is
+ * assigned a detailed error code from enum dlb2_error.
+ *
+ * Errors:
+ * EINVAL - The port ID is invalid or the domain is not configured.
+ * EFAULT - Internal error (resp->status not set).
+ */
+int dlb2_hw_disable_ldb_port(struct dlb2_hw *hw,
+                            u32 domain_id,
+                            struct dlb2_disable_ldb_port_args *args,
+                            struct dlb2_cmd_response *resp,
+                            bool vdev_request,
+                            unsigned int vdev_id);
+
+/**
+ * dlb2_hw_enable_dir_port() - enable a directed port for scheduling
+ * @hw: dlb2_hw handle for a particular device.
+ * @domain_id: domain ID.
+ * @args: port enable arguments.
+ * @resp: response structure.
+ * @vdev_request: indicates whether this request came from a vdev.
+ * @vdev_id: If vdev_request is true, this contains the vdev's ID.
+ *
+ * This function configures the DLB to schedule QEs to a directed port.
+ * Ports are enabled by default.
+ *
+ * A vdev can be either an SR-IOV virtual function or a Scalable IOV virtual
+ * device.
+ *
+ * Return:
+ * Returns 0 upon success, < 0 otherwise. If an error occurs, resp->status is
+ * assigned a detailed error code from enum dlb2_error.
+ *
+ * Errors:
+ * EINVAL - The port ID is invalid or the domain is not configured.
+ * EFAULT - Internal error (resp->status not set).
+ */
+int dlb2_hw_enable_dir_port(struct dlb2_hw *hw,
+                           u32 domain_id,
+                           struct dlb2_enable_dir_port_args *args,
+                           struct dlb2_cmd_response *resp,
+                           bool vdev_request,
+                           unsigned int vdev_id);
+
+/**
+ * dlb2_hw_disable_dir_port() - disable a directed port for scheduling
+ * @hw: dlb2_hw handle for a particular device.
+ * @domain_id: domain ID.
+ * @args: port disable arguments.
+ * @resp: response structure.
+ * @vdev_request: indicates whether this request came from a vdev.
+ * @vdev_id: If vdev_request is true, this contains the vdev's ID.
+ *
+ * This function configures the DLB to stop scheduling QEs to a directed port.
+ * Ports are enabled by default.
+ *
+ * A vdev can be either an SR-IOV virtual function or a Scalable IOV virtual
+ * device.
+ *
+ * Return:
+ * Returns 0 upon success, < 0 otherwise. If an error occurs, resp->status is
+ * assigned a detailed error code from enum dlb2_error.
+ *
+ * Errors:
+ * EINVAL - The port ID is invalid or the domain is not configured.
+ * EFAULT - Internal error (resp->status not set).
+ */
+int dlb2_hw_disable_dir_port(struct dlb2_hw *hw,
+                            u32 domain_id,
+                            struct dlb2_disable_dir_port_args *args,
+                            struct dlb2_cmd_response *resp,
+                            bool vdev_request,
+                            unsigned int vdev_id);
+
+/**
  * dlb2_reset_domain() - reset a scheduling domain
  * @hw: dlb2_hw handle for a particular device.
  * @domain_id: domain ID.
diff --git a/include/uapi/linux/dlb2_user.h b/include/uapi/linux/dlb2_user.h
index 1fdc7627c393..00e9833bae1b 100644
--- a/include/uapi/linux/dlb2_user.h
+++ b/include/uapi/linux/dlb2_user.h
@@ -537,6 +537,78 @@ struct dlb2_pending_port_unmaps_args {
        __u32 padding0;
 };
 
+/*
+ * DLB2_DOMAIN_CMD_ENABLE_LDB_PORT: Enable scheduling to a load-balanced port.
+ * Input parameters:
+ * - port_id: Load-balanced port ID.
+ * - 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.
+ */
+struct dlb2_enable_ldb_port_args {
+       /* Output parameters */
+       struct dlb2_cmd_response response;
+       /* Input parameters */
+       __u32 port_id;
+       __u32 padding0;
+};
+
+/*
+ * DLB2_DOMAIN_CMD_ENABLE_DIR_PORT: Enable scheduling to a directed port.
+ * Input parameters:
+ * - port_id: Directed port ID.
+ * - 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.
+ */
+struct dlb2_enable_dir_port_args {
+       /* Output parameters */
+       struct dlb2_cmd_response response;
+       /* Input parameters */
+       __u32 port_id;
+};
+
+/*
+ * DLB2_DOMAIN_CMD_DISABLE_LDB_PORT: Disable scheduling to a load-balanced
+ *     port.
+ * Input parameters:
+ * - port_id: Load-balanced port ID.
+ * - 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.
+ */
+struct dlb2_disable_ldb_port_args {
+       /* Output parameters */
+       struct dlb2_cmd_response response;
+       /* Input parameters */
+       __u32 port_id;
+       __u32 padding0;
+};
+
+/*
+ * DLB2_DOMAIN_CMD_DISABLE_DIR_PORT: Disable scheduling to a directed port.
+ * Input parameters:
+ * - port_id: Directed port ID.
+ * - 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.
+ */
+struct dlb2_disable_dir_port_args {
+       /* Output parameters */
+       struct dlb2_cmd_response response;
+       /* Input parameters */
+       __u32 port_id;
+       __u32 padding0;
+};
+
 enum dlb2_domain_user_interface_commands {
        DLB2_DOMAIN_CMD_CREATE_LDB_QUEUE,
        DLB2_DOMAIN_CMD_CREATE_DIR_QUEUE,
@@ -552,6 +624,10 @@ enum dlb2_domain_user_interface_commands {
        DLB2_DOMAIN_CMD_MAP_QID,
        DLB2_DOMAIN_CMD_UNMAP_QID,
        DLB2_DOMAIN_CMD_PENDING_PORT_UNMAPS,
+       DLB2_DOMAIN_CMD_ENABLE_LDB_PORT,
+       DLB2_DOMAIN_CMD_ENABLE_DIR_PORT,
+       DLB2_DOMAIN_CMD_DISABLE_LDB_PORT,
+       DLB2_DOMAIN_CMD_DISABLE_DIR_PORT,
 
        /* NUM_DLB2_DOMAIN_CMD must be last */
        NUM_DLB2_DOMAIN_CMD,
@@ -642,5 +718,21 @@ enum dlb2_domain_user_interface_commands {
                _IOWR(DLB2_IOC_MAGIC,                           \
                      DLB2_DOMAIN_CMD_PENDING_PORT_UNMAPS,      \
                      struct dlb2_pending_port_unmaps_args)
+#define DLB2_IOC_ENABLE_LDB_PORT                               \
+               _IOWR(DLB2_IOC_MAGIC,                           \
+                     DLB2_DOMAIN_CMD_ENABLE_LDB_PORT,          \
+                     struct dlb2_enable_ldb_port_args)
+#define DLB2_IOC_ENABLE_DIR_PORT                               \
+               _IOWR(DLB2_IOC_MAGIC,                           \
+                     DLB2_DOMAIN_CMD_ENABLE_DIR_PORT,          \
+                     struct dlb2_enable_dir_port_args)
+#define DLB2_IOC_DISABLE_LDB_PORT                              \
+               _IOWR(DLB2_IOC_MAGIC,                           \
+                     DLB2_DOMAIN_CMD_DISABLE_LDB_PORT,         \
+                     struct dlb2_disable_ldb_port_args)
+#define DLB2_IOC_DISABLE_DIR_PORT                              \
+               _IOWR(DLB2_IOC_MAGIC,                           \
+                     DLB2_DOMAIN_CMD_DISABLE_DIR_PORT,         \
+                     struct dlb2_disable_dir_port_args)
 
 #endif /* __DLB2_USER_H */
-- 
2.13.6

Reply via email to