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

drm/mst: Separate sideband packet header parsing from message building

In preparation of per-branch device down message handling, separate
header parsing from message building. This will allow us to peek at
figure out which branch device the message is from before starting to
parse the message contents.

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

+61 -49
+61 -49
drivers/gpu/drm/drm_dp_mst_topology.c
··· 687 687 raw->cur_len = idx; 688 688 } 689 689 690 - /* this adds a chunk of msg to the builder to get the final msg */ 691 - static bool drm_dp_sideband_msg_build(struct drm_dp_sideband_msg_rx *msg, 692 - u8 *replybuf, u8 replybuflen, bool hdr) 690 + static int drm_dp_sideband_msg_set_header(struct drm_dp_sideband_msg_rx *msg, 691 + struct drm_dp_sideband_msg_hdr *hdr, 692 + u8 hdrlen) 693 693 { 694 - int ret; 694 + /* 695 + * ignore out-of-order messages or messages that are part of a 696 + * failed transaction 697 + */ 698 + if (!hdr->somt && !msg->have_somt) 699 + return false; 700 + 701 + /* get length contained in this portion */ 702 + msg->curchunk_idx = 0; 703 + msg->curchunk_len = hdr->msg_len; 704 + msg->curchunk_hdrlen = hdrlen; 705 + 706 + /* we have already gotten an somt - don't bother parsing */ 707 + if (hdr->somt && msg->have_somt) 708 + return false; 709 + 710 + if (hdr->somt) { 711 + memcpy(&msg->initial_hdr, hdr, 712 + sizeof(struct drm_dp_sideband_msg_hdr)); 713 + msg->have_somt = true; 714 + } 715 + if (hdr->eomt) 716 + msg->have_eomt = true; 717 + 718 + return true; 719 + } 720 + 721 + /* this adds a chunk of msg to the builder to get the final msg */ 722 + static bool drm_dp_sideband_append_payload(struct drm_dp_sideband_msg_rx *msg, 723 + u8 *replybuf, u8 replybuflen) 724 + { 695 725 u8 crc4; 696 726 697 - if (hdr) { 698 - u8 hdrlen; 699 - struct drm_dp_sideband_msg_hdr recv_hdr; 700 - ret = drm_dp_decode_sideband_msg_hdr(&recv_hdr, replybuf, replybuflen, &hdrlen); 701 - if (ret == false) { 702 - print_hex_dump(KERN_DEBUG, "failed hdr", DUMP_PREFIX_NONE, 16, 1, replybuf, replybuflen, false); 703 - return false; 704 - } 705 - 706 - /* 707 - * ignore out-of-order messages or messages that are part of a 708 - * failed transaction 709 - */ 710 - if (!recv_hdr.somt && !msg->have_somt) 711 - return false; 712 - 713 - /* get length contained in this portion */ 714 - msg->curchunk_len = recv_hdr.msg_len; 715 - msg->curchunk_hdrlen = hdrlen; 716 - 717 - /* we have already gotten an somt - don't bother parsing */ 718 - if (recv_hdr.somt && msg->have_somt) 719 - return false; 720 - 721 - if (recv_hdr.somt) { 722 - memcpy(&msg->initial_hdr, &recv_hdr, sizeof(struct drm_dp_sideband_msg_hdr)); 723 - msg->have_somt = true; 724 - } 725 - if (recv_hdr.eomt) 726 - msg->have_eomt = true; 727 - 728 - /* copy the bytes for the remainder of this header chunk */ 729 - msg->curchunk_idx = min(msg->curchunk_len, (u8)(replybuflen - hdrlen)); 730 - memcpy(&msg->chunk[0], replybuf + hdrlen, msg->curchunk_idx); 731 - } else { 732 - memcpy(&msg->chunk[msg->curchunk_idx], replybuf, replybuflen); 733 - msg->curchunk_idx += replybuflen; 734 - } 727 + memcpy(&msg->chunk[msg->curchunk_idx], replybuf, replybuflen); 728 + msg->curchunk_idx += replybuflen; 735 729 736 730 if (msg->curchunk_idx >= msg->curchunk_len) { 737 731 /* do CRC */ ··· 3702 3708 u8 replyblock[32]; 3703 3709 int replylen, curreply; 3704 3710 int ret; 3711 + u8 hdrlen; 3712 + struct drm_dp_sideband_msg_hdr hdr; 3705 3713 struct drm_dp_sideband_msg_rx *msg; 3706 - int basereg = up ? DP_SIDEBAND_MSG_UP_REQ_BASE : DP_SIDEBAND_MSG_DOWN_REP_BASE; 3714 + int basereg = up ? DP_SIDEBAND_MSG_UP_REQ_BASE : 3715 + DP_SIDEBAND_MSG_DOWN_REP_BASE; 3716 + 3707 3717 msg = up ? &mgr->up_req_recv : &mgr->down_rep_recv; 3708 3718 3709 3719 len = min(mgr->max_dpcd_transaction_bytes, 16); 3710 - ret = drm_dp_dpcd_read(mgr->aux, basereg, 3711 - replyblock, len); 3720 + ret = drm_dp_dpcd_read(mgr->aux, basereg, replyblock, len); 3712 3721 if (ret != len) { 3713 3722 DRM_DEBUG_KMS("failed to read DPCD down rep %d %d\n", len, ret); 3714 3723 return false; 3715 3724 } 3716 - ret = drm_dp_sideband_msg_build(msg, replyblock, len, true); 3725 + 3726 + ret = drm_dp_decode_sideband_msg_hdr(&hdr, replyblock, len, &hdrlen); 3727 + if (ret == false) { 3728 + print_hex_dump(KERN_DEBUG, "failed hdr", DUMP_PREFIX_NONE, 16, 3729 + 1, replyblock, len, false); 3730 + DRM_DEBUG_KMS("ERROR: failed header\n"); 3731 + return false; 3732 + } 3733 + 3734 + if (!drm_dp_sideband_msg_set_header(msg, &hdr, hdrlen)) { 3735 + DRM_DEBUG_KMS("sideband msg set header failed %d\n", 3736 + replyblock[0]); 3737 + return false; 3738 + } 3739 + 3740 + replylen = min(msg->curchunk_len, (u8)(len - hdrlen)); 3741 + ret = drm_dp_sideband_append_payload(msg, replyblock + hdrlen, replylen); 3717 3742 if (!ret) { 3718 3743 DRM_DEBUG_KMS("sideband msg build failed %d\n", replyblock[0]); 3719 3744 return false; 3720 3745 } 3721 - replylen = msg->curchunk_len + msg->curchunk_hdrlen; 3722 3746 3723 - replylen -= len; 3747 + replylen = msg->curchunk_len + msg->curchunk_hdrlen - len; 3724 3748 curreply = len; 3725 3749 while (replylen > 0) { 3726 3750 len = min3(replylen, mgr->max_dpcd_transaction_bytes, 16); ··· 3750 3738 return false; 3751 3739 } 3752 3740 3753 - ret = drm_dp_sideband_msg_build(msg, replyblock, len, false); 3741 + ret = drm_dp_sideband_append_payload(msg, replyblock, len); 3754 3742 if (!ret) { 3755 3743 DRM_DEBUG_KMS("failed to build sideband msg\n"); 3756 3744 return false;