aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-07-29 15:47:38 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-31 12:45:41 -0400
commit64a76f667d987a559ad0726b4692c987800b22bc (patch)
tree863fe7378dceb010d84dc723f734192b0c5b0e1f /drivers/char
parent85e9ca333d03fbd56b9e123c8456f0d98e20faad (diff)
hpet: /dev/hpet - fixes and cleanup
Minor /dev/hpet updates and bugfixes: * Remove dead code, mostly remnants of an incomplete/unusable kernel interface ... noted when addressing "sparse" warnings: + hpet_unregister() and a routine it calls + hpet_task and all references, including hpet_task_lock + hpet_data.hd_flags (and HPET_DATA_PLATFORM) * Correct and improve boot message: + displays *counter* (shared between comparators) bit width, not *timer* bit widths (which are often mixed) + relabel "timers" as "comparators"; this is less confusing, they are not independent like normal timers are (sigh) + display MHz not Hz; it's never less than 10 MHz. * Tighten and correct the userspace interface code + don't accidentally program comparators in 64-bit mode using 32-bit values ... always force comparators into 32-bit mode + provide the correct bit definition flagging comparators with periodic capability ... the ABI is unchanged * Update Documentation/hpet.txt + be more correct and current + expand description a bit + don't mention that now-gone kernel interface Plus, add a FIXME comment for something that could cause big trouble on systems with more capable HPETs than at least Intel seems to ship. It seems that few folk use this userspace interface; it's not very usable given the general lack of HPET IRQ routing. I'm told that the only real point of it any more is to mmap for fast timestamps; IMO that's handled better through the gettimeofday() vsyscall. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Acked-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/hpet.c90
1 files changed, 24 insertions, 66 deletions
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index f3981ffe20f0..4bc1da4d4f80 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -53,6 +53,11 @@
53 53
54#define HPET_RANGE_SIZE 1024 /* from HPET spec */ 54#define HPET_RANGE_SIZE 1024 /* from HPET spec */
55 55
56
57/* WARNING -- don't get confused. These macros are never used
58 * to write the (single) counter, and rarely to read it.
59 * They're badly named; to fix, someday.
60 */
56#if BITS_PER_LONG == 64 61#if BITS_PER_LONG == 64
57#define write_counter(V, MC) writeq(V, MC) 62#define write_counter(V, MC) writeq(V, MC)
58#define read_counter(MC) readq(MC) 63#define read_counter(MC) readq(MC)
@@ -77,7 +82,7 @@ static struct clocksource clocksource_hpet = {
77 .rating = 250, 82 .rating = 250,
78 .read = read_hpet, 83 .read = read_hpet,
79 .mask = CLOCKSOURCE_MASK(64), 84 .mask = CLOCKSOURCE_MASK(64),
80 .mult = 0, /*to be caluclated*/ 85 .mult = 0, /* to be calculated */
81 .shift = 10, 86 .shift = 10,
82 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 87 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
83}; 88};
@@ -86,8 +91,6 @@ static struct clocksource *hpet_clocksource;
86 91
87/* A lock for concurrent access by app and isr hpet activity. */ 92/* A lock for concurrent access by app and isr hpet activity. */
88static DEFINE_SPINLOCK(hpet_lock); 93static DEFINE_SPINLOCK(hpet_lock);
89/* A lock for concurrent intermodule access to hpet and isr hpet activity. */
90static DEFINE_SPINLOCK(hpet_task_lock);
91 94
92#define HPET_DEV_NAME (7) 95#define HPET_DEV_NAME (7)
93 96
@@ -99,7 +102,6 @@ struct hpet_dev {
99 unsigned long hd_irqdata; 102 unsigned long hd_irqdata;
100 wait_queue_head_t hd_waitqueue; 103 wait_queue_head_t hd_waitqueue;
101 struct fasync_struct *hd_async_queue; 104 struct fasync_struct *hd_async_queue;
102 struct hpet_task *hd_task;
103 unsigned int hd_flags; 105 unsigned int hd_flags;
104 unsigned int hd_irq; 106 unsigned int hd_irq;
105 unsigned int hd_hdwirq; 107 unsigned int hd_hdwirq;
@@ -173,11 +175,6 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
173 writel(isr, &devp->hd_hpet->hpet_isr); 175 writel(isr, &devp->hd_hpet->hpet_isr);
174 spin_unlock(&hpet_lock); 176 spin_unlock(&hpet_lock);
175 177
176 spin_lock(&hpet_task_lock);
177 if (devp->hd_task)
178 devp->hd_task->ht_func(devp->hd_task->ht_data);
179 spin_unlock(&hpet_task_lock);
180
181 wake_up_interruptible(&devp->hd_waitqueue); 178 wake_up_interruptible(&devp->hd_waitqueue);
182 179
183 kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN); 180 kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN);
@@ -260,8 +257,7 @@ static int hpet_open(struct inode *inode, struct file *file)
260 257
261 for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) 258 for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
262 for (i = 0; i < hpetp->hp_ntimer; i++) 259 for (i = 0; i < hpetp->hp_ntimer; i++)
263 if (hpetp->hp_dev[i].hd_flags & HPET_OPEN 260 if (hpetp->hp_dev[i].hd_flags & HPET_OPEN)
264 || hpetp->hp_dev[i].hd_task)
265 continue; 261 continue;
266 else { 262 else {
267 devp = &hpetp->hp_dev[i]; 263 devp = &hpetp->hp_dev[i];
@@ -504,7 +500,11 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
504 devp->hd_irq = irq; 500 devp->hd_irq = irq;
505 t = devp->hd_ireqfreq; 501 t = devp->hd_ireqfreq;
506 v = readq(&timer->hpet_config); 502 v = readq(&timer->hpet_config);
507 g = v | Tn_INT_ENB_CNF_MASK; 503
504 /* 64-bit comparators are not yet supported through the ioctls,
505 * so force this into 32-bit mode if it supports both modes
506 */
507 g = v | Tn_32MODE_CNF_MASK | Tn_INT_ENB_CNF_MASK;
508 508
509 if (devp->hd_flags & HPET_PERIODIC) { 509 if (devp->hd_flags & HPET_PERIODIC) {
510 write_counter(t, &timer->hpet_compare); 510 write_counter(t, &timer->hpet_compare);
@@ -514,6 +514,12 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
514 v |= Tn_VAL_SET_CNF_MASK; 514 v |= Tn_VAL_SET_CNF_MASK;
515 writeq(v, &timer->hpet_config); 515 writeq(v, &timer->hpet_config);
516 local_irq_save(flags); 516 local_irq_save(flags);
517
518 /* NOTE: what we modify here is a hidden accumulator
519 * register supported by periodic-capable comparators.
520 * We never want to modify the (single) counter; that
521 * would affect all the comparators.
522 */
517 m = read_counter(&hpet->hpet_mc); 523 m = read_counter(&hpet->hpet_mc);
518 write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); 524 write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
519 } else { 525 } else {
@@ -667,57 +673,6 @@ static int hpet_is_known(struct hpet_data *hdp)
667 return 0; 673 return 0;
668} 674}
669 675
670static inline int hpet_tpcheck(struct hpet_task *tp)
671{
672 struct hpet_dev *devp;
673 struct hpets *hpetp;
674
675 devp = tp->ht_opaque;
676
677 if (!devp)
678 return -ENXIO;
679
680 for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
681 if (devp >= hpetp->hp_dev
682 && devp < (hpetp->hp_dev + hpetp->hp_ntimer)
683 && devp->hd_hpet == hpetp->hp_hpet)
684 return 0;
685
686 return -ENXIO;
687}
688
689#if 0
690int hpet_unregister(struct hpet_task *tp)
691{
692 struct hpet_dev *devp;
693 struct hpet_timer __iomem *timer;
694 int err;
695
696 if ((err = hpet_tpcheck(tp)))
697 return err;
698
699 spin_lock_irq(&hpet_task_lock);
700 spin_lock(&hpet_lock);
701
702 devp = tp->ht_opaque;
703 if (devp->hd_task != tp) {
704 spin_unlock(&hpet_lock);
705 spin_unlock_irq(&hpet_task_lock);
706 return -ENXIO;
707 }
708
709 timer = devp->hd_timer;
710 writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK),
711 &timer->hpet_config);
712 devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC);
713 devp->hd_task = NULL;
714 spin_unlock(&hpet_lock);
715 spin_unlock_irq(&hpet_task_lock);
716
717 return 0;
718}
719#endif /* 0 */
720
721static ctl_table hpet_table[] = { 676static ctl_table hpet_table[] = {
722 { 677 {
723 .ctl_name = CTL_UNNUMBERED, 678 .ctl_name = CTL_UNNUMBERED,
@@ -872,9 +827,12 @@ int hpet_alloc(struct hpet_data *hdp)
872 printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); 827 printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
873 printk("\n"); 828 printk("\n");
874 829
875 printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n", 830 printk(KERN_INFO
876 hpetp->hp_which, hpetp->hp_ntimer, 831 "hpet%u: %u comparators, %d-bit %u.%06u MHz counter\n",
877 cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq); 832 hpetp->hp_which, hpetp->hp_ntimer,
833 cap & HPET_COUNTER_SIZE_MASK ? 64 : 32,
834 (unsigned) (hpetp->hp_tick_freq / 1000000),
835 (unsigned) (hpetp->hp_tick_freq % 1000000));
878 836
879 mcfg = readq(&hpet->hpet_config); 837 mcfg = readq(&hpet->hpet_config);
880 if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { 838 if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {