mirror of https://gitee.com/openkylin/linux.git
drm/dp/mst: process broadcast messages correctly
In case broadcast message received in UP request, RAD cannot be used to identify message originator. Message should be parsed, originator should be found by GUID from parsed message. Also reply with broadcast in case broadcast message received (for now it is always broadcast) Acked-by: Dave Airlie <airlied@gmail.com> Signed-off-by: Mykola Lysenko <Mykola.Lysenko@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org
This commit is contained in:
parent
6a53b31349
commit
bd93432087
|
@ -1215,6 +1215,50 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_
|
|||
return mstb;
|
||||
}
|
||||
|
||||
static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper(
|
||||
struct drm_dp_mst_branch *mstb,
|
||||
uint8_t *guid)
|
||||
{
|
||||
struct drm_dp_mst_branch *found_mstb;
|
||||
struct drm_dp_mst_port *port;
|
||||
|
||||
list_for_each_entry(port, &mstb->ports, next) {
|
||||
if (!port->mstb)
|
||||
continue;
|
||||
|
||||
if (port->guid_valid && memcmp(port->guid, guid, 16) == 0)
|
||||
return port->mstb;
|
||||
|
||||
found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid);
|
||||
|
||||
if (found_mstb)
|
||||
return found_mstb;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device_by_guid(
|
||||
struct drm_dp_mst_topology_mgr *mgr,
|
||||
uint8_t *guid)
|
||||
{
|
||||
struct drm_dp_mst_branch *mstb;
|
||||
|
||||
/* find the port by iterating down */
|
||||
mutex_lock(&mgr->lock);
|
||||
|
||||
if (mgr->guid_valid && memcmp(mgr->guid, guid, 16) == 0)
|
||||
mstb = mgr->mst_primary;
|
||||
else
|
||||
mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid);
|
||||
|
||||
if (mstb)
|
||||
kref_get(&mstb->kref);
|
||||
|
||||
mutex_unlock(&mgr->lock);
|
||||
return mstb;
|
||||
}
|
||||
|
||||
static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_mst_branch *mstb)
|
||||
{
|
||||
|
@ -1325,6 +1369,7 @@ static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr,
|
|||
struct drm_dp_sideband_msg_tx *txmsg)
|
||||
{
|
||||
struct drm_dp_mst_branch *mstb = txmsg->dst;
|
||||
u8 req_type;
|
||||
|
||||
/* both msg slots are full */
|
||||
if (txmsg->seqno == -1) {
|
||||
|
@ -1341,7 +1386,13 @@ static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr,
|
|||
txmsg->seqno = 1;
|
||||
mstb->tx_slots[txmsg->seqno] = txmsg;
|
||||
}
|
||||
hdr->broadcast = 0;
|
||||
|
||||
req_type = txmsg->msg[0] & 0x7f;
|
||||
if (req_type == DP_CONNECTION_STATUS_NOTIFY ||
|
||||
req_type == DP_RESOURCE_STATUS_NOTIFY)
|
||||
hdr->broadcast = 1;
|
||||
else
|
||||
hdr->broadcast = 0;
|
||||
hdr->path_msg = txmsg->path_msg;
|
||||
hdr->lct = mstb->lct;
|
||||
hdr->lcr = mstb->lct - 1;
|
||||
|
@ -2157,28 +2208,50 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
|
|||
|
||||
if (mgr->up_req_recv.have_eomt) {
|
||||
struct drm_dp_sideband_msg_req_body msg;
|
||||
struct drm_dp_mst_branch *mstb;
|
||||
struct drm_dp_mst_branch *mstb = NULL;
|
||||
bool seqno;
|
||||
mstb = drm_dp_get_mst_branch_device(mgr,
|
||||
mgr->up_req_recv.initial_hdr.lct,
|
||||
mgr->up_req_recv.initial_hdr.rad);
|
||||
if (!mstb) {
|
||||
DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
|
||||
memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
|
||||
return 0;
|
||||
|
||||
if (!mgr->up_req_recv.initial_hdr.broadcast) {
|
||||
mstb = drm_dp_get_mst_branch_device(mgr,
|
||||
mgr->up_req_recv.initial_hdr.lct,
|
||||
mgr->up_req_recv.initial_hdr.rad);
|
||||
if (!mstb) {
|
||||
DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
|
||||
memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
seqno = mgr->up_req_recv.initial_hdr.seqno;
|
||||
drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg);
|
||||
|
||||
if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
|
||||
drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false);
|
||||
drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
|
||||
|
||||
if (!mstb)
|
||||
mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.conn_stat.guid);
|
||||
|
||||
if (!mstb) {
|
||||
DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
|
||||
memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
drm_dp_update_port(mstb, &msg.u.conn_stat);
|
||||
DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
|
||||
(*mgr->cbs->hotplug)(mgr);
|
||||
|
||||
} else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
|
||||
drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false);
|
||||
drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
|
||||
if (!mstb)
|
||||
mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.resource_stat.guid);
|
||||
|
||||
if (!mstb) {
|
||||
DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
|
||||
memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue