@@ -37,6 +37,11 @@ static bool userspace_control;
3737 */
3838static bool has_manual_suspend ;
3939
40+ /*
41+ * Lightbar version
42+ */
43+ static int lb_version ;
44+
4045static ssize_t interval_msec_show (struct device * dev ,
4146 struct device_attribute * attr , char * buf )
4247{
@@ -93,18 +98,20 @@ static int lb_throttle(void)
9398
9499static struct cros_ec_command * alloc_lightbar_cmd_msg (struct cros_ec_dev * ec )
95100{
101+ int len = max (ec -> ec_dev -> max_response , ec -> ec_dev -> max_request );
96102 struct cros_ec_command * msg ;
97- int len ;
98-
99- len = max (sizeof (struct ec_params_lightbar ),
100- sizeof (struct ec_response_lightbar ));
101103
102104 msg = kmalloc (sizeof (* msg ) + len , GFP_KERNEL );
103105 if (!msg )
104106 return NULL ;
105107
106108 msg -> version = 0 ;
107109 msg -> command = EC_CMD_LIGHTBAR_CMD + ec -> cmd_offset ;
110+ /*
111+ * Default sizes for regular commands.
112+ * Can be set smaller to optimize transfer,
113+ * larger when sending large light sequences.
114+ */
108115 msg -> outsize = sizeof (struct ec_params_lightbar );
109116 msg -> insize = sizeof (struct ec_response_lightbar );
110117
@@ -471,25 +478,34 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
471478static ssize_t program_store (struct device * dev , struct device_attribute * attr ,
472479 const char * buf , size_t count )
473480{
474- int extra_bytes , max_size , ret ;
481+ size_t extra_bytes , max_size ;
475482 struct ec_params_lightbar * param ;
476483 struct cros_ec_command * msg ;
477484 struct cros_ec_dev * ec = to_cros_ec_dev (dev );
485+ int ret ;
478486
479487 /*
480488 * We might need to reject the program for size reasons. The EC
481489 * enforces a maximum program size, but we also don't want to try
482490 * and send a program that is too big for the protocol. In order
483491 * to ensure the latter, we also need to ensure we have extra bytes
484492 * to represent the rest of the packet.
493+ * With V3, larger program can be sent, limited only by the EC.
494+ * Only the protocol limit the payload size.
485495 */
486- extra_bytes = sizeof (* param ) - sizeof (param -> set_program .data );
487- max_size = min (EC_LB_PROG_LEN , ec -> ec_dev -> max_request - extra_bytes );
488- if (count > max_size ) {
489- dev_err (dev , "Program is %u bytes, too long to send (max: %u)" ,
490- (unsigned int )count , max_size );
491-
492- return - EINVAL ;
496+ if (lb_version < 3 ) {
497+ extra_bytes = sizeof (* param ) - sizeof (param -> set_program .data );
498+ max_size = min (EC_LB_PROG_LEN , ec -> ec_dev -> max_request - extra_bytes );
499+ if (count > max_size ) {
500+ dev_err (dev , "Program is %zu bytes, too long to send (max: %zu)" ,
501+ count , max_size );
502+
503+ return - EINVAL ;
504+ }
505+ } else {
506+ extra_bytes = offsetof(typeof (* param ), set_program_ex ) +
507+ sizeof (param -> set_program_ex );
508+ max_size = ec -> ec_dev -> max_request - extra_bytes ;
493509 }
494510
495511 msg = alloc_lightbar_cmd_msg (ec );
@@ -499,26 +515,44 @@ static ssize_t program_store(struct device *dev, struct device_attribute *attr,
499515 ret = lb_throttle ();
500516 if (ret )
501517 goto exit ;
518+ param = (struct ec_params_lightbar * )msg -> data ;
502519
503- dev_info (dev , "Copying %zu byte program to EC" , count );
520+ if (lb_version < 3 ) {
521+ dev_info (dev , "Copying %zu byte program to EC" , count );
504522
505- param = (struct ec_params_lightbar * )msg -> data ;
506- param -> cmd = LIGHTBAR_CMD_SET_PROGRAM ;
523+ param -> cmd = LIGHTBAR_CMD_SET_PROGRAM ;
507524
508- param -> set_program .size = count ;
509- memcpy (param -> set_program .data , buf , count );
525+ param -> set_program .size = count ;
526+ memcpy (param -> set_program .data , buf , count );
510527
511- /*
512- * We need to set the message size manually or else it will use
513- * EC_LB_PROG_LEN. This might be too long, and the program
514- * is unlikely to use all of the space.
515- */
516- msg -> outsize = count + extra_bytes ;
528+ /*
529+ * We need to set the message size manually or else it will use
530+ * EC_LB_PROG_LEN. This might be too long, and the program
531+ * is unlikely to use all of the space.
532+ */
533+ msg -> outsize = count + extra_bytes ;
517534
518- ret = cros_ec_cmd_xfer_status (ec -> ec_dev , msg );
519- if (ret < 0 )
520- goto exit ;
535+ ret = cros_ec_cmd_xfer_status (ec -> ec_dev , msg );
536+ if (ret < 0 )
537+ goto exit ;
538+ } else {
539+ size_t offset = 0 ;
540+ size_t payload = 0 ;
541+
542+ param -> cmd = LIGHTBAR_CMD_SET_PROGRAM_EX ;
543+ while (offset < count ) {
544+ payload = min (max_size , count - offset );
545+ param -> set_program_ex .offset = offset ;
546+ param -> set_program_ex .size = payload ;
547+ memcpy (param -> set_program_ex .data , & buf [offset ], payload );
548+ msg -> outsize = payload + extra_bytes ;
521549
550+ ret = cros_ec_cmd_xfer_status (ec -> ec_dev , msg );
551+ if (ret < 0 )
552+ goto exit ;
553+ offset += payload ;
554+ }
555+ }
522556 ret = count ;
523557exit :
524558 kfree (msg );
@@ -596,7 +630,7 @@ static int cros_ec_lightbar_probe(struct platform_device *pd)
596630 * Ask then for the lightbar version, if it's 0 then the 'cros_ec'
597631 * doesn't have a lightbar.
598632 */
599- if (!get_lightbar_version (ec_dev , NULL , NULL ))
633+ if (!get_lightbar_version (ec_dev , & lb_version , NULL ))
600634 return - ENODEV ;
601635
602636 /* Take control of the lightbar from the EC. */
0 commit comments