Commit 471f3a21 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-fixes-2024-12-05' of...

Merge tag 'drm-misc-fixes-2024-12-05' of https://gitlab.freedesktop.org/drm/misc/kernel

 into drm-fixes

drm-misc-fixes v6.13-rc2:
- v3d performance counter fix.
- A lot of DP-MST related fixes.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/2ce1650d-801f-4265-a876-5a8743f1c82b@linux.intel.com
parents 915bac60 c98b1049
Loading
Loading
Loading
Loading
+84 −20
Original line number Diff line number Diff line
@@ -3700,8 +3700,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
		ret = 0;
		mgr->payload_id_table_cleared = false;

		memset(&mgr->down_rep_recv, 0, sizeof(mgr->down_rep_recv));
		memset(&mgr->up_req_recv, 0, sizeof(mgr->up_req_recv));
		mgr->reset_rx_state = true;
	}

out_unlock:
@@ -3859,6 +3858,11 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr,
}
EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume);

static void reset_msg_rx_state(struct drm_dp_sideband_msg_rx *msg)
{
	memset(msg, 0, sizeof(*msg));
}

static bool
drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
		      struct drm_dp_mst_branch **mstb)
@@ -3937,6 +3941,34 @@ drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
	return true;
}

static int get_msg_request_type(u8 data)
{
	return data & 0x7f;
}

static bool verify_rx_request_type(struct drm_dp_mst_topology_mgr *mgr,
				   const struct drm_dp_sideband_msg_tx *txmsg,
				   const struct drm_dp_sideband_msg_rx *rxmsg)
{
	const struct drm_dp_sideband_msg_hdr *hdr = &rxmsg->initial_hdr;
	const struct drm_dp_mst_branch *mstb = txmsg->dst;
	int tx_req_type = get_msg_request_type(txmsg->msg[0]);
	int rx_req_type = get_msg_request_type(rxmsg->msg[0]);
	char rad_str[64];

	if (tx_req_type == rx_req_type)
		return true;

	drm_dp_mst_rad_to_str(mstb->rad, mstb->lct, rad_str, sizeof(rad_str));
	drm_dbg_kms(mgr->dev,
		    "Got unexpected MST reply, mstb: %p seqno: %d lct: %d rad: %s rx_req_type: %s (%02x) != tx_req_type: %s (%02x)\n",
		    mstb, hdr->seqno, mstb->lct, rad_str,
		    drm_dp_mst_req_type_str(rx_req_type), rx_req_type,
		    drm_dp_mst_req_type_str(tx_req_type), tx_req_type);

	return false;
}

static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
{
	struct drm_dp_sideband_msg_tx *txmsg;
@@ -3952,9 +3984,9 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)

	/* find the message */
	mutex_lock(&mgr->qlock);

	txmsg = list_first_entry_or_null(&mgr->tx_msg_downq,
					 struct drm_dp_sideband_msg_tx, next);
	mutex_unlock(&mgr->qlock);

	/* Were we actually expecting a response, and from this mstb? */
	if (!txmsg || txmsg->dst != mstb) {
@@ -3963,6 +3995,15 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
		hdr = &msg->initial_hdr;
		drm_dbg_kms(mgr->dev, "Got MST reply with no msg %p %d %d %02x %02x\n",
			    mstb, hdr->seqno, hdr->lct, hdr->rad[0], msg->msg[0]);

		mutex_unlock(&mgr->qlock);

		goto out_clear_reply;
	}

	if (!verify_rx_request_type(mgr, txmsg, msg)) {
		mutex_unlock(&mgr->qlock);

		goto out_clear_reply;
	}

@@ -3978,20 +4019,15 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
			    txmsg->reply.u.nak.nak_data);
	}

	memset(msg, 0, sizeof(struct drm_dp_sideband_msg_rx));
	drm_dp_mst_topology_put_mstb(mstb);

	mutex_lock(&mgr->qlock);
	txmsg->state = DRM_DP_SIDEBAND_TX_RX;
	list_del(&txmsg->next);

	mutex_unlock(&mgr->qlock);

	wake_up_all(&mgr->tx_waitq);

	return 0;

out_clear_reply:
	memset(msg, 0, sizeof(struct drm_dp_sideband_msg_rx));
	reset_msg_rx_state(msg);
out:
	if (mstb)
		drm_dp_mst_topology_put_mstb(mstb);
