Commit 79fb229b authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-next-2023-09-27' of git://anongit.freedesktop.org/drm/drm-misc into drm-next



drm-misc-next for v6.7-rc1:

UAPI Changes:
- drm_file owner is now updated during use, in the case of a drm fd
  opened by the display server for a client, the correct owner is
  displayed.
- Qaic gains support for the QAIC_DETACH_SLICE_BO ioctl to allow bo
  recycling.

Cross-subsystem Changes:
- Disable boot logo for au1200fb, mmpfb and unexport logo helpers.
  Only fbcon should manage display of logo.
- Update freescale in MAINTAINERS.
- Add some bridge files to bridge in MAINTAINERS.
- Update gma500 driver repo in MAINTAINERS to point to drm-misc.

Core Changes:
- Move size computations to drm buddy allocator.
- Make drm_atomic_helper_shutdown(NULL) a nop.
- Assorted small fixes in drm_debugfs, DP-MST payload addition error handling.
- Fix DRM_BRIDGE_ATTACH_NO_CONNECTOR handling.
- Handle bad (h/v)sync_end in EDID by clipping to htotal.
- Build GPUVM as a module.

Driver Changes:
- Simple drivers don't need to cache prepared result.
- Call drm_atomic_helper_shutdown() in shutdown/unbind for a whole lot
  more drm drivers.
- Assorted small fixes in amdgpu, ssd130x, bridge/it6621, accel/qaic,
  nouveau, tc358768.
- Add NV12 for komeda writeback.
- Add arbitration lost event to synopsis/dw-hdmi-cec.
- Speed up s/r in nouveau by not restoring some big bo's.
- Assorted nouveau display rework in preparation for GSP-RM,
  especially related to how the modeset sequence works and
  the DP sequence in relation to link training.
- Update anx7816 panel.
- Support NVSYNC and NHSYNC in tegra.
- Allow multiple power domains in simple driver.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/f1fae5eb-25b8-192a-9a53-215e1184ce81@linux.intel.com
parents f107ff76 78f54469
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -123,6 +123,16 @@ DRM_IOCTL_QAIC_PART_DEV
  AIC100 device and can be used for limiting a process to some subset of
  resources.

DRM_IOCTL_QAIC_DETACH_SLICE_BO
  This IOCTL allows userspace to remove the slicing information from a BO that
  was originally provided by a call to DRM_IOCTL_QAIC_ATTACH_SLICE_BO. This
  is the inverse of DRM_IOCTL_QAIC_ATTACH_SLICE_BO. The BO must be idle for
  DRM_IOCTL_QAIC_DETACH_SLICE_BO to be called. After a successful detach slice
  operation the BO may have new slicing information attached with a new call
  to DRM_IOCTL_QAIC_ATTACH_SLICE_BO. After detach slice, the BO cannot be
  executed until after a new attach slice operation. Combining attach slice
  and detach slice calls allows userspace to use a BO with multiple workloads.

Userspace Client Isolation
==========================

+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ properties:
      - analogix,anx7808
      - analogix,anx7812
      - analogix,anx7814
      - analogix,anx7816
      - analogix,anx7818

  reg:
+6 −2
Original line number Diff line number Diff line
@@ -6908,7 +6908,9 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
F:	Documentation/devicetree/bindings/display/bridge/
F:	drivers/gpu/drm/bridge/
F:	drivers/gpu/drm/drm_bridge.c
F:	drivers/gpu/drm/drm_bridge_connector.c
F:	include/drm/drm_bridge.h
F:	include/drm/drm_bridge_connector.h
DRM DRIVERS FOR EXYNOS
M:	Inki Dae <inki.dae@samsung.com>
@@ -6932,10 +6934,12 @@ F: Documentation/devicetree/bindings/display/fsl,dcu.txt
F:	Documentation/devicetree/bindings/display/fsl,tcon.txt
F:	drivers/gpu/drm/fsl-dcu/
DRM DRIVERS FOR FREESCALE IMX
DRM DRIVERS FOR FREESCALE IMX 5/6
M:	Philipp Zabel <p.zabel@pengutronix.de>
L:	dri-devel@lists.freedesktop.org
S:	Maintained
T:	git git://anongit.freedesktop.org/drm/drm-misc
T:	git git://git.pengutronix.de/git/pza/linux
F:	Documentation/devicetree/bindings/display/imx/
F:	drivers/gpu/drm/imx/ipuv3/
F:	drivers/gpu/ipu-v3/
@@ -6954,7 +6958,7 @@ DRM DRIVERS FOR GMA500 (Poulsbo, Moorestown and derivative chipsets)
M:	Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
L:	dri-devel@lists.freedesktop.org
S:	Maintained
T:	git git://github.com/patjak/drm-gma500
T:	git git://anongit.freedesktop.org/drm/drm-misc
F:	drivers/gpu/drm/gma500/
DRM DRIVERS FOR HISILICON
+8 −5
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@
#define QAIC_DBC_OFF(i)		((i) * QAIC_DBC_SIZE + QAIC_DBC_BASE)

