aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/irdma/irdma_ws.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/irdma/irdma_ws.c')
-rw-r--r--sys/dev/irdma/irdma_ws.c157
1 files changed, 95 insertions, 62 deletions
diff --git a/sys/dev/irdma/irdma_ws.c b/sys/dev/irdma/irdma_ws.c
index d311343111b9..af781f23a22c 100644
--- a/sys/dev/irdma/irdma_ws.c
+++ b/sys/dev/irdma/irdma_ws.c
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
*
- * Copyright (c) 2017 - 2023 Intel Corporation
+ * Copyright (c) 2017 - 2026 Intel Corporation
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -118,10 +118,11 @@ irdma_free_node(struct irdma_sc_vsi *vsi,
* @vsi: vsi pointer
* @node: pointer to node
* @cmd: add, remove or modify
+ * @qs_handle: Pointer to store the qs_handle for a leaf node
*/
static int
irdma_ws_cqp_cmd(struct irdma_sc_vsi *vsi,
- struct irdma_ws_node *node, u8 cmd)
+ struct irdma_ws_node *node, u8 cmd, u16 *qs_handle)
{
struct irdma_ws_node_info node_info = {0};
@@ -142,10 +143,8 @@ irdma_ws_cqp_cmd(struct irdma_sc_vsi *vsi,
return -ENOMEM;
}
- if (node->type_leaf && cmd == IRDMA_OP_WS_ADD_NODE) {
- node->qs_handle = node_info.qs_handle;
- vsi->qos[node->user_pri].qs_handle = node_info.qs_handle;
- }
+ if (node->type_leaf && cmd == IRDMA_OP_WS_ADD_NODE && qs_handle)
+ *qs_handle = node_info.qs_handle;
return 0;
}
@@ -193,11 +192,8 @@ irdma_ws_in_use(struct irdma_sc_vsi *vsi, u8 user_pri)
{
int i;
- mutex_lock(&vsi->qos[user_pri].qos_mutex);
- if (!list_empty(&vsi->qos[user_pri].qplist)) {
- mutex_unlock(&vsi->qos[user_pri].qos_mutex);
+ if (!list_empty(&vsi->qos[user_pri].qplist))
return true;
- }
/*
* Check if the qs handle associated with the given user priority is in use by any other user priority. If so,
@@ -205,12 +201,9 @@ irdma_ws_in_use(struct irdma_sc_vsi *vsi, u8 user_pri)
*/
for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) {
if (vsi->qos[i].qs_handle == vsi->qos[user_pri].qs_handle &&
- !list_empty(&vsi->qos[i].qplist)) {
- mutex_unlock(&vsi->qos[user_pri].qos_mutex);
+ !list_empty(&vsi->qos[i].qplist))
return true;
- }
}
- mutex_unlock(&vsi->qos[user_pri].qos_mutex);
return false;
}
@@ -228,9 +221,10 @@ irdma_remove_leaf(struct irdma_sc_vsi *vsi, u8 user_pri)
int i;
qs_handle = vsi->qos[user_pri].qs_handle;
- for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++)
+ for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) {
if (vsi->qos[i].qs_handle == qs_handle)
vsi->qos[i].valid = false;
+ }
ws_tree_root = vsi->dev->ws_tree_root;
if (!ws_tree_root)
@@ -247,25 +241,93 @@ irdma_remove_leaf(struct irdma_sc_vsi *vsi, u8 user_pri)
if (!tc_node)
return;
- irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_DELETE_NODE);
- vsi->unregister_qset(vsi, tc_node);
list_del(&tc_node->siblings);
+ irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_DELETE_NODE, NULL);
+
+ vsi->unregister_qset(vsi, tc_node);
irdma_free_node(vsi, tc_node);
/* Check if VSI node can be freed */
if (list_empty(&vsi_node->child_list_head)) {
- irdma_ws_cqp_cmd(vsi, vsi_node, IRDMA_OP_WS_DELETE_NODE);
+ irdma_ws_cqp_cmd(vsi, vsi_node, IRDMA_OP_WS_DELETE_NODE, NULL);
list_del(&vsi_node->siblings);
irdma_free_node(vsi, vsi_node);
/* Free head node there are no remaining VSI nodes */
if (list_empty(&ws_tree_root->child_list_head)) {
irdma_ws_cqp_cmd(vsi, ws_tree_root,
- IRDMA_OP_WS_DELETE_NODE);
+ IRDMA_OP_WS_DELETE_NODE, NULL);
irdma_free_node(vsi, ws_tree_root);
vsi->dev->ws_tree_root = NULL;
}
}
}
+static int
+irdma_enable_leaf(struct irdma_sc_vsi *vsi,
+ struct irdma_ws_node *tc_node)
+{
+ int ret;
+
+ ret = vsi->register_qset(vsi, tc_node);
+ if (ret)
+ return ret;
+
+ tc_node->enable = true;
+ ret = irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_MODIFY_NODE, NULL);
+ if (ret)
+ goto enable_err;
+ return 0;
+
+enable_err:
+ vsi->unregister_qset(vsi, tc_node);
+
+ return ret;
+}
+
+static struct irdma_ws_node *
+irdma_add_leaf_node(struct irdma_sc_vsi *vsi,
+ struct irdma_ws_node *vsi_node,
+ u8 user_pri, u16 traffic_class)
+{
+ struct irdma_ws_node *tc_node =
+ irdma_alloc_node(vsi, user_pri, WS_NODE_TYPE_LEAF, vsi_node);
+ int i, ret = 0;
+
+ if (!tc_node)
+ return NULL;
+ ret = irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_ADD_NODE, &tc_node->qs_handle);
+ if (ret) {
+ irdma_free_node(vsi, tc_node);
+ return NULL;
+ }
+ vsi->qos[tc_node->user_pri].qs_handle = tc_node->qs_handle;
+
+ list_add(&tc_node->siblings, &vsi_node->child_list_head);
+
+ ret = irdma_enable_leaf(vsi, tc_node);
+ if (ret)
+ goto reg_err;
+
+ /*
+ * Iterate through other UPs and update the QS handle if they have a matching traffic class.
+ */
+ for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) {
+ if (vsi->qos[i].traffic_class == traffic_class) {
+ vsi->qos[i].qs_handle = tc_node->qs_handle;
+ vsi->qos[i].l2_sched_node_id =
+ tc_node->l2_sched_node_id;
+ vsi->qos[i].valid = true;
+ }
+ }
+ return tc_node;
+
+reg_err:
+ irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_DELETE_NODE, NULL);
+ list_del(&tc_node->siblings);
+ irdma_free_node(vsi, tc_node);
+
+ return NULL;
+}
+
/**
* irdma_ws_add - Build work scheduler tree, set RDMA qs_handle
* @vsi: vsi pointer
@@ -279,7 +341,6 @@ irdma_ws_add(struct irdma_sc_vsi *vsi, u8 user_pri)
struct irdma_ws_node *tc_node;
u16 traffic_class;
int ret = 0;
- int i;
mutex_lock(&vsi->dev->ws_mutex);
if (vsi->tc_change_pending) {
@@ -298,9 +359,11 @@ irdma_ws_add(struct irdma_sc_vsi *vsi, u8 user_pri)
ret = -ENOMEM;
goto exit;
}
- irdma_debug(vsi->dev, IRDMA_DEBUG_WS, "Creating root node = %d\n", ws_tree_root->index);
+ irdma_debug(vsi->dev, IRDMA_DEBUG_WS,
+ "Creating root node = %d\n", ws_tree_root->index);
- ret = irdma_ws_cqp_cmd(vsi, ws_tree_root, IRDMA_OP_WS_ADD_NODE);
+ ret = irdma_ws_cqp_cmd(vsi, ws_tree_root, IRDMA_OP_WS_ADD_NODE,
+ NULL);
if (ret) {
irdma_free_node(vsi, ws_tree_root);
goto exit;
@@ -324,7 +387,8 @@ irdma_ws_add(struct irdma_sc_vsi *vsi, u8 user_pri)
goto vsi_add_err;
}
- ret = irdma_ws_cqp_cmd(vsi, vsi_node, IRDMA_OP_WS_ADD_NODE);
+ ret = irdma_ws_cqp_cmd(vsi, vsi_node, IRDMA_OP_WS_ADD_NODE,
+ NULL);
if (ret) {
irdma_free_node(vsi, vsi_node);
goto vsi_add_err;
@@ -344,56 +408,22 @@ irdma_ws_add(struct irdma_sc_vsi *vsi, u8 user_pri)
irdma_debug(vsi->dev, IRDMA_DEBUG_WS,
"Node not found matching VSI %d and TC %d\n",
vsi->vsi_idx, traffic_class);
- tc_node = irdma_alloc_node(vsi, user_pri, WS_NODE_TYPE_LEAF,
- vsi_node);
+ tc_node = irdma_add_leaf_node(vsi, vsi_node, user_pri,
+ traffic_class);
if (!tc_node) {
ret = -ENOMEM;
goto leaf_add_err;
}
-
- ret = irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_ADD_NODE);
- if (ret) {
- irdma_free_node(vsi, tc_node);
- goto leaf_add_err;
- }
-
- list_add(&tc_node->siblings, &vsi_node->child_list_head);
- /*
- * callback to LAN to update the LAN tree with our node
- */
- ret = vsi->register_qset(vsi, tc_node);
- if (ret)
- goto reg_err;
-
- tc_node->enable = true;
- ret = irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_MODIFY_NODE);
- if (ret) {
- vsi->unregister_qset(vsi, tc_node);
- goto reg_err;
- }
}
irdma_debug(vsi->dev, IRDMA_DEBUG_WS,
"Using node %d which represents VSI %d TC %d\n",
tc_node->index, vsi->vsi_idx, traffic_class);
- /*
- * Iterate through other UPs and update the QS handle if they have a matching traffic class.
- */
- for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) {
- if (vsi->qos[i].traffic_class == traffic_class) {
- vsi->qos[i].qs_handle = tc_node->qs_handle;
- vsi->qos[i].l2_sched_node_id = tc_node->l2_sched_node_id;
- vsi->qos[i].valid = true;
- }
- }
goto exit;
-reg_err:
- irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_DELETE_NODE);
- list_del(&tc_node->siblings);
- irdma_free_node(vsi, tc_node);
leaf_add_err:
if (list_empty(&vsi_node->child_list_head)) {
- if (irdma_ws_cqp_cmd(vsi, vsi_node, IRDMA_OP_WS_DELETE_NODE))
+ if (irdma_ws_cqp_cmd(vsi, vsi_node, IRDMA_OP_WS_DELETE_NODE,
+ NULL))
goto exit;
list_del(&vsi_node->siblings);
irdma_free_node(vsi, vsi_node);
@@ -402,7 +432,8 @@ leaf_add_err:
vsi_add_err:
/* Free head node there are no remaining VSI nodes */
if (list_empty(&ws_tree_root->child_list_head)) {
- irdma_ws_cqp_cmd(vsi, ws_tree_root, IRDMA_OP_WS_DELETE_NODE);
+ irdma_ws_cqp_cmd(vsi, ws_tree_root, IRDMA_OP_WS_DELETE_NODE,
+ NULL);
vsi->dev->ws_tree_root = NULL;
irdma_free_node(vsi, ws_tree_root);
}
@@ -420,12 +451,14 @@ exit:
void
irdma_ws_remove(struct irdma_sc_vsi *vsi, u8 user_pri)
{
+ mutex_lock(&vsi->qos[user_pri].qos_mutex);
mutex_lock(&vsi->dev->ws_mutex);
if (irdma_ws_in_use(vsi, user_pri))
goto exit;
irdma_remove_leaf(vsi, user_pri);
exit:
mutex_unlock(&vsi->dev->ws_mutex);
+ mutex_unlock(&vsi->qos[user_pri].qos_mutex);
}
/**