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 { ...@@ -724,6 +724,7 @@ struct gve_priv {
union gve_adminq_command *adminq; union gve_adminq_command *adminq;
dma_addr_t adminq_bus_addr; dma_addr_t adminq_bus_addr;
struct dma_pool *adminq_pool; struct dma_pool *adminq_pool;
struct mutex adminq_lock; /* Protects adminq command execution */
u32 adminq_mask; /* masks prod_cnt to adminq size */ u32 adminq_mask; /* masks prod_cnt to adminq size */
u32 adminq_prod_cnt; /* free-running count of AQ cmds executed */ u32 adminq_prod_cnt; /* free-running count of AQ cmds executed */
u32 adminq_cmd_fail; /* free-running count of AQ cmds failed */ 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) ...@@ -284,6 +284,7 @@ int gve_adminq_alloc(struct device *dev, struct gve_priv *priv)
&priv->reg_bar0->adminq_base_address_lo); &priv->reg_bar0->adminq_base_address_lo);
iowrite32be(GVE_DRIVER_STATUS_RUN_MASK, &priv->reg_bar0->driver_status); iowrite32be(GVE_DRIVER_STATUS_RUN_MASK, &priv->reg_bar0->driver_status);
} }
mutex_init(&priv->adminq_lock);
gve_set_admin_queue_ok(priv); gve_set_admin_queue_ok(priv);
return 0; return 0;
} }
...@@ -511,28 +512,29 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv, ...@@ -511,28 +512,29 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv,
return 0; 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, static int gve_adminq_execute_cmd(struct gve_priv *priv,
union gve_adminq_command *cmd_orig) union gve_adminq_command *cmd_orig)
{ {
u32 tail, head; u32 tail, head;
int err; int err;
mutex_lock(&priv->adminq_lock);
tail = ioread32be(&priv->reg_bar0->adminq_event_counter); tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
head = priv->adminq_prod_cnt; head = priv->adminq_prod_cnt;
if (tail != head) if (tail != head) {
// This is not a valid path err = -EINVAL;
return -EINVAL; goto out;
}
err = gve_adminq_issue_cmd(priv, cmd_orig); err = gve_adminq_issue_cmd(priv, cmd_orig);
if (err) 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 /* 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