@@ -4073,16 +4109,20 @@ static void drm_dp_mst_up_req_work(struct work_struct *work)
static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
{
	struct drm_dp_pending_up_req *up_req;
	struct drm_dp_mst_branch *mst_primary;
	int ret = 0;

	if (!drm_dp_get_one_sb_msg(mgr, true, NULL))
		goto out;
		goto out_clear_reply;

	if (!mgr->up_req_recv.have_eomt)
		return 0;

	up_req = kzalloc(sizeof(*up_req), GFP_KERNEL);
	if (!up_req)
		return -ENOMEM;
	if (!up_req) {
		ret = -ENOMEM;
		goto out_clear_reply;
	}

	INIT_LIST_HEAD(&up_req->next);

@@ -4093,10 +4133,19 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
		drm_dbg_kms(mgr->dev, "Received unknown up req type, ignoring: %x\n",
			    up_req->msg.req_type);
		kfree(up_req);
		goto out;
		goto out_clear_reply;
	}

	mutex_lock(&mgr->lock);
	mst_primary = mgr->mst_primary;
	if (!mst_primary || !drm_dp_mst_topology_try_get_mstb(mst_primary)) {
		mutex_unlock(&mgr->lock);
		kfree(up_req);
		goto out_clear_reply;
	}
	mutex_unlock(&mgr->lock);

	drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, up_req->msg.req_type,
	drm_dp_send_up_ack_reply(mgr, mst_primary, up_req->msg.req_type,
				 false);

	if (up_req->msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
@@ -4113,13 +4162,13 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
			    conn_stat->peer_device_type);

		mutex_lock(&mgr->probe_lock);
		handle_csn = mgr->mst_primary->link_address_sent;
		handle_csn = mst_primary->link_address_sent;
		mutex_unlock(&mgr->probe_lock);

		if (!handle_csn) {
			drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it.");
			kfree(up_req);
			goto out;
			goto out_put_primary;
		}
	} else if (up_req->msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
		const struct drm_dp_resource_status_notify *res_stat =
@@ -4136,9 +4185,22 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
	mutex_unlock(&mgr->up_req_lock);
	queue_work(system_long_wq, &mgr->up_req_work);

out:
	memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
	return 0;
out_put_primary:
	drm_dp_mst_topology_put_mstb(mst_primary);
out_clear_reply:
	reset_msg_rx_state(&mgr->up_req_recv);
	return ret;
}

static void update_msg_rx_state(struct drm_dp_mst_topology_mgr *mgr)
{
	mutex_lock(&mgr->lock);
	if (mgr->reset_rx_state) {
		mgr->reset_rx_state = false;
		reset_msg_rx_state(&mgr->down_rep_recv);
		reset_msg_rx_state(&mgr->up_req_recv);
	}
	mutex_unlock(&mgr->lock);
}

/**
@@ -4175,6 +4237,8 @@ int drm_dp_mst_hpd_irq_handle_event(struct drm_dp_mst_topology_mgr *mgr, const u
		*handled = true;
	}

	update_msg_rx_state(mgr);

	if (esi[1] & DP_DOWN_REP_MSG_RDY) {
		ret = drm_dp_mst_handle_down_rep(mgr);
		*handled = true;
+1 −1
Original line number Diff line number Diff line
@@ -254,9 +254,9 @@ void v3d_perfmon_start(struct v3d_dev *v3d, struct v3d_perfmon *perfmon)
		V3D_CORE_WRITE(0, V3D_V4_PCTR_0_SRC_X(source), channel);
	}

	V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask);
	V3D_CORE_WRITE(0, V3D_V4_PCTR_0_CLR, mask);
	V3D_CORE_WRITE(0, V3D_PCTR_0_OVERFLOW, mask);
	V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask);

	v3d->active_perfmon = perfmon;
}
+7 −0
Original line number Diff line number Diff line
@@ -699,6 +699,13 @@ struct drm_dp_mst_topology_mgr {
	 */
	bool payload_id_table_cleared : 1;

	/**
	 * @reset_rx_state: The down request's reply and up request message
	 * receiver state must be reset, after the topology manager got
	 * removed. Protected by @lock.
	 */
	bool reset_rx_state : 1;

	/**
	 * @payload_count: The number of currently active payloads in hardware. This value is only
	 * intended to be used internally by MST helpers for payload tracking, and is only safe to