diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
index b5e7b919f241..4f1efe616698 100644
--- a/drivers/gpu/drm/panthor/panthor_drv.c
+++ b/drivers/gpu/drm/panthor/panthor_drv.c
@@ -1372,6 +1372,7 @@ static void panthor_debugfs_init(struct drm_minor *minor)
 /*
  * PanCSF driver version:
  * - 1.0 - initial interface
+ * - 1.1 - add user submission path
  */
 static const struct drm_driver panthor_drm_driver = {
 	.driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ |
@@ -1385,7 +1386,7 @@ static const struct drm_driver panthor_drm_driver = {
 	.desc = "Panthor DRM driver",
 	.date = "20230801",
 	.major = 1,
-	.minor = 0,
+	.minor = 1,
 
 	.gem_create_object = panthor_gem_create_object,
 	.gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table,
diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
index 463bcd3cf00f..b2cf053b3601 100644
--- a/drivers/gpu/drm/panthor/panthor_sched.c
+++ b/drivers/gpu/drm/panthor/panthor_sched.c
@@ -3089,7 +3089,7 @@ int panthor_group_create(struct panthor_file *pfile,
 	u32 gid, i, suspend_size;
 	int ret;
 
-	if (group_args->pad)
+	if (group_args->flags & ~DRM_PANTHOR_GROUP_CREATE_USER_SUBMIT)
 		return -EINVAL;
 
 	if (group_args->priority > PANTHOR_CSG_PRIORITY_HIGH)
diff --git a/include/uapi/drm/panthor_drm.h b/include/uapi/drm/panthor_drm.h
index 926b1deb1116..1a6a3877e5b3 100644
--- a/include/uapi/drm/panthor_drm.h
+++ b/include/uapi/drm/panthor_drm.h
@@ -127,6 +127,21 @@ enum drm_panthor_ioctl_id {
 
 	/** @DRM_PANTHOR_TILER_HEAP_DESTROY: Destroy a tiler heap. */
 	DRM_PANTHOR_TILER_HEAP_DESTROY,
+
+	/** @DRM_PANTHOR_GROUP_KICK: Re-evaluate group for scheduling. */
+	DRM_PANTHOR_GROUP_KICK,
+
+	/** @DRM_PANTHOR_XGS_QUEUE_CREATE: Create a cross-group sync queue. */
+	DRM_PANTHOR_XGS_QUEUE_CREATE,
+
+	/** @DRM_PANTHOR_XGS_QUEUE_DESTROY: Destroy a cross-group sync queue. */
+	DRM_PANTHOR_XGS_QUEUE_DESTROY,
+
+	/** @DRM_PANTHOR_XGS_QUEUE_SUBMIT: Submit a cross-group sync op to an XGS queue. */
+	DRM_PANTHOR_XGS_QUEUE_SUBMIT,
+
+	/** @DRM_PANTHOR_SYNC_UPDATE: Notify kernel that a HW syncobj has been updated. */
+	DRM_PANTHOR_SYNC_UPDATE,
 };
 
 /**
@@ -170,6 +185,16 @@ enum drm_panthor_ioctl_id {
 	DRM_IOCTL_PANTHOR(WR, TILER_HEAP_CREATE, tiler_heap_create)
 #define DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY \
 	DRM_IOCTL_PANTHOR(WR, TILER_HEAP_DESTROY, tiler_heap_destroy)
+#define DRM_IOCTL_PANTHOR_GROUP_KICK \
+	DRM_IOCTL_PANTHOR(WR, GROUP_KICK, group_kick)
+#define DRM_IOCTL_PANTHOR_XGS_QUEUE_CREATE \
+	DRM_IOCTL_PANTHOR(WR, XGS_QUEUE_CREATE, xgs_queue_create)
+#define DRM_IOCTL_PANTHOR_XGS_QUEUE_DESTROY \
+	DRM_IOCTL_PANTHOR(WR, XGS_QUEUE_DESTROY, xgs_queue_destroy)
+#define DRM_IOCTL_PANTHOR_XGS_QUEUE_SUBMIT \
+	DRM_IOCTL_PANTHOR(WR, XGS_QUEUE_SUBMIT, xgs_queue_submit)
+#define DRM_IOCTL_PANTHOR_SYNC_UPDATE \
+	DRM_IOCTL_PANTHOR(WR, SYNC_UPDATE, sync_update)
 
 /**
  * DOC: IOCTL arguments
@@ -680,6 +705,40 @@ struct drm_panthor_queue_create {
 
 	/** @ringbuf_size: Size of the ring buffer to allocate to this queue. */
 	__u32 ringbuf_size;
+
+	/**
+	 * @ringbuf_offset: file offset to map the ring buffer
+	 *
+	 * Returns a file offset which can be used to map the queues ring buffer.
+	 * The size of this buffer is as requested with @ringbuf_size
+	 *
+	 * Only valid if DRM_PANTHOR_GROUP_CREATE_USER_SUBMIT is set in
+	 * the respective drm_panthor_group_create::flags, 0 otherwise.
+	 */
+	__u64 ringbuf_offset;
+
+	/**
+	 * @user_io_offset: file offset to map user input/output pages.
+	 *
+	 * Returns a file offset which can be used to map the user input page
+	 * and the user output page (two consecutive pages).
+	 *
+	 * Only valid if DRM_PANTHOR_GROUP_CREATE_USER_SUBMIT is set in
+	 * the respective drm_panthor_group_create::flags, 0 otherwise.
+	 */
+	__u64 user_io_offset;
+
+	/**
+	 * @doorbell_offset: file offset to map doorbell page
+	 *
+	 * Returns a file offset which can be used to map the queues HW doorbell page.
+	 * Note: multiple queues can share same HW doorbell page, and this offset
+	 * will be the same in this case.
+	 *
+	 * Only valid if DRM_PANTHOR_GROUP_CREATE_USER_SUBMIT is set in
+	 * the respective drm_panthor_group_create::flags, 0 otherwise.
+	 */
+	__u64 doorbell_offset;
 };
 
 /**
@@ -696,6 +755,16 @@ enum drm_panthor_group_priority {
 	PANTHOR_GROUP_PRIORITY_HIGH,
 };
 
+/**
+ * enum drm_panthor_group_create_flags - Flags for group creation
+ */
+enum drm_panthor_group_create_flags {
+	/**
+	 * @DRM_PANTHOR_GROUP_CREATE_USER_SUBMIT: Enable user submission
+	 */
+	DRM_PANTHOR_GROUP_CREATE_USER_SUBMIT = 1 << 0,
+};
+
 /**
  * struct drm_panthor_group_create - Arguments passed to DRM_IOCTL_PANTHOR_GROUP_CREATE
  */
@@ -730,8 +799,8 @@ struct drm_panthor_group_create {
 	/** @priority: Group priority (see enum drm_panthor_group_priority). */
 	__u8 priority;
 
-	/** @pad: Padding field, MBZ. */
-	__u32 pad;
+	/** @flags: Combination of drm_panthor_group_create_flags flags */
+	__u32 flags;
 
 	/**
 	 * @compute_core_mask: Mask encoding cores that can be used for compute jobs.
@@ -772,6 +841,23 @@ struct drm_panthor_group_create {
 	 * destroying a group.
 	 */
 	__u32 group_handle;
+
+	/**
+	 * @eventfd_sync_update: eventfd to increment for group SYNC_UPDATE events
+	 *
+	 * Only valid when DRM_PANTHOR_GROUP_CREATE_USER_SUBMIT is set.
+	 * Can be set to -1 if UMD don't want to receive these events.
+	 */
+	__s32 eventfd_sync_update;
+
+	/**
+	 * @eventfd_group_state: eventfd to increment when group state has been changed
+	 *
+	 * Only valid when DRM_PANTHOR_GROUP_CREATE_USER_SUBMIT is set.
+	 * Can be set to -1 if UMD don't want to receive these events.
+	 * DRM_IOCTL_PANTHOR_GROUP_GET_STATE should be used to retrieve the new group state.
+	 */
+	__s32 eventfd_group_state;
 };
 
 /**
@@ -955,6 +1041,159 @@ struct drm_panthor_tiler_heap_destroy {
 	__u32 pad;
 };
 
+/**
+ * @struct drm_panthor_group_kick - arguments to DRM_IOCTL_PANTHOR_GROUP_KICK
+ */
+struct drm_panthor_group_kick {
+	/** @handle: handle to group */
+	__u32 handle;
+
+	/** @queue_mask: mask with queues to kick */
+	__u32 queue_mask;
+};
+
+/**
+ * struct drm_panthor_xgs_queue_create - Arguments passed to DRM_IOCTL_PANTHOR_XGS_QUEUE_CREATE
+ */
+struct drm_panthor_xgs_queue_create {
+	/** @vm_id: VM id to associate this XGS queue with */
+	__u32 vm_id;
+
+	/**
+	 * @eventfd_sync_update: eventfd to increment when a XGS object has been set
+	 *
+	 * Can be set to -1 if UMD don't want to receive these events.
+	 */
+	__s32 eventfd_sync_update;
+
+	/** @handle: Returned handle to the XGS queue created */
+	__u32 handle;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * struct drm_panthor_xgs_queue_destroy - Arguments passed to DRM_IOCTL_PANTHOR_XGS_QUEUE_DESTROY
+ */
+struct drm_panthor_xgs_queue_destroy {
+	/** @handle: handle to XGS queue to destroy */
+	__u32 handle;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_panthor_xgs_ops - Types of XGS operations
+ */
+enum drm_panthor_xgs_ops {
+	/** @DRM_PANTHOR_XGS_OP_WAIT_LE: Wait for condition to be less-or-equal specified value */
+	DRM_PANTHOR_XGS_OP_WAIT_LE = 0,
+
+	/** @DRM_PANTHOR_XGS_OP_WAIT_GT: Wait for condition to be greater than specified value */
+	DRM_PANTHOR_XGS_OP_WAIT_GT,
+
+	/** @DRM_PANTHOR_XGS_OP_SIGNAL_SET: Set XGS object to specified value */
+	DRM_PANTHOR_XGS_OP_SIGNAL_SET,
+
+	/** @DRM_PANTHOR_XGS_OP_SIGNAL_ADD: Add specified value to XGS object */
+	DRM_PANTHOR_XGS_OP_SIGNAL_ADD
+};
+
+/**
+ * enum drm_panthor_xgs_op_formnat - Format of XGS object
+ */
+enum drm_panthor_xgs_op_format {
+	/** @DRM_PANTHOR_XGS_OP_FORMAT_U32: XGS object is of 32-bit format */
+	DRM_PANTHOR_XGS_OP_FORMAT_U32 = 0,
+
+	/** @DRM_PANTHOR_XGS_OP_FORMAT_U64: XGS object is of 64-bit format */
+	DRM_PANTHOR_XGS_OP_FORMAT_U64
+};
+
+/**
+ * enum drm_panthor_xgs_op_flags - Flags for a XGS operation
+ */
+enum drm_panthor_xgs_op_flags {
+	/**
+	 * @DRM_PANTHOR_XGS_OP_INHERIT_ERROR_WAIT: Propagate XGS wait errors to XGS queue
+	 *
+	 * WAIT operations for a XGS which is signaled with error will set this XGS queue
+	 * in an error state. This error state is cleared on next XGS submit with either the
+	 * @DRM_PANTHOR_XGS_QUEUE_SUBMIT_ERROR_BARRIER_PRE or
+	 * DRM_PANTHOR_XGS_QUEUE_SUBMIT_ERROR_BARRIER_POST flag set.
+	 *
+	 * Note: Errors during SIGNAL operations will always set the XGS queue in an error state
+	 */
+	DRM_PANTHOR_XGS_OP_INHERIT_ERROR_WAIT = 1 << 0
+};
+
+/**
+ * struct drm_panthor_xgs_op - XGS operation
+ */
+struct drm_panthor_xgs_op {
+	/** @addr: GPU address of XGS object */
+	__u64 addr;
+
+	/** @value: value to WAIT for or SET/ADD */
+	__u64 value;
+
+	/** @op: operation from enum drm_panthor_xgs_ops */
+	__u8 op;
+
+	/** @format: format from enum drm_panthor_xgs_op_format */
+	__u8 format;
+
+	/** @flags: flags from enum drm_panthor_xgs_op_flags */
+	__u16 flags;
+
+	/** @pad: MBZ */
+	__u32 pad;
+};
+
+/**
+ * enum drm_panthor_xgs_queue_submit_flags - Flags for XGS queue submission
+ */
+enum drm_panthor_xgs_queue_submit_flags {
+	/** @DRM_PANTHOR_XGS_QUEUE_SUBMIT_ERROR_BARRIER_PRE: Error barrier pre operation
+	 *
+	 * Clear queue error state before processing the XGS operations
+	 */
+	DRM_PANTHOR_XGS_QUEUE_SUBMIT_ERROR_BARRIER_PRE = 1 << 0,
+
+	/** @DRM_PANTHOR_XGS_QUEUE_SUBMIT_ERROR_BARRIER_POST: Error barrier post operation
+	 *
+	 * Clear queue error state after processing the XGS operations
+	 */
+	DRM_PANTHOR_XGS_QUEUE_SUBMIT_ERROR_BARRIER_POST = 1 << 1
+};
+
+/**
+ * struct drm_panthor_xgs_queue_submit - Arguments passed to DRM_IOCTL_PANTHOR_XGS_QUEUE_SUBMIT
+ */
+struct drm_panthor_xgs_queue_submit {
+	/** @handle: XGS queue handle to submit work to */
+	__u32 handle;
+
+	/** @flags: flags from enum drm_panthor_xgs_queue_submit_flags */
+	__u32 flags;
+
+	/** @ops: Array of struct drm_panthor_xgs_op sync operations */
+	struct drm_panthor_obj_array ops;
+
+	/** @syncs: Array of struct drm_panthor_sync_op sync operations */
+	struct drm_panthor_obj_array syncs;
+};
+
+/**
+ * struct drm_panthor_sync_update - Arguments passed to DRM_IOCTL_PANTHOR_SYNC_UPDATE
+ */
+struct drm_panthor_sync_update {
+	/** @pad: MBZ */
+	__u64 pad;
+};
+
 #if defined(__cplusplus)
 }
 #endif
