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

drm/dp_mst: Add sideband down request tracing + selftests

Unfortunately the DP MST helpers do not have much in the way of
debugging utilities. So, let's add some!

This adds basic debugging output for down sideband requests that we send
from the driver, so that we can actually discern what's happening when
sideband requests timeout.

Since there wasn't really a good way of testing that any of this worked,
I ended up writing simple selftests that lightly test sideband message
encoding and decoding as well. Enjoy!

Changes since v1:
* Clean up DO_TEST() and sideband_msg_req_encode_decode() - danvet
* Get rid of pr_fmt(), just define a prefix string instead and use
drm_printf()
* Check highest bit of VCPI in drm_dp_decode_sideband_req() - danvet
* Make the switch case order between drm_dp_decode_sideband_req() and
drm_dp_encode_sideband_req() the same - danvet
* Only check DRM_UT_DP - danvet
* Clean up sideband_msg_req_equal() from selftests a bit, and add
comments explaining why we can't just use memcmp - danvet

Cc: Juston Li <juston.li@intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Harry Wentland <hwentlan@amd.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Lyude Paul <lyude@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190903204645.25487-8-lyude@redhat.com

+536 -5
+305 -4
drivers/gpu/drm/drm_dp_mst_topology.c
··· 37 37 #include <drm/drm_probe_helper.h> 38 38 39 39 #include "drm_crtc_helper_internal.h" 40 + #include "drm_dp_mst_topology_internal.h" 40 41 41 42 /** 42 43 * DOC: dp mst helper ··· 73 72 static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux); 74 73 static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux); 75 74 static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr); 75 + 76 + #define DBG_PREFIX "[dp_mst]" 76 77 77 78 #define DP_STR(x) [DP_ ## x] = #x 78 79 ··· 132 129 } 133 130 134 131 #undef DP_STR 132 + #define DP_STR(x) [DRM_DP_SIDEBAND_TX_ ## x] = #x 133 + 134 + static const char *drm_dp_mst_sideband_tx_state_str(int state) 135 + { 136 + static const char * const sideband_reason_str[] = { 137 + DP_STR(QUEUED), 138 + DP_STR(START_SEND), 139 + DP_STR(SENT), 140 + DP_STR(RX), 141 + DP_STR(TIMEOUT), 142 + }; 143 + 144 + if (state >= ARRAY_SIZE(sideband_reason_str) || 145 + !sideband_reason_str[state]) 146 + return "unknown"; 147 + 148 + return sideband_reason_str[state]; 149 + } 150 + 151 + static int 152 + drm_dp_mst_rad_to_str(const u8 rad[8], u8 lct, char *out, size_t len) 153 + { 154 + int i; 155 + u8 unpacked_rad[16]; 156 + 157 + for (i = 0; i < lct; i++) { 158 + if (i % 2) 159 + unpacked_rad[i] = rad[i / 2] >> 4; 160 + else 161 + unpacked_rad[i] = rad[i / 2] & BIT_MASK(4); 162 + } 163 + 164 + /* TODO: Eventually add something to printk so we can format the rad 165 + * like this: 1.2.3 166 + */ 167 + return snprintf(out, len, "%*phC", lct, unpacked_rad); 168 + } 135 169 136 170 /* sideband msg handling */ 137 171 static u8 drm_dp_msg_header_crc4(const uint8_t *data, size_t num_nibbles) ··· 301 261 return true; 302 262 } 303 263 304 - static void drm_dp_encode_sideband_req(struct drm_dp_sideband_msg_req_body *req, 305 - struct drm_dp_sideband_msg_tx *raw) 264 + void 265 + drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req, 266 + struct drm_dp_sideband_msg_tx *raw) 306 267 { 307 268 int idx = 0; 308 269 int i; ··· 403 362 break; 404 363 } 405 364 raw->cur_len = idx; 365 + } 366 + EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_dp_encode_sideband_req); 367 + 368 + /* Decode a sideband request we've encoded, mainly used for debugging */ 369 + int 370 + drm_dp_decode_sideband_req(const struct drm_dp_sideband_msg_tx *raw, 371 + struct drm_dp_sideband_msg_req_body *req) 372 + { 373 + const u8 *buf = raw->msg; 374 + int i, idx = 0; 375 + 376 + req->req_type = buf[idx++] & 0x7f; 377 + switch (req->req_type) { 378 + case DP_ENUM_PATH_RESOURCES: 379 + case DP_POWER_DOWN_PHY: 380 + case DP_POWER_UP_PHY: 381 + req->u.port_num.port_number = (buf[idx] >> 4) & 0xf; 382 + break; 383 + case DP_ALLOCATE_PAYLOAD: 384 + { 385 + struct drm_dp_allocate_payload *a = 386 + &req->u.allocate_payload; 387 + 388 + a->number_sdp_streams = buf[idx] & 0xf; 389 + a->port_number = (buf[idx] >> 4) & 0xf; 390 + 391 + WARN_ON(buf[++idx] & 0x80); 392 + a->vcpi = buf[idx] & 0x7f; 393 + 394 + a->pbn = buf[++idx] << 8; 395 + a->pbn |= buf[++idx]; 396 + 397 + idx++; 398 + for (i = 0; i < a->number_sdp_streams; i++) { 399 + a->sdp_stream_sink[i] = 400 + (buf[idx + (i / 2)] >> ((i % 2) ? 0 : 4)) & 0xf; 401 + } 402 + } 403 + break; 404 + case DP_QUERY_PAYLOAD: 405 + req->u.query_payload.port_number = (buf[idx] >> 4) & 0xf; 406 + WARN_ON(buf[++idx] & 0x80); 407 + req->u.query_payload.vcpi = buf[idx] & 0x7f; 408 + break; 409 + case DP_REMOTE_DPCD_READ: 410 + { 411 + struct drm_dp_remote_dpcd_read *r = &req->u.dpcd_read; 412 + 413 + r->port_number = (buf[idx] >> 4) & 0xf; 414 + 415 + r->dpcd_address = (buf[idx] << 16) & 0xf0000; 416 + r->dpcd_address |= (buf[++idx] << 8) & 0xff00; 417 + r->dpcd_address |= buf[++idx] & 0xff; 418 + 419 + r->num_bytes = buf[++idx]; 420 + } 421 + break; 422 + case DP_REMOTE_DPCD_WRITE: 423 + { 424 + struct drm_dp_remote_dpcd_write *w = 425 + &req->u.dpcd_write; 426 + 427 + w->port_number = (buf[idx] >> 4) & 0xf; 428 + 429 + w->dpcd_address = (buf[idx] << 16) & 0xf0000; 430 + w->dpcd_address |= (buf[++idx] << 8) & 0xff00; 431 + w->dpcd_address |= buf[++idx] & 0xff; 432 + 433 + w->num_bytes = buf[++idx]; 434 + 435 + w->bytes = kmemdup(&buf[++idx], w->num_bytes, 436 + GFP_KERNEL); 437 + if (!w->bytes) 438 + return -ENOMEM; 439 + } 440 + break; 441 + case DP_REMOTE_I2C_READ: 442 + { 443 + struct drm_dp_remote_i2c_read *r = &req->u.i2c_read; 444 + struct drm_dp_remote_i2c_read_tx *tx; 445 + bool failed = false; 446 + 447 + r->num_transactions = buf[idx] & 0x3; 448 + r->port_number = (buf[idx] >> 4) & 0xf; 449 + for (i = 0; i < r->num_transactions; i++) { 450 + tx = &r->transactions[i]; 451 + 452 + tx->i2c_dev_id = buf[++idx] & 0x7f; 453 + tx->num_bytes = buf[++idx]; 454 + tx->bytes = kmemdup(&buf[++idx], 455 + tx->num_bytes, 456 + GFP_KERNEL); 457 + if (!tx->bytes) { 458 + failed = true; 459 + break; 460 + } 461 + idx += tx->num_bytes; 462 + tx->no_stop_bit = (buf[idx] >> 5) & 0x1; 463 + tx->i2c_transaction_delay = buf[idx] & 0xf; 464 + } 465 + 466 + if (failed) { 467 + for (i = 0; i < r->num_transactions; i++) 468 + kfree(tx->bytes); 469 + return -ENOMEM; 470 + } 471 + 472 + r->read_i2c_device_id = buf[++idx] & 0x7f; 473 + r->num_bytes_read = buf[++idx]; 474 + } 475 + break; 476 + case DP_REMOTE_I2C_WRITE: 477 + { 478 + struct drm_dp_remote_i2c_write *w = &req->u.i2c_write; 479 + 480 + w->port_number = (buf[idx] >> 4) & 0xf; 481 + w->write_i2c_device_id = buf[++idx] & 0x7f; 482 + w->num_bytes = buf[++idx]; 483 + w->bytes = kmemdup(&buf[++idx], w->num_bytes, 484 + GFP_KERNEL); 485 + if (!w->bytes) 486 + return -ENOMEM; 487 + } 488 + break; 489 + } 490 + 491 + return 0; 492 + } 493 + EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_dp_decode_sideband_req); 494 + 495 + void 496 + drm_dp_dump_sideband_msg_req_body(const struct drm_dp_sideband_msg_req_body *req, 497 + int indent, struct drm_printer *printer) 498 + { 499 + int i; 500 + 501 + #define P(f, ...) drm_printf_indent(printer, indent, f, ##__VA_ARGS__) 502 + if (req->req_type == DP_LINK_ADDRESS) { 503 + /* No contents to print */ 504 + P("type=%s\n", drm_dp_mst_req_type_str(req->req_type)); 505 + return; 506 + } 507 + 508 + P("type=%s contents:\n", drm_dp_mst_req_type_str(req->req_type)); 509 + indent++; 510 + 511 + switch (req->req_type) { 512 + case DP_ENUM_PATH_RESOURCES: 513 + case DP_POWER_DOWN_PHY: 514 + case DP_POWER_UP_PHY: 515 + P("port=%d\n", req->u.port_num.port_number); 516 + break; 517 + case DP_ALLOCATE_PAYLOAD: 518 + P("port=%d vcpi=%d pbn=%d sdp_streams=%d %*ph\n", 519 + req->u.allocate_payload.port_number, 520 + req->u.allocate_payload.vcpi, req->u.allocate_payload.pbn, 521 + req->u.allocate_payload.number_sdp_streams, 522 + req->u.allocate_payload.number_sdp_streams, 523 + req->u.allocate_payload.sdp_stream_sink); 524 + break; 525 + case DP_QUERY_PAYLOAD: 526 + P("port=%d vcpi=%d\n", 527 + req->u.query_payload.port_number, 528 + req->u.query_payload.vcpi); 529 + break; 530 + case DP_REMOTE_DPCD_READ: 531 + P("port=%d dpcd_addr=%05x len=%d\n", 532 + req->u.dpcd_read.port_number, req->u.dpcd_read.dpcd_address, 533 + req->u.dpcd_read.num_bytes); 534 + break; 535 + case DP_REMOTE_DPCD_WRITE: 536 + P("port=%d addr=%05x len=%d: %*ph\n", 537 + req->u.dpcd_write.port_number, 538 + req->u.dpcd_write.dpcd_address, 539 + req->u.dpcd_write.num_bytes, req->u.dpcd_write.num_bytes, 540 + req->u.dpcd_write.bytes); 541 + break; 542 + case DP_REMOTE_I2C_READ: 543 + P("port=%d num_tx=%d id=%d size=%d:\n", 544 + req->u.i2c_read.port_number, 545 + req->u.i2c_read.num_transactions, 546 + req->u.i2c_read.read_i2c_device_id, 547 + req->u.i2c_read.num_bytes_read); 548 + 549 + indent++; 550 + for (i = 0; i < req->u.i2c_read.num_transactions; i++) { 551 + const struct drm_dp_remote_i2c_read_tx *rtx = 552 + &req->u.i2c_read.transactions[i]; 553 + 554 + P("%d: id=%03d size=%03d no_stop_bit=%d tx_delay=%03d: %*ph\n", 555 + i, rtx->i2c_dev_id, rtx->num_bytes, 556 + rtx->no_stop_bit, rtx->i2c_transaction_delay, 557 + rtx->num_bytes, rtx->bytes); 558 + } 559 + break; 560 + case DP_REMOTE_I2C_WRITE: 561 + P("port=%d id=%d size=%d: %*ph\n", 562 + req->u.i2c_write.port_number, 563 + req->u.i2c_write.write_i2c_device_id, 564 + req->u.i2c_write.num_bytes, req->u.i2c_write.num_bytes, 565 + req->u.i2c_write.bytes); 566 + break; 567 + default: 568 + P("???\n"); 569 + break; 570 + } 571 + #undef P 572 + } 573 + EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_dp_dump_sideband_msg_req_body); 574 + 575 + static inline void 576 + drm_dp_mst_dump_sideband_msg_tx(struct drm_printer *p, 577 + const struct drm_dp_sideband_msg_tx *txmsg) 578 + { 579 + struct drm_dp_sideband_msg_req_body req; 580 + char buf[64]; 581 + int ret; 582 + int i; 583 + 584 + drm_dp_mst_rad_to_str(txmsg->dst->rad, txmsg->dst->lct, buf, 585 + sizeof(buf)); 586 + drm_printf(p, "txmsg cur_offset=%x cur_len=%x seqno=%x state=%s path_msg=%d dst=%s\n", 587 + txmsg->cur_offset, txmsg->cur_len, txmsg->seqno, 588 + drm_dp_mst_sideband_tx_state_str(txmsg->state), 589 + txmsg->path_msg, buf); 590 + 591 + ret = drm_dp_decode_sideband_req(txmsg, &req); 592 + if (ret) { 593 + drm_printf(p, "<failed to decode sideband req: %d>\n", ret); 594 + return; 595 + } 596 + drm_dp_dump_sideband_msg_req_body(&req, 1, p); 597 + 598 + switch (req.req_type) { 599 + case DP_REMOTE_DPCD_WRITE: 600 + kfree(req.u.dpcd_write.bytes); 601 + break; 602 + case DP_REMOTE_I2C_READ: 603 + for (i = 0; i < req.u.i2c_read.num_transactions; i++) 604 + kfree(req.u.i2c_read.transactions[i].bytes); 605 + break; 606 + case DP_REMOTE_I2C_WRITE: 607 + kfree(req.u.i2c_write.bytes); 608 + break; 609 + } 406 610 } 407 611 408 612 static void drm_dp_crc_sideband_chunk_req(u8 *msg, u8 len) ··· 1180 894 } 1181 895 } 1182 896 out: 897 + if (unlikely(ret == -EIO && drm_debug & DRM_UT_DP)) { 898 + struct drm_printer p = drm_debug_printer(DBG_PREFIX); 899 + 900 + drm_dp_mst_dump_sideband_msg_tx(&p, txmsg); 901 + } 1183 902 mutex_unlock(&mgr->qlock); 1184 903 1185 904 return ret; ··· 2321 2030 idx += tosend + 1; 2322 2031 2323 2032 ret = drm_dp_send_sideband_msg(mgr, up, chunk, idx); 2324 - if (ret) { 2325 - DRM_DEBUG_KMS("sideband msg failed to send\n"); 2033 + if (unlikely(ret && drm_debug & DRM_UT_DP)) { 2034 + struct drm_printer p = drm_debug_printer(DBG_PREFIX); 2035 + 2036 + drm_printf(&p, "sideband msg failed to send\n"); 2037 + drm_dp_mst_dump_sideband_msg_tx(&p, txmsg); 2326 2038 return ret; 2327 2039 } 2328 2040 ··· 2387 2093 { 2388 2094 mutex_lock(&mgr->qlock); 2389 2095 list_add_tail(&txmsg->next, &mgr->tx_msg_downq); 2096 + 2097 + if (unlikely(drm_debug & DRM_UT_DP)) { 2098 + struct drm_printer p = drm_debug_printer(DBG_PREFIX); 2099 + 2100 + drm_dp_mst_dump_sideband_msg_tx(&p, txmsg); 2101 + } 2102 + 2390 2103 if (list_is_singular(&mgr->tx_msg_downq)) 2391 2104 process_single_down_tx_qlock(mgr); 2392 2105 mutex_unlock(&mgr->qlock);
+24
drivers/gpu/drm/drm_dp_mst_topology_internal.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only 2 + * 3 + * Declarations for DP MST related functions which are only used in selftests 4 + * 5 + * Copyright © 2018 Red Hat 6 + * Authors: 7 + * Lyude Paul <lyude@redhat.com> 8 + */ 9 + 10 + #ifndef _DRM_DP_MST_HELPER_INTERNAL_H_ 11 + #define _DRM_DP_MST_HELPER_INTERNAL_H_ 12 + 13 + #include <drm/drm_dp_mst_helper.h> 14 + 15 + void 16 + drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req, 17 + struct drm_dp_sideband_msg_tx *raw); 18 + int drm_dp_decode_sideband_req(const struct drm_dp_sideband_msg_tx *raw, 19 + struct drm_dp_sideband_msg_req_body *req); 20 + void 21 + drm_dp_dump_sideband_msg_req_body(const struct drm_dp_sideband_msg_req_body *req, 22 + int indent, struct drm_printer *printer); 23 + 24 + #endif /* !_DRM_DP_MST_HELPER_INTERNAL_H_ */
+1
drivers/gpu/drm/selftests/drm_modeset_selftests.h
··· 33 33 selftest(damage_iter_damage_src_moved, igt_damage_iter_damage_src_moved) 34 34 selftest(damage_iter_damage_not_visible, igt_damage_iter_damage_not_visible) 35 35 selftest(dp_mst_calc_pbn_mode, igt_dp_mst_calc_pbn_mode) 36 + selftest(dp_mst_sideband_msg_req_decode, igt_dp_mst_sideband_msg_req_decode)
+204
drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c
··· 3 3 * Test cases for for the DRM DP MST helpers 4 4 */ 5 5 6 + #define PREFIX_STR "[drm_dp_mst_helper]" 7 + 6 8 #include <drm/drm_dp_mst_helper.h> 7 9 #include <drm/drm_print.h> 8 10 11 + #include "../drm_dp_mst_topology_internal.h" 9 12 #include "test-drm_modeset_common.h" 10 13 11 14 int igt_dp_mst_calc_pbn_mode(void *ignored) ··· 33 30 test_params[i].bpp, pbn); 34 31 } 35 32 33 + return 0; 34 + } 35 + 36 + static bool 37 + sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in, 38 + const struct drm_dp_sideband_msg_req_body *out) 39 + { 40 + const struct drm_dp_remote_i2c_read_tx *txin, *txout; 41 + int i; 42 + 43 + if (in->req_type != out->req_type) 44 + return false; 45 + 46 + switch (in->req_type) { 47 + /* 48 + * Compare struct members manually for request types which can't be 49 + * compared simply using memcmp(). This is because said request types 50 + * contain pointers to other allocated structs 51 + */ 52 + case DP_REMOTE_I2C_READ: 53 + #define IN in->u.i2c_read 54 + #define OUT out->u.i2c_read 55 + if (IN.num_bytes_read != OUT.num_bytes_read || 56 + IN.num_transactions != OUT.num_transactions || 57 + IN.port_number != OUT.port_number || 58 + IN.read_i2c_device_id != OUT.read_i2c_device_id) 59 + return false; 60 + 61 + for (i = 0; i < IN.num_transactions; i++) { 62 + txin = &IN.transactions[i]; 63 + txout = &OUT.transactions[i]; 64 + 65 + if (txin->i2c_dev_id != txout->i2c_dev_id || 66 + txin->no_stop_bit != txout->no_stop_bit || 67 + txin->num_bytes != txout->num_bytes || 68 + txin->i2c_transaction_delay != 69 + txout->i2c_transaction_delay) 70 + return false; 71 + 72 + if (memcmp(txin->bytes, txout->bytes, 73 + txin->num_bytes) != 0) 74 + return false; 75 + } 76 + break; 77 + #undef IN 78 + #undef OUT 79 + 80 + case DP_REMOTE_DPCD_WRITE: 81 + #define IN in->u.dpcd_write 82 + #define OUT out->u.dpcd_write 83 + if (IN.dpcd_address != OUT.dpcd_address || 84 + IN.num_bytes != OUT.num_bytes || 85 + IN.port_number != OUT.port_number) 86 + return false; 87 + 88 + return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0; 89 + #undef IN 90 + #undef OUT 91 + 92 + case DP_REMOTE_I2C_WRITE: 93 + #define IN in->u.i2c_write 94 + #define OUT out->u.i2c_write 95 + if (IN.port_number != OUT.port_number || 96 + IN.write_i2c_device_id != OUT.write_i2c_device_id || 97 + IN.num_bytes != OUT.num_bytes) 98 + return false; 99 + 100 + return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0; 101 + #undef IN 102 + #undef OUT 103 + 104 + default: 105 + return memcmp(in, out, sizeof(*in)) == 0; 106 + } 107 + 108 + return true; 109 + } 110 + 111 + static bool 112 + sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in) 113 + { 114 + struct drm_dp_sideband_msg_req_body out = {0}; 115 + struct drm_printer p = drm_err_printer(PREFIX_STR); 116 + struct drm_dp_sideband_msg_tx txmsg; 117 + int i, ret; 118 + 119 + drm_dp_encode_sideband_req(in, &txmsg); 120 + ret = drm_dp_decode_sideband_req(&txmsg, &out); 121 + if (ret < 0) { 122 + drm_printf(&p, "Failed to decode sideband request: %d\n", 123 + ret); 124 + return false; 125 + } 126 + 127 + if (!sideband_msg_req_equal(in, &out)) { 128 + drm_printf(&p, "Encode/decode failed, expected:\n"); 129 + drm_dp_dump_sideband_msg_req_body(in, 1, &p); 130 + drm_printf(&p, "Got:\n"); 131 + drm_dp_dump_sideband_msg_req_body(&out, 1, &p); 132 + return false; 133 + } 134 + 135 + switch (in->req_type) { 136 + case DP_REMOTE_DPCD_WRITE: 137 + kfree(out.u.dpcd_write.bytes); 138 + break; 139 + case DP_REMOTE_I2C_READ: 140 + for (i = 0; i < out.u.i2c_read.num_transactions; i++) 141 + kfree(out.u.i2c_read.transactions[i].bytes); 142 + break; 143 + case DP_REMOTE_I2C_WRITE: 144 + kfree(out.u.i2c_write.bytes); 145 + break; 146 + } 147 + 148 + /* Clear everything but the req_type for the input */ 149 + memset(&in->u, 0, sizeof(in->u)); 150 + 151 + return true; 152 + } 153 + 154 + int igt_dp_mst_sideband_msg_req_decode(void *unused) 155 + { 156 + struct drm_dp_sideband_msg_req_body in = { 0 }; 157 + u8 data[] = { 0xff, 0x0, 0xdd }; 158 + int i; 159 + 160 + #define DO_TEST() FAIL_ON(!sideband_msg_req_encode_decode(&in)) 161 + 162 + in.req_type = DP_ENUM_PATH_RESOURCES; 163 + in.u.port_num.port_number = 5; 164 + DO_TEST(); 165 + 166 + in.req_type = DP_POWER_UP_PHY; 167 + in.u.port_num.port_number = 5; 168 + DO_TEST(); 169 + 170 + in.req_type = DP_POWER_DOWN_PHY; 171 + in.u.port_num.port_number = 5; 172 + DO_TEST(); 173 + 174 + in.req_type = DP_ALLOCATE_PAYLOAD; 175 + in.u.allocate_payload.number_sdp_streams = 3; 176 + for (i = 0; i < in.u.allocate_payload.number_sdp_streams; i++) 177 + in.u.allocate_payload.sdp_stream_sink[i] = i + 1; 178 + DO_TEST(); 179 + in.u.allocate_payload.port_number = 0xf; 180 + DO_TEST(); 181 + in.u.allocate_payload.vcpi = 0x7f; 182 + DO_TEST(); 183 + in.u.allocate_payload.pbn = U16_MAX; 184 + DO_TEST(); 185 + 186 + in.req_type = DP_QUERY_PAYLOAD; 187 + in.u.query_payload.port_number = 0xf; 188 + DO_TEST(); 189 + in.u.query_payload.vcpi = 0x7f; 190 + DO_TEST(); 191 + 192 + in.req_type = DP_REMOTE_DPCD_READ; 193 + in.u.dpcd_read.port_number = 0xf; 194 + DO_TEST(); 195 + in.u.dpcd_read.dpcd_address = 0xfedcb; 196 + DO_TEST(); 197 + in.u.dpcd_read.num_bytes = U8_MAX; 198 + DO_TEST(); 199 + 200 + in.req_type = DP_REMOTE_DPCD_WRITE; 201 + in.u.dpcd_write.port_number = 0xf; 202 + DO_TEST(); 203 + in.u.dpcd_write.dpcd_address = 0xfedcb; 204 + DO_TEST(); 205 + in.u.dpcd_write.num_bytes = ARRAY_SIZE(data); 206 + in.u.dpcd_write.bytes = data; 207 + DO_TEST(); 208 + 209 + in.req_type = DP_REMOTE_I2C_READ; 210 + in.u.i2c_read.port_number = 0xf; 211 + DO_TEST(); 212 + in.u.i2c_read.read_i2c_device_id = 0x7f; 213 + DO_TEST(); 214 + in.u.i2c_read.num_transactions = 3; 215 + in.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3; 216 + for (i = 0; i < in.u.i2c_read.num_transactions; i++) { 217 + in.u.i2c_read.transactions[i].bytes = data; 218 + in.u.i2c_read.transactions[i].num_bytes = ARRAY_SIZE(data); 219 + in.u.i2c_read.transactions[i].i2c_dev_id = 0x7f & ~i; 220 + in.u.i2c_read.transactions[i].i2c_transaction_delay = 0xf & ~i; 221 + } 222 + DO_TEST(); 223 + 224 + in.req_type = DP_REMOTE_I2C_WRITE; 225 + in.u.i2c_write.port_number = 0xf; 226 + DO_TEST(); 227 + in.u.i2c_write.write_i2c_device_id = 0x7f; 228 + DO_TEST(); 229 + in.u.i2c_write.num_bytes = ARRAY_SIZE(data); 230 + in.u.i2c_write.bytes = data; 231 + DO_TEST(); 232 + 233 + #undef DO_TEST 36 234 return 0; 37 235 }
+1
drivers/gpu/drm/selftests/test-drm_modeset_common.h
··· 40 40 int igt_damage_iter_damage_src_moved(void *ignored); 41 41 int igt_damage_iter_damage_not_visible(void *ignored); 42 42 int igt_dp_mst_calc_pbn_mode(void *ignored); 43 + int igt_dp_mst_sideband_msg_req_decode(void *ignored); 43 44 44 45 #endif
+1 -1
include/drm/drm_dp_mst_helper.h
··· 287 287 struct drm_dp_remote_i2c_read { 288 288 u8 num_transactions; 289 289 u8 port_number; 290 - struct { 290 + struct drm_dp_remote_i2c_read_tx { 291 291 u8 i2c_dev_id; 292 292 u8 num_bytes; 293 293 u8 *bytes;