Skip to content

Commit d5d6619

Browse files
committed
media: i2c: imx500: keep chip active while network firmware is loaded
Hold a pm_runtime reference for the lifetime of imx500->fw_network. The reference is taken in imx500_set_ctrl() before kernel_read_file_from_fd() and released in imx500_clear_fw_network() on vfree. This prevents the autosuspend from racing the read (kernel oops in __memcpy) and from silently dropping the rpk before stream-on. Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
1 parent 48abadb commit d5d6619

1 file changed

Lines changed: 22 additions & 1 deletion

File tree

drivers/media/i2c/imx500.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1924,9 +1924,17 @@ static int imx500_clear_weights(struct imx500 *imx500)
19241924

19251925
static void imx500_clear_fw_network(struct imx500 *imx500)
19261926
{
1927+
struct i2c_client *client = v4l2_get_subdevdata(&imx500->sd);
1928+
19271929
/* Remove any previous firmware blob. */
1928-
if (imx500->fw_network)
1930+
if (imx500->fw_network) {
19291931
vfree(imx500->fw_network);
1932+
/*
1933+
* Release the PM ref taken when the fw was loaded in
1934+
* imx500_set_ctrl().
1935+
*/
1936+
pm_runtime_put_noidle(&client->dev);
1937+
}
19301938

19311939
imx500->fw_network = NULL;
19321940
imx500->network_written = false;
@@ -2138,6 +2146,13 @@ static int imx500_set_ctrl(struct v4l2_ctrl *ctrl)
21382146
}
21392147

21402148
imx500_clear_fw_network(imx500);
2149+
2150+
/*
2151+
* Take a pm_runtime reference before the read. This keeps
2152+
* the device active as long as a NW firmware has been loaded.
2153+
*/
2154+
pm_runtime_get_noresume(&client->dev);
2155+
21412156
ret = kernel_read_file_from_fd(ctrl->val, 0,
21422157
(void **)&imx500->fw_network, INT_MAX,
21432158
&imx500->fw_network_size,
@@ -2152,6 +2167,12 @@ static int imx500_set_ctrl(struct v4l2_ctrl *ctrl)
21522167
dev_err(&client->dev, "%s failed to read fw image: %d\n",
21532168
__func__, ret);
21542169
imx500_clear_fw_network(imx500);
2170+
/*
2171+
* kernel_read_file_from_fd leaves fw_network NULL on
2172+
* error, so imx500_clear_fw_network did not put.
2173+
* Release the ref we took above.
2174+
*/
2175+
pm_runtime_put_noidle(&client->dev);
21552176
return ret;
21562177
}
21572178
if (ret != imx500->fw_network_size) {

0 commit comments

Comments
 (0)