|
@@ -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;
|