Skip to content

Commit

Permalink
dpaa2: Avoid re-using dpaa2_cmd to eliminate race condition
Browse files Browse the repository at this point in the history
There is work-in-progress to handle errors during drivers attach
routines properly as well, i.e. kernel still panics as a result of
drivers detaching.
  • Loading branch information
Dmitry Salychev authored and Dmitry Salychev committed Feb 27, 2023
1 parent 28137bd commit 0746e1f
Show file tree
Hide file tree
Showing 16 changed files with 1,482 additions and 909 deletions.
91 changes: 51 additions & 40 deletions sys/dev/dpaa2/dpaa2_bp.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,21 +90,32 @@ dpaa2_bp_detach(device_t dev)
device_t child = dev;
struct dpaa2_bp_softc *sc = device_get_softc(dev);
struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev);
struct dpaa2_cmd cmd;
uint16_t rc_token, bp_token;
int error;

if (sc->cmd != NULL) {
(void)DPAA2_CMD_BP_DISABLE(dev, child, sc->cmd);
(void)DPAA2_CMD_BP_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd,
sc->bp_token));
(void)DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd,
sc->rc_token));
DPAA2_CMD_INIT(&cmd);

dpaa2_mcp_free_command(sc->cmd);
sc->cmd = NULL;
error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
if (error) {
device_printf(dev, "%s: failed to open DPRC: error=%d\n",
__func__, error);
goto free_res;
}

dinfo->portal = NULL;
error = DPAA2_CMD_BP_OPEN(dev, child, &cmd, dinfo->id, &bp_token);
if (error) {
device_printf(dev, "%s: failed to open DPBP: id=%d, error=%d\n",
__func__, dinfo->id, error);
goto close_rc;
}
DPAA2_CMD_BP_DISABLE(dev, child, DPAA2_CMD_TK(&cmd, bp_token));
DPAA2_CMD_BP_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, bp_token));
close_rc:
DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
free_res:
bus_release_resources(sc->dev, dpaa2_bp_spec, sc->res);

dinfo->portal = NULL;
return (0);
}

Expand All @@ -118,73 +129,73 @@ dpaa2_bp_attach(device_t dev)
struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
struct dpaa2_devinfo *mcp_dinfo;
struct dpaa2_cmd cmd;
uint16_t rc_token, bp_token;
int error;

sc->dev = dev;
sc->cmd = NULL;

error = bus_alloc_resources(sc->dev, dpaa2_bp_spec, sc->res);
if (error) {
device_printf(dev, "%s: failed to allocate resources: "
"error=%d\n", __func__, error);
return (ENXIO);
goto err_exit;
}

/* Send commands to MC via allocated portal. */
/* Setup allocated MC portal */
mcp_dev = (device_t) rman_get_start(sc->res[MCP_RID(0)]);
mcp_dinfo = device_get_ivars(mcp_dev);
dinfo->portal = mcp_dinfo->portal;

/* Allocate a command to send to MC hardware. */
error = dpaa2_mcp_init_command(&sc->cmd, DPAA2_CMD_DEF);
if (error) {
device_printf(dev, "%s: failed to allocate dpaa2_cmd: "
"error=%d\n", __func__, error);
dpaa2_bp_detach(dev);
return (ENXIO);
}
DPAA2_CMD_INIT(&cmd);

/* Open resource container and DPBP object. */
error = DPAA2_CMD_RC_OPEN(dev, child, sc->cmd, rcinfo->id,
&sc->rc_token);
error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
if (error) {
device_printf(dev, "%s: failed to open DPRC: error=%d\n",
__func__, error);
dpaa2_bp_detach(dev);
return (ENXIO);
goto free_res;
}
error = DPAA2_CMD_BP_OPEN(dev, child, sc->cmd, dinfo->id, &sc->bp_token);
error = DPAA2_CMD_BP_OPEN(dev, child, &cmd, dinfo->id, &bp_token);
if (error) {
device_printf(dev, "%s: failed to open DPBP: id=%d, error=%d\n",
__func__, dinfo->id, error);
dpaa2_bp_detach(dev);
return (ENXIO);
goto close_rc;
}

