aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c91
1 files changed, 83 insertions, 8 deletions
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 7e5d98c7b908..8ae13de272c4 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -803,6 +803,18 @@ static struct drm_dp_mst_branch *drm_dp_add_mst_branch_device(u8 lct, u8 *rad)
803 return mstb; 803 return mstb;
804} 804}
805 805
806static void drm_dp_free_mst_port(struct kref *kref);
807
808static void drm_dp_free_mst_branch_device(struct kref *kref)
809{
810 struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
811 if (mstb->port_parent) {
812 if (list_empty(&mstb->port_parent->next))
813 kref_put(&mstb->port_parent->kref, drm_dp_free_mst_port);
814 }
815 kfree(mstb);
816}
817
806static void drm_dp_destroy_mst_branch_device(struct kref *kref) 818static void drm_dp_destroy_mst_branch_device(struct kref *kref)
807{ 819{
808 struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref); 820 struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
@@ -810,6 +822,15 @@ static void drm_dp_destroy_mst_branch_device(struct kref *kref)
810 bool wake_tx = false; 822 bool wake_tx = false;
811 823
812 /* 824 /*
825 * init kref again to be used by ports to remove mst branch when it is
826 * not needed anymore
827 */
828 kref_init(kref);
829
830 if (mstb->port_parent && list_empty(&mstb->port_parent->next))
831 kref_get(&mstb->port_parent->kref);
832
833 /*
813 * destroy all ports - don't need lock 834 * destroy all ports - don't need lock
814 * as there are no more references to the mst branch 835 * as there are no more references to the mst branch
815 * device at this point. 836 * device at this point.
@@ -835,7 +856,8 @@ static void drm_dp_destroy_mst_branch_device(struct kref *kref)
835 856
836 if (wake_tx) 857 if (wake_tx)
837 wake_up(&mstb->mgr->tx_waitq); 858 wake_up(&mstb->mgr->tx_waitq);
838 kfree(mstb); 859
860 kref_put(kref, drm_dp_free_mst_branch_device);
839} 861}
840 862
841static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb) 863static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb)
@@ -883,6 +905,7 @@ static void drm_dp_destroy_port(struct kref *kref)
883 * from an EDID retrieval */ 905 * from an EDID retrieval */
884 906
885 mutex_lock(&mgr->destroy_connector_lock); 907 mutex_lock(&mgr->destroy_connector_lock);
908 kref_get(&port->parent->kref);
886 list_add(&port->next, &mgr->destroy_connector_list); 909 list_add(&port->next, &mgr->destroy_connector_list);
887 mutex_unlock(&mgr->destroy_connector_lock); 910 mutex_unlock(&mgr->destroy_connector_lock);
888 schedule_work(&mgr->destroy_connector_work); 911 schedule_work(&mgr->destroy_connector_work);
@@ -1617,6 +1640,37 @@ static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
1617 return 0; 1640 return 0;
1618} 1641}
1619 1642
1643static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm_dp_mst_branch *mstb)
1644{
1645 if (!mstb->port_parent)
1646 return NULL;
1647
1648 if (mstb->port_parent->mstb != mstb)
1649 return mstb->port_parent;
1650
1651 return drm_dp_get_last_connected_port_to_mstb(mstb->port_parent->parent);
1652}
1653
1654static struct drm_dp_mst_branch *drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr,
1655 struct drm_dp_mst_branch *mstb,
1656 int *port_num)
1657{
1658 struct drm_dp_mst_branch *rmstb = NULL;
1659 struct drm_dp_mst_port *found_port;
1660 mutex_lock(&mgr->lock);
1661 if (mgr->mst_primary) {
1662 found_port = drm_dp_get_last_connected_port_to_mstb(mstb);
1663
1664 if (found_port) {
1665 rmstb = found_port->parent;
1666 kref_get(&rmstb->kref);
1667 *port_num = found_port->port_num;
1668 }
1669 }
1670 mutex_unlock(&mgr->lock);
1671 return rmstb;
1672}
1673
1620static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, 1674static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
1621 struct drm_dp_mst_port *port, 1675 struct drm_dp_mst_port *port,
1622 int id, 1676 int id,
@@ -1624,13 +1678,18 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
1624{ 1678{
1625 struct drm_dp_sideband_msg_tx *txmsg; 1679 struct drm_dp_sideband_msg_tx *txmsg;
1626 struct drm_dp_mst_branch *mstb; 1680 struct drm_dp_mst_branch *mstb;
1627 int len, ret; 1681 int len, ret, port_num;
1628 u8 sinks[DRM_DP_MAX_SDP_STREAMS]; 1682 u8 sinks[DRM_DP_MAX_SDP_STREAMS];
1629 int i; 1683 int i;
1630 1684
1685 port_num = port->port_num;
1631 mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent); 1686 mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
1632 if (!mstb) 1687 if (!mstb) {
1633 return -EINVAL; 1688 mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, &port_num);
1689
1690 if (!mstb)
1691 return -EINVAL;
1692 }
1634 1693
1635 txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); 1694 txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
1636 if (!txmsg) { 1695 if (!txmsg) {
@@ -1642,7 +1701,7 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
1642 sinks[i] = i; 1701 sinks[i] = i;
1643 1702
1644 txmsg->dst = mstb; 1703 txmsg->dst = mstb;
1645 len = build_allocate_payload(txmsg, port->port_num, 1704 len = build_allocate_payload(txmsg, port_num,
1646 id, 1705 id,
1647 pbn, port->num_sdp_streams, sinks); 1706 pbn, port->num_sdp_streams, sinks);
1648 1707
@@ -2788,6 +2847,13 @@ static void drm_dp_tx_work(struct work_struct *work)
2788 mutex_unlock(&mgr->qlock); 2847 mutex_unlock(&mgr->qlock);
2789} 2848}
2790 2849
2850static void drm_dp_free_mst_port(struct kref *kref)
2851{
2852 struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
2853 kref_put(&port->parent->kref, drm_dp_free_mst_branch_device);
2854 kfree(port);
2855}
2856
2791static void drm_dp_destroy_connector_work(struct work_struct *work) 2857static void drm_dp_destroy_connector_work(struct work_struct *work)
2792{ 2858{
2793 struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work); 2859 struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
@@ -2808,13 +2874,22 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
2808 list_del(&port->next); 2874 list_del(&port->next);
2809 mutex_unlock(&mgr->destroy_connector_lock); 2875 mutex_unlock(&mgr->destroy_connector_lock);
2810 2876
2877 kref_init(&port->kref);
2878 INIT_LIST_HEAD(&port->next);
2879
2811 mgr->cbs->destroy_connector(mgr, port->connector); 2880 mgr->cbs->destroy_connector(mgr, port->connector);
2812 2881
2813 drm_dp_port_teardown_pdt(port, port->pdt); 2882 drm_dp_port_teardown_pdt(port, port->pdt);
2814 2883
2815 if (!port->input && port->vcpi.vcpi > 0) 2884 if (!port->input && port->vcpi.vcpi > 0) {
2816 drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); 2885 if (mgr->mst_state) {
2817 kfree(port); 2886 drm_dp_mst_reset_vcpi_slots(mgr, port);
2887 drm_dp_update_payload_part1(mgr);
2888 drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
2889 }
2890 }
2891
2892 kref_put(&port->kref, drm_dp_free_mst_port);
2818 send_hotplug = true; 2893 send_hotplug = true;
2819 } 2894 }
2820 if (send_hotplug) 2895 if (send_hotplug)