leds-pca955x: add proper error handling and fix bogus memory handling

Check the return value of led_classdev_register and unregister all
registered devices, if registering one device fails. Also the dynamic
memory handling is totally bogus. You can't allocate multiple chunks via
kzalloc() and expect them to be in order later. I wonder how this ever
worked.

Signed-off-by: Sven Wegener <sven.wegener@stealer.net>
Acked-by: Nate Case <ncase@xes-inc.com>
Tested-by: Nate Case <ncase@xes-inc.com>
Acked-by: Richard Purdie <rpurdie@rpsys.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Sven Wegener and committed by Linus Torvalds 95bf14bf 07f696c7

+39 -33
+39 -33
drivers/leds/leds-pca955x.c
··· 248 248 const struct i2c_device_id *id) 249 249 { 250 250 struct pca955x_led *pca955x; 251 - int i; 252 - int err = -ENODEV; 253 251 struct pca955x_chipdef *chip; 254 252 struct i2c_adapter *adapter; 255 253 struct led_platform_data *pdata; 254 + int i, err; 256 255 257 256 chip = &pca955x_chipdefs[id->driver_data]; 258 257 adapter = to_i2c_adapter(client->dev.parent); ··· 281 282 } 282 283 } 283 284 284 - for (i = 0; i < chip->bits; i++) { 285 - pca955x = kzalloc(sizeof(struct pca955x_led), GFP_KERNEL); 286 - if (!pca955x) { 287 - err = -ENOMEM; 288 - goto exit; 289 - } 285 + pca955x = kzalloc(sizeof(*pca955x) * chip->bits, GFP_KERNEL); 286 + if (!pca955x) 287 + return -ENOMEM; 290 288 291 - pca955x->chipdef = chip; 292 - pca955x->client = client; 293 - pca955x->led_num = i; 289 + i2c_set_clientdata(client, pca955x); 290 + 291 + for (i = 0; i < chip->bits; i++) { 292 + pca955x[i].chipdef = chip; 293 + pca955x[i].client = client; 294 + pca955x[i].led_num = i; 295 + 294 296 /* Platform data can specify LED names and default triggers */ 295 297 if (pdata) { 296 298 if (pdata->leds[i].name) 297 - snprintf(pca955x->name, 32, "pca955x:%s", 298 - pdata->leds[i].name); 299 + snprintf(pca955x[i].name, 300 + sizeof(pca955x[i].name), "pca955x:%s", 301 + pdata->leds[i].name); 299 302 if (pdata->leds[i].default_trigger) 300 - pca955x->led_cdev.default_trigger = 303 + pca955x[i].led_cdev.default_trigger = 301 304 pdata->leds[i].default_trigger; 302 305 } else { 303 - snprintf(pca955x->name, 32, "pca955x:%d", i); 306 + snprintf(pca955x[i].name, sizeof(pca955x[i].name), 307 + "pca955x:%d", i); 304 308 } 305 - spin_lock_init(&pca955x->lock); 306 309 307 - pca955x->led_cdev.name = pca955x->name; 308 - pca955x->led_cdev.brightness_set = 309 - pca955x_led_set; 310 + spin_lock_init(&pca955x[i].lock); 310 311 311 - /* 312 - * Client data is a pointer to the _first_ pca955x_led 313 - * struct 314 - */ 315 - if (i == 0) 316 - i2c_set_clientdata(client, pca955x); 312 + pca955x[i].led_cdev.name = pca955x[i].name; 313 + pca955x[i].led_cdev.brightness_set = pca955x_led_set; 317 314 318 - INIT_WORK(&(pca955x->work), pca955x_led_work); 315 + INIT_WORK(&pca955x[i].work, pca955x_led_work); 319 316 320 - led_classdev_register(&client->dev, &(pca955x->led_cdev)); 317 + err = led_classdev_register(&client->dev, &pca955x[i].led_cdev); 318 + if (err < 0) 319 + goto exit; 321 320 } 322 321 323 322 /* Turn off LEDs */ ··· 333 336 pca955x_write_psc(client, 1, 0); 334 337 335 338 return 0; 339 + 336 340 exit: 341 + while (i--) { 342 + led_classdev_unregister(&pca955x[i].led_cdev); 343 + cancel_work_sync(&pca955x[i].work); 344 + } 345 + 346 + kfree(pca955x); 347 + i2c_set_clientdata(client, NULL); 348 + 337 349 return err; 338 350 } 339 351 340 352 static int __devexit pca955x_remove(struct i2c_client *client) 341 353 { 342 354 struct pca955x_led *pca955x = i2c_get_clientdata(client); 343 - int leds = pca955x->chipdef->bits; 344 355 int i; 345 356 346 - for (i = 0; i < leds; i++) { 347 - led_classdev_unregister(&(pca955x->led_cdev)); 348 - cancel_work_sync(&(pca955x->work)); 349 - kfree(pca955x); 350 - pca955x = pca955x + 1; 357 + for (i = 0; i < pca955x->chipdef->bits; i++) { 358 + led_classdev_unregister(&pca955x[i].led_cdev); 359 + cancel_work_sync(&pca955x[i].work); 351 360 } 361 + 362 + kfree(pca955x); 363 + i2c_set_clientdata(client, NULL); 352 364 353 365 return 0; 354 366 }