/* Prepare DPBP object. */
error = DPAA2_CMD_BP_RESET(dev, child, sc->cmd);
error = DPAA2_CMD_BP_RESET(dev, child, &cmd);
if (error) {
device_printf(dev, "%s: failed to reset DPBP: id=%d, error=%d\n",
__func__, dinfo->id, error);
dpaa2_bp_detach(dev);
return (ENXIO);
goto close_bp;
}
error = DPAA2_CMD_BP_ENABLE(dev, child, sc->cmd);
error = DPAA2_CMD_BP_ENABLE(dev, child, &cmd);
if (error) {
device_printf(dev, "%s: failed to enable DPBP: id=%d, "
"error=%d\n", __func__, dinfo->id, error);
dpaa2_bp_detach(dev);
return (ENXIO);
goto close_bp;
}
error = DPAA2_CMD_BP_GET_ATTRIBUTES(dev, child, sc->cmd, &sc->attr);
error = DPAA2_CMD_BP_GET_ATTRIBUTES(dev, child, &cmd, &sc->attr);
if (error) {
device_printf(dev, "%s: failed to get DPBP attributes: id=%d, "
"error=%d\n", __func__, dinfo->id, error);
dpaa2_bp_detach(dev);
return (ENXIO);
goto disable_bp;
}

DPAA2_CMD_BP_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, bp_token));
DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
return (0);

disable_bp:
DPAA2_CMD_BP_DISABLE(dev, child, DPAA2_CMD_TK(&cmd, bp_token));
close_bp:
DPAA2_CMD_BP_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, bp_token));
close_rc:
DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
free_res:
bus_release_resources(sc->dev, dpaa2_bp_spec, sc->res);
err_exit:
dinfo->portal = NULL;
return (ENXIO);
}

static device_method_t dpaa2_bp_methods[] = {
Expand Down
6 changes: 0 additions & 6 deletions sys/dev/dpaa2/dpaa2_bp.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,6 @@ struct dpaa2_bp_conf {
struct dpaa2_bp_softc {
device_t dev;
struct dpaa2_bp_attr attr;

/* Help to send commands to MC. */
struct dpaa2_cmd *cmd;
uint16_t rc_token;
uint16_t bp_token;

struct resource *res[DPAA2_BP_MAX_RESOURCES];
};

Expand Down
110 changes: 65 additions & 45 deletions sys/dev/dpaa2/dpaa2_con.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,25 +93,49 @@ static int dpaa2_con_detach(device_t dev);
static int
dpaa2_con_probe(device_t dev)
{
/* DPCON device will be added by a parent resource container itself. */
/* DPCON device will be added by the parent resource container itself. */
device_set_desc(dev, "DPAA2 Concentrator");
return (BUS_PROBE_DEFAULT);
}

static int
dpaa2_con_detach(device_t dev)
{
device_t pdev = device_get_parent(dev);
device_t child = dev;
struct dpaa2_con_softc *sc = device_get_softc(dev);
struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
struct dpaa2_cmd cmd;
uint16_t rc_token, con_token;
int error;

DPAA2_CMD_CON_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->con_token));
DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->rc_token));
dpaa2_mcp_free_command(sc->cmd);
DPAA2_CMD_INIT(&cmd);

sc->cmd = NULL;
sc->con_token = 0;
sc->rc_token = 0;
error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
if (error) {
device_printf(dev, "%s: failed to open DPRC: error=%d\n",
__func__, error);
goto free_res;
}
error = DPAA2_CMD_CON_OPEN(dev, child, &cmd, dinfo->id, &con_token);
if (error) {
device_printf(dev, "%s: failed to open DPCON: id=%d, error=%d\n",
__func__, dinfo->id, error);
goto close_rc;
}
error = DPAA2_CMD_CON_RESET(dev, child, &cmd);
if (error) {
device_printf(dev, "%s: failed to reset DPCON: id=%d, error=%d\n",
__func__, dinfo->id, error);
}

DPAA2_CMD_CON_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, con_token));
close_rc:
DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
free_res:
dinfo->portal = NULL;
bus_release_resources(sc->dev, dpaa2_con_spec, sc->res);
return (0);
}

Expand All @@ -125,6 +149,8 @@ dpaa2_con_attach(device_t dev)
struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
struct dpaa2_devinfo *mcp_dinfo;
struct dpaa2_cmd cmd;
uint16_t rc_token, con_token;
int error;

