Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit befad944 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'drm-fixes-2018-10-05' of git://anongit.freedesktop.org/drm/drm

Dave writes:
  "amdgpu and two core fixes

   Two fixes for amdgpu:
   one corrects a use of process->mm
   one fix for display code race condition that can result in a crash

   Two core fixes:
   One for a use-after-free in the leasing code
   One for a cma/fbdev crash."

* tag 'drm-fixes-2018-10-05' of git://anongit.freedesktop.org/drm/drm:
  drm/amdkfd: Fix incorrect use of process->mm
  drm/amd/display: Signal hw_done() after waiting for flip_done()
  drm/cma-helper: Fix crash in fbdev error path
  drm: fix use-after-free read in drm_mode_create_lease_ioctl()
parents 010bd965 bdf800c6
Loading
Loading
Loading
Loading
+29 −8
Original line number Diff line number Diff line
@@ -358,8 +358,8 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm,
					struct queue *q,
					struct qcm_process_device *qpd)
{
	int retval;
	struct mqd_manager *mqd_mgr;
	int retval;

	mqd_mgr = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE);
	if (!mqd_mgr)
@@ -387,8 +387,12 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm,
	if (!q->properties.is_active)
		return 0;

	if (WARN(q->process->mm != current->mm,
		 "should only run in user thread"))
		retval = -EFAULT;
	else
		retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd, q->pipe, q->queue,
			&q->properties, q->process->mm);
					   &q->properties, current->mm);
	if (retval)
		goto out_uninit_mqd;

@@ -545,9 +549,15 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q)
		retval = map_queues_cpsch(dqm);
	else if (q->properties.is_active &&
		 (q->properties.type == KFD_QUEUE_TYPE_COMPUTE ||
		  q->properties.type == KFD_QUEUE_TYPE_SDMA))
		retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd, q->pipe, q->queue,
				       &q->properties, q->process->mm);
		  q->properties.type == KFD_QUEUE_TYPE_SDMA)) {
		if (WARN(q->process->mm != current->mm,
			 "should only run in user thread"))
			retval = -EFAULT;
		else
			retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd,
						   q->pipe, q->queue,
						   &q->properties, current->mm);
	}

out_unlock:
	dqm_unlock(dqm);
@@ -653,6 +663,7 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
static int restore_process_queues_nocpsch(struct device_queue_manager *dqm,
					  struct qcm_process_device *qpd)
{
	struct mm_struct *mm = NULL;
	struct queue *q;
	struct mqd_manager *mqd_mgr;
	struct kfd_process_device *pdd;
@@ -686,6 +697,15 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm,
		kfd_flush_tlb(pdd);
	}

	/* Take a safe reference to the mm_struct, which may otherwise
	 * disappear even while the kfd_process is still referenced.
	 */
	mm = get_task_mm(pdd->process->lead_thread);
	if (!mm) {
		retval = -EFAULT;
		goto out;
	}

	/* activate all active queues on the qpd */
	list_for_each_entry(q, &qpd->queues_list, list) {
		if (!q->properties.is_evicted)
@@ -700,14 +720,15 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm,
		q->properties.is_evicted = false;
		q->properties.is_active = true;
		retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd, q->pipe,
				       q->queue, &q->properties,
				       q->process->mm);
				       q->queue, &q->properties, mm);
		if (retval)
			goto out;
		dqm->queue_count++;
	}
	qpd->evicted = 0;
out:
	if (mm)
		mmput(mm);
	dqm_unlock(dqm);
	return retval;
}
+8 −2
Original line number Diff line number Diff line
@@ -4633,12 +4633,18 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
	}
	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);

	/* Signal HW programming completion */
	drm_atomic_helper_commit_hw_done(state);

	if (wait_for_vblank)
		drm_atomic_helper_wait_for_flip_done(dev, state);

	/*
	 * FIXME:
	 * Delay hw_done() until flip_done() is signaled. This is to block
	 * another commit from freeing the CRTC state while we're still
	 * waiting on flip_done.
	 */
	drm_atomic_helper_commit_hw_done(state);

	drm_atomic_helper_cleanup_planes(dev, state);

	/* Finally, drop a runtime PM reference for each newly disabled CRTC,
+26 −9
Original line number Diff line number Diff line
@@ -63,19 +63,20 @@ static void drm_client_close(struct drm_client_dev *client)
EXPORT_SYMBOL(drm_client_close);

/**
 * drm_client_new - Create a DRM client
 * drm_client_init - Initialise a DRM client
 * @dev: DRM device
 * @client: DRM client
 * @name: Client name
 * @funcs: DRM client functions (optional)
 *
 * This initialises the client and opens a &drm_file. Use drm_client_add() to complete the process.
 * The caller needs to hold a reference on @dev before calling this function.
 * The client is freed when the &drm_device is unregistered. See drm_client_release().
 *
 * Returns:
 * Zero on success or negative error code on failure.
 */
int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
		    const char *name, const struct drm_client_funcs *funcs)
{
	int ret;
@@ -95,10 +96,6 @@ int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
	if (ret)
		goto err_put_module;

	mutex_lock(&dev->clientlist_mutex);
	list_add(&client->list, &dev->clientlist);
	mutex_unlock(&dev->clientlist_mutex);

	drm_dev_get(dev);

	return 0;
@@ -109,13 +106,33 @@ int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,

	return ret;
}
EXPORT_SYMBOL(drm_client_new);
EXPORT_SYMBOL(drm_client_init);

/**
 * drm_client_add - Add client to the device list
 * @client: DRM client
 *
 * Add the client to the &drm_device client list to activate its callbacks.
 * @client must be initialized by a call to drm_client_init(). After
 * drm_client_add() it is no longer permissible to call drm_client_release()
 * directly (outside the unregister callback), instead cleanup will happen
 * automatically on driver unload.
 */
void drm_client_add(struct drm_client_dev *client)
{
	struct drm_device *dev = client->dev;

	mutex_lock(&dev->clientlist_mutex);
	list_add(&client->list, &dev->clientlist);
	mutex_unlock(&dev->clientlist_mutex);
}
EXPORT_SYMBOL(drm_client_add);

/**
 * drm_client_release - Release DRM client resources
 * @client: DRM client
 *
 * Releases resources by closing the &drm_file that was opened by drm_client_new().
 * Releases resources by closing the &drm_file that was opened by drm_client_init().
 * It is called automatically if the &drm_client_funcs.unregister callback is _not_ set.
 *
 * This function should only be called from the unregister callback. An exception
+3 −1
Original line number Diff line number Diff line
@@ -160,7 +160,7 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,

	fb_helper = &fbdev_cma->fb_helper;

	ret = drm_client_new(dev, &fb_helper->client, "fbdev", NULL);
	ret = drm_client_init(dev, &fb_helper->client, "fbdev", NULL);
	if (ret)
		goto err_free;

@@ -169,6 +169,8 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
	if (ret)
		goto err_client_put;

	drm_client_add(&fb_helper->client);

	return fbdev_cma;

err_client_put:
+3 −1
Original line number Diff line number Diff line
@@ -3218,12 +3218,14 @@ int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
	if (!fb_helper)
		return -ENOMEM;

	ret = drm_client_new(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
	ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
	if (ret) {
		kfree(fb_helper);
		return ret;
	}

	drm_client_add(&fb_helper->client);

	fb_helper->preferred_bpp = preferred_bpp;

	drm_fbdev_client_hotplug(&fb_helper->client);
Loading