#define to_qaic_bo(obj) container_of(obj, struct qaic_bo, base)
#define to_qaic_drm_device(dev) container_of(dev, struct qaic_drm_device, drm)
#define to_drm(qddev) (&(qddev)->drm)
#define to_accel_kdev(qddev) (to_drm(qddev)->accel->kdev) /* Return Linux device of accel node */

extern bool datapath_polling;

@@ -137,6 +140,8 @@ struct qaic_device {
};

struct qaic_drm_device {
	/* The drm device struct of this drm device */
	struct drm_device	drm;
	/* Pointer to the root device struct driven by this driver */
	struct qaic_device	*qdev;
	/*
@@ -146,8 +151,6 @@ struct qaic_drm_device {
	 * device is the actual physical device
	 */
	s32			partition_id;
	/* Pointer to the drm device struct of this drm device */
	struct drm_device	*ddev;
	/* Head in list of users who have opened this drm device */
	struct list_head	users;
	/* Synchronizes access to users list */
@@ -158,8 +161,6 @@ struct qaic_bo {
	struct drm_gem_object	base;
	/* Scatter/gather table for allocate/imported BO */
	struct sg_table		*sgt;
	/* BO size requested by user. GEM object might be bigger in size. */
	u64			size;
	/* Head in list of slices of this BO */
	struct list_head	slices;
	/* Total nents, for all slices of this BO */
@@ -221,7 +222,8 @@ struct qaic_bo {
		 */
		u32		queue_level_before;
	} perf_stats;

	/* Synchronizes BO operations */
	struct mutex		lock;
};

struct bo_slice {
@@ -277,6 +279,7 @@ int qaic_execute_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *f
int qaic_partial_execute_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
int qaic_wait_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
int qaic_perf_stats_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
int qaic_detach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
void irq_polling_work(struct work_struct *work);

#endif /* _QAIC_H_ */
+143 −44
Original line number Diff line number Diff line
@@ -154,6 +154,7 @@ static void free_slice(struct kref *kref)
{
	struct bo_slice *slice = container_of(kref, struct bo_slice, ref_count);

	slice->bo->total_slice_nents -= slice->nents;
	list_del(&slice->slice);
	drm_gem_object_put(&slice->bo->base);
	sg_free_table(slice->sgt);
@@ -579,7 +580,7 @@ static void qaic_gem_print_info(struct drm_printer *p, unsigned int indent,
{
	struct qaic_bo *bo = to_qaic_bo(obj);

	drm_printf_indent(p, indent, "user requested size=%llu\n", bo->size);
	drm_printf_indent(p, indent, "BO DMA direction %d\n", bo->dir);
}

static const struct vm_operations_struct drm_vm_ops = {
@@ -623,6 +624,7 @@ static void qaic_free_object(struct drm_gem_object *obj)
		qaic_free_sgt(bo->sgt);
	}

	mutex_destroy(&bo->lock);
	drm_gem_object_release(obj);
	kfree(bo);
}
@@ -634,6 +636,19 @@ static const struct drm_gem_object_funcs qaic_gem_funcs = {
	.vm_ops = &drm_vm_ops,
};

static void qaic_init_bo(struct qaic_bo *bo, bool reinit)
{
	if (reinit) {
		bo->sliced = false;
		reinit_completion(&bo->xfer_done);
	} else {
		mutex_init(&bo->lock);
		init_completion(&bo->xfer_done);
	}
	complete_all(&bo->xfer_done);
	INIT_LIST_HEAD(&bo->slices);
}

static struct qaic_bo *qaic_alloc_init_bo(void)
{
	struct qaic_bo *bo;
@@ -642,9 +657,7 @@ static struct qaic_bo *qaic_alloc_init_bo(void)
	if (!bo)
		return ERR_PTR(-ENOMEM);

	INIT_LIST_HEAD(&bo->slices);
	init_completion(&bo->xfer_done);
	complete_all(&bo->xfer_done);
	qaic_init_bo(bo, false);

	return bo;
}
@@ -695,8 +708,6 @@ int qaic_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
	if (ret)
		goto free_bo;

	bo->size = args->size;

	ret = drm_gem_handle_create(file_priv, obj, &args->handle);
	if (ret)
		goto free_sgt;
@@ -828,7 +839,6 @@ static int qaic_prepare_import_bo(struct qaic_bo *bo, struct qaic_attach_slice_h
	}

	bo->sgt = sgt;
	bo->size = hdr->size;

	return 0;
}
@@ -838,7 +848,7 @@ static int qaic_prepare_export_bo(struct qaic_device *qdev, struct qaic_bo *bo,
{
	int ret;

	if (bo->size != hdr->size)
	if (bo->base.size < hdr->size)
		return -EINVAL;

	ret = dma_map_sgtable(&qdev->pdev->dev, bo->sgt, hdr->dir, 0);
@@ -857,9 +867,9 @@ static int qaic_prepare_bo(struct qaic_device *qdev, struct qaic_bo *bo,
		ret = qaic_prepare_import_bo(bo, hdr);
	else
		ret = qaic_prepare_export_bo(qdev, bo, hdr);

	if (ret == 0)
	bo->dir = hdr->dir;
	bo->dbc = &qdev->dbc[hdr->dbc_id];
	bo->nr_slice = hdr->count;

	return ret;
}
@@ -868,7 +878,6 @@ static void qaic_unprepare_import_bo(struct qaic_bo *bo)
{
	dma_buf_unmap_attachment(bo->base.import_attach, bo->sgt, bo->dir);
	bo->sgt = NULL;
	bo->size = 0;
}

static void qaic_unprepare_export_bo(struct qaic_device *qdev, struct qaic_bo *bo)
@@ -884,6 +893,8 @@ static void qaic_unprepare_bo(struct qaic_device *qdev, struct qaic_bo *bo)
		qaic_unprepare_export_bo(qdev, bo);

	bo->dir = 0;
	bo->dbc = NULL;
	bo->nr_slice = 0;
}

static void qaic_free_slices_bo(struct qaic_bo *bo)
@@ -892,6 +903,9 @@ static void qaic_free_slices_bo(struct qaic_bo *bo)

	list_for_each_entry_safe(slice, temp, &bo->slices, slice)
		kref_put(&slice->ref_count, free_slice);
	if (WARN_ON_ONCE(bo->total_slice_nents != 0))
		bo->total_slice_nents = 0;
	bo->nr_slice = 0;
}

static int qaic_attach_slicing_bo(struct qaic_device *qdev, struct qaic_bo *bo,
@@ -908,15 +922,11 @@ static int qaic_attach_slicing_bo(struct qaic_device *qdev, struct qaic_bo *bo,
		}
	}

