Commit 797d72ce authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-next-2021-10-06' of git://anongit.freedesktop.org/drm/drm-misc into drm-next



drm-misc-next for v5.16:

UAPI Changes:
- Allow empty drm leases for creating separate GEM namespaces.

Cross-subsystem Changes:
- Slightly rework dma_buf_poll.
- Add dma_resv_for_each_fence_unlocked to iterate, and use it inside
  the lockless dma-resv functions.

Core Changes:
- Allow devm_drm_of_get_bridge to build without CONFIG_OF for compile testing.
- Add more DP2 headers.
- fix CONFIG_FB dependency in fb_helper.
- Add DRM_FORMAT_R8 to drm_format_info, and helpers for RGB332 and RGB888.
- Fix crash on a 0 or invalid EDID.

Driver Changes:
- Apply and revert DRM_MODESET_LOCK_ALL_BEGIN.
- Add mode_valid to ti-sn65dsi86 bridge.
- Support multiple syncobjs in v3d.
- Add R8, RGB332 and RGB888 pixel formats to GUD.
- Use devm_add_action_or_reset in dw-hdmi-cec.

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

# gpg: Signature made Wed 06 Oct 2021 20:48:12 AEST
# gpg:                using RSA key B97BD6A80CAC4981091AE547FE558C72A67013C3
# gpg: Good signature from "Maarten Lankhorst <maarten.lankhorst@linux.intel.com>" [expired]
# gpg:                 aka "Maarten Lankhorst <maarten@debian.org>" [expired]
# gpg:                 aka "Maarten Lankhorst <maarten.lankhorst@canonical.com>" [expired]
# gpg: Note: This key has expired!
# Primary key fingerprint: B97B D6A8 0CAC 4981 091A  E547 FE55 8C72 A670 13C3
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/2602f4e9-a8ac-83f8-6c2a-39fd9ca2e1ba@linux.intel.com
parents b1f81666 9962601c
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -26,6 +26,10 @@ properties:
      - auo,b101uan08.3
        # BOE TV105WUM-NW0 10.5" WUXGA TFT LCD panel
      - boe,tv105wum-nw0
        # BOE TV110C9M-LL3 10.95" WUXGA TFT LCD panel
      - boe,tv110c9m-ll3
        # INX HJ110IZ-01A 10.95" WUXGA TFT LCD panel
      - innolux,hj110iz-01a

  reg:
    description: the virtual channel number of a DSI peripheral
@@ -36,6 +40,9 @@ properties:
  pp1800-supply:
    description: core voltage supply

  pp3300-supply:
    description: core voltage supply

  avdd-supply:
    description: phandle of the regulator that provides positive voltage

+12 −0
Original line number Diff line number Diff line
@@ -151,6 +151,18 @@ Overview
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
   :doc: overview

Display Driver Integration
--------------------------

.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
   :doc: display driver integration

Special Care with MIPI-DSI bridges
----------------------------------

.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
   :doc: special care dsi

Bridge Operations
-----------------

+0 −17
Original line number Diff line number Diff line
@@ -353,23 +353,6 @@ converted, except for struct drm_driver.gem_prime_mmap.

Level: Intermediate

Use DRM_MODESET_LOCK_ALL_* helpers instead of boilerplate
---------------------------------------------------------

For cases where drivers are attempting to grab the modeset locks with a local
acquire context. Replace the boilerplate code surrounding
drm_modeset_lock_all_ctx() with DRM_MODESET_LOCK_ALL_BEGIN() and
DRM_MODESET_LOCK_ALL_END() instead.

This should also be done for all places where drm_modeset_lock_all() is still
used.

As a reference, take a look at the conversions already completed in drm core.

Contact: Sean Paul, respective driver maintainers

Level: Starter

Rename CMA helpers to DMA helpers
---------------------------------

+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ Concepts
Compared to normal mutexes two additional concepts/objects show up in the lock
interface for w/w mutexes:

Acquire context: To ensure eventual forward progress it is important the a task
Acquire context: To ensure eventual forward progress it is important that a task
trying to acquire locks doesn't grab a new reservation id, but keeps the one it
acquired when starting the lock acquisition. This ticket is stored in the
acquire context. Furthermore the acquire context keeps track of debugging state
+70 −82
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ static void dma_buf_release(struct dentry *dentry)
	 * If you hit this BUG() it means someone dropped their ref to the
	 * dma-buf while still having pending operation to the buffer.
	 */
	BUG_ON(dmabuf->cb_shared.active || dmabuf->cb_excl.active);
	BUG_ON(dmabuf->cb_in.active || dmabuf->cb_out.active);

	dma_buf_stats_teardown(dmabuf);
	dmabuf->ops->release(dmabuf);
@@ -206,16 +206,55 @@ static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
	wake_up_locked_poll(dcb->poll, dcb->active);
	dcb->active = 0;
	spin_unlock_irqrestore(&dcb->poll->lock, flags);
	dma_fence_put(fence);
}

static bool dma_buf_poll_shared(struct dma_resv *resv,
				struct dma_buf_poll_cb_t *dcb)
{
	struct dma_resv_list *fobj = dma_resv_shared_list(resv);
	struct dma_fence *fence;
	int i, r;

	if (!fobj)
		return false;

