Skip to content

Commit f555a68

Browse files
naushirpelwell
authored andcommitted
media: i2c: imx500: Keep the device 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 1759b25 commit f555a68

1 file changed

Lines changed: 18 additions & 2 deletions

File tree

drivers/media/i2c/imx500.c

Lines changed: 18 additions & 2 deletions
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_resume_and_get(&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,
@@ -2151,7 +2166,8 @@ static int imx500_set_ctrl(struct v4l2_ctrl *ctrl)
21512166
if (ret < 0) {
21522167
dev_err(&client->dev, "%s failed to read fw image: %d\n",
21532168
__func__, ret);
2154-
imx500_clear_fw_network(imx500);
2169+
/* Release the ref we took above. */
2170+
pm_runtime_put_noidle(&client->dev);
21552171
return ret;
21562172
}
21572173
if (ret != imx500->fw_network_size) {

0 commit comments

Comments
 (0)