	if (bo->total_slice_nents > qdev->dbc[hdr->dbc_id].nelem) {
	if (bo->total_slice_nents > bo->dbc->nelem) {
		qaic_free_slices_bo(bo);
		return -ENOSPC;
	}

	bo->sliced = true;
	bo->nr_slice = hdr->count;
	list_add_tail(&bo->bo_list, &qdev->dbc[hdr->dbc_id].bo_lists);

	return 0;
}

@@ -994,10 +1004,13 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
	}

	bo = to_qaic_bo(obj);
	ret = mutex_lock_interruptible(&bo->lock);
	if (ret)
		goto put_bo;

	if (bo->sliced) {
		ret = -EINVAL;
		goto put_bo;
		goto unlock_bo;
	}

	dbc = &qdev->dbc[args->hdr.dbc_id];
@@ -1018,9 +1031,10 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
	if (args->hdr.dir == DMA_TO_DEVICE)
		dma_sync_sgtable_for_cpu(&qdev->pdev->dev, bo->sgt, args->hdr.dir);

	bo->dbc = dbc;
	bo->sliced = true;
	list_add_tail(&bo->bo_list, &bo->dbc->bo_lists);
	srcu_read_unlock(&dbc->ch_lock, rcu_id);
	drm_gem_object_put(obj);
	mutex_unlock(&bo->lock);
	kfree(slice_ent);
	srcu_read_unlock(&qdev->dev_lock, qdev_rcu_id);
	srcu_read_unlock(&usr->qddev_lock, usr_rcu_id);
@@ -1031,6 +1045,8 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
	qaic_unprepare_bo(qdev, bo);
unlock_ch_srcu:
	srcu_read_unlock(&dbc->ch_lock, rcu_id);
unlock_bo:
	mutex_unlock(&bo->lock);
put_bo:
	drm_gem_object_put(obj);
free_slice_ent:
@@ -1185,15 +1201,18 @@ static int send_bo_list_to_device(struct qaic_device *qdev, struct drm_file *fil
		}

