Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/mst: Support simultaneous down replies

Currently we have one down reply message servicing the mst manager, so
we need to serialize all tx msgs to ensure we only have one message in
flight at a time. For obvious reasons this is suboptimal (but less
suboptimal than the free-for-all we had before serialization).

This patch removes the single down_rep_recv message from manager and
adds 2 replies in the branch structure. The 2 replies mirrors the tx_slots
which we use to rate-limit outgoing messages and correspond to seqno in
the packet headers.

Cc: Wayne Lin <Wayne.Lin@amd.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Wayne Lin <waynelin@amd.com>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20200213211523.156998-3-sean@poorly.run

+78 -61
+48 -32
drivers/gpu/drm/drm_dp_mst_topology.c
··· 3696 3696 } 3697 3697 EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume); 3698 3698 3699 - static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) 3699 + static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up, 3700 + struct drm_dp_mst_branch **mstb, int *seqno) 3700 3701 { 3701 3702 int len; 3702 3703 u8 replyblock[32]; ··· 3709 3708 int basereg = up ? DP_SIDEBAND_MSG_UP_REQ_BASE : 3710 3709 DP_SIDEBAND_MSG_DOWN_REP_BASE; 3711 3710 3712 - msg = up ? &mgr->up_req_recv : &mgr->down_rep_recv; 3711 + *mstb = NULL; 3712 + *seqno = -1; 3713 3713 3714 3714 len = min(mgr->max_dpcd_transaction_bytes, 16); 3715 3715 ret = drm_dp_dpcd_read(mgr->aux, basereg, replyblock, len); ··· 3725 3723 1, replyblock, len, false); 3726 3724 DRM_DEBUG_KMS("ERROR: failed header\n"); 3727 3725 return false; 3726 + } 3727 + 3728 + *seqno = hdr.seqno; 3729 + 3730 + if (up) { 3731 + msg = &mgr->up_req_recv; 3732 + } else { 3733 + /* Caller is responsible for giving back this reference */ 3734 + *mstb = drm_dp_get_mst_branch_device(mgr, hdr.lct, hdr.rad); 3735 + if (!*mstb) { 3736 + DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", 3737 + hdr.lct); 3738 + return false; 3739 + } 3740 + msg = &(*mstb)->down_rep_recv[hdr.seqno]; 3728 3741 } 3729 3742 3730 3743 if (!drm_dp_sideband_msg_set_header(msg, &hdr, hdrlen)) { ··· 3782 3765 static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr) 3783 3766 { 3784 3767 struct drm_dp_sideband_msg_tx *txmsg; 3785 - struct drm_dp_mst_branch *mstb; 3786 - struct drm_dp_sideband_msg_hdr *hdr = &mgr->down_rep_recv.initial_hdr; 3787 - int slot = -1; 3768 + struct drm_dp_mst_branch *mstb = NULL; 3769 + struct drm_dp_sideband_msg_rx *msg = NULL; 3770 + int seqno = -1; 3788 3771 3789 - if (!drm_dp_get_one_sb_msg(mgr, false)) 3790 - goto clear_down_rep_recv; 3772 + if (!drm_dp_get_one_sb_msg(mgr, false, &mstb, &seqno)) 3773 + goto out_clear_reply; 3791 3774 3792 - if (!mgr->down_rep_recv.have_eomt) 3793 - return 0; 3775 + msg = &mstb->down_rep_recv[seqno]; 3794 3776 3795 - mstb = drm_dp_get_mst_branch_device(mgr, hdr->lct, hdr->rad); 3796 - if (!mstb) { 3797 - DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", 3798 - hdr->lct); 3799 - goto clear_down_rep_recv; 3800 - } 3777 + /* Multi-packet message transmission, don't clear the reply */ 3778 + if (!msg->have_eomt) 3779 + goto out; 3801 3780 3802 3781 /* find the message */ 3803 - slot = hdr->seqno; 3804 3782 mutex_lock(&mgr->qlock); 3805 - txmsg = mstb->tx_slots[slot]; 3783 + txmsg = mstb->tx_slots[seqno]; 3806 3784 /* remove from slots */ 3807 3785 mutex_unlock(&mgr->qlock); 3808 3786 3809 3787 if (!txmsg) { 3788 + struct drm_dp_sideband_msg_hdr *hdr; 3789 + hdr = &msg->initial_hdr; 3810 3790 DRM_DEBUG_KMS("Got MST reply with no msg %p %d %d %02x %02x\n", 3811 3791 mstb, hdr->seqno, hdr->lct, hdr->rad[0], 3812 - mgr->down_rep_recv.msg[0]); 3813 - goto no_msg; 3792 + msg->msg[0]); 3793 + goto out_clear_reply; 3814 3794 } 3815 3795 3816 - drm_dp_sideband_parse_reply(&mgr->down_rep_recv, &txmsg->reply); 3796 + drm_dp_sideband_parse_reply(msg, &txmsg->reply); 3817 3797 3818 - if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) 3798 + if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) { 3819 3799 DRM_DEBUG_KMS("Got NAK reply: req 0x%02x (%s), reason 0x%02x (%s), nak data 0x%02x\n", 3820 3800 txmsg->reply.req_type, 3821 3801 drm_dp_mst_req_type_str(txmsg->reply.req_type), 3822 3802 txmsg->reply.u.nak.reason, 3823 3803 drm_dp_mst_nak_reason_str(txmsg->reply.u.nak.reason), 3824 3804 txmsg->reply.u.nak.nak_data); 3805 + goto out_clear_reply; 3806 + } 3825 3807 3826 - memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); 3808 + memset(msg, 0, sizeof(struct drm_dp_sideband_msg_rx)); 3827 3809 drm_dp_mst_topology_put_mstb(mstb); 3828 3810 3829 3811 mutex_lock(&mgr->qlock); 3830 3812 txmsg->state = DRM_DP_SIDEBAND_TX_RX; 3831 - mstb->tx_slots[slot] = NULL; 3813 + mstb->tx_slots[seqno] = NULL; 3832 3814 mgr->is_waiting_for_dwn_reply = false; 3833 3815 mutex_unlock(&mgr->qlock); 3834 3816 ··· 3835 3819 3836 3820 return 0; 3837 3821 3838 - no_msg: 3839 - drm_dp_mst_topology_put_mstb(mstb); 3840 - clear_down_rep_recv: 3822 + out_clear_reply: 3841 3823 mutex_lock(&mgr->qlock); 3842 3824 mgr->is_waiting_for_dwn_reply = false; 3843 3825 mutex_unlock(&mgr->qlock); 3844 - memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); 3826 + if (msg) 3827 + memset(msg, 0, sizeof(struct drm_dp_sideband_msg_rx)); 3828 + out: 3829 + if (mstb) 3830 + drm_dp_mst_topology_put_mstb(mstb); 3845 3831 3846 3832 return 0; 3847 3833 } ··· 3919 3901 3920 3902 static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) 3921 3903 { 3922 - struct drm_dp_sideband_msg_hdr *hdr = &mgr->up_req_recv.initial_hdr; 3923 3904 struct drm_dp_pending_up_req *up_req; 3924 - bool seqno; 3905 + int seqno; 3925 3906 3926 - if (!drm_dp_get_one_sb_msg(mgr, true)) 3907 + if (!drm_dp_get_one_sb_msg(mgr, true, NULL, &seqno)) 3927 3908 goto out; 3928 3909 3929 3910 if (!mgr->up_req_recv.have_eomt) ··· 3935 3918 } 3936 3919 INIT_LIST_HEAD(&up_req->next); 3937 3920 3938 - seqno = hdr->seqno; 3939 3921 drm_dp_sideband_parse_req(&mgr->up_req_recv, &up_req->msg); 3940 3922 3941 3923 if (up_req->msg.req_type != DP_CONNECTION_STATUS_NOTIFY && ··· 3968 3952 res_stat->available_pbn); 3969 3953 } 3970 3954 3971 - up_req->hdr = *hdr; 3955 + up_req->hdr = mgr->up_req_recv.initial_hdr; 3972 3956 mutex_lock(&mgr->up_req_lock); 3973 3957 list_add_tail(&up_req->next, &mgr->up_req_list); 3974 3958 mutex_unlock(&mgr->up_req_lock);
+30 -29
include/drm/drm_dp_mst_helper.h
··· 160 160 bool fec_capable; 161 161 }; 162 162 163 + /* sideband msg header - not bit struct */ 164 + struct drm_dp_sideband_msg_hdr { 165 + u8 lct; 166 + u8 lcr; 167 + u8 rad[8]; 168 + bool broadcast; 169 + bool path_msg; 170 + u8 msg_len; 171 + bool somt; 172 + bool eomt; 173 + bool seqno; 174 + }; 175 + 176 + struct drm_dp_sideband_msg_rx { 177 + u8 chunk[48]; 178 + u8 msg[256]; 179 + u8 curchunk_len; 180 + u8 curchunk_idx; /* chunk we are parsing now */ 181 + u8 curchunk_hdrlen; 182 + u8 curlen; /* total length of the msg */ 183 + bool have_somt; 184 + bool have_eomt; 185 + struct drm_dp_sideband_msg_hdr initial_hdr; 186 + }; 187 + 163 188 /** 164 189 * struct drm_dp_mst_branch - MST branch device. 165 190 * @rad: Relative Address to talk to this branch device. ··· 257 232 int last_seqno; 258 233 bool link_address_sent; 259 234 235 + /** 236 + * @down_rep_recv: Message receiver state for down replies. 237 + */ 238 + struct drm_dp_sideband_msg_rx down_rep_recv[2]; 239 + 260 240 /* global unique identifier to identify branch devices */ 261 241 u8 guid[16]; 262 242 }; 263 243 264 - 265 - /* sideband msg header - not bit struct */ 266 - struct drm_dp_sideband_msg_hdr { 267 - u8 lct; 268 - u8 lcr; 269 - u8 rad[8]; 270 - bool broadcast; 271 - bool path_msg; 272 - u8 msg_len; 273 - bool somt; 274 - bool eomt; 275 - bool seqno; 276 - }; 277 244 278 245 struct drm_dp_nak_reply { 279 246 u8 guid[16]; ··· 322 305 u8 port_number; 323 306 }; 324 307 325 - 326 - struct drm_dp_sideband_msg_rx { 327 - u8 chunk[48]; 328 - u8 msg[256]; 329 - u8 curchunk_len; 330 - u8 curchunk_idx; /* chunk we are parsing now */ 331 - u8 curchunk_hdrlen; 332 - u8 curlen; /* total length of the msg */ 333 - bool have_somt; 334 - bool have_eomt; 335 - struct drm_dp_sideband_msg_hdr initial_hdr; 336 - }; 337 308 338 309 #define DRM_DP_MAX_SDP_STREAMS 16 339 310 struct drm_dp_allocate_payload { ··· 560 555 */ 561 556 int conn_base_id; 562 557 563 - /** 564 - * @down_rep_recv: Message receiver state for down replies. 565 - */ 566 - struct drm_dp_sideband_msg_rx down_rep_recv; 567 558 /** 568 559 * @up_req_recv: Message receiver state for up requests. 569 560 */