Revert "usb: typec: ucsi: Update UCSI structure to have message in and message out fields"

This reverts commit 3e082978c33151d576694deac8abde021ea669a8.

The new buffer management code has not been tested or reviewed properly
and breaks boot of machines like the Lenovo ThinkPad X13s:

Unable to handle kernel NULL pointer dereference at virtual address
0000000000000000

CPU: 0 UID: 0 PID: 813 Comm: kworker/0:3 Not tainted 6.19.0-rc2 #26 PREEMPT
Hardware name: LENOVO 21BYZ9SRUS/21BYZ9SRUS, BIOS N3HET87W (1.59 ) 12/05/2023
Workqueue: events ucsi_handle_connector_change [typec_ucsi]

Call trace:
ucsi_sync_control_common+0xe4/0x1ec [typec_ucsi] (P)
ucsi_run_command+0xcc/0x194 [typec_ucsi]
ucsi_send_command_common+0x84/0x2a0 [typec_ucsi]
ucsi_get_connector_status+0x48/0x78 [typec_ucsi]
ucsi_handle_connector_change+0x5c/0x4f4 [typec_ucsi]
process_one_work+0x208/0x60c
worker_thread+0x244/0x388

The new code completely ignores concurrency so that the message length
can be updated while a transaction is ongoing. In the above case, the
length ends up being modified by another thread while processing an ack
so that the NULL cci pointer is dereferenced.

Fixing this will require designing a proper interface for managing these
transactions, something which most likely involves reverting most of the
offending commit anyway.

Revert the broken code to fix the regression and let Intel come up with
a properly tested implementation for a later kernel.

Fixes: 3e082978c331 ("usb: typec: ucsi: Update UCSI structure to have message in and message out fields")
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://patch.msgid.link/20251222152204.2846-5-johan@kernel.org

authored by Johan Hovold and committed by Greg Kroah-Hartman e7a9f660 2e46b4e0