		bo = to_qaic_bo(obj);
		ret = mutex_lock_interruptible(&bo->lock);
		if (ret)
			goto failed_to_send_bo;

		if (!bo->sliced) {
			ret = -EINVAL;
			goto failed_to_send_bo;
			goto unlock_bo;
		}

		if (is_partial && pexec[i].resize > bo->size) {
		if (is_partial && pexec[i].resize > bo->base.size) {
			ret = -EINVAL;
			goto failed_to_send_bo;
			goto unlock_bo;
		}

		spin_lock_irqsave(&dbc->xfer_lock, flags);
@@ -1202,7 +1221,7 @@ static int send_bo_list_to_device(struct qaic_device *qdev, struct drm_file *fil
		if (queued) {
			spin_unlock_irqrestore(&dbc->xfer_lock, flags);
			ret = -EINVAL;
			goto failed_to_send_bo;
			goto unlock_bo;
		}

		bo->req_id = dbc->next_req_id++;
@@ -1233,17 +1252,20 @@ static int send_bo_list_to_device(struct qaic_device *qdev, struct drm_file *fil
			if (ret) {
				bo->queued = false;
				spin_unlock_irqrestore(&dbc->xfer_lock, flags);
				goto failed_to_send_bo;
				goto unlock_bo;
			}
		}
		reinit_completion(&bo->xfer_done);
		list_add_tail(&bo->xfer_list, &dbc->xfer_list);
		spin_unlock_irqrestore(&dbc->xfer_lock, flags);
		dma_sync_sgtable_for_device(&qdev->pdev->dev, bo->sgt, bo->dir);
		mutex_unlock(&bo->lock);
	}

	return 0;

unlock_bo:
	mutex_unlock(&bo->lock);
failed_to_send_bo:
	if (likely(obj))
		drm_gem_object_put(obj);
@@ -1799,6 +1821,91 @@ int qaic_perf_stats_bo_ioctl(struct drm_device *dev, void *data, struct drm_file
	return ret;
}

static void detach_slice_bo(struct qaic_device *qdev, struct qaic_bo *bo)
{
	qaic_free_slices_bo(bo);
	qaic_unprepare_bo(qdev, bo);
	qaic_init_bo(bo, true);
	list_del(&bo->bo_list);
	drm_gem_object_put(&bo->base);
}

int qaic_detach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
	struct qaic_detach_slice *args = data;
	int rcu_id, usr_rcu_id, qdev_rcu_id;
	struct dma_bridge_chan *dbc;
	struct drm_gem_object *obj;
	struct qaic_device *qdev;
	struct qaic_user *usr;
	unsigned long flags;
	struct qaic_bo *bo;
	int ret;

	if (args->pad != 0)
		return -EINVAL;

	usr = file_priv->driver_priv;
	usr_rcu_id = srcu_read_lock(&usr->qddev_lock);
	if (!usr->qddev) {
		ret = -ENODEV;
		goto unlock_usr_srcu;
	}

	qdev = usr->qddev->qdev;
	qdev_rcu_id = srcu_read_lock(&qdev->dev_lock);
	if (qdev->in_reset) {
		ret = -ENODEV;
		goto unlock_dev_srcu;
	}

	obj = drm_gem_object_lookup(file_priv, args->handle);
	if (!obj) {
		ret = -ENOENT;
		goto unlock_dev_srcu;
	}

	bo = to_qaic_bo(obj);
	ret = mutex_lock_interruptible(&bo->lock);
	if (ret)
		goto put_bo;

	if (!bo->sliced) {
		ret = -EINVAL;
		goto unlock_bo;
	}

	dbc = bo->dbc;
	rcu_id = srcu_read_lock(&dbc->ch_lock);
	if (dbc->usr != usr) {
		ret = -EINVAL;
		goto unlock_ch_srcu;
	}

	/* Check if BO is committed to H/W for DMA */
	spin_lock_irqsave(&dbc->xfer_lock, flags);
	if (bo->queued) {
		spin_unlock_irqrestore(&dbc->xfer_lock, flags);
		ret = -EBUSY;
		goto unlock_ch_srcu;
	}
	spin_unlock_irqrestore(&dbc->xfer_lock, flags);

	detach_slice_bo(qdev, bo);

unlock_ch_srcu:
	srcu_read_unlock(&dbc->ch_lock, rcu_id);
unlock_bo:
	mutex_unlock(&bo->lock);
put_bo:
	drm_gem_object_put(obj);
unlock_dev_srcu:
	srcu_read_unlock(&qdev->dev_lock, qdev_rcu_id);
unlock_usr_srcu:
	srcu_read_unlock(&usr->qddev_lock, usr_rcu_id);
	return ret;
}

static void empty_xfer_list(struct qaic_device *qdev, struct dma_bridge_chan *dbc)
{
	unsigned long flags;
@@ -1810,6 +1917,12 @@ static void empty_xfer_list(struct qaic_device *qdev, struct dma_bridge_chan *db
		bo->queued = false;
		list_del(&bo->xfer_list);
		spin_unlock_irqrestore(&dbc->xfer_lock, flags);
		bo->nr_slice_xfer_done = 0;
		bo->req_id = 0;
		bo->perf_stats.req_received_ts = 0;
		bo->perf_stats.req_submit_ts = 0;
		bo->perf_stats.req_processed_ts = 0;
		bo->perf_stats.queue_level_before = 0;
		dma_sync_sgtable_for_cpu(&qdev->pdev->dev, bo->sgt, bo->dir);
		complete_all(&bo->xfer_done);
		drm_gem_object_put(&bo->base);
@@ -1857,7 +1970,6 @@ void wakeup_dbc(struct qaic_device *qdev, u32 dbc_id)

void release_dbc(struct qaic_device *qdev, u32 dbc_id)
{
	struct bo_slice *slice, *slice_temp;
	struct qaic_bo *bo, *bo_temp;
	struct dma_bridge_chan *dbc;

@@ -1875,24 +1987,11 @@ void release_dbc(struct qaic_device *qdev, u32 dbc_id)
	dbc->usr = NULL;

	list_for_each_entry_safe(bo, bo_temp, &dbc->bo_lists, bo_list) {
		list_for_each_entry_safe(slice, slice_temp, &bo->slices, slice)
			kref_put(&slice->ref_count, free_slice);
		bo->sliced = false;
		INIT_LIST_HEAD(&bo->slices);
		bo->total_slice_nents = 0;
		bo->dir = 0;
		bo->dbc = NULL;
		bo->nr_slice = 0;
		bo->nr_slice_xfer_done = 0;
		bo->queued = false;
		bo->req_id = 0;
		init_completion(&bo->xfer_done);
		complete_all(&bo->xfer_done);
		list_del(&bo->bo_list);
		bo->perf_stats.req_received_ts = 0;
		bo->perf_stats.req_submit_ts = 0;
		bo->perf_stats.req_processed_ts = 0;
		bo->perf_stats.queue_level_before = 0;
		drm_gem_object_get(&bo->base);
		mutex_lock(&bo->lock);
		detach_slice_bo(qdev, bo);
		mutex_unlock(&bo->lock);
		drm_gem_object_put(&bo->base);
	}

	dbc->in_use = false;
Loading