| @@ -867,8 +867,16 @@ static void drm_dp_destroy_port(struct kref *kref) · 866 unmodified lines |
| 867 | port->vcpi.num_slots = 0; | 867 | port->vcpi.num_slots = 0; |
| 868 | | 868 | |
| 869 | kfree(port->cached_edid); | 869 | kfree(port->cached_edid); |
| 870 | if (port->connector) | 870 | |
| 871 | (*port->mgr->cbs->destroy_connector)(mgr, port->connector); | 871 | /* we can't destroy the connector here, as |
| | 872 | we might be holding the mode_config.mutex |
| | 873 | from an EDID retrieval */ |
| | 874 | if (port->connector) { |
| | 875 | mutex_lock(&mgr->destroy_connector_lock); |
| | 876 | list_add(&port->connector->destroy_list, &mgr->destroy_connector_list); |
| | 877 | mutex_unlock(&mgr->destroy_connector_lock); |
| | 878 | schedule_work(&mgr->destroy_connector_work); |
| | 879 | } |
| 872 | drm_dp_port_teardown_pdt(port, port->pdt); | 880 | drm_dp_port_teardown_pdt(port, port->pdt); |
| 873 | | 881 | |
| 874 | if (!port->input && port->vcpi.vcpi > 0) | 882 | if (!port->input && port->vcpi.vcpi > 0) |
| @@ -2649,6 +2657,30 @@ static void drm_dp_tx_work(struct work_struct *work) · 1774 unmodified lines |
| 2649 | mutex_unlock(&mgr->qlock); | 2657 | mutex_unlock(&mgr->qlock); |
| 2650 | } | 2658 | } |
| 2651 | | 2659 | |
| | 2660 | static void drm_dp_destroy_connector_work(struct work_struct *work) |
| | 2661 | { |
| | 2662 | struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work); |
| | 2663 | struct drm_connector *connector; |
| | 2664 | |
| | 2665 | /* |
| | 2666 | * Not a regular list traverse as we have to drop the destroy |
| | 2667 | * connector lock before destroying the connector, to avoid AB->BA |
| | 2668 | * ordering between this lock and the config mutex. |
| | 2669 | */ |
| | 2670 | for (;;) { |
| | 2671 | mutex_lock(&mgr->destroy_connector_lock); |
| | 2672 | connector = list_first_entry_or_null(&mgr->destroy_connector_list, struct drm_connector, destroy_list); |
| | 2673 | if (!connector) { |
| | 2674 | mutex_unlock(&mgr->destroy_connector_lock); |
| | 2675 | break; |
| | 2676 | } |
| | 2677 | list_del(&connector->destroy_list); |
| | 2678 | mutex_unlock(&mgr->destroy_connector_lock); |
| | 2679 | |
| | 2680 | mgr->cbs->destroy_connector(mgr, connector); |
| | 2681 | } |
| | 2682 | } |
| | 2683 | |
| 2652 | /** | 2684 | /** |
| 2653 | * drm_dp_mst_topology_mgr_init - initialise a topology manager | 2685 | * drm_dp_mst_topology_mgr_init - initialise a topology manager |
| 2654 | * @mgr: manager struct to initialise | 2686 | * @mgr: manager struct to initialise |
| @@ -2668,10 +2700,13 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, · 13 unmodified lines |
| 2668 | mutex_init(&mgr->lock); | 2700 | mutex_init(&mgr->lock); |
| 2669 | mutex_init(&mgr->qlock); | 2701 | mutex_init(&mgr->qlock); |
| 2670 | mutex_init(&mgr->payload_lock); | 2702 | mutex_init(&mgr->payload_lock); |
| | 2703 | mutex_init(&mgr->destroy_connector_lock); |
| 2671 | INIT_LIST_HEAD(&mgr->tx_msg_upq); | 2704 | INIT_LIST_HEAD(&mgr->tx_msg_upq); |
| 2672 | INIT_LIST_HEAD(&mgr->tx_msg_downq); | 2705 | INIT_LIST_HEAD(&mgr->tx_msg_downq); |
| | 2706 | INIT_LIST_HEAD(&mgr->destroy_connector_list); |
| 2673 | INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work); | 2707 | INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work); |
| 2674 | INIT_WORK(&mgr->tx_work, drm_dp_tx_work); | 2708 | INIT_WORK(&mgr->tx_work, drm_dp_tx_work); |
| | 2709 | INIT_WORK(&mgr->destroy_connector_work, drm_dp_destroy_connector_work); |
| 2675 | init_waitqueue_head(&mgr->tx_waitq); | 2710 | init_waitqueue_head(&mgr->tx_waitq); |
| 2676 | mgr->dev = dev; | 2711 | mgr->dev = dev; |
| 2677 | mgr->aux = aux; | 2712 | mgr->aux = aux; |
| @@ -2696,6 +2731,7 @@ EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init); · 18 unmodified lines |
| 2696 | */ | 2731 | */ |
| 2697 | void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr) | 2732 | void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr) |
| 2698 | { | 2733 | { |
| | 2734 | flush_work(&mgr->destroy_connector_work); |
| 2699 | mutex_lock(&mgr->payload_lock); | 2735 | mutex_lock(&mgr->payload_lock); |
| 2700 | kfree(mgr->payloads); | 2736 | kfree(mgr->payloads); |
| 2701 | mgr->payloads = NULL; | 2737 | mgr->payloads = NULL; |