aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/ab8500-debugfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/ab8500-debugfs.c')
-rw-r--r--drivers/mfd/ab8500-debugfs.c77
1 files changed, 53 insertions, 24 deletions
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index 2e40e12fc687..4699fff322a0 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -23,6 +23,10 @@ static u32 debug_address;
23 23
24static int irq_first; 24static int irq_first;
25static int irq_last; 25static int irq_last;
26static u32 irq_count[AB8500_NR_IRQS];
27
28static struct device_attribute *dev_attr[AB8500_NR_IRQS];
29static char *event_name[AB8500_NR_IRQS];
26 30
27/** 31/**
28 * struct ab8500_reg_range 32 * struct ab8500_reg_range
@@ -364,12 +368,15 @@ static irqreturn_t ab8500_debug_handler(int irq, void *data)
364{ 368{
365 char buf[16]; 369 char buf[16];
366 struct kobject *kobj = (struct kobject *)data; 370 struct kobject *kobj = (struct kobject *)data;
371 unsigned int irq_abb = irq - irq_first;
367 372
373 if (irq_abb < AB8500_NR_IRQS)
374 irq_count[irq_abb]++;
368 /* 375 /*
369 * This makes it possible to use poll for events (POLLPRI | POLLERR) 376 * This makes it possible to use poll for events (POLLPRI | POLLERR)
370 * from userspace on sysfs file named irq-<nr> 377 * from userspace on sysfs file named <irq-nr>
371 */ 378 */
372 sprintf(buf, "irq-%d", irq); 379 sprintf(buf, "%d", irq);
373 sysfs_notify(kobj, NULL, buf); 380 sysfs_notify(kobj, NULL, buf);
374 381
375 return IRQ_HANDLED; 382 return IRQ_HANDLED;
@@ -555,19 +562,26 @@ static int ab8500_subscribe_unsubscribe_open(struct inode *inode,
555} 562}
556 563
557/* 564/*
558 * This function is used for all interrupts and will always print 565 * Userspace should use poll() on this file. When an event occur
559 * the same string. It is however this file sysfs_notify called on.
560 * Userspace should read this file and then poll. When an event occur
561 * the blocking poll will be released. 566 * the blocking poll will be released.
562 */ 567 */
563static ssize_t show_irq(struct device *dev, 568static ssize_t show_irq(struct device *dev,
564 struct device_attribute *attr, char *buf) 569 struct device_attribute *attr, char *buf)
565{ 570{
566 return sprintf(buf, "irq\n"); 571 unsigned long name;
567} 572 unsigned int irq_index;
573 int err;
568 574
569static struct device_attribute *dev_attr[AB8500_NR_IRQS]; 575 err = strict_strtoul(attr->attr.name, 0, &name);
570static char *event_name[AB8500_NR_IRQS]; 576 if (err)
577 return err;
578
579 irq_index = name - irq_first;
580 if (irq_index >= AB8500_NR_IRQS)
581 return -EINVAL;
582 else
583 return sprintf(buf, "%u\n", irq_count[irq_index]);
584}
571 585
572static ssize_t ab8500_subscribe_write(struct file *file, 586static ssize_t ab8500_subscribe_write(struct file *file,
573 const char __user *user_buf, 587 const char __user *user_buf,
@@ -578,6 +592,7 @@ static ssize_t ab8500_subscribe_write(struct file *file,
578 int buf_size; 592 int buf_size;
579 unsigned long user_val; 593 unsigned long user_val;
580 int err; 594 int err;
595 unsigned int irq_index;
581 596
582 /* Get userspace string and assure termination */ 597 /* Get userspace string and assure termination */
583 buf_size = min(count, (sizeof(buf)-1)); 598 buf_size = min(count, (sizeof(buf)-1));
@@ -597,19 +612,23 @@ static ssize_t ab8500_subscribe_write(struct file *file,
597 return -EINVAL; 612 return -EINVAL;
598 } 613 }
599 614
615 irq_index = user_val - irq_first;
616 if (irq_index >= AB8500_NR_IRQS)
617 return -EINVAL;
618
600 /* 619 /*
601 * This will create a sysfs file named irq-<nr> which userspace can 620 * This will create a sysfs file named <irq-nr> which userspace can
602 * use to select or poll and get the AB8500 events 621 * use to select or poll and get the AB8500 events
603 */ 622 */
604 dev_attr[user_val] = kmalloc(sizeof(struct device_attribute), 623 dev_attr[irq_index] = kmalloc(sizeof(struct device_attribute),
605 GFP_KERNEL); 624 GFP_KERNEL);
606 event_name[user_val] = kmalloc(buf_size, GFP_KERNEL); 625 event_name[irq_index] = kmalloc(buf_size, GFP_KERNEL);
607 sprintf(event_name[user_val], "irq-%lu", user_val); 626 sprintf(event_name[irq_index], "%lu", user_val);
608 dev_attr[user_val]->show = show_irq; 627 dev_attr[irq_index]->show = show_irq;
609 dev_attr[user_val]->store = NULL; 628 dev_attr[irq_index]->store = NULL;
610 dev_attr[user_val]->attr.name = event_name[user_val]; 629 dev_attr[irq_index]->attr.name = event_name[irq_index];
611 dev_attr[user_val]->attr.mode = S_IRUGO; 630 dev_attr[irq_index]->attr.mode = S_IRUGO;
612 err = sysfs_create_file(&dev->kobj, &dev_attr[user_val]->attr); 631 err = sysfs_create_file(&dev->kobj, &dev_attr[irq_index]->attr);
613 if (err < 0) { 632 if (err < 0) {
614 printk(KERN_ERR "sysfs_create_file failed %d\n", err); 633 printk(KERN_ERR "sysfs_create_file failed %d\n", err);
615 return err; 634 return err;
@@ -621,6 +640,7 @@ static ssize_t ab8500_subscribe_write(struct file *file,
621 if (err < 0) { 640 if (err < 0) {
622 printk(KERN_ERR "request_threaded_irq failed %d, %lu\n", 641 printk(KERN_ERR "request_threaded_irq failed %d, %lu\n",
623 err, user_val); 642 err, user_val);
643 sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
624 return err; 644 return err;
625 } 645 }
626 646
@@ -636,6 +656,7 @@ static ssize_t ab8500_unsubscribe_write(struct file *file,
636 int buf_size; 656 int buf_size;
637 unsigned long user_val; 657 unsigned long user_val;
638 int err; 658 int err;
659 unsigned int irq_index;
639 660
640 /* Get userspace string and assure termination */ 661 /* Get userspace string and assure termination */
641 buf_size = min(count, (sizeof(buf)-1)); 662 buf_size = min(count, (sizeof(buf)-1));
@@ -655,12 +676,20 @@ static ssize_t ab8500_unsubscribe_write(struct file *file,
655 return -EINVAL; 676 return -EINVAL;
656 } 677 }
657 678
658 free_irq(user_val, &dev->kobj); 679 irq_index = user_val - irq_first;
659 kfree(event_name[user_val]); 680 if (irq_index >= AB8500_NR_IRQS)
660 kfree(dev_attr[user_val]); 681 return -EINVAL;
682
683 /* Set irq count to 0 when unsubscribe */
684 irq_count[irq_index] = 0;
685
686 if (dev_attr[irq_index])
687 sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
661 688
662 if (dev_attr[user_val]) 689
663 sysfs_remove_file(&dev->kobj, &dev_attr[user_val]->attr); 690 free_irq(user_val, &dev->kobj);
691 kfree(event_name[irq_index]);
692 kfree(dev_attr[irq_index]);
664 693
665 return buf_size; 694 return buf_size;
666} 695}