mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
Merge "disp: msm: dp: fix refcount issues on mst port disconnect"
This commit is contained in:
commit
dab2d306d2
1 changed files with 47 additions and 37 deletions
|
|
@ -259,7 +259,20 @@ static void dp_mst_sim_topology_put_port(struct drm_dp_mst_port *port)
|
|||
kref_put(&port->topology_kref, dp_mst_sim_destroy_port);
|
||||
}
|
||||
|
||||
/* DRM DP MST Framework simulator OPs */
|
||||
/*
|
||||
* DRM DP MST Framework simulator OPs
|
||||
*
|
||||
* If simulation mode is enabled, on HPD connect, mst mode is enabled on the
|
||||
* topology manager and 2 simulated ports are created using
|
||||
* dp_mst_sim_add_port. These 2 ports are added to the MST branch device.
|
||||
* Each node in the DP MST topology has 2 reference objects one for memory
|
||||
* allocation and the other for its use on the topology tree. When the last
|
||||
* topology reference is released on a port, the port gets destroyed and when
|
||||
* the last malloc reference is released, then the port memory is freed.
|
||||
* Each port also gets a reference on its parent branch object to make sure
|
||||
* that the branch is not destroyed prematurely.
|
||||
*/
|
||||
|
||||
static void dp_mst_sim_add_port(struct dp_mst_private *mst,
|
||||
struct dp_mst_sim_port_data *port_msg)
|
||||
{
|
||||
|
|
@ -324,6 +337,31 @@ put_port:
|
|||
dp_mst_sim_topology_put_port(port);
|
||||
}
|
||||
|
||||
static void dp_mst_sim_remove_port(struct dp_mst_private *mst,
|
||||
struct drm_dp_mst_port *port)
|
||||
{
|
||||
struct drm_dp_mst_branch *mstb;
|
||||
int i;
|
||||
|
||||
mstb = mst->mst_mgr.mst_primary;
|
||||
if (!mstb) {
|
||||
DP_ERR("Unable to remove port. mst branch device is null\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&mstb->mgr->lock);
|
||||
list_del(&port->next);
|
||||
mutex_unlock(&mstb->mgr->lock);
|
||||
dp_mst_sim_topology_put_port(port);
|
||||
|
||||
for (i = 0; i < DP_MST_SIM_MAX_PORTS; i++) {
|
||||
if (mst->simulator.port_edids[i].port_number ==
|
||||
port->port_num) {
|
||||
mst->simulator.port_edids[i].valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dp_mst_sim_link_probe_work(struct work_struct *work)
|
||||
{
|
||||
struct dp_mst_sim_mode *sim;
|
||||
|
|
@ -500,13 +538,8 @@ static int dp_mst_sim_topology_mgr_set_mst(
|
|||
struct dp_mst_private *mst = container_of(mgr,
|
||||
struct dp_mst_private, mst_mgr);
|
||||
|
||||
/*
|
||||
* Setting mst off on the mgr initiates shutdown of the branch device.
|
||||
* Moving the disable to bridge disable in order to make sure the
|
||||
* connector is valid till the hpd notification is completed.
|
||||
*/
|
||||
if (!mst_state)
|
||||
return 0;
|
||||
DP_MST_DEBUG("enter: mst_state %d\n", mst_state);
|
||||
SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY, mst_state);
|
||||
|
||||
rc = drm_dp_mst_topology_mgr_set_mst(mgr, mst_state);
|
||||
if (rc < 0) {
|
||||
|
|
@ -514,7 +547,8 @@ static int dp_mst_sim_topology_mgr_set_mst(
|
|||
return rc;
|
||||
}
|
||||
|
||||
queue_work(system_long_wq, &mst->simulator.probe_work);
|
||||
if (mst_state)
|
||||
queue_work(system_long_wq, &mst->simulator.probe_work);
|
||||
|
||||
mst->simulator.mst_state = mst_state;
|
||||
return 0;
|
||||
|
|
@ -574,7 +608,6 @@ static void dp_mst_sim_handle_hpd_irq(void *dp_display,
|
|||
if (port->connector && port->connector->base.id ==
|
||||
info->mst_sim_remove_con_id) {
|
||||
in_list = true;
|
||||
list_del(&port->next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -584,13 +617,8 @@ static void dp_mst_sim_handle_hpd_irq(void *dp_display,
|
|||
DRM_ERROR("invalid connector id %d\n",
|
||||
info->mst_sim_remove_con_id);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < DP_MST_SIM_MAX_PORTS; i++) {
|
||||
if (mst->simulator.port_edids[i].port_number ==
|
||||
port->port_num) {
|
||||
mst->simulator.port_edids[i].valid = false;
|
||||
}
|
||||
} else {
|
||||
dp_mst_sim_remove_port(mst, port);
|
||||
}
|
||||
|
||||
dp_mst_sim_topology_put_port(port);
|
||||
|
|
@ -855,14 +883,6 @@ static void _dp_mst_bridge_pre_enable_part1(struct dp_mst_bridge *dp_bridge)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take a reference to the port topology to make sure the port object
|
||||
* is available while waiting for the connector to be cleaned up after
|
||||
* hpd low. This reference will be released in the disable path.
|
||||
*/
|
||||
if (mst->simulator.mst_state)
|
||||
dp_mst_sim_topology_get_port(port);
|
||||
|
||||
pbn = mst->mst_fw_cbs->calc_pbn_mode(&dp_bridge->dp_mode);
|
||||
|
||||
slots = mst->mst_fw_cbs->find_vcpi_slots(&mst->mst_mgr, pbn);
|
||||
|
|
@ -940,7 +960,6 @@ static void _dp_mst_bridge_pre_disable_part2(struct dp_mst_bridge *dp_bridge)
|
|||
struct sde_connector *c_conn =
|
||||
to_sde_connector(dp_bridge->connector);
|
||||
struct drm_dp_mst_port *port = c_conn->mst_port;
|
||||
int rc = 0;
|
||||
|
||||
DP_MST_DEBUG("enter\n");
|
||||
SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY);
|
||||
|
|
@ -960,17 +979,8 @@ static void _dp_mst_bridge_pre_disable_part2(struct dp_mst_bridge *dp_bridge)
|
|||
port->vcpi.vcpi = dp_bridge->vcpi;
|
||||
mst->mst_fw_cbs->deallocate_vcpi(&mst->mst_mgr, port);
|
||||
|
||||
if (mst->simulator.mst_state) {
|
||||
rc = drm_dp_mst_topology_mgr_set_mst(&mst->mst_mgr, false);
|
||||
if (rc < 0)
|
||||
DRM_WARN("unable to set mst topology mgr, rc: %d\n",
|
||||
rc);
|
||||
|
||||
/* release the reference taken during pre_enable */
|
||||
dp_mst_sim_topology_put_port(port);
|
||||
|
||||
mst->simulator.mst_state = false;
|
||||
}
|
||||
if (mst->simulator.mst_state)
|
||||
dp_mst_sim_remove_port(mst, port);
|
||||
|
||||
dp_bridge->vcpi = 0;
|
||||
dp_bridge->pbn = 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue