Skip to content

Commit 471f3a2

Browse files
committed
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: Dave 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
2 parents 915bac6 + c98b104 commit 471f3a2

File tree

3 files changed

+92
-21
lines changed

3 files changed

+92
-21
lines changed

drivers/gpu/drm/display/drm_dp_mst_topology.c

Lines changed: 84 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3700,8 +3700,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
37003700
ret = 0;
37013701
mgr->payload_id_table_cleared = false;
37023702

3703-
memset(&mgr->down_rep_recv, 0, sizeof(mgr->down_rep_recv));
3704-
memset(&mgr->up_req_recv, 0, sizeof(mgr->up_req_recv));
3703+
mgr->reset_rx_state = true;
37053704
}
37063705

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

3861+
static void reset_msg_rx_state(struct drm_dp_sideband_msg_rx *msg)
3862+
{
3863+
memset(msg, 0, sizeof(*msg));
3864+
}
3865+
38623866
static bool
38633867
drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
38643868
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,
39373941
return true;
39383942
}
39393943

3944+
static int get_msg_request_type(u8 data)
3945+
{
3946+
return data & 0x7f;
3947+
}
3948+
3949+
static bool verify_rx_request_type(struct drm_dp_mst_topology_mgr *mgr,
3950+
const struct drm_dp_sideband_msg_tx *txmsg,
3951+
const struct drm_dp_sideband_msg_rx *rxmsg)
3952+
{
3953+
const struct drm_dp_sideband_msg_hdr *hdr = &rxmsg->initial_hdr;
3954+
const struct drm_dp_mst_branch *mstb = txmsg->dst;
3955+
int tx_req_type = get_msg_request_type(txmsg->msg[0]);
3956+
int rx_req_type = get_msg_request_type(rxmsg->msg[0]);
3957+
char rad_str[64];
3958+
3959+
if (tx_req_type == rx_req_type)
3960+
return true;
3961+
3962+
drm_dp_mst_rad_to_str(mstb->rad, mstb->lct, rad_str, sizeof(rad_str));
3963+
drm_dbg_kms(mgr->dev,
3964+
"Got unexpected MST reply, mstb: %p seqno: %d lct: %d rad: %s rx_req_type: %s (%02x) != tx_req_type: %s (%02x)\n",
3965+
mstb, hdr->seqno, mstb->lct, rad_str,
3966+
drm_dp_mst_req_type_str(rx_req_type), rx_req_type,
3967+
drm_dp_mst_req_type_str(tx_req_type), tx_req_type);
3968+
3969+
return false;
3970+
}
3971+
39403972
static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
39413973
{
39423974
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)
39523984

39533985
/* find the message */
39543986
mutex_lock(&mgr->qlock);
3987+
39553988
txmsg = list_first_entry_or_null(&mgr->tx_msg_downq,
39563989
struct drm_dp_sideband_msg_tx, next);
3957-
mutex_unlock(&mgr->qlock);
39583990

39593991
/* Were we actually expecting a response, and from this mstb? */
39603992
if (!txmsg || txmsg->dst != mstb) {
@@ -3963,6 +3995,15 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
39633995
hdr = &msg->initial_hdr;
39643996
drm_dbg_kms(mgr->dev, "Got MST reply with no msg %p %d %d %02x %02x\n",
39653997
mstb, hdr->seqno, hdr->lct, hdr->rad[0], msg->msg[0]);
3998+
3999+
mutex_unlock(&mgr->qlock);
4000+
4001+
goto out_clear_reply;
4002+
}
4003+
4004+
if (!verify_rx_request_type(mgr, txmsg, msg)) {
4005+
mutex_unlock(&mgr->qlock);
4006+
39664007
goto out_clear_reply;
39674008
}
39684009

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

3981-
memset(msg, 0, sizeof(struct drm_dp_sideband_msg_rx));
3982-
drm_dp_mst_topology_put_mstb(mstb);
3983-
3984-
mutex_lock(&mgr->qlock);
39854022
txmsg->state = DRM_DP_SIDEBAND_TX_RX;
39864023
list_del(&txmsg->next);
4024+
39874025
mutex_unlock(&mgr->qlock);
39884026

39894027
wake_up_all(&mgr->tx_waitq);
39904028

