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

Configure Feed

Select the types of activity you want to include in your feed.

platform/chrome: lightbar: Add support for large sequence

Current sequences are limited to 192 bytes. Increase support to whatever
the EC support. If the sequence is too long, the EC will return an
OVERFLOW error.

Test: Check sending a large sequence is received by the EC.

Signed-off-by: Gwendal Grignou <gwendal@google.com>
Link: https://lore.kernel.org/r/20260130081351.487517-2-gwendal@google.com
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>

authored by

Gwendal Grignou and committed by
Tzung-Bi Shih
9600b8bd 2d8251d9

+74 -27
+61 -27
drivers/platform/chrome/cros_ec_lightbar.c
··· 37 37 */ 38 38 static bool has_manual_suspend; 39 39 40 + /* 41 + * Lightbar version 42 + */ 43 + static int lb_version; 44 + 40 45 static ssize_t interval_msec_show(struct device *dev, 41 46 struct device_attribute *attr, char *buf) 42 47 { ··· 98 93 99 94 static struct cros_ec_command *alloc_lightbar_cmd_msg(struct cros_ec_dev *ec) 100 95 { 96 + int len = max(ec->ec_dev->max_response, ec->ec_dev->max_request); 101 97 struct cros_ec_command *msg; 102 - int len; 103 - 104 - len = max(sizeof(struct ec_params_lightbar), 105 - sizeof(struct ec_response_lightbar)); 106 98 107 99 msg = kmalloc(sizeof(*msg) + len, GFP_KERNEL); 108 100 if (!msg) ··· 107 105 108 106 msg->version = 0; 109 107 msg->command = EC_CMD_LIGHTBAR_CMD + ec->cmd_offset; 108 + /* 109 + * Default sizes for regular commands. 110 + * Can be set smaller to optimize transfer, 111 + * larger when sending large light sequences. 112 + */ 110 113 msg->outsize = sizeof(struct ec_params_lightbar); 111 114 msg->insize = sizeof(struct ec_response_lightbar); 112 115 ··· 478 471 static ssize_t program_store(struct device *dev, struct device_attribute *attr, 479 472 const char *buf, size_t count) 480 473 { 481 - int extra_bytes, max_size, ret; 474 + size_t extra_bytes, max_size; 482 475 struct ec_params_lightbar *param; 483 476 struct cros_ec_command *msg; 484 477 struct cros_ec_dev *ec = to_cros_ec_dev(dev); 478 + int ret; 485 479 486 480 /* 487 481 * We might need to reject the program for size reasons. The EC ··· 490 482 * and send a program that is too big for the protocol. In order 491 483 * to ensure the latter, we also need to ensure we have extra bytes 492 484 * to represent the rest of the packet. 485 + * With V3, larger program can be sent, limited only by the EC. 486 + * Only the protocol limit the payload size. 493 487 */ 494 - extra_bytes = sizeof(*param) - sizeof(param->set_program.data); 495 - max_size = min(EC_LB_PROG_LEN, ec->ec_dev->max_request - extra_bytes); 496 - if (count > max_size) { 497 - dev_err(dev, "Program is %u bytes, too long to send (max: %u)", 498 - (unsigned int)count, max_size); 488 + if (lb_version < 3) { 489 + extra_bytes = sizeof(*param) - sizeof(param->set_program.data); 490 + max_size = min(EC_LB_PROG_LEN, ec->ec_dev->max_request - extra_bytes); 491 + if (count > max_size) { 492 + dev_err(dev, "Program is %zu bytes, too long to send (max: %zu)", 493 + count, max_size); 499 494 500 - return -EINVAL; 495 + return -EINVAL; 496 + } 497 + } else { 498 + extra_bytes = offsetof(typeof(*param), set_program_ex) + 499 + sizeof(param->set_program_ex); 500 + max_size = ec->ec_dev->max_request - extra_bytes; 501 501 } 502 502 503 503 msg = alloc_lightbar_cmd_msg(ec); ··· 515 499 ret = lb_throttle(); 516 500 if (ret) 517 501 goto exit; 518 - 519 - dev_info(dev, "Copying %zu byte program to EC", count); 520 - 521 502 param = (struct ec_params_lightbar *)msg->data; 522 - param->cmd = LIGHTBAR_CMD_SET_PROGRAM; 523 503 524 - param->set_program.size = count; 525 - memcpy(param->set_program.data, buf, count); 504 + if (lb_version < 3) { 505 + dev_info(dev, "Copying %zu byte program to EC", count); 526 506 527 - /* 528 - * We need to set the message size manually or else it will use 529 - * EC_LB_PROG_LEN. This might be too long, and the program 530 - * is unlikely to use all of the space. 531 - */ 532 - msg->outsize = count + extra_bytes; 507 + param->cmd = LIGHTBAR_CMD_SET_PROGRAM; 533 508 534 - ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 535 - if (ret < 0) 536 - goto exit; 509 + param->set_program.size = count; 510 + memcpy(param->set_program.data, buf, count); 537 511 512 + /* 513 + * We need to set the message size manually or else it will use 514 + * EC_LB_PROG_LEN. This might be too long, and the program 515 + * is unlikely to use all of the space. 516 + */ 517 + msg->outsize = count + extra_bytes; 518 + 519 + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 520 + if (ret < 0) 521 + goto exit; 522 + } else { 523 + size_t offset = 0; 524 + size_t payload = 0; 525 + 526 + param->cmd = LIGHTBAR_CMD_SET_PROGRAM_EX; 527 + while (offset < count) { 528 + payload = min(max_size, count - offset); 529 + param->set_program_ex.offset = offset; 530 + param->set_program_ex.size = payload; 531 + memcpy(param->set_program_ex.data, &buf[offset], payload); 532 + msg->outsize = payload + extra_bytes; 533 + 534 + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 535 + if (ret < 0) 536 + goto exit; 537 + offset += payload; 538 + } 539 + } 538 540 ret = count; 539 541 exit: 540 542 kfree(msg); ··· 630 596 * Ask then for the lightbar version, if it's 0 then the 'cros_ec' 631 597 * doesn't have a lightbar. 632 598 */ 633 - if (!get_lightbar_version(ec_dev, NULL, NULL)) 599 + if (!get_lightbar_version(ec_dev, &lb_version, NULL)) 634 600 return -ENODEV; 635 601 636 602 /* Take control of the lightbar from the EC. */
+13
include/linux/platform_data/cros_ec_commands.h
··· 2020 2020 uint8_t data[EC_LB_PROG_LEN]; 2021 2021 } __ec_todo_unpacked; 2022 2022 2023 + /* 2024 + * Lightbar program for large sequences. Sequences are sent in pieces, with 2025 + * increasing offset. The sequences are still limited by the amount reserved in 2026 + * EC RAM. 2027 + */ 2028 + struct lightbar_program_ex { 2029 + uint16_t offset; 2030 + uint8_t size; 2031 + uint8_t data[0]; 2032 + } __ec_todo_unpacked; 2033 + 2023 2034 struct ec_params_lightbar { 2024 2035 uint8_t cmd; /* Command (see enum lightbar_command) */ 2025 2036 union { ··· 2077 2066 struct lightbar_params_v2_colors set_v2par_colors; 2078 2067 2079 2068 struct lightbar_program set_program; 2069 + struct lightbar_program_ex set_program_ex; 2080 2070 }; 2081 2071 } __ec_todo_packed; 2082 2072 ··· 2166 2154 LIGHTBAR_CMD_GET_PARAMS_V2_COLORS = 32, 2167 2155 LIGHTBAR_CMD_SET_PARAMS_V2_COLORS = 33, 2168 2156 LIGHTBAR_CMD_GET_PARAMS_V3 = 34, 2157 + LIGHTBAR_CMD_SET_PROGRAM_EX = 35, 2169 2158 LIGHTBAR_NUM_CMDS 2170 2159 }; 2171 2160