diff options
Diffstat (limited to 'drivers/gpu/drm/drm_dp_mst_topology.c')
| -rw-r--r-- | drivers/gpu/drm/drm_dp_mst_topology.c | 29 | 
1 files changed, 28 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 27fbd79d0daf..71ea0521ea96 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1672,13 +1672,19 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,  	u8 sinks[DRM_DP_MAX_SDP_STREAMS];  	int i; +	port = drm_dp_get_validated_port_ref(mgr, port); +	if (!port) +		return -EINVAL; +  	port_num = port->port_num;  	mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);  	if (!mstb) {  		mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, &port_num); -		if (!mstb) +		if (!mstb) { +			drm_dp_put_port(port);  			return -EINVAL; +		}  	}  	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); @@ -1707,6 +1713,7 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,  	kfree(txmsg);  fail_put:  	drm_dp_put_mst_branch_device(mstb); +	drm_dp_put_port(port);  	return ret;  } @@ -1789,6 +1796,11 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)  		req_payload.start_slot = cur_slots;  		if (mgr->proposed_vcpis[i]) {  			port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi); +			port = drm_dp_get_validated_port_ref(mgr, port); +			if (!port) { +				mutex_unlock(&mgr->payload_lock); +				return -EINVAL; +			}  			req_payload.num_slots = mgr->proposed_vcpis[i]->num_slots;  			req_payload.vcpi = mgr->proposed_vcpis[i]->vcpi;  		} else { @@ -1816,6 +1828,9 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)  			mgr->payloads[i].payload_state = req_payload.payload_state;  		}  		cur_slots += req_payload.num_slots; + +		if (port) +			drm_dp_put_port(port);  	}  	for (i = 0; i < mgr->max_payloads; i++) { @@ -2121,6 +2136,8 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr)  	if (mgr->mst_primary) {  		int sret; +		u8 guid[16]; +  		sret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, mgr->dpcd, DP_RECEIVER_CAP_SIZE);  		if (sret != DP_RECEIVER_CAP_SIZE) {  			DRM_DEBUG_KMS("dpcd read failed - undocked during suspend?\n"); @@ -2135,6 +2152,16 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr)  			ret = -1;  			goto out_unlock;  		} + +		/* Some hubs forget their guids after they resume */ +		sret = drm_dp_dpcd_read(mgr->aux, DP_GUID, guid, 16); +		if (sret != 16) { +			DRM_DEBUG_KMS("dpcd read failed - undocked during suspend?\n"); +			ret = -1; +			goto out_unlock; +		} +		drm_dp_check_mstb_guid(mgr->mst_primary, guid); +  		ret = 0;  	} else  		ret = -1;  | 