+3 -2
drivers/usb/typec/ucsi/cros_ec_ucsi.c
··· 105 105 return 0; 106 106 } 107 107 108 - static int cros_ucsi_sync_control(struct ucsi *ucsi, u64 cmd, u32 *cci) 108 + static int cros_ucsi_sync_control(struct ucsi *ucsi, u64 cmd, u32 *cci, 109 + void *data, size_t size) 109 110 { 110 111 struct cros_ucsi_data *udata = ucsi_get_drvdata(ucsi); 111 112 int ret; 112 113 113 - ret = ucsi_sync_control_common(ucsi, cmd, cci); 114 + ret = ucsi_sync_control_common(ucsi, cmd, cci, data, size); 114 115 switch (ret) { 115 116 case -EBUSY: 116 117 /* EC may return -EBUSY if CCI.busy is set.
+4 -5
drivers/usb/typec/ucsi/debugfs.c
··· 37 37 case UCSI_SET_USB: 38 38 case UCSI_SET_POWER_LEVEL: 39 39 case UCSI_READ_POWER_LEVEL: 40 - ucsi->message_in_size = 0; 41 - ret = ucsi_send_command(ucsi, val); 40 + ret = ucsi_send_command(ucsi, val, NULL, 0); 42 41 break; 43 42 case UCSI_GET_CAPABILITY: 44 43 case UCSI_GET_CONNECTOR_CAPABILITY: ··· 52 53 case UCSI_GET_ATTENTION_VDO: 53 54 case UCSI_GET_CAM_CS: 54 55 case UCSI_GET_LPM_PPM_INFO: 55 - ucsi->message_in_size = sizeof(ucsi->debugfs->response); 56 - ret = ucsi_send_command(ucsi, val); 57 - memcpy(&ucsi->debugfs->response, ucsi->message_in, sizeof(ucsi->debugfs->response)); 56 + ret = ucsi_send_command(ucsi, val, 57 + &ucsi->debugfs->response, 58 + sizeof(ucsi->debugfs->response)); 58 59 break; 59 60 default: 60 61 ret = -EOPNOTSUPP;
+3 -8
drivers/usb/typec/ucsi/displayport.c
··· 67 67 } 68 68 69 69 command = UCSI_GET_CURRENT_CAM | UCSI_CONNECTOR_NUMBER(dp->con->num); 70 - ucsi->message_in_size = sizeof(cur); 71 - ret = ucsi_send_command(ucsi, command); 70 + ret = ucsi_send_command(ucsi, command, &cur, sizeof(cur)); 72 71 if (ret < 0) { 73 72 if (ucsi->version > 0x0100) 74 73 goto err_unlock; 75 74 cur = 0xff; 76 - } else { 77 - memcpy(&cur, ucsi->message_in, ucsi->message_in_size); 78 75 } 79 76 80 77 if (cur != 0xff) { ··· 126 129 } 127 130 128 131 command = UCSI_CMD_SET_NEW_CAM(dp->con->num, 0, dp->offset, 0); 129 - dp->con->ucsi->message_in_size = 0; 130 - ret = ucsi_send_command(dp->con->ucsi, command); 132 + ret = ucsi_send_command(dp->con->ucsi, command, NULL, 0); 131 133 if (ret < 0) 132 134 goto out_unlock; 133 135 ··· 193 197 194 198 command = UCSI_CMD_SET_NEW_CAM(dp->con->num, 1, dp->offset, pins); 195 199 196 - dp->con->ucsi->message_in_size = 0; 197 - return ucsi_send_command(dp->con->ucsi, command); 200 + return ucsi_send_command(dp->con->ucsi, command, NULL, 0); 198 201 } 199 202 200 203 static int ucsi_displayport_vdm(struct typec_altmode *alt,
+36 -68
drivers/usb/typec/ucsi/ucsi.c
··· 55 55 } 56 56 EXPORT_SYMBOL_GPL(ucsi_notify_common); 57 57 58 - int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci) 58 + int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci, 59 + void *data, size_t size) 59 60 { 60 61 bool ack = UCSI_COMMAND(command) == UCSI_ACK_CC_CI; 61 62 int ret; ··· 84 83 if (!ret && cci) 85 84 ret = ucsi->ops->read_cci(ucsi, cci); 86 85 87 - if (!ret && ucsi->message_in_size > 0 && 86 + if (!ret && data && 88 87 (*cci & UCSI_CCI_COMMAND_COMPLETE)) 89 - ret = ucsi->ops->read_message_in(ucsi, ucsi->message_in, 90 - ucsi->message_in_size); 88 + ret = ucsi->ops->read_message_in(ucsi, data, size); 91 89 92 90 return ret; 93 91 } ··· 103 103 ctrl |= UCSI_ACK_CONNECTOR_CHANGE; 104 104 } 105 105 106 - ucsi->message_in_size = 0; 107 - return ucsi->ops->sync_control(ucsi, ctrl, NULL); 106 + return ucsi->ops->sync_control(ucsi, ctrl, NULL, NULL, 0); 108 107 } 109 108 110 - static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, bool conn_ack) 109 + static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, 110 + void *data, size_t size, bool conn_ack) 111 111 { 112 112 int ret, err; 113 113 114 114 *cci = 0; 115 115 116 - if (ucsi->message_in_size > UCSI_MAX_DATA_LENGTH(ucsi)) 116 + if (size > UCSI_MAX_DATA_LENGTH(ucsi)) 117 117 return -EINVAL; 118 118 119 - ret = ucsi->ops->sync_control(ucsi, command, cci); 119 + ret = ucsi->ops->sync_control(ucsi, command, cci, data, size); 120 120 121 - if (*cci & UCSI_CCI_BUSY) { 122 - ucsi->message_in_size = 0; 123 - return ucsi_run_command(ucsi, UCSI_CANCEL, cci, false) ?: -EBUSY; 124 - } 121 + if (*cci & UCSI_CCI_BUSY) 122 + return ucsi_run_command(ucsi, UCSI_CANCEL, cci, NULL, 0, false) ?: -EBUSY; 125 123 if (ret) 126 124 return ret; 127 125 ··· 151 153 int ret; 152 154 153 155 command = UCSI_GET_ERROR_STATUS | UCSI_CONNECTOR_NUMBER(connector_num); 154 - ucsi->message_in_size = sizeof(error); 155 - ret = ucsi_run_command(ucsi, command, &cci, false); 156 + ret = ucsi_run_command(ucsi, command, &cci, &error, sizeof(error), false); 156 157 if (ret < 0) 157 158 return ret; 158 - 159 - memcpy(&error, ucsi->message_in, sizeof(error)); 160 159 161 160 switch (error) { 162 161 case UCSI_ERROR_INCOMPATIBLE_PARTNER: ··· 200 205 return -EIO; 201 206 } 202 207 203 - static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd, bool conn_ack) 208 + static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd, 209 + void *data, size_t size, bool conn_ack) 204 210 { 205 211 u8 connector_num; 206 212 u32 cci; ··· 229 233 230 234 mutex_lock(&ucsi->ppm_lock); 231 235 232 - ret = ucsi_run_command(ucsi, cmd, &cci, conn_ack); 236 + ret = ucsi_run_command(ucsi, cmd, &cci, data, size, conn_ack); 233 237 234 238 if (cci & UCSI_CCI_ERROR) 235 239 ret = ucsi_read_error(ucsi, connector_num); ··· 238 242 return ret; 239 243 } 240 244 241 - int ucsi_send_command(struct ucsi *ucsi, u64 command) 245 + int ucsi_send_command(struct ucsi *ucsi, u64 command, 246 + void *data, size_t size) 242 247 { 243 - return ucsi_send_command_common(ucsi, command, false); 248 + return ucsi_send_command_common(ucsi, command, data, size, false); 244 249 } 245 250 EXPORT_SYMBOL_GPL(ucsi_send_command); 246 251 ··· 319 322 int i; 320 323 321 324 command = UCSI_GET_CURRENT_CAM | UCSI_CONNECTOR_NUMBER(con->num); 322 - con->ucsi->message_in_size = sizeof(cur); 323 - ret = ucsi_send_command(con->ucsi, command); 325 + ret = ucsi_send_command(con->ucsi, command, &cur, sizeof(cur)); 324 326 if (ret < 0) { 325 327 if (con->ucsi->version > 0x0100) { 326 328 dev_err(con->ucsi->dev, ··· 327 331 return; 328 332 } 329 333 cur = 0xff; 330 - } else { 331 - memcpy(&cur, con->ucsi->message_in, sizeof(cur)); 332 334 } 333 335 334 336 if (cur < UCSI_MAX_ALTMODES) ··· 510 516 command |= UCSI_GET_ALTMODE_RECIPIENT(recipient); 511 517 command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num); 512 518 command |= UCSI_GET_ALTMODE_OFFSET(i); 513 - ucsi->message_in_size = sizeof(alt); 514 - len = ucsi_send_command(con->ucsi, command); 519 + len = ucsi_send_command(con->ucsi, command, &alt, sizeof(alt)); 515 520 /* 516 521 * We are collecting all altmodes first and then registering. 517 522 * Some type-C device will return zero length data beyond last ··· 518 525 */ 519 526 if (len < 0) 520 527 return len; 521 - 522 - memcpy(&alt, ucsi->message_in, sizeof(alt)); 523 528 524 529 /* We got all altmodes, now break out and register them */ 525 530 if (!len || !alt.svid) ··· 586 595 command |= UCSI_GET_ALTMODE_RECIPIENT(recipient); 587 596 command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num); 588 597 command |= UCSI_GET_ALTMODE_OFFSET(i); 589 - con->ucsi->message_in_size = sizeof(alt); 590 - len = ucsi_send_command(con->ucsi, command); 598 + len = ucsi_send_command(con->ucsi, command, alt, sizeof(alt)); 591 599 if (len == -EBUSY) 592 600 continue; 593 601 if (len <= 0) 594 602 return len; 595 - 596 - memcpy(&alt, con->ucsi->message_in, sizeof(alt)); 597 603 598 604 /* 599 605 * This code is requesting one alt mode at a time, but some PPMs ··· 659 671 UCSI_MAX_DATA_LENGTH(con->ucsi)); 660 672 int ret; 661 673 662 - con->ucsi->message_in_size = size; 663 - ret = ucsi_send_command_common(con->ucsi, command, conn_ack); 664 - memcpy(&con->status, con->ucsi->message_in, size); 674 + ret = ucsi_send_command_common(con->ucsi, command, &con->status, size, conn_ack); 665 675 666 676 return ret < 0 ? ret : 0; 667 677 } ··· 682 696 command |= UCSI_GET_PDOS_PDO_OFFSET(offset); 683 697 command |= UCSI_GET_PDOS_NUM_PDOS(num_pdos - 1); 684 698 command |= is_source(role) ? UCSI_GET_PDOS_SRC_PDOS : 0; 685 - ucsi->message_in_size = num_pdos * sizeof(u32); 686 - ret = ucsi_send_command(ucsi, command); 687 - memcpy(pdos + offset, ucsi->message_in, num_pdos * sizeof(u32)); 699 + ret = ucsi_send_command(ucsi, command, pdos + offset, 700 + num_pdos * sizeof(u32)); 688 701 if (ret < 0 && ret != -ETIMEDOUT) 689 702 dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n", ret); 690 703 ··· 770 785 command |= UCSI_GET_PD_MESSAGE_BYTES(len); 771 786 command |= UCSI_GET_PD_MESSAGE_TYPE(type); 772 787 773 - con->ucsi->message_in_size = len; 774 - ret = ucsi_send_command(con->ucsi, command); 775 - memcpy(data + offset, con->ucsi->message_in, len); 788 + ret = ucsi_send_command(con->ucsi, command, data + offset, len); 776 789 if (ret < 0) 777 790 return ret; 778 791 } ··· 935 952 int ret; 936 953 937 954 command = UCSI_GET_CABLE_PROPERTY | UCSI_CONNECTOR_NUMBER(con->num); 938 - con->ucsi->message_in_size = sizeof(cable_prop); 939 - ret = ucsi_send_command(con->ucsi, command); 940 - memcpy(&cable_prop, con->ucsi->message_in, sizeof(cable_prop)); 955 + ret = ucsi_send_command(con->ucsi, command, &cable_prop, sizeof(cable_prop)); 941 956 if (ret < 0) { 942 957 dev_err(con->ucsi->dev, "GET_CABLE_PROPERTY failed (%d)\n", ret); 943 958 return ret; ··· 996 1015 return 0; 997 1016 998 1017 command = UCSI_GET_CONNECTOR_CAPABILITY | UCSI_CONNECTOR_NUMBER(con->num); 999 - con->ucsi->message_in_size = sizeof(con->cap); 1000 - ret = ucsi_send_command(con->ucsi, command); 1001 - memcpy(&con->cap, con->ucsi->message_in, sizeof(con->cap)); 1018 + ret = ucsi_send_command(con->ucsi, command, &con->cap, sizeof(con->cap)); 1002 1019 if (ret < 0) { 1003 1020 dev_err(con->ucsi->dev, "GET_CONNECTOR_CAPABILITY failed (%d)\n", ret); 1004 1021 return ret; ··· 1380 1401 else if (con->ucsi->version >= UCSI_VERSION_2_0) 1381 1402 command |= hard ? 0 : UCSI_CONNECTOR_RESET_DATA_VER_2_0; 1382 1403 1383 - con->ucsi->message_in_size = 0; 1384 - return ucsi_send_command(con->ucsi, command); 1404 + return ucsi_send_command(con->ucsi, command, NULL, 0); 1385 1405 } 1386 1406 1387 1407 static int ucsi_reset_ppm(struct ucsi *ucsi) ··· 1461 1483 { 1462 1484 int ret; 1463 1485 1464 - con->ucsi->message_in_size = 0; 1465 - ret = ucsi_send_command(con->ucsi, command); 1486 + ret = ucsi_send_command(con->ucsi, command, NULL, 0); 1466 1487 if (ret == -ETIMEDOUT) { 1467 1488 u64 c; 1468 1489 ··· 1469 1492 ucsi_reset_ppm(con->ucsi); 1470 1493 1471 1494 c = UCSI_SET_NOTIFICATION_ENABLE | con->ucsi->ntfy; 1472 - con->ucsi->message_in_size = 0; 1473 - ucsi_send_command(con->ucsi, c); 1495 + ucsi_send_command(con->ucsi, c, NULL, 0); 1474 1496 1475 1497 ucsi_reset_connector(con, true); 1476 1498 } ··· 1622 1646 /* Get connector capability */ 1623 1647 command = UCSI_GET_CONNECTOR_CAPABILITY; 1624 1648 command |= UCSI_CONNECTOR_NUMBER(con->num); 1625 - ucsi->message_in_size = sizeof(con->cap); 1626 - ret = ucsi_send_command(ucsi, command); 1649 + ret = ucsi_send_command(ucsi, command, &con->cap, sizeof(con->cap)); 1627 1650 if (ret < 0) 1628 1651 goto out_unlock; 1629 - 1630 - memcpy(&con->cap, ucsi->message_in, sizeof(con->cap)); 1631 1652 1632 1653 if (UCSI_CONCAP(con, OPMODE_DRP)) 1633 1654 cap->data = TYPEC_PORT_DRD; ··· 1822 1849 /* Enable basic notifications */ 1823 1850 ntfy = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR; 1824 1851 command = UCSI_SET_NOTIFICATION_ENABLE | ntfy; 1825 - ucsi->message_in_size = 0; 1826 - ret = ucsi_send_command(ucsi, command); 1852 + ret = ucsi_send_command(ucsi, command, NULL, 0); 1827 1853 if (ret < 0) 1828 1854 goto err_reset; 1829 1855 1830 1856 /* Get PPM capabilities */ 1831 1857 command = UCSI_GET_CAPABILITY; 1832 - ucsi->message_in_size = BITS_TO_BYTES(UCSI_GET_CAPABILITY_SIZE); 1833 - ret = ucsi_send_command(ucsi, command); 1858 + ret = ucsi_send_command(ucsi, command, &ucsi->cap, 1859 + BITS_TO_BYTES(UCSI_GET_CAPABILITY_SIZE)); 1834 1860 if (ret < 0) 1835 1861 goto err_reset; 1836 - 1837 - memcpy(&ucsi->cap, ucsi->message_in, BITS_TO_BYTES(UCSI_GET_CAPABILITY_SIZE)); 1838 1862 1839 1863 if (!ucsi->cap.num_connectors) { 1840 1864 ret = -ENODEV; ··· 1862 1892 /* Enable all supported notifications */ 1863 1893 ntfy = ucsi_get_supported_notifications(ucsi); 1864 1894 command = UCSI_SET_NOTIFICATION_ENABLE | ntfy; 1865 - ucsi->message_in_size = 0; 1866 - ret = ucsi_send_command(ucsi, command); 1895 + ret = ucsi_send_command(ucsi, command, NULL, 0); 1867 1896 if (ret < 0) 1868 1897 goto err_unregister; 1869 1898 ··· 1913 1944 1914 1945 /* Restore UCSI notification enable mask after system resume */ 1915 1946 command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; 1916 - ucsi->message_in_size = 0; 1917 - ret = ucsi_send_command(ucsi, command); 1947 + ret = ucsi_send_command(ucsi, command, NULL, 0); 1918 1948 if (ret < 0) { 1919 1949 dev_err(ucsi->dev, "failed to re-enable notifications (%d)\n", ret); 1920 1950 return;
+6 -13
drivers/usb/typec/ucsi/ucsi.h
··· 29 29 #define UCSI_MESSAGE_OUT 32 30 30 #define UCSIv2_MESSAGE_OUT 272 31 31 32 - /* Define maximum lengths for message buffers */ 33 - #define UCSI_MAX_MESSAGE_IN_LENGTH 256 34 - #define UCSI_MAX_MESSAGE_OUT_LENGTH 256 35 - 36 32 /* UCSI versions */ 37 33 #define UCSI_VERSION_1_0 0x0100 38 34 #define UCSI_VERSION_1_1 0x0110 ··· 80 84 int (*read_cci)(struct ucsi *ucsi, u32 *cci); 81 85 int (*poll_cci)(struct ucsi *ucsi, u32 *cci); 82 86 int (*read_message_in)(struct ucsi *ucsi, void *val, size_t val_len); 83 - int (*sync_control)(struct ucsi *ucsi, u64 command, u32 *cci); 87 + int (*sync_control)(struct ucsi *ucsi, u64 command, u32 *cci, 88 + void *data, size_t size); 84 89 int (*async_control)(struct ucsi *ucsi, u64 command); 85 90 bool (*update_altmodes)(struct ucsi *ucsi, u8 recipient, 86 91 struct ucsi_altmode *orig, ··· 493 496 unsigned long quirks; 494 497 #define UCSI_NO_PARTNER_PDOS BIT(0) /* Don't read partner's PDOs */ 495 498 #define UCSI_DELAY_DEVICE_PDOS BIT(1) /* Reading PDOs fails until the parter is in PD mode */ 496 - 497 - /* Fixed-size buffers for incoming and outgoing messages */ 498 - u8 message_in[UCSI_MAX_MESSAGE_IN_LENGTH]; 499 - size_t message_in_size; 500 - u8 message_out[UCSI_MAX_MESSAGE_OUT_LENGTH]; 501 - size_t message_out_size; 502 499 }; 503 500 504 501 #define UCSI_MAX_DATA_LENGTH(u) (((u)->version < UCSI_VERSION_2_0) ? 0x10 : 0xff) ··· 555 564 struct usb_pd_identity cable_identity; 556 565 }; 557 566 558 - int ucsi_send_command(struct ucsi *ucsi, u64 command); 567 + int ucsi_send_command(struct ucsi *ucsi, u64 command, 568 + void *retval, size_t size); 559 569 560 570 void ucsi_altmode_update_active(struct ucsi_connector *con); 561 571 int ucsi_resume(struct ucsi *ucsi); 562 572 563 573 void ucsi_notify_common(struct ucsi *ucsi, u32 cci); 564 - int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci); 574 + int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci, 575 + void *data, size_t size); 565 576 566 577 #if IS_ENABLED(CONFIG_POWER_SUPPLY) 567 578 int ucsi_register_port_psy(struct ucsi_connector *con);
+5 -4
drivers/usb/typec/ucsi/ucsi_acpi.c
··· 105 105 .async_control = ucsi_acpi_async_control 106 106 }; 107 107 108 - static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command, u32 *cci) 108 + static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command, u32 *cci, 109 + void *val, size_t len) 109 110 { 110 111 u16 bogus_change = UCSI_CONSTAT_POWER_LEVEL_CHANGE | 111 112 UCSI_CONSTAT_PDOS_CHANGE; 112 113 struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); 113 114 int ret; 114 115 115 - ret = ucsi_sync_control_common(ucsi, command, cci); 116 + ret = ucsi_sync_control_common(ucsi, command, cci, val, len); 116 117 if (ret < 0) 117 118 return ret; 118 119 ··· 125 124 if (UCSI_COMMAND(ua->cmd) == UCSI_GET_CONNECTOR_STATUS && 126 125 ua->check_bogus_event) { 127 126 /* Clear the bogus change */ 128 - if (*(u16 *)ucsi->message_in == bogus_change) 129 - *(u16 *)ucsi->message_in = 0; 127 + if (*(u16 *)val == bogus_change) 128 + *(u16 *)val = 0; 130 129 131 130 ua->check_bogus_event = false; 132 131 }
+6 -5
drivers/usb/typec/ucsi/ucsi_ccg.c
··· 606 606 return ccg_write(uc, reg, (u8 *)&command, sizeof(command)); 607 607 } 608 608 609 - static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command, u32 *cci) 609 + static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command, u32 *cci, 610 + void *data, size_t size) 610 611 { 611 612 struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi); 612 613 struct ucsi_connector *con; ··· 629 628 ucsi_ccg_update_set_new_cam_cmd(uc, con, &command); 630 629 } 631 630 632 - ret = ucsi_sync_control_common(ucsi, command, cci); 631 + ret = ucsi_sync_control_common(ucsi, command, cci, data, size); 633 632 634 633 switch (UCSI_COMMAND(command)) { 635 634 case UCSI_GET_CURRENT_CAM: 636 635 if (uc->has_multiple_dp) 637 - ucsi_ccg_update_get_current_cam_cmd(uc, (u8 *)ucsi->message_in); 636 + ucsi_ccg_update_get_current_cam_cmd(uc, (u8 *)data); 638 637 break; 639 638 case UCSI_GET_ALTERNATE_MODES: 640 639 if (UCSI_ALTMODE_RECIPIENT(command) == UCSI_RECIPIENT_SOP) { 641 - struct ucsi_altmode *alt = (struct ucsi_altmode *)ucsi->message_in; 640 + struct ucsi_altmode *alt = data; 642 641 643 642 if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID) 644 643 ucsi_ccg_nvidia_altmode(uc, alt, command); ··· 646 645 break; 647 646 case UCSI_GET_CAPABILITY: 648 647 if (uc->fw_build == CCG_FW_BUILD_NVIDIA_TEGRA) { 649 - struct ucsi_capability *cap = (struct ucsi_capability *)ucsi->message_in; 648 + struct ucsi_capability *cap = data; 650 649 651 650 cap->features &= ~UCSI_CAP_ALT_MODE_DETAILS; 652 651 }
+8 -7
drivers/usb/typec/ucsi/ucsi_yoga_c630.c
··· 88 88 89 89 static int yoga_c630_ucsi_sync_control(struct ucsi *ucsi, 90 90 u64 command, 91 - u32 *cci) 91 + u32 *cci, 92 + void *data, size_t size) 92 93 { 93 94 int ret; 94 95 ··· 107 106 }; 108 107 109 108 dev_dbg(ucsi->dev, "faking DP altmode for con1\n"); 110 - memset(ucsi->message_in, 0, ucsi->message_in_size); 111 - memcpy(ucsi->message_in, &alt, min(sizeof(alt), ucsi->message_in_size)); 109 + memset(data, 0, size); 110 + memcpy(data, &alt, min(sizeof(alt), size)); 112 111 *cci = UCSI_CCI_COMMAND_COMPLETE | UCSI_SET_CCI_LENGTH(sizeof(alt)); 113 112 return 0; 114 113 } ··· 121 120 if (UCSI_COMMAND(command) == UCSI_GET_ALTERNATE_MODES && 122 121 UCSI_GET_ALTMODE_GET_CONNECTOR_NUMBER(command) == 2) { 123 122 dev_dbg(ucsi->dev, "ignoring altmodes for con2\n"); 124 - memset(ucsi->message_in, 0, ucsi->message_in_size); 123 + memset(data, 0, size); 125 124 *cci = UCSI_CCI_COMMAND_COMPLETE; 126 125 return 0; 127 126 } 128 127 129 - ret = ucsi_sync_control_common(ucsi, command, cci); 128 + ret = ucsi_sync_control_common(ucsi, command, cci, data, size); 130 129 if (ret < 0) 131 130 return ret; 132 131 133 132 /* UCSI_GET_CURRENT_CAM is off-by-one on all ports */ 134 - if (UCSI_COMMAND(command) == UCSI_GET_CURRENT_CAM && ucsi->message_in_size > 0) 135 - ucsi->message_in[0]--; 133 + if (UCSI_COMMAND(command) == UCSI_GET_CURRENT_CAM && data) 134 + ((u8 *)data)[0]--; 136 135 137 136 return ret; 138 137 }