mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 00:35:01 +00:00
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
This commit is contained in:
commit
471f3a21ad
@ -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;
|
||||
}
|
||||
|
||||
drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, up_req->msg.req_type,
|
||||
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, 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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user