* Patch "drm/dp/mst: deallocate payload on port destruction" has been added to the 4.4-stable tree
@ 2016-03-01 19:50 gregkh
0 siblings, 0 replies; only message in thread
From: gregkh @ 2016-03-01 19:50 UTC (permalink / raw)
To: Mykola.Lysenko, Harry.Wentland, airlied, gregkh; +Cc: stable, stable-commits
This is a note to let you know that I've just added the patch titled
drm/dp/mst: deallocate payload on port destruction
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
drm-dp-mst-deallocate-payload-on-port-destruction.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@vger.kernel.org> know about it.
>From 91a25e463130c8e19bdb42f2d827836c7937992e Mon Sep 17 00:00:00 2001
From: Mykola Lysenko <Mykola.Lysenko@amd.com>
Date: Wed, 27 Jan 2016 09:39:36 -0500
Subject: drm/dp/mst: deallocate payload on port destruction
From: Mykola Lysenko <Mykola.Lysenko@amd.com>
commit 91a25e463130c8e19bdb42f2d827836c7937992e upstream.
This is needed to properly deallocate port payload
after downstream branch get unplugged.
In order to do this unplugged MST topology should
be preserved, to find first alive port on path to
unplugged MST topology, and send payload deallocation
request to branch device of found port.
For this mstb and port kref's are used in reversed
order to track when port and branch memory could be
freed.
Added additional functions to find appropriate mstb
as described above.
Signed-off-by: Mykola Lysenko <Mykola.Lysenko@amd.com>
Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_dp_mst_topology.c | 91 +++++++++++++++++++++++++++++++---
1 file changed, 83 insertions(+), 8 deletions(-)
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -798,6 +798,18 @@ static struct drm_dp_mst_branch *drm_dp_
return mstb;
}
+static void drm_dp_free_mst_port(struct kref *kref);
+
+static void drm_dp_free_mst_branch_device(struct kref *kref)
+{
+ struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
+ if (mstb->port_parent) {
+ if (list_empty(&mstb->port_parent->next))
+ kref_put(&mstb->port_parent->kref, drm_dp_free_mst_port);
+ }
+ kfree(mstb);
+}
+
static void drm_dp_destroy_mst_branch_device(struct kref *kref)
{
struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
@@ -805,6 +817,15 @@ static void drm_dp_destroy_mst_branch_de
bool wake_tx = false;
/*
+ * init kref again to be used by ports to remove mst branch when it is
+ * not needed anymore
+ */
+ kref_init(kref);
+
+ if (mstb->port_parent && list_empty(&mstb->port_parent->next))
+ kref_get(&mstb->port_parent->kref);
+
+ /*
* destroy all ports - don't need lock
* as there are no more references to the mst branch
* device at this point.
@@ -830,7 +851,8 @@ static void drm_dp_destroy_mst_branch_de
if (wake_tx)
wake_up(&mstb->mgr->tx_waitq);
- kfree(mstb);
+
+ kref_put(kref, drm_dp_free_mst_branch_device);
}
static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb)
@@ -878,6 +900,7 @@ static void drm_dp_destroy_port(struct k
* from an EDID retrieval */
mutex_lock(&mgr->destroy_connector_lock);
+ kref_get(&port->parent->kref);
list_add(&port->next, &mgr->destroy_connector_list);
mutex_unlock(&mgr->destroy_connector_lock);
schedule_work(&mgr->destroy_connector_work);
@@ -1602,6 +1625,37 @@ static int drm_dp_send_enum_path_resourc
return 0;
}
+static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm_dp_mst_branch *mstb)
+{
+ if (!mstb->port_parent)
+ return NULL;
+
+ if (mstb->port_parent->mstb != mstb)
+ return mstb->port_parent;
+
+ return drm_dp_get_last_connected_port_to_mstb(mstb->port_parent->parent);
+}
+
+static struct drm_dp_mst_branch *drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_branch *mstb,
+ int *port_num)
+{
+ struct drm_dp_mst_branch *rmstb = NULL;
+ struct drm_dp_mst_port *found_port;
+ mutex_lock(&mgr->lock);
+ if (mgr->mst_primary) {
+ found_port = drm_dp_get_last_connected_port_to_mstb(mstb);
+
+ if (found_port) {
+ rmstb = found_port->parent;
+ kref_get(&rmstb->kref);
+ *port_num = found_port->port_num;
+ }
+ }
+ mutex_unlock(&mgr->lock);
+ return rmstb;
+}
+
static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_port *port,
int id,
@@ -1609,11 +1663,16 @@ static int drm_dp_payload_send_msg(struc
{
struct drm_dp_sideband_msg_tx *txmsg;
struct drm_dp_mst_branch *mstb;
- int len, ret;
+ int len, ret, port_num;
+ port_num = port->port_num;
mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
- if (!mstb)
- return -EINVAL;
+ if (!mstb) {
+ mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, &port_num);
+
+ if (!mstb)
+ return -EINVAL;
+ }
txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
if (!txmsg) {
@@ -1622,7 +1681,7 @@ static int drm_dp_payload_send_msg(struc
}
txmsg->dst = mstb;
- len = build_allocate_payload(txmsg, port->port_num,
+ len = build_allocate_payload(txmsg, port_num,
id,
pbn);
@@ -2752,6 +2811,13 @@ static void drm_dp_tx_work(struct work_s
mutex_unlock(&mgr->qlock);
}
+static void drm_dp_free_mst_port(struct kref *kref)
+{
+ struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
+ kref_put(&port->parent->kref, drm_dp_free_mst_branch_device);
+ kfree(port);
+}
+
static void drm_dp_destroy_connector_work(struct work_struct *work)
{
struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
@@ -2772,13 +2838,22 @@ static void drm_dp_destroy_connector_wor
list_del(&port->next);
mutex_unlock(&mgr->destroy_connector_lock);
+ kref_init(&port->kref);
+ INIT_LIST_HEAD(&port->next);
+
mgr->cbs->destroy_connector(mgr, port->connector);
drm_dp_port_teardown_pdt(port, port->pdt);
- if (!port->input && port->vcpi.vcpi > 0)
- drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
- kfree(port);
+ if (!port->input && port->vcpi.vcpi > 0) {
+ if (mgr->mst_state) {
+ drm_dp_mst_reset_vcpi_slots(mgr, port);
+ drm_dp_update_payload_part1(mgr);
+ drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
+ }
+ }
+
+ kref_put(&port->kref, drm_dp_free_mst_port);
send_hotplug = true;
}
if (send_hotplug)
Patches currently in stable-queue which might be from Mykola.Lysenko@amd.com are
queue-4.4/drm-dp-mst-deallocate-payload-on-port-destruction.patch
queue-4.4/drm-dp-mst-process-broadcast-messages-correctly.patch
queue-4.4/drm-dp-mst-fix-in-rad-element-access.patch
queue-4.4/drm-dp-mst-always-send-reply-for-up-request.patch
queue-4.4/drm-dp-mst-fix-in-mstb-rad-initialization.patch
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2016-03-01 19:50 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-01 19:50 Patch "drm/dp/mst: deallocate payload on port destruction" has been added to the 4.4-stable tree gregkh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox