aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
authorDaniel Gl?ckner <dg@emlix.com>2010-08-10 21:02:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-11 11:59:08 -0400
commit5ba1821d1b4a506f8c9be93d962f22b24b6140a5 (patch)
treee083b9e40a9573eb362e3b4c1a91dc0071183a7d /drivers/gpio/gpiolib.c
parent9c4ba9466117b16a2b85034bb87db528aaeb3f07 (diff)
gpiolib: get rid of struct poll_desc and worklet
As sysfs_notify_dirent has been made irq safe, there is no reason to not call it directly from irq. With the work_struct removed, the remaining element in poll_desc is a sysfs_dirent pointer which may not be NULL. We can therefore store it directly in the idr and pass it as context to the irq handler. Most part of the patch deals with renaming defines and variables to reflect their new use without functional change. I also took the opportunity to initialize the idr statically. Signed-off-by: Daniel Gl?ckner <dg@emlix.com> Cc: David Brownell <david-b@pacbell.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r--drivers/gpio/gpiolib.c80
1 files changed, 27 insertions, 53 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 1a8c18cbf201..8a29404985f1 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -57,9 +57,9 @@ struct gpio_desc {
57#define FLAG_TRIG_RISE 6 /* trigger on rising edge */ 57#define FLAG_TRIG_RISE 6 /* trigger on rising edge */
58#define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ 58#define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */
59 59
60#define PDESC_ID_SHIFT 16 /* add new flags before this one */ 60#define ID_SHIFT 16 /* add new flags before this one */
61 61
62#define GPIO_FLAGS_MASK ((1 << PDESC_ID_SHIFT) - 1) 62#define GPIO_FLAGS_MASK ((1 << ID_SHIFT) - 1)
63#define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE)) 63#define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))
64 64
65#ifdef CONFIG_DEBUG_FS 65#ifdef CONFIG_DEBUG_FS
@@ -69,12 +69,7 @@ struct gpio_desc {
69static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; 69static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
70 70
71#ifdef CONFIG_GPIO_SYSFS 71#ifdef CONFIG_GPIO_SYSFS
72struct poll_desc { 72static DEFINE_IDR(dirent_idr);
73 struct work_struct work;
74 struct sysfs_dirent *value_sd;
75};
76
77static struct idr pdesc_idr;
78#endif 73#endif
79 74
80static inline void desc_set_label(struct gpio_desc *d, const char *label) 75static inline void desc_set_label(struct gpio_desc *d, const char *label)
@@ -325,24 +320,16 @@ static const DEVICE_ATTR(value, 0644,
325 320
326static irqreturn_t gpio_sysfs_irq(int irq, void *priv) 321static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
327{ 322{
328 struct work_struct *work = priv; 323 struct sysfs_dirent *value_sd = priv;
329 324
330 schedule_work(work); 325 sysfs_notify_dirent(value_sd);
331 return IRQ_HANDLED; 326 return IRQ_HANDLED;
332} 327}
333 328
334static void gpio_notify_sysfs(struct work_struct *work)
335{
336 struct poll_desc *pdesc;
337
338 pdesc = container_of(work, struct poll_desc, work);
339 sysfs_notify_dirent(pdesc->value_sd);
340}
341
342static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, 329static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
343 unsigned long gpio_flags) 330 unsigned long gpio_flags)
344{ 331{
345 struct poll_desc *pdesc; 332 struct sysfs_dirent *value_sd;
346 unsigned long irq_flags; 333 unsigned long irq_flags;
347 int ret, irq, id; 334 int ret, irq, id;
348 335
@@ -353,18 +340,16 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
353 if (irq < 0) 340 if (irq < 0)
354 return -EIO; 341 return -EIO;
355 342
356 id = desc->flags >> PDESC_ID_SHIFT; 343 id = desc->flags >> ID_SHIFT;
357 pdesc = idr_find(&pdesc_idr, id); 344 value_sd = idr_find(&dirent_idr, id);
358 if (pdesc) { 345 if (value_sd)
359 free_irq(irq, &pdesc->work); 346 free_irq(irq, value_sd);
360 cancel_work_sync(&pdesc->work);
361 }
362 347
363 desc->flags &= ~GPIO_TRIGGER_MASK; 348 desc->flags &= ~GPIO_TRIGGER_MASK;
364 349
365 if (!gpio_flags) { 350 if (!gpio_flags) {
366 ret = 0; 351 ret = 0;
367 goto free_sd; 352 goto free_id;
368 } 353 }
369 354
370 irq_flags = IRQF_SHARED; 355 irq_flags = IRQF_SHARED;
@@ -375,55 +360,46 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
375 irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? 360 irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
376 IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; 361 IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
377 362
378 if (!pdesc) { 363 if (!value_sd) {
379 pdesc = kmalloc(sizeof(*pdesc), GFP_KERNEL); 364 value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value");
380 if (!pdesc) { 365 if (!value_sd) {
381 ret = -ENOMEM; 366 ret = -ENODEV;
382 goto err_out; 367 goto err_out;
383 } 368 }
384 369
385 do { 370 do {
386 ret = -ENOMEM; 371 ret = -ENOMEM;
387 if (idr_pre_get(&pdesc_idr, GFP_KERNEL)) 372 if (idr_pre_get(&dirent_idr, GFP_KERNEL))
388 ret = idr_get_new_above(&pdesc_idr, 373 ret = idr_get_new_above(&dirent_idr, value_sd,
389 pdesc, 1, &id); 374 1, &id);
390 } while (ret == -EAGAIN); 375 } while (ret == -EAGAIN);
391 376
392 if (ret) 377 if (ret)
393 goto free_mem; 378 goto free_sd;
394 379
395 desc->flags &= GPIO_FLAGS_MASK; 380 desc->flags &= GPIO_FLAGS_MASK;
396 desc->flags |= (unsigned long)id << PDESC_ID_SHIFT; 381 desc->flags |= (unsigned long)id << ID_SHIFT;
397 382
398 if (desc->flags >> PDESC_ID_SHIFT != id) { 383 if (desc->flags >> ID_SHIFT != id) {
399 ret = -ERANGE; 384 ret = -ERANGE;
400 goto free_id; 385 goto free_id;
401 } 386 }
402
403 pdesc->value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value");
404 if (!pdesc->value_sd) {
405 ret = -ENODEV;
406 goto free_id;
407 }
408 INIT_WORK(&pdesc->work, gpio_notify_sysfs);
409 } 387 }
410 388
411 ret = request_irq(irq, gpio_sysfs_irq, irq_flags, 389 ret = request_irq(irq, gpio_sysfs_irq, irq_flags,
412 "gpiolib", &pdesc->work); 390 "gpiolib", value_sd);
413 if (ret) 391 if (ret)
414 goto free_sd; 392 goto free_id;
415 393
416 desc->flags |= gpio_flags; 394 desc->flags |= gpio_flags;
417 return 0; 395 return 0;
418 396
419free_sd:
420 if (pdesc)
421 sysfs_put(pdesc->value_sd);
422free_id: 397free_id:
423 idr_remove(&pdesc_idr, id); 398 idr_remove(&dirent_idr, id);
424 desc->flags &= GPIO_FLAGS_MASK; 399 desc->flags &= GPIO_FLAGS_MASK;
425free_mem: 400free_sd:
426 kfree(pdesc); 401 if (value_sd)
402 sysfs_put(value_sd);
427err_out: 403err_out:
428 return ret; 404 return ret;
429} 405}
@@ -994,8 +970,6 @@ static int __init gpiolib_sysfs_init(void)
994 unsigned long flags; 970 unsigned long flags;
995 unsigned gpio; 971 unsigned gpio;
996 972
997 idr_init(&pdesc_idr);
998
999 status = class_register(&gpio_class); 973 status = class_register(&gpio_class);
1000 if (status < 0) 974 if (status < 0)
1001 return status; 975 return status;