Commit 1108566c authored by Ziwei Xiao's avatar Ziwei Xiao Committed by Jakub Kicinski

gve: Add adminq mutex lock

We were depending on the rtnl_lock to make sure there is only one adminq
command running at a time. But some commands may take too long to hold
the rtnl_lock, such as the upcoming flow steering operations. For such
situations, it can temporarily drop the rtnl_lock, and replace it for
these operations with a new adminq lock, which can ensure the adminq
command execution to be thread-safe.
Signed-off-by: default avatarZiwei Xiao <ziweixiao@google.com>
Reviewed-by: default avatarPraveen Kaligineedi <pkaligineedi@google.com>
Reviewed-by: default avatarHarshitha Ramamurthy <hramamurthy@google.com>
Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20240625001232.1476315-2-ziweixiao@google.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 63173885
......@@ -724,6 +724,7 @@ struct gve_priv {
union gve_adminq_command *adminq;
dma_addr_t adminq_bus_addr;
struct dma_pool *adminq_pool;
struct mutex adminq_lock; /* Protects adminq command execution */
u32 adminq_mask; /* masks prod_cnt to adminq size */
u32 adminq_prod_cnt; /* free-running count of AQ cmds executed */
u32 adminq_cmd_fail; /* free-running count of AQ cmds failed */
......
......@@ -284,6 +284,7 @@ int gve_adminq_alloc(struct device *dev, struct gve_priv *priv)
&priv->reg_bar0->adminq_base_address_lo);
iowrite32be(GVE_DRIVER_STATUS_RUN_MASK, &priv->reg_bar0->driver_status);
}
mutex_init(&priv->adminq_lock);
gve_set_admin_queue_ok(priv);
return 0;
}
......@@ -511,28 +512,29 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv,
return 0;
}
/* This function is not threadsafe - the caller is responsible for any
* necessary locks.
* The caller is also responsible for making sure there are no commands
* waiting to be executed.
*/
static int gve_adminq_execute_cmd(struct gve_priv *priv,
union gve_adminq_command *cmd_orig)
{
u32 tail, head;
int err;
mutex_lock(&priv->adminq_lock);
tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
head = priv->adminq_prod_cnt;
if (tail != head)
// This is not a valid path
return -EINVAL;
if (tail != head) {
err = -EINVAL;
goto out;
}
err = gve_adminq_issue_cmd(priv, cmd_orig);
if (err)
return err;
goto out;
return gve_adminq_kick_and_wait(priv);
err = gve_adminq_kick_and_wait(priv);
out:
mutex_unlock(&priv->adminq_lock);
return err;
}
/* The device specifies that the management vector can either be the first irq
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment