Commit f4f19c03 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-fixes-2023-07-20' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes



Memory leak fixes in drm/client, memory access/leak fixes for
accel/qaic, another leak fix in dma-buf and three nouveau fixes around
hotplugging.

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

From: Maxime Ripard <mripard@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/fmj5nok7zggux2lcpdtls2iknweba54wfc6o4zxq6i6s3dgi2r@7z3eawwhyhen
parents 78e9b217 ea293f82
Loading
Loading
Loading
Loading
+25 −14
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/mm.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/overflow.h>
#include <linux/pci.h>
#include <linux/scatterlist.h>
#include <linux/types.h>
@@ -366,7 +367,7 @@ static int encode_passthrough(struct qaic_device *qdev, void *trans, struct wrap
	if (in_trans->hdr.len % 8 != 0)
		return -EINVAL;

	if (msg_hdr_len + in_trans->hdr.len > QAIC_MANAGE_EXT_MSG_LENGTH)
	if (size_add(msg_hdr_len, in_trans->hdr.len) > QAIC_MANAGE_EXT_MSG_LENGTH)
		return -ENOSPC;

	trans_wrapper = add_wrapper(wrappers,
@@ -418,9 +419,12 @@ static int find_and_map_user_pages(struct qaic_device *qdev,
	}

	ret = get_user_pages_fast(xfer_start_addr, nr_pages, 0, page_list);
	if (ret < 0 || ret != nr_pages) {
		ret = -EFAULT;
	if (ret < 0)
		goto free_page_list;
	if (ret != nr_pages) {
		nr_pages = ret;
		ret = -EFAULT;
		goto put_pages;
	}

	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
@@ -557,11 +561,8 @@ static int encode_dma(struct qaic_device *qdev, void *trans, struct wrapper_list
	msg = &wrapper->msg;
	msg_hdr_len = le32_to_cpu(msg->hdr.len);

	if (msg_hdr_len > (UINT_MAX - QAIC_MANAGE_EXT_MSG_LENGTH))
		return -EINVAL;

	/* There should be enough space to hold at least one ASP entry. */
	if (msg_hdr_len + sizeof(*out_trans) + sizeof(struct wire_addr_size_pair) >
	if (size_add(msg_hdr_len, sizeof(*out_trans) + sizeof(struct wire_addr_size_pair)) >
	    QAIC_MANAGE_EXT_MSG_LENGTH)
		return -ENOMEM;

@@ -634,7 +635,7 @@ static int encode_activate(struct qaic_device *qdev, void *trans, struct wrapper
	msg = &wrapper->msg;
	msg_hdr_len = le32_to_cpu(msg->hdr.len);

	if (msg_hdr_len + sizeof(*out_trans) > QAIC_MANAGE_MAX_MSG_LENGTH)
	if (size_add(msg_hdr_len, sizeof(*out_trans)) > QAIC_MANAGE_MAX_MSG_LENGTH)
		return -ENOSPC;

	if (!in_trans->queue_size)
@@ -718,7 +719,7 @@ static int encode_status(struct qaic_device *qdev, void *trans, struct wrapper_l
	msg = &wrapper->msg;
	msg_hdr_len = le32_to_cpu(msg->hdr.len);

	if (msg_hdr_len + in_trans->hdr.len > QAIC_MANAGE_MAX_MSG_LENGTH)
	if (size_add(msg_hdr_len, in_trans->hdr.len) > QAIC_MANAGE_MAX_MSG_LENGTH)
		return -ENOSPC;

	trans_wrapper = add_wrapper(wrappers, sizeof(*trans_wrapper));
@@ -748,7 +749,8 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
	int ret;
	int i;

	if (!user_msg->count) {
	if (!user_msg->count ||
	    user_msg->len < sizeof(*trans_hdr)) {
		ret = -EINVAL;
		goto out;
	}
@@ -765,12 +767,13 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
	}

	for (i = 0; i < user_msg->count; ++i) {
		if (user_len >= user_msg->len) {
		if (user_len > user_msg->len - sizeof(*trans_hdr)) {
			ret = -EINVAL;
			break;
		}
		trans_hdr = (struct qaic_manage_trans_hdr *)(user_msg->data + user_len);
		if (user_len + trans_hdr->len > user_msg->len) {
		if (trans_hdr->len < sizeof(trans_hdr) ||
		    size_add(user_len, trans_hdr->len) > user_msg->len) {
			ret = -EINVAL;
			break;
		}
@@ -953,15 +956,23 @@ static int decode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
	int ret;
	int i;

	if (msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH)
	if (msg_hdr_len < sizeof(*trans_hdr) ||
	    msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH)
		return -EINVAL;

	user_msg->len = 0;
	user_msg->count = le32_to_cpu(msg->hdr.count);

	for (i = 0; i < user_msg->count; ++i) {
		u32 hdr_len;

		if (msg_len > msg_hdr_len - sizeof(*trans_hdr))
			return -EINVAL;

		trans_hdr = (struct wire_trans_hdr *)(msg->data + msg_len);
		if (msg_len + le32_to_cpu(trans_hdr->len) > msg_hdr_len)
		hdr_len = le32_to_cpu(trans_hdr->len);
		if (hdr_len < sizeof(*trans_hdr) ||
		    size_add(msg_len, hdr_len) > msg_hdr_len)
			return -EINVAL;

		switch (le32_to_cpu(trans_hdr->type)) {
+9 −4
Original line number Diff line number Diff line
@@ -571,6 +571,7 @@ int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
	dma_resv_for_each_fence_unlocked(&cursor, fence) {

		if (dma_resv_iter_is_restarted(&cursor)) {
			struct dma_fence **new_fences;
			unsigned int count;

			while (*num_fences)
@@ -579,13 +580,17 @@ int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
			count = cursor.num_fences + 1;

			/* Eventually re-allocate the array */
			*fences = krealloc_array(*fences, count,
			new_fences = krealloc_array(*fences, count,
						    sizeof(void *),
						    GFP_KERNEL);
			if (count && !*fences) {
			if (count && !new_fences) {
				kfree(*fences);
				*fences = NULL;
				*num_fences = 0;
				dma_resv_iter_end(&cursor);
				return -ENOMEM;
			}
			*fences = new_fences;
		}

		(*fences)[(*num_fences)++] = dma_fence_get(fence);
+6 −0
Original line number Diff line number Diff line
@@ -311,6 +311,9 @@ static bool drm_client_target_cloned(struct drm_device *dev,
	can_clone = true;
	dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false);

	if (!dmt_mode)
		goto fail;

	for (i = 0; i < connector_count; i++) {
		if (!enabled[i])
			continue;
@@ -326,11 +329,13 @@ static bool drm_client_target_cloned(struct drm_device *dev,
		if (!modes[i])
			can_clone = false;
	}
	kfree(dmt_mode);

	if (can_clone) {
		DRM_DEBUG_KMS("can clone using 1024x768\n");
		return true;
	}
fail:
	DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
	return false;
}
@@ -862,6 +867,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
				break;
			}

			kfree(modeset->mode);
			modeset->mode = drm_mode_duplicate(dev, mode);
			drm_connector_get(connector);
			modeset->connectors[modeset->num_connectors++] = connector;
+4 −0
Original line number Diff line number Diff line
@@ -1877,6 +1877,8 @@ nv50_pior_destroy(struct drm_encoder *encoder)
	nvif_outp_dtor(&nv_encoder->outp);

	drm_encoder_cleanup(encoder);

	mutex_destroy(&nv_encoder->dp.hpd_irq_lock);
	kfree(encoder);
}

@@ -1921,6 +1923,8 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
	nv_encoder->i2c = ddc;
	nv_encoder->aux = aux;

	mutex_init(&nv_encoder->dp.hpd_irq_lock);

	encoder = to_drm_encoder(nv_encoder);
	encoder->possible_crtcs = dcbe->heads;
	encoder->possible_clones = 0;
+2 −2
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ struct nvkm_i2c_bus {
	const struct nvkm_i2c_bus_func *func;
	struct nvkm_i2c_pad *pad;
#define NVKM_I2C_BUS_CCB(n) /* 'n' is ccb index */                           (n)
#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100)
#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */  ((n) + 0x10)
#define NVKM_I2C_BUS_PRI /* ccb primary comm. port */                        -1
#define NVKM_I2C_BUS_SEC /* ccb secondary comm. port */                      -2
	int id;
@@ -38,7 +38,7 @@ struct nvkm_i2c_aux {
	const struct nvkm_i2c_aux_func *func;
	struct nvkm_i2c_pad *pad;
#define NVKM_I2C_AUX_CCB(n) /* 'n' is ccb index */                           (n)
#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100)
#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */  ((n) + 0x10)
	int id;

	struct mutex mutex;
Loading