sc->dev = dev;
Expand All @@ -133,65 +159,59 @@ dpaa2_con_attach(device_t dev)
if (error) {
device_printf(dev, "%s: failed to allocate resources: "
"error=%d\n", __func__, error);
return (ENXIO);
goto err_exit;
}

/* Obtain MC portal. */
/* Setup allocated MC portal */
mcp_dev = (device_t) rman_get_start(sc->res[MCP_RID(0)]);
mcp_dinfo = device_get_ivars(mcp_dev);
dinfo->portal = mcp_dinfo->portal;

/* Allocate a command to send to MC hardware. */
error = dpaa2_mcp_init_command(&sc->cmd, DPAA2_CMD_DEF);
if (error) {
device_printf(dev, "Failed to allocate dpaa2_cmd: error=%d\n",
error);
goto err_exit;
}
DPAA2_CMD_INIT(&cmd);

/* Open resource container and DPCON object. */
error = DPAA2_CMD_RC_OPEN(dev, child, sc->cmd, rcinfo->id,
&sc->rc_token);
error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token);
if (error) {
device_printf(dev, "Failed to open DPRC: error=%d\n", error);
goto err_free_cmd;
device_printf(dev, "%s: failed to open DPRC: error=%d\n",
__func__, error);
goto free_res;
}
error = DPAA2_CMD_CON_OPEN(dev, child, sc->cmd, dinfo->id,
&sc->con_token);
error = DPAA2_CMD_CON_OPEN(dev, child, &cmd, dinfo->id, &con_token);
if (error) {
device_printf(dev, "Failed to open DPCON: id=%d, error=%d\n",
dinfo->id, error);
goto err_close_rc;
device_printf(dev, "%s: failed to open DPCON: id=%d, error=%d\n",
__func__, dinfo->id, error);
goto close_rc;
}

/* Prepare DPCON object. */
error = DPAA2_CMD_CON_RESET(dev, child, sc->cmd);
error = DPAA2_CMD_CON_RESET(dev, child, &cmd);
if (error) {
device_printf(dev, "Failed to reset DPCON: id=%d, error=%d\n",
dinfo->id, error);
goto err_close_con;
device_printf(dev, "%s: failed to reset DPCON: id=%d, error=%d\n",
__func__, dinfo->id, error);
goto close_con;
}
error = DPAA2_CMD_CON_GET_ATTRIBUTES(dev, child, sc->cmd, &sc->attr);
error = DPAA2_CMD_CON_GET_ATTRIBUTES(dev, child, &cmd, &sc->attr);
if (error) {
device_printf(dev, "Failed to get DPCON attributes: id=%d, "
"error=%d\n", dinfo->id, error);
goto err_close_con;
device_printf(dev, "%s: failed to get DPCON attributes: id=%d, "
"error=%d\n", __func__, dinfo->id, error);
goto close_con;
}

/* TODO: Enable debug output via sysctl (to reduce output). */
if (bootverbose)
if (bootverbose) {
device_printf(dev, "chan_id=%d, priorities=%d\n",
sc->attr.chan_id, sc->attr.prior_num);
}

DPAA2_CMD_CON_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, con_token));
DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));

return (0);

err_close_con:
DPAA2_CMD_CON_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->con_token));
err_close_rc:
DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->rc_token));
err_free_cmd:
dpaa2_mcp_free_command(sc->cmd);
err_exit:
close_con:
DPAA2_CMD_CON_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, con_token));
close_rc:
DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token));
free_res:
dinfo->portal = NULL;
bus_release_resources(sc->dev, dpaa2_con_spec, sc->res);
err_exit:
return (ENXIO);
}

Expand Down
5 changes: 0 additions & 5 deletions sys/dev/dpaa2/dpaa2_con.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,6 @@ struct dpaa2_con_softc {
device_t dev;
struct resource *res[DPAA2_CON_MAX_RESOURCES];
struct dpaa2_con_attr attr;

/* Help to send commands to MC. */
struct dpaa2_cmd *cmd;
uint16_t rc_token;
uint16_t con_token;
};

extern struct resource_spec dpaa2_con_spec[];
Expand Down
Loading

0 comments on commit 0746e1f

Please sign in to comment.