aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHersen Wu <hersenxs.wu@amd.com>2016-01-22 17:07:28 -0500
committerDave Airlie <airlied@redhat.com>2016-02-05 00:23:49 -0500
commit5e93b8208d3c419b515fb75e2601931c027e12ab (patch)
tree62dcd4ccedcf6b77fa5a8e814de5a4731e7b5a0f
parentcfcfa086d43ced33e1099b9befb12f17fca102e1 (diff)
drm/dp/mst: move GUID storage from mgr, port to only mst branch
Previous implementation does not handle case below: boot up one MST branch to DP connector of ASIC. After boot up, hot plug 2nd MST branch to DP output of 1st MST, GUID is not created for 2nd MST branch. When downstream port of 2nd MST branch send upstream request, it fails because 2nd MST branch GUID is not available. New Implementation: only create GUID for MST branch and save it within Branch. Signed-off-by: Hersen Wu <hersenxs.wu@amd.com> Reviewed-by: Harry Wentland <harry.wentland@amd.com> Cc: stable@vger.kernel.org Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c64
-rw-r--r--include/drm/drm_dp_mst_helper.h25
2 files changed, 38 insertions, 51 deletions
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 630e6eb55fa3..2c12a20ff08e 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1018,18 +1018,27 @@ static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port *port)
1018 return send_link; 1018 return send_link;
1019} 1019}
1020 1020
1021static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb, 1021static void drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid)
1022 struct drm_dp_mst_port *port)
1023{ 1022{
1024 int ret; 1023 int ret;
1025 if (port->dpcd_rev >= 0x12) { 1024
1026 port->guid_valid = drm_dp_validate_guid(mstb->mgr, port->guid); 1025 memcpy(mstb->guid, guid, 16);
1027 if (!port->guid_valid) { 1026
1028 ret = drm_dp_send_dpcd_write(mstb->mgr, 1027 if (!drm_dp_validate_guid(mstb->mgr, mstb->guid)) {
1029 port, 1028 if (mstb->port_parent) {
1030 DP_GUID, 1029 ret = drm_dp_send_dpcd_write(
1031 16, port->guid); 1030 mstb->mgr,
1032 port->guid_valid = true; 1031 mstb->port_parent,
1032 DP_GUID,
1033 16,
1034 mstb->guid);
1035 } else {
1036
1037 ret = drm_dp_dpcd_write(
1038 mstb->mgr->aux,
1039 DP_GUID,
1040 mstb->guid,
1041 16);
1033 } 1042 }
1034 } 1043 }
1035} 1044}
@@ -1086,7 +1095,6 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
1086 port->dpcd_rev = port_msg->dpcd_revision; 1095 port->dpcd_rev = port_msg->dpcd_revision;
1087 port->num_sdp_streams = port_msg->num_sdp_streams; 1096 port->num_sdp_streams = port_msg->num_sdp_streams;
1088 port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks; 1097 port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks;
1089 memcpy(port->guid, port_msg->peer_guid, 16);
1090 1098
1091 /* manage mstb port lists with mgr lock - take a reference 1099 /* manage mstb port lists with mgr lock - take a reference
1092 for this list */ 1100 for this list */
@@ -1099,11 +1107,9 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
1099 1107
1100 if (old_ddps != port->ddps) { 1108 if (old_ddps != port->ddps) {
1101 if (port->ddps) { 1109 if (port->ddps) {
1102 drm_dp_check_port_guid(mstb, port);
1103 if (!port->input) 1110 if (!port->input)
1104 drm_dp_send_enum_path_resources(mstb->mgr, mstb, port); 1111 drm_dp_send_enum_path_resources(mstb->mgr, mstb, port);
1105 } else { 1112 } else {
1106 port->guid_valid = false;
1107 port->available_pbn = 0; 1113 port->available_pbn = 0;
1108 } 1114 }
1109 } 1115 }
@@ -1161,9 +1167,7 @@ static void drm_dp_update_port(struct drm_dp_mst_branch *mstb,
1161 if (old_ddps != port->ddps) { 1167 if (old_ddps != port->ddps) {
1162 dowork = true; 1168 dowork = true;
1163 if (port->ddps) { 1169 if (port->ddps) {
1164 drm_dp_check_port_guid(mstb, port);
1165 } else { 1170 } else {
1166 port->guid_valid = false;
1167 port->available_pbn = 0; 1171 port->available_pbn = 0;
1168 } 1172 }
1169 } 1173 }
@@ -1220,13 +1224,14 @@ static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper(
1220 struct drm_dp_mst_branch *found_mstb; 1224 struct drm_dp_mst_branch *found_mstb;
1221 struct drm_dp_mst_port *port; 1225 struct drm_dp_mst_port *port;
1222 1226
1227 if (memcmp(mstb->guid, guid, 16) == 0)
1228 return mstb;
1229
1230
1223 list_for_each_entry(port, &mstb->ports, next) { 1231 list_for_each_entry(port, &mstb->ports, next) {
1224 if (!port->mstb) 1232 if (!port->mstb)
1225 continue; 1233 continue;
1226 1234
1227 if (port->guid_valid && memcmp(port->guid, guid, 16) == 0)
1228 return port->mstb;
1229
1230 found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid); 1235 found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid);
1231 1236
1232 if (found_mstb) 1237 if (found_mstb)
@@ -1245,10 +1250,7 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device_by_guid(
1245 /* find the port by iterating down */ 1250 /* find the port by iterating down */
1246 mutex_lock(&mgr->lock); 1251 mutex_lock(&mgr->lock);
1247 1252
1248 if (mgr->guid_valid && memcmp(mgr->guid, guid, 16) == 0) 1253 mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid);
1249 mstb = mgr->mst_primary;
1250 else
1251 mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid);
1252 1254
1253 if (mstb) 1255 if (mstb)
1254 kref_get(&mstb->kref); 1256 kref_get(&mstb->kref);
@@ -1566,6 +1568,9 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
1566 txmsg->reply.u.link_addr.ports[i].num_sdp_streams, 1568 txmsg->reply.u.link_addr.ports[i].num_sdp_streams,
1567 txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks); 1569 txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks);
1568 } 1570 }
1571
1572 drm_dp_check_mstb_guid(mstb, txmsg->reply.u.link_addr.guid);
1573
1569 for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) { 1574 for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
1570 drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]); 1575 drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]);
1571 } 1576 }
@@ -2006,20 +2011,6 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
2006 goto out_unlock; 2011 goto out_unlock;
2007 } 2012 }
2008 2013
2009
2010 /* sort out guid */
2011 ret = drm_dp_dpcd_read(mgr->aux, DP_GUID, mgr->guid, 16);
2012 if (ret != 16) {
2013 DRM_DEBUG_KMS("failed to read DP GUID %d\n", ret);
2014 goto out_unlock;
2015 }
2016
2017 mgr->guid_valid = drm_dp_validate_guid(mgr, mgr->guid);
2018 if (!mgr->guid_valid) {
2019 ret = drm_dp_dpcd_write(mgr->aux, DP_GUID, mgr->guid, 16);
2020 mgr->guid_valid = true;
2021 }
2022
2023 queue_work(system_long_wq, &mgr->work); 2014 queue_work(system_long_wq, &mgr->work);
2024 2015
2025 ret = 0; 2016 ret = 0;
@@ -2241,6 +2232,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
2241 } 2232 }
2242 2233
2243 drm_dp_update_port(mstb, &msg.u.conn_stat); 2234 drm_dp_update_port(mstb, &msg.u.conn_stat);
2235
2244 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); 2236 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);
2245 } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { 2237 } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
2246 drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false); 2238 drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 24ab1787b771..fdb47051d549 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -44,8 +44,6 @@ struct drm_dp_vcpi {
44/** 44/**
45 * struct drm_dp_mst_port - MST port 45 * struct drm_dp_mst_port - MST port
46 * @kref: reference count for this port. 46 * @kref: reference count for this port.
47 * @guid_valid: for DP 1.2 devices if we have validated the GUID.
48 * @guid: guid for DP 1.2 device on this port.
49 * @port_num: port number 47 * @port_num: port number
50 * @input: if this port is an input port. 48 * @input: if this port is an input port.
51 * @mcs: message capability status - DP 1.2 spec. 49 * @mcs: message capability status - DP 1.2 spec.
@@ -70,10 +68,6 @@ struct drm_dp_vcpi {
70struct drm_dp_mst_port { 68struct drm_dp_mst_port {
71 struct kref kref; 69 struct kref kref;
72 70
73 /* if dpcd 1.2 device is on this port - its GUID info */
74 bool guid_valid;
75 u8 guid[16];
76
77 u8 port_num; 71 u8 port_num;
78 bool input; 72 bool input;
79 bool mcs; 73 bool mcs;
@@ -110,10 +104,12 @@ struct drm_dp_mst_port {
110 * @tx_slots: transmission slots for this device. 104 * @tx_slots: transmission slots for this device.
111 * @last_seqno: last sequence number used to talk to this. 105 * @last_seqno: last sequence number used to talk to this.
112 * @link_address_sent: if a link address message has been sent to this device yet. 106 * @link_address_sent: if a link address message has been sent to this device yet.
107 * @guid: guid for DP 1.2 branch device. port under this branch can be
108 * identified by port #.
113 * 109 *
114 * This structure represents an MST branch device, there is one 110 * This structure represents an MST branch device, there is one
115 * primary branch device at the root, along with any others connected 111 * primary branch device at the root, along with any other branches connected
116 * to downstream ports 112 * to downstream port of parent branches.
117 */ 113 */
118struct drm_dp_mst_branch { 114struct drm_dp_mst_branch {
119 struct kref kref; 115 struct kref kref;
@@ -132,6 +128,9 @@ struct drm_dp_mst_branch {
132 struct drm_dp_sideband_msg_tx *tx_slots[2]; 128 struct drm_dp_sideband_msg_tx *tx_slots[2];
133 int last_seqno; 129 int last_seqno;
134 bool link_address_sent; 130 bool link_address_sent;
131
132 /* global unique identifier to identify branch devices */
133 u8 guid[16];
135}; 134};
136 135
137 136
@@ -406,11 +405,9 @@ struct drm_dp_payload {
406 * @conn_base_id: DRM connector ID this mgr is connected to. 405 * @conn_base_id: DRM connector ID this mgr is connected to.
407 * @down_rep_recv: msg receiver state for down replies. 406 * @down_rep_recv: msg receiver state for down replies.
408 * @up_req_recv: msg receiver state for up requests. 407 * @up_req_recv: msg receiver state for up requests.
409 * @lock: protects mst state, primary, guid, dpcd. 408 * @lock: protects mst state, primary, dpcd.
410 * @mst_state: if this manager is enabled for an MST capable port. 409 * @mst_state: if this manager is enabled for an MST capable port.
411 * @mst_primary: pointer to the primary branch device. 410 * @mst_primary: pointer to the primary branch device.
412 * @guid_valid: GUID valid for the primary branch device.
413 * @guid: GUID for primary port.
414 * @dpcd: cache of DPCD for primary port. 411 * @dpcd: cache of DPCD for primary port.
415 * @pbn_div: PBN to slots divisor. 412 * @pbn_div: PBN to slots divisor.
416 * 413 *
@@ -432,13 +429,11 @@ struct drm_dp_mst_topology_mgr {
432 struct drm_dp_sideband_msg_rx up_req_recv; 429 struct drm_dp_sideband_msg_rx up_req_recv;
433 430
434 /* pointer to info about the initial MST device */ 431 /* pointer to info about the initial MST device */
435 struct mutex lock; /* protects mst_state + primary + guid + dpcd */ 432 struct mutex lock; /* protects mst_state + primary + dpcd */
436 433
437 bool mst_state; 434 bool mst_state;
438 struct drm_dp_mst_branch *mst_primary; 435 struct drm_dp_mst_branch *mst_primary;
439 /* primary MST device GUID */ 436
440 bool guid_valid;
441 u8 guid[16];
442 u8 dpcd[DP_RECEIVER_CAP_SIZE]; 437 u8 dpcd[DP_RECEIVER_CAP_SIZE];
443 u8 sink_count; 438 u8 sink_count;
444 int pbn_div; 439 int pbn_div;