	for (i = 0; i < fobj->shared_count; ++i) {
		fence = rcu_dereference_protected(fobj->shared[i],
						  dma_resv_held(resv));
		dma_fence_get(fence);
		r = dma_fence_add_callback(fence, &dcb->cb, dma_buf_poll_cb);
		if (!r)
			return true;
		dma_fence_put(fence);
	}

	return false;
}

static bool dma_buf_poll_excl(struct dma_resv *resv,
			      struct dma_buf_poll_cb_t *dcb)
{
	struct dma_fence *fence = dma_resv_excl_fence(resv);
	int r;

	if (!fence)
		return false;

	dma_fence_get(fence);
	r = dma_fence_add_callback(fence, &dcb->cb, dma_buf_poll_cb);
	if (!r)
		return true;
	dma_fence_put(fence);

	return false;
}

static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
{
	struct dma_buf *dmabuf;
	struct dma_resv *resv;
	struct dma_resv_list *fobj;
	struct dma_fence *fence_excl;
	__poll_t events;
	unsigned shared_count, seq;

	dmabuf = file->private_data;
	if (!dmabuf || !dmabuf->resv)
@@ -229,101 +268,50 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
	if (!events)
		return 0;

retry:
	seq = read_seqcount_begin(&resv->seq);
	rcu_read_lock();
	dma_resv_lock(resv, NULL);

	fobj = rcu_dereference(resv->fence);
	if (fobj)
		shared_count = fobj->shared_count;
	else
		shared_count = 0;
	fence_excl = dma_resv_excl_fence(resv);
	if (read_seqcount_retry(&resv->seq, seq)) {
		rcu_read_unlock();
		goto retry;
	}

	if (fence_excl && (!(events & EPOLLOUT) || shared_count == 0)) {
		struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl;
		__poll_t pevents = EPOLLIN;

		if (shared_count == 0)
			pevents |= EPOLLOUT;
	if (events & EPOLLOUT) {
		struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_out;

		/* Check that callback isn't busy */
		spin_lock_irq(&dmabuf->poll.lock);
		if (dcb->active) {
			dcb->active |= pevents;
			events &= ~pevents;
		} else
			dcb->active = pevents;
		if (dcb->active)
			events &= ~EPOLLOUT;
		else
			dcb->active = EPOLLOUT;
		spin_unlock_irq(&dmabuf->poll.lock);

		if (events & pevents) {
			if (!dma_fence_get_rcu(fence_excl)) {
				/* force a recheck */
				events &= ~pevents;
				dma_buf_poll_cb(NULL, &dcb->cb);
			} else if (!dma_fence_add_callback(fence_excl, &dcb->cb,
							   dma_buf_poll_cb)) {
				events &= ~pevents;
				dma_fence_put(fence_excl);
			} else {
				/*
				 * No callback queued, wake up any additional
				 * waiters.
				 */
				dma_fence_put(fence_excl);
		if (events & EPOLLOUT) {
			if (!dma_buf_poll_shared(resv, dcb) &&
			    !dma_buf_poll_excl(resv, dcb))
				/* No callback queued, wake up any other waiters */
				dma_buf_poll_cb(NULL, &dcb->cb);
			}
			else
				events &= ~EPOLLOUT;
		}
	}

	if ((events & EPOLLOUT) && shared_count > 0) {
		struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_shared;
		int i;
	if (events & EPOLLIN) {
		struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_in;

		/* Only queue a new callback if no event has fired yet */
		/* Check that callback isn't busy */
		spin_lock_irq(&dmabuf->poll.lock);
		if (dcb->active)
			events &= ~EPOLLOUT;
			events &= ~EPOLLIN;
		else
			dcb->active = EPOLLOUT;
			dcb->active = EPOLLIN;
		spin_unlock_irq(&dmabuf->poll.lock);

		if (!(events & EPOLLOUT))
			goto out;

		for (i = 0; i < shared_count; ++i) {
			struct dma_fence *fence = rcu_dereference(fobj->shared[i]);

			if (!dma_fence_get_rcu(fence)) {
				/*
				 * fence refcount dropped to zero, this means
				 * that fobj has been freed
				 *
				 * call dma_buf_poll_cb and force a recheck!
				 */
				events &= ~EPOLLOUT;
		if (events & EPOLLIN) {
			if (!dma_buf_poll_excl(resv, dcb))
				/* No callback queued, wake up any other waiters */
				dma_buf_poll_cb(NULL, &dcb->cb);
				break;
			}
			if (!dma_fence_add_callback(fence, &dcb->cb,
						    dma_buf_poll_cb)) {
				dma_fence_put(fence);
				events &= ~EPOLLOUT;
				break;
			}
			dma_fence_put(fence);
			else
				events &= ~EPOLLIN;
		}

		/* No callback queued, wake up any additional waiters. */
		if (i == shared_count)
			dma_buf_poll_cb(NULL, &dcb->cb);
	}

out:
	rcu_read_unlock();
	dma_resv_unlock(resv);
	return events;
}

@@ -566,8 +554,8 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
	dmabuf->owner = exp_info->owner;
	spin_lock_init(&dmabuf->name_lock);
	init_waitqueue_head(&dmabuf->poll);
	dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll;
	dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;
	dmabuf->cb_in.poll = dmabuf->cb_out.poll = &dmabuf->poll;
	dmabuf->cb_in.active = dmabuf->cb_out.active = 0;

	if (!resv) {
		resv = (struct dma_resv *)&dmabuf[1];
Loading