leds: blinkm: Don't init a workqueue per brightness_set call
Subsystems (2)
PATCH 1/1 leds: blinkm: Don't init a workqueue per brightness_set call
Calling INIT_WORK in blinkm_led_common_set() means we init a workqueue every time when brightness_set callback is called.
Move INIT_WORK to blinkm_probe() so we only need to init the workqueue once.
So we only need to init a workqueue per blinkm led rather than init a workqueue per brightness_set call.
---
This patch is v2 of "[PATCH RFT] leds: blinkm: Avoid calling INIT_WORK in blinkm_led_common_set()" I think the new subject line is better for the reason I sent the patch.
v2:
Now we have a workqueue per blinkm led.
I think the code can be simpler and has better readability if we embeded struct work_struct in struct blinkm_led.
Note I don't have this hardware, so I added Request-For-Test (RFT) in the subject line. Axel
drivers/leds/leds-blinkm.c | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-)
drivers/leds/leds-blinkm.c +7 -23
@@ -37,19 +37,15 @@ static int blinkm_transfer_hw(struct i2c_client *client, int cmd);static int blinkm_test_run (struct i2c_client *client);struct blinkm_led { +struct work_struct work;struct i2c_client *i2c_client;struct led_classdev led_cdev;int id;atomic_t active; }; -struct blinkm_work { -struct blinkm_led *blinkm_led; -struct work_struct work; -}; -#define cdev_to_blmled (c) container_of(c, struct blinkm_led, led_cdev) -#define work_to_blmwork (c) container_of(c, struct blinkm_work, work) +#define work_to_blmled (c) container_of(c, struct blinkm_led, work)struct blinkm_data {struct i2c_client *i2c_client;
@@ -446,12 +442,9 @@ static int blinkm_transfer_hw(struct i2c_client *client, int cmd)static void led_work (struct work_struct *work) {int ret; -struct blinkm_led *led; -struct blinkm_data *data ; -struct blinkm_work *blm_work =work_to_blmwork (work); +struct blinkm_led *led =work_to_blmled (work); +struct blinkm_data *data =i2c_get_clientdata (led->i2c_client); - led = blm_work->blinkm_led; - data =i2c_get_clientdata (led->i2c_client); ret =blinkm_transfer_hw (led->i2c_client,BLM_GO_RGB );atomic_dec (&led->active); dev_dbg(&led->i2c_client->dev,
@@ -459,7 +452,6 @@ static void led_work(struct work_struct *work)" next_blue = %d, active = %d\n" , data->next_red, data->next_green, data->next_blue, atomic_read(&led->active)); -kfree (blm_work); } static int blinkm_led_common_set(struct led_classdev *led_cdev,
@@ -468,7 +460,6 @@ static int blinkm_led_common_set(struct led_classdev *led_cdev,/* led_brightness is 0, 127 or 255 - we just use it here as-is */ struct blinkm_led *led =cdev_to_blmled (led_cdev);struct blinkm_data *data =i2c_get_clientdata (led->i2c_client); -struct blinkm_work *bl_work;switch (color) {case RED :
@@ -510,10 +501,6 @@ static int blinkm_led_common_set(struct led_classdev *led_cdev,return -EINVAL ; } - bl_work =kzalloc (sizeof (*bl_work),GFP_ATOMIC ); -if (!bl_work) -return -ENOMEM ; -atomic_inc (&led->active);dev_dbg (&led->i2c_client->dev, "#TO_SCHED# next_red = %d, next_green = %d,"
@@ -521,11 +508,8 @@ static int blinkm_led_common_set(struct led_classdev *led_cdev, data->next_red, data->next_green, data->next_blue, atomic_read(&led->active)); -/* a fresh work _item_ for each change */ - bl_work->blinkm_led = led; -INIT_WORK (&bl_work->work, led_work);/* queue work in own queue for easy sync on exit*/ -schedule_work (&bl_work->work); +schedule_work (&led->work);return 0 ; }
@@ -667,6 +651,7 @@ static int __devinit blinkm_probe(struct i2c_client *client, }for (i =0 ; i <3 ; i++) { +INIT_WORK (&data->blinkm_leds[i].work, led_work);/* RED = 0, GREEN = 1, BLUE = 2 */ led[i] = &data->blinkm_leds[i]; led[i]->i2c_client = client;
@@ -746,8 +731,7 @@ exit: static int __devexit blinkm_remove(struct i2c_client *client) {struct blinkm_data *data =i2c_get_clientdata (client); -int ret =0 ; -int i; +int i, ret;/* make sure no workqueue entries are pending */ for (i =0 ; i <3 ; i++) {
Signature · 1 line
1.7.9.5
A message that is not in the archive (sent off-list or not yet received): CAFRkauDWf8y24DgoS1wE2ZvG4QtP6sYKbMatHmKjNvR_aFWtuA@mail.gmail.com
Quoted 22 lines · Axel Lin
2012/10/29 Axel Lin <[email protected]>
Quoted 10 lines
Calling
INIT_WORKinblinkm_led_common_set()means we init a workqueue every time
whenbrightness_setcallback is called.
MoveINIT_WORKtoblinkm_probe()so we only need to init the workqueue once.So we only need to init a workqueue per blinkm led rather than init a workqueue
perbrightness_setcall.Ah. the commit log and subject line is wrong.
We are using the global workqueue.
What the patch does is to avoid init work rather than workqueue perbrightness_setcall.
We just need to callINIT_WORKonce for the first time that structure is set up.
Quoted 4 lines
There should be no functional change with this patch.
Regards,
Axel
Right, I think I did same review when this driver posted on the list firstly. Probably it is a hardware issue. So let Jan-Simon give us some updates.
If the hardware requires this specific handling, I suggest we add some comments or documents to clarify that.
Thanks,
-Bryan