From: <sunpeng.li-5C7GfCeVMHo@public.gmane.org>
To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Cc: "Leo Li" <sunpeng.li-5C7GfCeVMHo@public.gmane.org>,
"Ville Syrjälä"
<ville.syrjala-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Subject: [PATCH 2/7] drm/dp_mst: Register AUX devices for MST ports
Date: Thu, 16 May 2019 11:17:58 -0400 [thread overview]
Message-ID: <1558019883-12397-3-git-send-email-sunpeng.li@amd.com> (raw)
In-Reply-To: <1558019883-12397-1-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
All available downstream ports - physical and logical - are exposed for
each MST device. They are listed in /dev/, following the same naming
scheme as SST devices by appending an incremental ID.
Although all downstream ports are exposed, only some will work as
expected. Consider the following topology:
+---------+
| ASIC |
+---------+
Conn-0|
|
+----v----+
+----| MST HUB |----+
| +---------+ |
| |
|Port-1 Port-2|
+-----v-----+ +-----v-----+
| MST | | SST |
| Display | | Display |
+-----------+ +-----------+
|Port-1
x
MST Path | MST Device
----------+----------------------------------
sst:0 | MST Hub
mst:0-1 | MST Display
mst:0-1-1 | MST Display's disconnected DP out
mst:0-1-8 | MST Display's internal sink
mst:0-2 | SST Display
On certain MST displays, the upstream physical port will ACK DPCD reads.
However, reads on the local logical port to the internal sink will
*NAK*. i.e. reading mst:0-1 ACKs, but mst:0-1-8 NAKs.
There may also be duplicates. Some displays will return the same GUID
when reading DPCD from both mst:0-1 and mst:0-1-8.
There are some device-dependent behavior as well. The MST hub used
during testing will actually *ACK* read requests on a disconnected
physical port, whereas the MST displays will NAK.
In light of these discrepancies, it's simpler to expose all downstream
ports - both physical and logical - and let the user decide what to use.
Cc: Lyude Paul <lyude@redhat.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Leo Li <sunpeng.li@amd.com>
---
drivers/gpu/drm/drm_dp_aux_dev.c | 14 ++++-
drivers/gpu/drm/drm_dp_mst_topology.c | 103 +++++++++++++++++++++++++++++-----
include/drm/drm_dp_helper.h | 4 ++
include/drm/drm_dp_mst_helper.h | 6 ++
4 files changed, 112 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 6d84611..01c02b9 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -34,6 +34,7 @@
#include <linux/uaccess.h>
#include <linux/uio.h>
#include <drm/drm_dp_helper.h>
+#include <drm/drm_dp_mst_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drmP.h>
@@ -114,6 +115,7 @@ static ssize_t name_show(struct device *dev,
return res;
}
+
static DEVICE_ATTR_RO(name);
static struct attribute *drm_dp_aux_attrs[] = {
@@ -160,7 +162,11 @@ static ssize_t auxdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
break;
}
- res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+ if (aux_dev->aux->is_remote)
+ res = drm_dp_mst_dpcd_read(aux_dev->aux, pos, buf, todo);
+ else
+ res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+
if (res <= 0)
break;
@@ -207,7 +213,11 @@ static ssize_t auxdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
break;
}
- res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+ if (aux_dev->aux->is_remote)
+ res = drm_dp_mst_dpcd_write(aux_dev->aux, pos, buf, todo);
+ else
+ res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+
if (res <= 0)
break;
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 2ab16c9..54da68e 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -35,6 +35,8 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
+#include "drm_crtc_helper_internal.h"
+
/**
* DOC: dp mst helper
*
@@ -52,6 +54,9 @@ static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
int id,
struct drm_dp_payload *payload);
+static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port,
+ int offset, int size, u8 *bytes);
static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_port *port,
int offset, int size, u8 *bytes);
@@ -941,6 +946,8 @@ static void drm_dp_destroy_port(struct kref *kref)
struct drm_dp_mst_topology_mgr *mgr = port->mgr;
if (!port->input) {
+ drm_dp_aux_unregister_devnode(&port->aux);
+
port->vcpi.num_slots = 0;
kfree(port->cached_edid);
@@ -1095,6 +1102,46 @@ static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port *port)
return send_link;
}
+/**
+ * drm_dp_mst_dpcd_read() - read a series of bytes from the DPCD via sideband
+ * @aux: Fake sideband AUX CH
+ * @offset: address of the (first) register to read
+ * @buffer: buffer to store the register values
+ * @size: number of bytes in @buffer
+ *
+ * Performs the same functionality for remote devices via
+ * sideband messaging as drm_dp_dpcd_read() does for local
+ * devices via actual AUX CH.
+ */
+ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux,
+ unsigned int offset, void *buffer, size_t size)
+{
+ struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port, aux);
+
+ return drm_dp_send_dpcd_read(port->mgr, port,
+ offset, size, buffer);
+}
+
+/**
+ * drm_dp_mst_dpcd_write() - write a series of bytes to the DPCD via sideband
+ * @aux: Fake sideband AUX CH
+ * @offset: address of the (first) register to write
+ * @buffer: buffer containing the values to write
+ * @size: number of bytes in @buffer
+ *
+ * Performs the same functionality for remote devices via
+ * sideband messaging as drm_dp_dpcd_write() does for local
+ * devices via actual AUX CH.
+ */
+ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux,
+ unsigned int offset, void *buffer, size_t size)
+{
+ struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port, aux);
+
+ return drm_dp_send_dpcd_write(port->mgr, port,
+ offset, size, buffer);
+}
+
static void drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid)
{
int ret;
@@ -1158,6 +1205,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
port->mgr = mstb->mgr;
port->aux.name = "DPMST";
port->aux.dev = dev->dev;
+ port->aux.is_remote = true;
created = true;
} else {
old_pdt = port->pdt;
@@ -1188,7 +1236,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
drm_dp_send_enum_path_resources(mstb->mgr, mstb, port);
} else {
port->available_pbn = 0;
- }
+ }
}
if (old_pdt != port->pdt && !port->input) {
@@ -1220,6 +1268,8 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
drm_connector_set_tile_property(port->connector);
}
(*mstb->mgr->cbs->register_connector)(port->connector);
+
+ drm_dp_aux_register_devnode(&port->aux);
}
out:
@@ -1404,7 +1454,6 @@ static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
return false;
}
-#if 0
static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32 offset, u8 num_bytes)
{
struct drm_dp_sideband_msg_req_body req;
@@ -1417,7 +1466,6 @@ static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32
return 0;
}
-#endif
static int drm_dp_send_sideband_msg(struct drm_dp_mst_topology_mgr *mgr,
bool up, u8 *msg, int len)
@@ -1994,26 +2042,55 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
}
EXPORT_SYMBOL(drm_dp_update_payload_part2);
-#if 0 /* unused as of yet */
static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_port *port,
- int offset, int size)
+ int offset, int size, u8 *bytes)
{
int len;
+ int ret = 0;
struct drm_dp_sideband_msg_tx *txmsg;
+ struct drm_dp_mst_branch *mstb;
+
+ mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
+ if (!mstb)
+ return -EINVAL;
txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
- if (!txmsg)
- return -ENOMEM;
+ if (!txmsg) {
+ ret = -ENOMEM;
+ goto fail_put;
+ }
- len = build_dpcd_read(txmsg, port->port_num, 0, 8);
+ len = build_dpcd_read(txmsg, port->port_num, offset, size);
txmsg->dst = port->parent;
drm_dp_queue_down_tx(mgr, txmsg);
- return 0;
+ ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
+ if (ret < 0)
+ goto fail_free;
+
+ /* DPCD read should never be NACKed */
+ if (WARN_ON_ONCE(txmsg->reply.reply_type == 1)) {
+ ret = -EIO;
+ goto fail_free;
+ }
+
+ if (txmsg->reply.u.remote_dpcd_read_ack.num_bytes != size) {
+ ret = -EPROTO;
+ goto fail_free;
+ }
+
+ ret = min_t(size_t, txmsg->reply.u.remote_dpcd_read_ack.num_bytes, size);
+ memcpy(bytes, txmsg->reply.u.remote_dpcd_read_ack.bytes, ret);
+
+fail_free:
+ kfree(txmsg);
+fail_put:
+ drm_dp_put_mst_branch_device(mstb);
+
+ return ret;
}
-#endif
static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_port *port,
@@ -2041,9 +2118,9 @@ static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
if (ret > 0) {
- if (txmsg->reply.reply_type == 1) {
- ret = -EINVAL;
- } else
+ if (txmsg->reply.reply_type == 1)
+ ret = -EIO;
+ else
ret = 0;
}
kfree(txmsg);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 509667e..6dea76a 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1265,6 +1265,10 @@ struct drm_dp_aux {
* @cec: struct containing fields used for CEC-Tunneling-over-AUX.
*/
struct drm_dp_aux_cec cec;
+ /**
+ * @is_remote: Is this "AUX CH" actually using sideband messaging.
+ */
+ bool is_remote;
};
ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 371cc28..30f8c11 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -615,6 +615,12 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
+
+ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux,
+ unsigned int offset, void *buffer, size_t size);
+ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux,
+ unsigned int offset, void *buffer, size_t size);
+
struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
struct drm_dp_mst_topology_mgr *mgr);
int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
--
2.7.4
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
next prev parent reply other threads:[~2019-05-16 15:17 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-16 15:17 [PATCH 0/7] Add DP MST AUX devices sunpeng.li-5C7GfCeVMHo
2019-05-16 15:17 ` [PATCH 1/7] drm/dp: Use non-cyclic idr sunpeng.li
[not found] ` <1558019883-12397-1-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2019-05-16 15:17 ` sunpeng.li-5C7GfCeVMHo [this message]
[not found] ` <1558019883-12397-3-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2019-05-16 21:40 ` [PATCH 2/7] drm/dp_mst: Register AUX devices for MST ports Lyude Paul
[not found] ` <3e237f325a98b044231661886329a808d6701146.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2019-05-30 18:20 ` Li, Sun peng (Leo)
2019-06-03 19:25 ` Lyude Paul
2019-06-03 19:28 ` Lyude Paul
2019-06-06 19:41 ` Li, Sun peng (Leo)
[not found] ` <1acd58fd-a5e8-0f07-709a-902ea67ba760-5C7GfCeVMHo@public.gmane.org>
2019-06-06 21:07 ` Lyude Paul
2019-06-27 22:21 ` Li, Sun peng (Leo)
[not found] ` <f800b501-422e-c7fb-ebce-bd0e1717d2b2-5C7GfCeVMHo@public.gmane.org>
2019-07-01 20:43 ` Lyude Paul
2019-05-16 15:17 ` [PATCH 3/7] drm/dp-mst: Use connector kdev as aux device parent sunpeng.li-5C7GfCeVMHo
[not found] ` <1558019883-12397-4-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2019-05-16 20:23 ` Lyude Paul
2019-05-16 21:30 ` Lyude Paul
2019-05-16 15:18 ` [PATCH 4/7] drm/sysfs: Add mstpath attribute to connector devices sunpeng.li-5C7GfCeVMHo
2019-05-16 15:18 ` [PATCH 7/7] drm/nouveau: Use connector kdev as aux device parent sunpeng.li-5C7GfCeVMHo
[not found] ` <1558019883-12397-8-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2019-05-16 21:40 ` Lyude Paul
2019-05-16 19:54 ` [PATCH 0/7] Add DP MST AUX devices Lyude Paul
2019-05-16 20:18 ` Lyude Paul
[not found] ` <2248d762446e824def09699f0ef719b9c90d0dbc.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2019-05-16 20:21 ` Li, Sun peng (Leo)
2019-05-16 15:18 ` [PATCH 5/7] drm/amd/display: Use connector kdev as aux device parent sunpeng.li
2019-05-16 17:21 ` Kazlauskas, Nicholas
2019-05-16 15:18 ` [PATCH 6/7] drm/bridge/analogix-anx78xx: " sunpeng.li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1558019883-12397-3-git-send-email-sunpeng.li@amd.com \
--to=sunpeng.li-5c7gfcevmho@public.gmane.org \
--cc=amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
--cc=dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
--cc=ville.syrjala-VuQAYsv1563Yd54FQh9/CA@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox