Skip to content

Commit 3953e72

Browse files
author
Dmitry Perchanov
committed
ipu-isys: fw init procedures moved to queue.
- Move firmware bring-up from video open to queue start streaming This will increase firmware stability for start-stop toggling without closing video node for all streams. - Move firmware shutdown from video close to queue stop streaming Improves recovery process for multithread processes that not close video handle. Signed-off-by: Dmitry Perchanov <dmitry.perchanov@intel.com>
1 parent 4e351cc commit 3953e72

2 files changed

Lines changed: 125 additions & 90 deletions

File tree

drivers/media/pci/intel/ipu-isys-queue.c

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/module.h>
77
#include <linux/string.h>
88
#include <linux/delay.h>
9+
#include <linux/pm_runtime.h>
910

1011
#include <media/media-entity.h>
1112
#include <media/videobuf2-dma-contig.h>
@@ -898,12 +899,93 @@ static int __start_streaming(struct vb2_queue *q, unsigned int count)
898899
return rval;
899900
}
900901

902+
static int isys_fw_open(struct ipu_isys_video *av)
903+
{
904+
struct ipu_isys *isys = av->isys;
905+
struct ipu_bus_device *adev = to_ipu_bus_device(&isys->adev->dev);
906+
struct ipu_device *isp = adev->isp;
907+
int rval;
908+
const struct ipu_isys_internal_pdata *ipdata;
909+
910+
dev_warn(&isys->adev->dev, "%s:%d %s: enter\n",
911+
__func__, __LINE__, av->vdev.name);
912+
913+
mutex_lock(&isys->mutex);
914+
915+
if (isys->reset_needed || isp->flr_done) {
916+
mutex_unlock(&isys->mutex);
917+
dev_warn(&isys->adev->dev, "%s:%d %s: isys power cycle required\n",
918+
__func__, __LINE__, av->vdev.name);
919+
return -EIO;
920+
}
921+
mutex_unlock(&isys->mutex);
922+
923+
rval = pm_runtime_get_sync(&isys->adev->dev);
924+
if (rval < 0) {
925+
pm_runtime_put_noidle(&isys->adev->dev);
926+
return rval;
927+
}
928+
929+
mutex_lock(&isys->mutex);
930+
if (isys->video_opened++) {
931+
/* Already open */
932+
mutex_unlock(&isys->mutex);
933+
dev_warn(&isys->adev->dev, "%s:%d %s: Already open, exit %d\n",
934+
__func__, __LINE__, av->vdev.name, isys->video_opened);
935+
return 0;
936+
}
937+
938+
ipdata = isys->pdata->ipdata;
939+
ipu_configure_spc(adev->isp,
940+
&ipdata->hw_variant,
941+
IPU_CPD_PKG_DIR_ISYS_SERVER_IDX,
942+
isys->pdata->base, isys->pkg_dir,
943+
isys->pkg_dir_dma_addr);
944+
945+
/*
946+
* Buffers could have been left to wrong queue at last closure.
947+
* Move them now back to empty buffer queue.
948+
*/
949+
ipu_cleanup_fw_msg_bufs(isys);
950+
951+
if (isys->fwcom) {
952+
/*
953+
* Something went wrong in previous shutdown. As we are now
954+
* restarting isys we can safely delete old context.
955+
*/
956+
dev_err(&isys->adev->dev, "%s:%d %s Clearing old context\n",
957+
__func__, __LINE__, av->vdev.name);
958+
ipu_fw_isys_cleanup(isys);
959+
}
960+
961+
rval = ipu_fw_isys_init(av->isys, ipdata->num_parallel_streams);
962+
if (rval < 0)
963+
goto out_lib_init;
964+
965+
mutex_unlock(&isys->mutex);
966+
967+
dev_warn(&isys->adev->dev, "%s:%d %s: exit\n",
968+
__func__, __LINE__, av->vdev.name);
969+
return 0;
970+
971+
out_lib_init:
972+
isys->video_opened--;
973+
mutex_unlock(&isys->mutex);
974+
pm_runtime_put(&isys->adev->dev);
975+
976+
return rval;
977+
}
978+
901979
static int start_streaming(struct vb2_queue *q, unsigned int count)
902980
{
903981
struct ipu_isys_queue *aq = vb2_queue_to_ipu_isys_queue(q);
904982
struct ipu_isys_video *av = ipu_isys_queue_to_video(aq);
905983
int rval;
906984

985+
rval = isys_fw_open(av);
986+
if (rval < 0) {
987+
dev_err(&av->isys->adev->dev, "isys_fw_open failed: %d\n", rval);
988+
}
907989
mutex_unlock(&av->mutex);
908990
mutex_lock(&av->isys->reset_mutex);
909991
while (av->isys->in_stop_streaming) {
@@ -1119,6 +1201,48 @@ static int ipu_isys_reset(struct ipu_isys_video *self_av)
11191201
return 0;
11201202
}
11211203

1204+
static int isys_fw_release(struct ipu_isys_video *av)
1205+
{
1206+
struct ipu_isys *isys = av->isys;
1207+
int ret = 0;
1208+
1209+
dev_warn(&isys->adev->dev, "%s:%d %s: enter\n",
1210+
__func__, __LINE__, av->vdev.name);
1211+
mutex_lock(&isys->reset_mutex);
1212+
while (isys->in_reset) {
1213+
mutex_unlock(&isys->reset_mutex);
1214+
dev_warn(&isys->adev->dev, "%s:%d %s: wait for reset\n",
1215+
__func__, __LINE__, av->vdev.name);
1216+
usleep_range(10000, 11000);
1217+
mutex_lock(&isys->reset_mutex);
1218+
}
1219+
mutex_unlock(&isys->reset_mutex);
1220+
1221+
mutex_lock(&isys->mutex);
1222+
1223+
if (!--isys->video_opened) {
1224+
dev_warn(&isys->adev->dev, "%s:%d %s: close fw\n",
1225+
__func__, __LINE__, av->vdev.name);
1226+
ipu_fw_isys_close(isys);
1227+
// isys->reset_needed = true; // force reset
1228+
if (isys->fwcom) {
1229+
isys->reset_needed = true;
1230+
ret = -EIO;
1231+
}
1232+
}
1233+
1234+
mutex_unlock(&isys->mutex);
1235+
1236+
if (isys->reset_needed)
1237+
pm_runtime_put_sync(&isys->adev->dev);
1238+
else
1239+
pm_runtime_put(&isys->adev->dev);
1240+
1241+
dev_warn(&isys->adev->dev, "%s:%d %s: exit\n",
1242+
__func__, __LINE__, av->vdev.name);
1243+
return ret;
1244+
}
1245+
11221246
static void stop_streaming(struct vb2_queue *q)
11231247
{
11241248
struct ipu_isys_queue *aq = vb2_queue_to_ipu_isys_queue(q);
@@ -1187,6 +1311,7 @@ static void stop_streaming(struct vb2_queue *q)
11871311
av->isys->in_stop_streaming = false;
11881312
mutex_unlock(&av->isys->reset_mutex);
11891313

1314+
isys_fw_release(av);
11901315
}
11911316

11921317
static unsigned int

drivers/media/pci/intel/ipu-isys-video.c

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -145,26 +145,7 @@ const struct ipu_isys_pixelformat ipu_isys_pfmts_packed[] = {
145145
static int video_open(struct file *file)
146146
{
147147
struct ipu_isys_video *av = video_drvdata(file);
148-
struct ipu_isys *isys = av->isys;
149-
struct ipu_bus_device *adev = to_ipu_bus_device(&isys->adev->dev);
150-
struct ipu_device *isp = adev->isp;
151148
int rval;
152-
const struct ipu_isys_internal_pdata *ipdata;
153-
154-
mutex_lock(&isys->mutex);
155-
156-
if (isys->reset_needed || isp->flr_done) {
157-
mutex_unlock(&isys->mutex);
158-
dev_warn(&isys->adev->dev, "isys power cycle required\n");
159-
return -EIO;
160-
}
161-
mutex_unlock(&isys->mutex);
162-
163-
rval = pm_runtime_get_sync(&isys->adev->dev);
164-
if (rval < 0) {
165-
pm_runtime_put_noidle(&isys->adev->dev);
166-
return rval;
167-
}
168149

169150
rval = v4l2_fh_open(file);
170151
if (rval)
@@ -180,47 +161,9 @@ static int video_open(struct file *file)
180161
if (rval)
181162
goto out_v4l2_fh_release;
182163

183-
mutex_lock(&isys->mutex);
184-
185-
if (isys->video_opened++) {
186-
/* Already open */
187-
mutex_unlock(&isys->mutex);
188-
return 0;
189-
}
190-
191-
ipdata = isys->pdata->ipdata;
192-
ipu_configure_spc(adev->isp,
193-
&ipdata->hw_variant,
194-
IPU_CPD_PKG_DIR_ISYS_SERVER_IDX,
195-
isys->pdata->base, isys->pkg_dir,
196-
isys->pkg_dir_dma_addr);
197-
198-
/*
199-
* Buffers could have been left to wrong queue at last closure.
200-
* Move them now back to empty buffer queue.
201-
*/
202-
ipu_cleanup_fw_msg_bufs(isys);
203-
204-
if (isys->fwcom) {
205-
/*
206-
* Something went wrong in previous shutdown. As we are now
207-
* restarting isys we can safely delete old context.
208-
*/
209-
dev_err(&isys->adev->dev, "Clearing old context\n");
210-
ipu_fw_isys_cleanup(isys);
211-
}
212-
213-
rval = ipu_fw_isys_init(av->isys, ipdata->num_parallel_streams);
214-
if (rval < 0)
215-
goto out_lib_init;
216-
217-
mutex_unlock(&isys->mutex);
218164

219165
return 0;
220166

221-
out_lib_init:
222-
isys->video_opened--;
223-
mutex_unlock(&isys->mutex);
224167
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
225168
ipu_pipeline_pm_use(&av->vdev.entity, 0);
226169
#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
@@ -232,8 +175,6 @@ static int video_open(struct file *file)
232175
out_v4l2_fh_release:
233176
v4l2_fh_release(file);
234177
out_power_down:
235-
pm_runtime_put(&isys->adev->dev);
236-
237178
return rval;
238179
}
239180

@@ -246,44 +187,13 @@ static int video_release(struct file *file)
246187
av->vdev.name);
247188
vb2_fop_release(file);
248189

249-
mutex_lock(&av->isys->reset_mutex);
250-
while (av->isys->in_reset) {
251-
mutex_unlock(&av->isys->reset_mutex);
252-
dev_dbg(&av->isys->adev->dev, "release: %s: wait for reset\n",
253-
av->vdev.name
254-
);
255-
usleep_range(10000, 11000);
256-
mutex_lock(&av->isys->reset_mutex);
257-
}
258-
mutex_unlock(&av->isys->reset_mutex);
259-
260-
mutex_lock(&av->isys->mutex);
261-
262-
if (!--av->isys->video_opened) {
263-
dev_dbg(&av->isys->adev->dev, "release: %s: close fw\n",
264-
av->vdev.name);
265-
ipu_fw_isys_close(av->isys);
266-
if (av->isys->fwcom) {
267-
av->isys->reset_needed = true;
268-
ret = -EIO;
269-
}
270-
}
271-
272-
mutex_unlock(&av->isys->mutex);
273-
274190
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
275191
ipu_pipeline_pm_use(&av->vdev.entity, 0);
276192
#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
277193
v4l2_pipeline_pm_use(&av->vdev.entity, 0);
278194
#else
279195
v4l2_pipeline_pm_put(&av->vdev.entity);
280196
#endif
281-
282-
if (av->isys->reset_needed)
283-
pm_runtime_put_sync(&av->isys->adev->dev);
284-
else
285-
pm_runtime_put(&av->isys->adev->dev);
286-
287197
dev_dbg(&av->isys->adev->dev, "release: %s: exit\n",
288198
av->vdev.name);
289199
return ret;

0 commit comments

Comments
 (0)