3991-
return 0;
3992-
39934029
out_clear_reply:
3994-
memset(msg, 0, sizeof(struct drm_dp_sideband_msg_rx));
4030+
reset_msg_rx_state(msg);
39954031
out:
39964032
if (mstb)
39974033
drm_dp_mst_topology_put_mstb(mstb);
@@ -4073,16 +4109,20 @@ static void drm_dp_mst_up_req_work(struct work_struct *work)
40734109
static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
40744110
{
40754111
struct drm_dp_pending_up_req *up_req;
4112+
struct drm_dp_mst_branch *mst_primary;
4113+
int ret = 0;
40764114

40774115
if (!drm_dp_get_one_sb_msg(mgr, true, NULL))
4078-
goto out;
4116+
goto out_clear_reply;
40794117

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

40834121
up_req = kzalloc(sizeof(*up_req), GFP_KERNEL);
4084-
if (!up_req)
4085-
return -ENOMEM;
4122+
if (!up_req) {
4123+
ret = -ENOMEM;
4124+
goto out_clear_reply;
4125+
}
40864126

40874127
INIT_LIST_HEAD(&up_req->next);
40884128

@@ -4093,10 +4133,19 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
40934133
drm_dbg_kms(mgr->dev, "Received unknown up req type, ignoring: %x\n",
40944134
up_req->msg.req_type);
40954135
kfree(up_req);
4096-
goto out;
4136+
goto out_clear_reply;
4137+
}
4138+
4139+
mutex_lock(&mgr->lock);
4140+
mst_primary = mgr->mst_primary;
4141+
if (!mst_primary || !drm_dp_mst_topology_try_get_mstb(mst_primary)) {
4142+
mutex_unlock(&mgr->lock);
4143+
kfree(up_req);
4144+
goto out_clear_reply;
40974145
}
4146+
mutex_unlock(&mgr->lock);
40984147

4099-
drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, up_req->msg.req_type,
4148+
drm_dp_send_up_ack_reply(mgr, mst_primary, up_req->msg.req_type,
41004149
false);
41014150

41024151
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)
41134162
conn_stat->peer_device_type);
41144163

41154164
mutex_lock(&mgr->probe_lock);
4116-
handle_csn = mgr->mst_primary->link_address_sent;
4165+
handle_csn = mst_primary->link_address_sent;
41174166
mutex_unlock(&mgr->probe_lock);
41184167

41194168
if (!handle_csn) {
41204169
drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it.");
41214170
kfree(up_req);
4122-
goto out;
4171+
goto out_put_primary;
41234172
}
41244173
} else if (up_req->msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
41254174
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)
41364185
mutex_unlock(&mgr->up_req_lock);
41374186
queue_work(system_long_wq, &mgr->up_req_work);
41384187

4139-
out:
4140-
memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
4141-
return 0;
4188+
out_put_primary:
4189+
drm_dp_mst_topology_put_mstb(mst_primary);
4190+
out_clear_reply:
4191+
reset_msg_rx_state(&mgr->up_req_recv);
4192+
return ret;
4193+
}
4194+
4195+
static void update_msg_rx_state(struct drm_dp_mst_topology_mgr *mgr)
4196+
{
4197+
mutex_lock(&mgr->lock);
4198+
if (mgr->reset_rx_state) {
4199+
mgr->reset_rx_state = false;
4200+
reset_msg_rx_state(&mgr->down_rep_recv);
4201+
reset_msg_rx_state(&mgr->up_req_recv);
4202+
}
4203+
mutex_unlock(&mgr->lock);
41424204
}
41434205

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

4240+
update_msg_rx_state(mgr);
4241+
41784242
if (esi[1] & DP_DOWN_REP_MSG_RDY) {
41794243
ret = drm_dp_mst_handle_down_rep(mgr);
41804244
*handled = true;

drivers/gpu/drm/v3d/v3d_perfmon.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,9 @@ void v3d_perfmon_start(struct v3d_dev *v3d, struct v3d_perfmon *perfmon)
254254
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_SRC_X(source), channel);
255255
}
256256

257+
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask);
257258
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_CLR, mask);
258259
V3D_CORE_WRITE(0, V3D_PCTR_0_OVERFLOW, mask);
259-
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask);
260260

261261
v3d->active_perfmon = perfmon;
262262
}

include/drm/display/drm_dp_mst_helper.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,13 @@ struct drm_dp_mst_topology_mgr {
699699
*/
700700
bool payload_id_table_cleared : 1;
701701

702+
/**
703+
* @reset_rx_state: The down request's reply and up request message
704+
* receiver state must be reset, after the topology manager got
705+
* removed. Protected by @lock.
706+
*/
707+
bool reset_rx_state : 1;
708+
702709
/**
703710
* @payload_count: The number of currently active payloads in hardware. This value is only
704711
* intended to be used internally by MST helpers for payload tracking, and is only safe to

0 commit comments

Comments
 (0)