diff options
author | Dave Airlie <airlied@redhat.com> | 2020-05-08 15:16:36 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2020-05-08 15:17:08 +1000 |
commit | 3fd911b69b3117e03181262fc19ae6c3ef6962ce (patch) | |
tree | 7c1f253b56715cd6f19b8c53301c44279bd58c55 /drivers/gpu/drm/drm_dp_mst_topology.c | |
parent | 370fb6b0aaf07c66a3317d5b35fba4345b31035c (diff) | |
parent | 0ea2ea42b31abc1141f2fd3911f952a97d401fcb (diff) | |
download | linux-3fd911b69b3117e03181262fc19ae6c3ef6962ce.tar.bz2 |
Merge tag 'drm-misc-next-2020-05-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 5.8:
UAPI Changes:
Cross-subsystem Changes:
* MAINTAINERS: restore alphabetical order; update cirrus driver
* Dcomuentation: document visionix, chronteli, ite vendor prefices; update
documentation for Chrontel CH7033, IT6505, IVO, BOE,
Panasonic, Chunghwa, AUO bindings; convert dw_mipi_dsi.txt
to YAML; remove todo item for drm_display_mode.hsync removal;
Core Changes:
* drm: add devm_drm_dev_alloc() for managed allocations of drm_device;
use DRM_MODESET_LOCK_ALL_*() in mode-object code; remove
drm_display_mode.hsync; small cleanups of unused variables,
compiler warnings and static functions
* drm/client: dual-lincensing: GPL-2.0 or MIT
* drm/mm: optimize tree searches in rb_hole_addr()
Driver Changes:
* drm/{many}: use devm_drm_dev_alloc(); don't use drm_device.dev_private
* drm/ast: don't double-assign to drm_crtc_funcs.set_config; drop
drm_connector_register()
* drm/bochs: drop drm_connector_register()
* drm/bridge: add support for Chrontel ch7033; fix stack usage with
old gccs; return error pointer in drm_panel_bridge_add()
* drm/cirrus: Move to tiny
* drm/dp_mst: don't use 2nd sideband tx slot; revert "Remove single tx
msg restriction"
* drm/lima: support runtime PM;
* drm/meson: limit modes wrt chipset
* drm/panel: add support for Visionox rm69299; fix clock on
boe-tv101wum-n16; fix panel type for AUO G101EVN10;
add support for Ivo M133NFW4 R0; add support for BOE
NV133FHM-N61; add support for AUO G121EAN01.4, G156XTN01.0,
G190EAN01
* drm/pl111: improve vexpress init; fix module auto-loading
* drm/stm: read number of endpoints from device tree
* drm/vboxvideo: use managed PCI functions; drop DRM_MTRR_WC
* drm/vkms: fix use-after-free in vkms_gem_create(); enable cursor
support by default
* fbdev: use boolean values in several drivers
* fbdev/controlfb: fix COMPILE_TEST
* fbdev/w100fb: fix double-free bug
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20200507072503.GA10979@linux-uq9g
Diffstat (limited to 'drivers/gpu/drm/drm_dp_mst_topology.c')
-rw-r--r-- | drivers/gpu/drm/drm_dp_mst_topology.c | 137 |
1 files changed, 41 insertions, 96 deletions
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 13213c4b77d1..b90cca361afe 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1197,14 +1197,8 @@ static int drm_dp_mst_wait_tx_reply(struct drm_dp_mst_branch *mstb, /* remove from q */ if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED || - txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND) { + txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND) list_del(&txmsg->next); - } - - if (txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND || - txmsg->state == DRM_DP_SIDEBAND_TX_SENT) { - mstb->tx_slots[txmsg->seqno] = NULL; - } } out: if (unlikely(ret == -EIO) && drm_debug_enabled(DRM_UT_DP)) { @@ -1214,6 +1208,7 @@ out: } mutex_unlock(&mgr->qlock); + drm_dp_mst_kick_tx(mgr); return ret; } @@ -2682,22 +2677,6 @@ static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr, struct drm_dp_mst_branch *mstb = txmsg->dst; u8 req_type; - /* both msg slots are full */ - if (txmsg->seqno == -1) { - if (mstb->tx_slots[0] && mstb->tx_slots[1]) { - DRM_DEBUG_KMS("%s: failed to find slot\n", __func__); - return -EAGAIN; - } - if (mstb->tx_slots[0] == NULL && mstb->tx_slots[1] == NULL) { - txmsg->seqno = mstb->last_seqno; - mstb->last_seqno ^= 1; - } else if (mstb->tx_slots[0] == NULL) - txmsg->seqno = 0; - else - txmsg->seqno = 1; - mstb->tx_slots[txmsg->seqno] = txmsg; - } - req_type = txmsg->msg[0] & 0x7f; if (req_type == DP_CONNECTION_STATUS_NOTIFY || req_type == DP_RESOURCE_STATUS_NOTIFY) @@ -2709,7 +2688,7 @@ static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr, hdr->lcr = mstb->lct - 1; if (mstb->lct > 1) memcpy(hdr->rad, mstb->rad, mstb->lct / 2); - hdr->seqno = txmsg->seqno; + return 0; } /* @@ -2724,15 +2703,15 @@ static int process_single_tx_qlock(struct drm_dp_mst_topology_mgr *mgr, int len, space, idx, tosend; int ret; + if (txmsg->state == DRM_DP_SIDEBAND_TX_SENT) + return 0; + memset(&hdr, 0, sizeof(struct drm_dp_sideband_msg_hdr)); - if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED) { - txmsg->seqno = -1; + if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED) txmsg->state = DRM_DP_SIDEBAND_TX_START_SEND; - } - /* make hdr from dst mst - for replies use seqno - otherwise assign one */ + /* make hdr from dst mst */ ret = set_hdr_from_dst_qlock(&hdr, txmsg); if (ret < 0) return ret; @@ -2785,40 +2764,17 @@ static void process_single_down_tx_qlock(struct drm_dp_mst_topology_mgr *mgr) if (list_empty(&mgr->tx_msg_downq)) return; - txmsg = list_first_entry(&mgr->tx_msg_downq, struct drm_dp_sideband_msg_tx, next); + txmsg = list_first_entry(&mgr->tx_msg_downq, + struct drm_dp_sideband_msg_tx, next); ret = process_single_tx_qlock(mgr, txmsg, false); - if (ret == 1) { - /* txmsg is sent it should be in the slots now */ - list_del(&txmsg->next); - } else if (ret) { + if (ret < 0) { DRM_DEBUG_KMS("failed to send msg in q %d\n", ret); list_del(&txmsg->next); - if (txmsg->seqno != -1) - txmsg->dst->tx_slots[txmsg->seqno] = NULL; txmsg->state = DRM_DP_SIDEBAND_TX_TIMEOUT; wake_up_all(&mgr->tx_waitq); } } -/* called holding qlock */ -static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_sideband_msg_tx *txmsg) -{ - int ret; - - /* construct a chunk from the first msg in the tx_msg queue */ - ret = process_single_tx_qlock(mgr, txmsg, true); - - if (ret != 1) - DRM_DEBUG_KMS("failed to send msg in q %d\n", ret); - - if (txmsg->seqno != -1) { - WARN_ON((unsigned int)txmsg->seqno > - ARRAY_SIZE(txmsg->dst->tx_slots)); - txmsg->dst->tx_slots[txmsg->seqno] = NULL; - } -} - static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_sideband_msg_tx *txmsg) { @@ -3451,7 +3407,7 @@ static int drm_dp_encode_up_ack_reply(struct drm_dp_sideband_msg_tx *msg, u8 req static int drm_dp_send_up_ack_reply(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_branch *mstb, - int req_type, int seqno, bool broadcast) + int req_type, bool broadcast) { struct drm_dp_sideband_msg_tx *txmsg; @@ -3460,13 +3416,11 @@ static int drm_dp_send_up_ack_reply(struct drm_dp_mst_topology_mgr *mgr, return -ENOMEM; txmsg->dst = mstb; - txmsg->seqno = seqno; drm_dp_encode_up_ack_reply(txmsg, req_type); mutex_lock(&mgr->qlock); - - process_single_up_tx_qlock(mgr, txmsg); - + /* construct a chunk from the first msg in the tx_msg queue */ + process_single_tx_qlock(mgr, txmsg, true); mutex_unlock(&mgr->qlock); kfree(txmsg); @@ -3691,8 +3645,9 @@ out_fail: } EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume); -static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up, - struct drm_dp_mst_branch **mstb, int *seqno) +static bool +drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up, + struct drm_dp_mst_branch **mstb) { int len; u8 replyblock[32]; @@ -3700,13 +3655,13 @@ static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up, int ret; u8 hdrlen; struct drm_dp_sideband_msg_hdr hdr; - struct drm_dp_sideband_msg_rx *msg; + struct drm_dp_sideband_msg_rx *msg = + up ? &mgr->up_req_recv : &mgr->down_rep_recv; int basereg = up ? DP_SIDEBAND_MSG_UP_REQ_BASE : DP_SIDEBAND_MSG_DOWN_REP_BASE; if (!up) *mstb = NULL; - *seqno = -1; len = min(mgr->max_dpcd_transaction_bytes, 16); ret = drm_dp_dpcd_read(mgr->aux, basereg, replyblock, len); @@ -3723,11 +3678,7 @@ static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up, return false; } - *seqno = hdr.seqno; - - if (up) { - msg = &mgr->up_req_recv; - } else { + if (!up) { /* Caller is responsible for giving back this reference */ *mstb = drm_dp_get_mst_branch_device(mgr, hdr.lct, hdr.rad); if (!*mstb) { @@ -3735,7 +3686,6 @@ static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up, hdr.lct); return false; } - msg = &(*mstb)->down_rep_recv[hdr.seqno]; } if (!drm_dp_sideband_msg_set_header(msg, &hdr, hdrlen)) { @@ -3779,13 +3729,10 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr) { struct drm_dp_sideband_msg_tx *txmsg; struct drm_dp_mst_branch *mstb = NULL; - struct drm_dp_sideband_msg_rx *msg = NULL; - int seqno = -1; + struct drm_dp_sideband_msg_rx *msg = &mgr->down_rep_recv; - if (!drm_dp_get_one_sb_msg(mgr, false, &mstb, &seqno)) - goto out_clear_reply; - - msg = &mstb->down_rep_recv[seqno]; + if (!drm_dp_get_one_sb_msg(mgr, false, &mstb)) + goto out; /* Multi-packet message transmission, don't clear the reply */ if (!msg->have_eomt) @@ -3793,11 +3740,12 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr) /* find the message */ mutex_lock(&mgr->qlock); - txmsg = mstb->tx_slots[seqno]; - /* remove from slots */ + txmsg = list_first_entry_or_null(&mgr->tx_msg_downq, + struct drm_dp_sideband_msg_tx, next); mutex_unlock(&mgr->qlock); - if (!txmsg) { + /* Were we actually expecting a response, and from this mstb? */ + if (!txmsg || txmsg->dst != mstb) { struct drm_dp_sideband_msg_hdr *hdr; hdr = &msg->initial_hdr; DRM_DEBUG_KMS("Got MST reply with no msg %p %d %d %02x %02x\n", @@ -3822,7 +3770,7 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr) mutex_lock(&mgr->qlock); txmsg->state = DRM_DP_SIDEBAND_TX_RX; - mstb->tx_slots[seqno] = NULL; + list_del(&txmsg->next); mutex_unlock(&mgr->qlock); wake_up_all(&mgr->tx_waitq); @@ -3830,8 +3778,7 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr) return 0; out_clear_reply: - if (msg) - memset(msg, 0, sizeof(struct drm_dp_sideband_msg_rx)); + memset(msg, 0, sizeof(struct drm_dp_sideband_msg_rx)); out: if (mstb) drm_dp_mst_topology_put_mstb(mstb); @@ -3911,9 +3858,8 @@ static void drm_dp_mst_up_req_work(struct work_struct *work) static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) { struct drm_dp_pending_up_req *up_req; - int seqno; - if (!drm_dp_get_one_sb_msg(mgr, true, NULL, &seqno)) + if (!drm_dp_get_one_sb_msg(mgr, true, NULL)) goto out; if (!mgr->up_req_recv.have_eomt) @@ -3937,7 +3883,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) } drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, up_req->msg.req_type, - seqno, false); + false); if (up_req->msg.req_type == DP_CONNECTION_STATUS_NOTIFY) { const struct drm_dp_connection_status_notify *conn_stat = @@ -4703,26 +4649,25 @@ static inline void drm_dp_delayed_destroy_mstb(struct drm_dp_mst_branch *mstb) { struct drm_dp_mst_topology_mgr *mgr = mstb->mgr; - struct drm_dp_mst_port *port, *tmp; + struct drm_dp_mst_port *port, *port_tmp; + struct drm_dp_sideband_msg_tx *txmsg, *txmsg_tmp; bool wake_tx = false; mutex_lock(&mgr->lock); - list_for_each_entry_safe(port, tmp, &mstb->ports, next) { + list_for_each_entry_safe(port, port_tmp, &mstb->ports, next) { list_del(&port->next); drm_dp_mst_topology_put_port(port); } mutex_unlock(&mgr->lock); - /* drop any tx slots msg */ + /* drop any tx slot msg */ mutex_lock(&mstb->mgr->qlock); - if (mstb->tx_slots[0]) { - mstb->tx_slots[0]->state = DRM_DP_SIDEBAND_TX_TIMEOUT; - mstb->tx_slots[0] = NULL; - wake_tx = true; - } - if (mstb->tx_slots[1]) { - mstb->tx_slots[1]->state = DRM_DP_SIDEBAND_TX_TIMEOUT; - mstb->tx_slots[1] = NULL; + list_for_each_entry_safe(txmsg, txmsg_tmp, &mgr->tx_msg_downq, next) { + if (txmsg->dst != mstb) + continue; + + txmsg->state = DRM_DP_SIDEBAND_TX_TIMEOUT; + list_del(&txmsg->next); wake_tx = true; } mutex_unlock(&mstb->mgr->qlock); |