diff options
Diffstat (limited to 'drivers/platform/chrome')
-rw-r--r-- | drivers/platform/chrome/Kconfig | 7 | ||||
-rw-r--r-- | drivers/platform/chrome/Makefile | 3 | ||||
-rw-r--r-- | drivers/platform/chrome/chromeos_laptop.c | 9 | ||||
-rw-r--r-- | drivers/platform/chrome/chromeos_of_hw_prober.c | 33 | ||||
-rw-r--r-- | drivers/platform/chrome/chromeos_pstore.c | 7 | ||||
-rw-r--r-- | drivers/platform/chrome/cros_ec.c | 3 | ||||
-rw-r--r-- | drivers/platform/chrome/cros_ec_debugfs.c | 52 | ||||
-rw-r--r-- | drivers/platform/chrome/cros_ec_proto.c | 24 | ||||
-rw-r--r-- | drivers/platform/chrome/cros_ec_proto_test_util.h | 5 | ||||
-rw-r--r-- | drivers/platform/chrome/cros_ec_sensorhub.c | 23 | ||||
-rw-r--r-- | drivers/platform/chrome/cros_ec_typec.c | 97 | ||||
-rw-r--r-- | drivers/platform/chrome/cros_kbd_led_backlight.c | 24 |
12 files changed, 206 insertions, 81 deletions
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig index 1b2f2bd09662..2281d6dacc9b 100644 --- a/drivers/platform/chrome/Kconfig +++ b/drivers/platform/chrome/Kconfig @@ -155,13 +155,14 @@ config CROS_EC_LPC module will be called cros_ec_lpcs. config CROS_EC_PROTO - bool + tristate help ChromeOS EC communication protocol helpers. config CROS_KBD_LED_BACKLIGHT tristate "Backlight LED support for Chrome OS keyboards" - depends on LEDS_CLASS && (ACPI || CROS_EC || MFD_CROS_EC_DEV) + depends on LEDS_CLASS + depends on MFD_CROS_EC_DEV || (MFD_CROS_EC_DEV=n && ACPI) help This option enables support for the keyboard backlight LEDs on select Chrome OS systems. @@ -285,7 +286,7 @@ config CROS_USBPD_NOTIFY default MFD_CROS_EC_DEV help If you say Y here, you get support for Type-C PD event notifications - from the ChromeOS EC. On ACPI platorms this driver will bind to the + from the ChromeOS EC. On ACPI platforms this driver will bind to the GOOG0003 ACPI device, and on platforms which don't have this device it will get initialized on ECs which support the feature EC_FEATURE_USB_PD. diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile index 1a5a484563cc..b981a1bb5bd8 100644 --- a/drivers/platform/chrome/Makefile +++ b/drivers/platform/chrome/Makefile @@ -25,7 +25,8 @@ endif obj-$(CONFIG_CROS_EC_TYPEC) += cros-ec-typec.o obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpcs.o -obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o cros_ec_trace.o +cros-ec-proto-objs := cros_ec_proto.o cros_ec_trace.o +obj-$(CONFIG_CROS_EC_PROTO) += cros-ec-proto.o obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT) += cros_kbd_led_backlight.o obj-$(CONFIG_CROS_EC_CHARDEV) += cros_ec_chardev.o obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 3ab668764383..0b92047265de 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -726,9 +726,9 @@ static int __init chromeos_laptop_setup_irq(struct i2c_peripheral *i2c_dev) if (irq < 0) return irq; - i2c_dev->irq_resource = (struct resource) - DEFINE_RES_NAMED(irq, 1, NULL, - IORESOURCE_IRQ | i2c_dev->irqflags); + i2c_dev->irq_resource = DEFINE_RES_IRQ(irq); + i2c_dev->irq_resource.flags |= i2c_dev->irqflags; + i2c_dev->board_info.resources = &i2c_dev->irq_resource; i2c_dev->board_info.num_resources = 1; } @@ -782,8 +782,7 @@ err_out: while (--i >= 0) { i2c_dev = &i2c_peripherals[i]; info = &i2c_dev->board_info; - if (!IS_ERR_OR_NULL(info->fwnode)) - fwnode_remove_software_node(info->fwnode); + fwnode_remove_software_node(info->fwnode); } kfree(i2c_peripherals); return error; diff --git a/drivers/platform/chrome/chromeos_of_hw_prober.c b/drivers/platform/chrome/chromeos_of_hw_prober.c index c6992f5cdc76..f3cd612e5584 100644 --- a/drivers/platform/chrome/chromeos_of_hw_prober.c +++ b/drivers/platform/chrome/chromeos_of_hw_prober.c @@ -57,7 +57,9 @@ static int chromeos_i2c_component_prober(struct device *dev, const void *_data) } DEFINE_CHROMEOS_I2C_PROBE_DATA_DUMB_BY_TYPE(touchscreen); +DEFINE_CHROMEOS_I2C_PROBE_DATA_DUMB_BY_TYPE(trackpad); +DEFINE_CHROMEOS_I2C_PROBE_CFG_SIMPLE_BY_TYPE(touchscreen); DEFINE_CHROMEOS_I2C_PROBE_CFG_SIMPLE_BY_TYPE(trackpad); static const struct chromeos_i2c_probe_data chromeos_i2c_probe_hana_trackpad = { @@ -75,6 +77,17 @@ static const struct chromeos_i2c_probe_data chromeos_i2c_probe_hana_trackpad = { }, }; +static const struct chromeos_i2c_probe_data chromeos_i2c_probe_squirtle_touchscreen = { + .cfg = &chromeos_i2c_probe_simple_touchscreen_cfg, + .opts = &(const struct i2c_of_probe_simple_opts) { + .res_node_compatible = "elan,ekth6a12nay", + .supply_name = "vcc33", + .gpio_name = "reset", + .post_power_on_delay_ms = 10, + .post_gpio_config_delay_ms = 300, + }, +}; + static const struct hw_prober_entry hw_prober_platforms[] = { { .compatible = "google,hana", @@ -84,6 +97,26 @@ static const struct hw_prober_entry hw_prober_platforms[] = { .compatible = "google,hana", .prober = chromeos_i2c_component_prober, .data = &chromeos_i2c_probe_hana_trackpad, + }, { + .compatible = "google,spherion", + .prober = chromeos_i2c_component_prober, + .data = &chromeos_i2c_probe_hana_trackpad, + }, { + .compatible = "google,squirtle", + .prober = chromeos_i2c_component_prober, + .data = &chromeos_i2c_probe_dumb_trackpad, + }, { + .compatible = "google,squirtle", + .prober = chromeos_i2c_component_prober, + .data = &chromeos_i2c_probe_squirtle_touchscreen, + }, { + .compatible = "google,steelix", + .prober = chromeos_i2c_component_prober, + .data = &chromeos_i2c_probe_dumb_trackpad, + }, { + .compatible = "google,voltorb", + .prober = chromeos_i2c_component_prober, + .data = &chromeos_i2c_probe_dumb_trackpad, }, }; diff --git a/drivers/platform/chrome/chromeos_pstore.c b/drivers/platform/chrome/chromeos_pstore.c index f37c0ef4af1f..a6eed99507d4 100644 --- a/drivers/platform/chrome/chromeos_pstore.c +++ b/drivers/platform/chrome/chromeos_pstore.c @@ -9,6 +9,10 @@ #include <linux/platform_device.h> #include <linux/pstore_ram.h> +static int ecc_size; +module_param(ecc_size, int, 0400); +MODULE_PARM_DESC(ecc_size, "ECC parity data size in bytes. A positive value enables ECC for the ramoops region."); + static const struct dmi_system_id chromeos_pstore_dmi_table[] __initconst = { { /* @@ -117,6 +121,9 @@ static int __init chromeos_pstore_init(void) { bool acpi_dev_found; + if (ecc_size > 0) + chromeos_ramoops_data.ecc_info.ecc_size = ecc_size; + /* First check ACPI for non-hardcoded values from firmware. */ acpi_dev_found = chromeos_check_acpi(); diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c index 110771a8645e..fd58781a2fb7 100644 --- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -318,6 +318,9 @@ EXPORT_SYMBOL(cros_ec_register); */ void cros_ec_unregister(struct cros_ec_device *ec_dev) { + if (ec_dev->mkbp_event_supported) + blocking_notifier_chain_unregister(&ec_dev->event_notifier, + &ec_dev->notifier_ready); platform_device_unregister(ec_dev->pd); platform_device_unregister(ec_dev->ec); mutex_destroy(&ec_dev->lock); diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c index 92ac9a2f9c88..d10f9561990c 100644 --- a/drivers/platform/chrome/cros_ec_debugfs.c +++ b/drivers/platform/chrome/cros_ec_debugfs.c @@ -207,22 +207,15 @@ static ssize_t cros_ec_pdinfo_read(struct file *file, char read_buf[EC_USB_PD_MAX_PORTS * 40], *p = read_buf; struct cros_ec_debugfs *debug_info = file->private_data; struct cros_ec_device *ec_dev = debug_info->ec->ec_dev; - struct { - struct cros_ec_command msg; - union { - struct ec_response_usb_pd_control_v1 resp; - struct ec_params_usb_pd_control params; - }; - } __packed ec_buf; - struct cros_ec_command *msg; - struct ec_response_usb_pd_control_v1 *resp; - struct ec_params_usb_pd_control *params; + DEFINE_RAW_FLEX(struct cros_ec_command, msg, data, + MAX(sizeof(struct ec_response_usb_pd_control_v1), + sizeof(struct ec_params_usb_pd_control))); + struct ec_response_usb_pd_control_v1 *resp = + (struct ec_response_usb_pd_control_v1 *)msg->data; + struct ec_params_usb_pd_control *params = + (struct ec_params_usb_pd_control *)msg->data; int i; - msg = &ec_buf.msg; - params = (struct ec_params_usb_pd_control *)msg->data; - resp = (struct ec_response_usb_pd_control_v1 *)msg->data; - msg->command = EC_CMD_USB_PD_CONTROL; msg->version = 1; msg->insize = sizeof(*resp); @@ -253,17 +246,15 @@ static ssize_t cros_ec_pdinfo_read(struct file *file, static bool cros_ec_uptime_is_supported(struct cros_ec_device *ec_dev) { - struct { - struct cros_ec_command cmd; - struct ec_response_uptime_info resp; - } __packed msg = {}; + DEFINE_RAW_FLEX(struct cros_ec_command, msg, data, + sizeof(struct ec_response_uptime_info)); int ret; - msg.cmd.command = EC_CMD_GET_UPTIME_INFO; - msg.cmd.insize = sizeof(msg.resp); + msg->command = EC_CMD_GET_UPTIME_INFO; + msg->insize = sizeof(struct ec_response_uptime_info); - ret = cros_ec_cmd_xfer_status(ec_dev, &msg.cmd); - if (ret == -EPROTO && msg.cmd.result == EC_RES_INVALID_COMMAND) + ret = cros_ec_cmd_xfer_status(ec_dev, msg); + if (ret == -EPROTO && msg->result == EC_RES_INVALID_COMMAND) return false; /* Other errors maybe a transient error, do not rule about support. */ @@ -275,20 +266,17 @@ static ssize_t cros_ec_uptime_read(struct file *file, char __user *user_buf, { struct cros_ec_debugfs *debug_info = file->private_data; struct cros_ec_device *ec_dev = debug_info->ec->ec_dev; - struct { - struct cros_ec_command cmd; - struct ec_response_uptime_info resp; - } __packed msg = {}; - struct ec_response_uptime_info *resp; + DEFINE_RAW_FLEX(struct cros_ec_command, msg, data, + sizeof(struct ec_response_uptime_info)); + struct ec_response_uptime_info *resp = + (struct ec_response_uptime_info *)msg->data; char read_buf[32]; int ret; - resp = (struct ec_response_uptime_info *)&msg.resp; - - msg.cmd.command = EC_CMD_GET_UPTIME_INFO; - msg.cmd.insize = sizeof(*resp); + msg->command = EC_CMD_GET_UPTIME_INFO; + msg->insize = sizeof(*resp); - ret = cros_ec_cmd_xfer_status(ec_dev, &msg.cmd); + ret = cros_ec_cmd_xfer_status(ec_dev, msg); if (ret < 0) return ret; diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 877b107fee4b..3e94a0a82173 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -139,12 +139,10 @@ static int cros_ec_xfer_command(struct cros_ec_device *ec_dev, struct cros_ec_co static int cros_ec_wait_until_complete(struct cros_ec_device *ec_dev, uint32_t *result) { - struct { - struct cros_ec_command msg; - struct ec_response_get_comms_status status; - } __packed buf; - struct cros_ec_command *msg = &buf.msg; - struct ec_response_get_comms_status *status = &buf.status; + DEFINE_RAW_FLEX(struct cros_ec_command, msg, data, + sizeof(struct ec_response_get_comms_status)); + struct ec_response_get_comms_status *status = + (struct ec_response_get_comms_status *)msg->data; int ret = 0, i; msg->version = 0; @@ -757,16 +755,13 @@ static int get_next_event_xfer(struct cros_ec_device *ec_dev, static int get_next_event(struct cros_ec_device *ec_dev) { - struct { - struct cros_ec_command msg; - struct ec_response_get_next_event_v3 event; - } __packed buf; - struct cros_ec_command *msg = &buf.msg; - struct ec_response_get_next_event_v3 *event = &buf.event; + DEFINE_RAW_FLEX(struct cros_ec_command, msg, data, + sizeof(struct ec_response_get_next_event_v3)); + struct ec_response_get_next_event_v3 *event = + (struct ec_response_get_next_event_v3 *)msg->data; int cmd_version = ec_dev->mkbp_event_supported - 1; u32 size; - memset(msg, 0, sizeof(*msg)); if (ec_dev->suspended) { dev_dbg(ec_dev->dev, "Device suspended.\n"); return -EHOSTDOWN; @@ -1157,3 +1152,6 @@ int cros_ec_get_cmd_versions(struct cros_ec_device *ec_dev, u16 cmd) return resp.version_mask; } EXPORT_SYMBOL_GPL(cros_ec_get_cmd_versions); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ChromeOS EC communication protocol helpers"); diff --git a/drivers/platform/chrome/cros_ec_proto_test_util.h b/drivers/platform/chrome/cros_ec_proto_test_util.h index 414002271c9c..b17239f052c2 100644 --- a/drivers/platform/chrome/cros_ec_proto_test_util.h +++ b/drivers/platform/chrome/cros_ec_proto_test_util.h @@ -13,7 +13,6 @@ struct ec_xfer_mock { struct kunit *test; /* input */ - struct cros_ec_command msg; void *i_data; /* output */ @@ -21,6 +20,10 @@ struct ec_xfer_mock { int result; void *o_data; u32 o_data_len; + + /* input */ + /* Must be last -ends in a flexible-array member. */ + struct cros_ec_command msg; }; extern int cros_kunit_ec_xfer_mock_default_result; diff --git a/drivers/platform/chrome/cros_ec_sensorhub.c b/drivers/platform/chrome/cros_ec_sensorhub.c index 50cdae67fa32..9bad8f72680e 100644 --- a/drivers/platform/chrome/cros_ec_sensorhub.c +++ b/drivers/platform/chrome/cros_ec_sensorhub.c @@ -8,6 +8,7 @@ #include <linux/init.h> #include <linux/device.h> +#include <linux/delay.h> #include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/platform_data/cros_ec_commands.h> @@ -18,6 +19,7 @@ #include <linux/types.h> #define DRV_NAME "cros-ec-sensorhub" +#define CROS_EC_CMD_INFO_RETRIES 50 static void cros_ec_sensorhub_free_sensor(void *arg) { @@ -53,7 +55,7 @@ static int cros_ec_sensorhub_register(struct device *dev, int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 }; struct cros_ec_command *msg = sensorhub->msg; struct cros_ec_dev *ec = sensorhub->ec; - int ret, i; + int ret, i, retries; char *name; @@ -65,12 +67,25 @@ static int cros_ec_sensorhub_register(struct device *dev, sensorhub->params->cmd = MOTIONSENSE_CMD_INFO; sensorhub->params->info.sensor_num = i; - ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + retries = CROS_EC_CMD_INFO_RETRIES; + do { + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret == -EBUSY) { + /* The EC is still busy initializing sensors. */ + usleep_range(5000, 6000); + retries--; + } + } while (ret == -EBUSY && retries); + if (ret < 0) { - dev_warn(dev, "no info for EC sensor %d : %d/%d\n", - i, ret, msg->result); + dev_err(dev, "no info for EC sensor %d : %d/%d\n", + i, ret, msg->result); continue; } + if (retries < CROS_EC_CMD_INFO_RETRIES) { + dev_warn(dev, "%d retries needed to bring up sensor %d\n", + CROS_EC_CMD_INFO_RETRIES - retries, i); + } switch (sensorhub->resp->info.type) { case MOTIONSENSE_TYPE_ACCEL: diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index d2228720991f..b712bcff6fb2 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -22,8 +22,10 @@ #define DRV_NAME "cros-ec-typec" -#define DP_PORT_VDO (DP_CONF_SET_PIN_ASSIGN(BIT(DP_PIN_ASSIGN_C) | BIT(DP_PIN_ASSIGN_D)) | \ - DP_CAP_DFP_D | DP_CAP_RECEPTACLE) +#define DP_PORT_VDO (DP_CAP_DFP_D | DP_CAP_RECEPTACLE | \ + DP_CONF_SET_PIN_ASSIGN(BIT(DP_PIN_ASSIGN_C) | \ + BIT(DP_PIN_ASSIGN_D) | \ + BIT(DP_PIN_ASSIGN_E))) static void cros_typec_role_switch_quirk(struct fwnode_handle *fwnode) { @@ -56,8 +58,91 @@ static int cros_typec_enter_usb_mode(struct typec_port *tc_port, enum usb_mode m &req, sizeof(req), NULL, 0); } +static int cros_typec_perform_role_swap(struct typec_port *tc_port, int target_role, u8 swap_type) +{ + struct cros_typec_port *port = typec_get_drvdata(tc_port); + struct cros_typec_data *data = port->typec_data; + struct ec_response_usb_pd_control_v2 resp; + struct ec_params_usb_pd_control req; + int role, ret; + + /* Must be at least v1 to support role swap. */ + if (!data->pd_ctrl_ver) + return -EOPNOTSUPP; + + /* First query the state */ + req.port = port->port_num; + req.role = USB_PD_CTRL_ROLE_NO_CHANGE; + req.mux = USB_PD_CTRL_MUX_NO_CHANGE; + req.swap = USB_PD_CTRL_SWAP_NONE; + + ret = cros_ec_cmd(data->ec, data->pd_ctrl_ver, EC_CMD_USB_PD_CONTROL, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret < 0) + return ret; + + switch (swap_type) { + case USB_PD_CTRL_SWAP_DATA: + role = (resp.role & PD_CTRL_RESP_ROLE_DATA) ? TYPEC_HOST : + TYPEC_DEVICE; + break; + case USB_PD_CTRL_SWAP_POWER: + role = (resp.role & PD_CTRL_RESP_ROLE_POWER) ? TYPEC_SOURCE : + TYPEC_SINK; + break; + default: + dev_warn(data->dev, "Unsupported role swap type %d\n", swap_type); + return -EOPNOTSUPP; + } + + if (role == target_role) + return 0; + + req.swap = swap_type; + ret = cros_ec_cmd(data->ec, data->pd_ctrl_ver, EC_CMD_USB_PD_CONTROL, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret < 0) + return ret; + + switch (swap_type) { + case USB_PD_CTRL_SWAP_DATA: + role = resp.role & PD_CTRL_RESP_ROLE_DATA ? TYPEC_HOST : TYPEC_DEVICE; + if (role != target_role) { + dev_err(data->dev, "Data role swap failed despite EC returning success\n"); + return -EIO; + } + typec_set_data_role(tc_port, target_role); + break; + case USB_PD_CTRL_SWAP_POWER: + role = resp.role & PD_CTRL_RESP_ROLE_POWER ? TYPEC_SOURCE : TYPEC_SINK; + if (role != target_role) { + dev_err(data->dev, "Power role swap failed despite EC returning success\n"); + return -EIO; + } + typec_set_pwr_role(tc_port, target_role); + break; + default: + /* Should never execute */ + break; + } + + return 0; +} + +static int cros_typec_dr_swap(struct typec_port *port, enum typec_data_role role) +{ + return cros_typec_perform_role_swap(port, role, USB_PD_CTRL_SWAP_DATA); +} + +static int cros_typec_pr_swap(struct typec_port *port, enum typec_role role) +{ + return cros_typec_perform_role_swap(port, role, USB_PD_CTRL_SWAP_POWER); +} + static const struct typec_operations cros_typec_usb_mode_ops = { - .enter_usb_mode = cros_typec_enter_usb_mode + .enter_usb_mode = cros_typec_enter_usb_mode, + .dr_set = cros_typec_dr_swap, + .pr_set = cros_typec_pr_swap, }; static int cros_typec_parse_port_props(struct typec_capability *cap, @@ -1269,9 +1354,9 @@ static int cros_typec_probe(struct platform_device *pdev) typec->dev = dev; typec->ec = dev_get_drvdata(pdev->dev.parent); - if (!typec->ec) { - dev_err(dev, "couldn't find parent EC device\n"); - return -ENODEV; + if (!typec->ec || !typec->ec->ec) { + dev_warn(dev, "couldn't find parent EC device\n"); + return -EPROBE_DEFER; } platform_set_drvdata(pdev, typec); diff --git a/drivers/platform/chrome/cros_kbd_led_backlight.c b/drivers/platform/chrome/cros_kbd_led_backlight.c index fc27bd7fc4b9..f4c2282129f5 100644 --- a/drivers/platform/chrome/cros_kbd_led_backlight.c +++ b/drivers/platform/chrome/cros_kbd_led_backlight.c @@ -137,16 +137,12 @@ static int keyboard_led_set_brightness_ec_pwm(struct led_classdev *cdev, enum led_brightness brightness) { - struct { - struct cros_ec_command msg; - struct ec_params_pwm_set_keyboard_backlight params; - } __packed buf; - struct ec_params_pwm_set_keyboard_backlight *params = &buf.params; - struct cros_ec_command *msg = &buf.msg; + DEFINE_RAW_FLEX(struct cros_ec_command, msg, data, + sizeof(struct ec_params_pwm_set_keyboard_backlight)); + struct ec_params_pwm_set_keyboard_backlight *params = + (struct ec_params_pwm_set_keyboard_backlight *)msg->data; struct keyboard_led *keyboard_led = container_of(cdev, struct keyboard_led, cdev); - memset(&buf, 0, sizeof(buf)); - msg->command = EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT; msg->outsize = sizeof(*params); @@ -158,17 +154,13 @@ keyboard_led_set_brightness_ec_pwm(struct led_classdev *cdev, static enum led_brightness keyboard_led_get_brightness_ec_pwm(struct led_classdev *cdev) { - struct { - struct cros_ec_command msg; - struct ec_response_pwm_get_keyboard_backlight resp; - } __packed buf; - struct ec_response_pwm_get_keyboard_backlight *resp = &buf.resp; - struct cros_ec_command *msg = &buf.msg; + DEFINE_RAW_FLEX(struct cros_ec_command, msg, data, + sizeof(struct ec_response_pwm_get_keyboard_backlight)); + struct ec_response_pwm_get_keyboard_backlight *resp = + (struct ec_response_pwm_get_keyboard_backlight *)msg->data; struct keyboard_led *keyboard_led = container_of(cdev, struct keyboard_led, cdev); int ret; - memset(&buf, 0, sizeof(buf)); - msg->command = EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT; msg->insize = sizeof(*resp); |