diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp
index 8bbef174..1be2cbcd 100644
--- a/src/libcamera/pipeline/ipu3/cio2.cpp
+++ b/src/libcamera/pipeline/ipu3/cio2.cpp
@@ -302,6 +302,8 @@ void CIO2Device::tryReturnBuffer(FrameBuffer *buffer)
 			break;
 		}
 	}
+
+	bufferAvailable.emit();
 }
 
 void CIO2Device::freeBuffers()
diff --git a/src/libcamera/pipeline/ipu3/cio2.h b/src/libcamera/pipeline/ipu3/cio2.h
index 5ecc4f47..d8d4a181 100644
--- a/src/libcamera/pipeline/ipu3/cio2.h
+++ b/src/libcamera/pipeline/ipu3/cio2.h
@@ -56,6 +56,8 @@ public:
 	Signal<FrameBuffer *> &bufferReady() { return output_->bufferReady; }
 	Signal<uint32_t> &frameStart() { return csi2_->frameStart; }
 
+	Signal<> bufferAvailable;
+
 private:
 	void freeBuffers();
 
diff --git a/src/libcamera/pipeline/ipu3/frames.cpp b/src/libcamera/pipeline/ipu3/frames.cpp
index 29d9aafc..d9a2249b 100644
--- a/src/libcamera/pipeline/ipu3/frames.cpp
+++ b/src/libcamera/pipeline/ipu3/frames.cpp
@@ -103,6 +103,8 @@ bool IPU3Frames::tryComplete(IPU3Frames::Info *info)
 
 	remove(info);
 
+	bufferAvailable.emit();
+
 	return true;
 }
 
diff --git a/src/libcamera/pipeline/ipu3/frames.h b/src/libcamera/pipeline/ipu3/frames.h
index 4acdf48e..59e64e81 100644
--- a/src/libcamera/pipeline/ipu3/frames.h
+++ b/src/libcamera/pipeline/ipu3/frames.h
@@ -12,6 +12,8 @@
 #include <queue>
 #include <vector>
 
+#include <libcamera/signal.h>
+
 namespace libcamera {
 
 class FrameBuffer;
@@ -49,6 +51,8 @@ public:
 	Info *find(unsigned int id);
 	Info *find(FrameBuffer *buffer);
 
+	Signal<> bufferAvailable;
+
 private:
 	std::queue<FrameBuffer *> availableParamBuffers_;
 	std::queue<FrameBuffer *> availableStatBuffers_;
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 6961d498..8ae47c6d 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -701,6 +701,8 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera)
 	data->ipa_->mapBuffers(ipaBuffers_);
 
 	data->frameInfos_.init(imgu->paramBuffers_, imgu->statBuffers_);
+	data->frameInfos_.bufferAvailable.connect(
+		data, &IPU3CameraData::queuePendingRequests);
 
 	return 0;
 }
@@ -1147,6 +1149,8 @@ int PipelineHandlerIPU3::registerCameras()
 		 */
 		data->cio2_.bufferReady().connect(data.get(),
 					&IPU3CameraData::cio2BufferReady);
+		data->cio2_.bufferAvailable.connect(
+			data.get(), &IPU3CameraData::queuePendingRequests);
 		data->imgu_->input_->bufferReady.connect(&data->cio2_,
 					&CIO2Device::tryReturnBuffer);
 		data->imgu_->output_->bufferReady.connect(data.get(),
