Commit ed51aeb3 authored by Robert Picco's avatar Robert Picco Committed by Linus Torvalds

[PATCH] hpet fixes

I eliminated the request_irq brain damage, chopped off procfs support
(didn't care for it too much in the first place and it was adopted from
rtc.c), made the check for FMODE_WRITE in hpet_open and responded to a few
other suggestions.
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 30c07cae
......@@ -434,6 +434,7 @@ Your cooperation is appreciated.
225 = /dev/pps Pulse Per Second driver
226 = /dev/systrace Systrace device
227 = /dev/mcelog X86_64 Machine Check Exception driver
228 = /dev/hpet HPET driver
240-254 Reserved for local use
255 Reserved for MISC_DYNAMIC_MINOR
......
......@@ -201,7 +201,7 @@ Table 1-3: Kernel info in /proc
devices Available devices (block and character)
dma Used DMS channels
filesystems Supported filesystems
driver Various drivers grouped here, currently rtc (2.4) and hpet (2.6)
driver Various drivers grouped here, currently rtc (2.4)
execdomains Execdomains, related to security (2.4)
fb Frame Buffer devices (2.4)
fs File system parameters, currently nfs/exports (2.4)
......
......@@ -103,7 +103,7 @@ hpet_open_close(int argc, const char **argv)
return;
}
fd = open(argv[0], O_RDWR);
fd = open(argv[0], O_RDONLY);
if (fd < 0)
fprintf(stderr, "hpet_open_close: open failed\n");
else
......@@ -136,7 +136,7 @@ hpet_poll(int argc, const char **argv)
freq = atoi(argv[1]);
iterations = atoi(argv[2]);
fd = open(argv[0], O_RDWR);
fd = open(argv[0], O_RDONLY);
if (fd < 0) {
fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
......@@ -230,7 +230,7 @@ hpet_fasync(int argc, const char **argv)
goto out;
}
fd = open(argv[0], O_RDWR);
fd = open(argv[0], O_RDONLY);
if (fd < 0) {
fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
......
......@@ -155,10 +155,9 @@ int __init hpet_enable(void)
hd.hd_address = hpet_virt_address;
hd.hd_nirqs = ntimer;
hd.hd_flags = HPET_DATA_PLATFORM;
#ifndef CONFIG_HPET_EMULATE_RTC
hd.hd_state = 0x1;
#else
hd.hd_state = 0x3;
HD_STATE(&hd, 0);
#ifdef CONFIG_HPET_EMULATE_RTC
HD_STATE(&hd, 1);
#endif
hd.hd_irq[0] = HPET_LEGACY_8254;
hd.hd_irq[1] = HPET_LEGACY_RTC;
......
......@@ -50,6 +50,8 @@ static spinlock_t hpet_lock = SPIN_LOCK_UNLOCKED;
/* A lock for concurrent intermodule access to hpet and isr hpet activity. */
static spinlock_t hpet_task_lock = SPIN_LOCK_UNLOCKED;
#define HPET_DEV_NAME (7)
struct hpet_dev {
struct hpets *hd_hpets;
struct hpet *hd_hpet;
......@@ -62,6 +64,7 @@ struct hpet_dev {
unsigned int hd_flags;
unsigned int hd_irq;
unsigned int hd_hdwirq;
char hd_name[HPET_DEV_NAME];
};
struct hpets {
......@@ -148,6 +151,9 @@ static int hpet_open(struct inode *inode, struct file *file)
struct hpets *hpetp;
int i;
if (file->f_mode & FMODE_WRITE)
return -EINVAL;
spin_lock_irq(&hpet_lock);
for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
......@@ -190,8 +196,8 @@ hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
add_wait_queue(&devp->hd_waitqueue, &wait);
do {
__set_current_state(TASK_INTERRUPTIBLE);
for ( ; ; ) {
set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irq(&hpet_lock);
data = devp->hd_irqdata;
......@@ -207,16 +213,14 @@ hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
retval = -ERESTARTSYS;
goto out;
}
schedule();
} while (1);
}
retval = put_user(data, (unsigned long __user *)buf);
if (!retval)
retval = sizeof(unsigned long);
out:
current->state = TASK_RUNNING;
out:
__set_current_state(TASK_RUNNING);
remove_wait_queue(&devp->hd_waitqueue, &wait);
return retval;
......@@ -255,9 +259,6 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
return -EINVAL;
if (vma->vm_flags & VM_WRITE)
return -EPERM;
devp = file->private_data;
addr = (unsigned long)devp->hd_hpet;
......@@ -371,12 +372,10 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
irq = devp->hd_hdwirq;
if (irq) {
char name[7];
sprintf(name, "hpet%d", (int)(devp - hpetp->hp_dev));
sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
if (request_irq
(irq, hpet_interrupt, SA_INTERRUPT, name, (void *)devp)) {
(irq, hpet_interrupt, SA_INTERRUPT, devp->hd_name, (void *)devp)) {
printk(KERN_ERR "hpet: IRQ %d is not free\n", irq);
irq = 0;
}
......@@ -731,73 +730,6 @@ static ctl_table dev_root[] = {
static struct ctl_table_header *sysctl_header;
static void *hpet_start(struct seq_file *s, loff_t * pos)
{
struct hpets *hpetp;
loff_t n;
for (n = *pos, hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
if (!n--)
return hpetp;
return 0;
}
static void *hpet_next(struct seq_file *s, void *v, loff_t * pos)
{
struct hpets *hpetp;
hpetp = v;
++*pos;
return hpetp->hp_next;
}
static void hpet_stop(struct seq_file *s, void *v)
{
return;
}
static int hpet_show(struct seq_file *s, void *v)
{
struct hpets *hpetp;
struct hpet *hpet;
u64 cap, vendor, period;
hpetp = v;
hpet = hpetp->hp_hpet;
cap = readq(&hpet->hpet_cap);
period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
HPET_COUNTER_CLK_PERIOD_SHIFT;
vendor = (cap & HPET_VENDOR_ID_MASK) >> HPET_VENDOR_ID_SHIFT;
seq_printf(s,
"HPET%d period = %d 10**-15 vendor = 0x%x number timer = %d\n",
hpetp->hp_which, (u32) period, (u32) vendor,
hpetp->hp_ntimer);
return 0;
}
static struct seq_operations hpet_seq_ops = {
.start = hpet_start,
.next = hpet_next,
.stop = hpet_stop,
.show = hpet_show
};
static int hpet_proc_open(struct inode *inode, struct file *file)
{
return seq_open(file, &hpet_seq_ops);
}
static struct file_operations hpet_proc_fops = {
.open = hpet_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release
};
/*
* Adjustment for when arming the timer with
* initial conditions. That is, main counter
......@@ -1025,19 +957,12 @@ static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops };
static int __init hpet_init(void)
{
struct proc_dir_entry *entry;
(void)acpi_bus_register_driver(&hpet_acpi_driver);
if (hpets) {
if (misc_register(&hpet_misc))
return -ENODEV;
entry = create_proc_entry("driver/hpet", 0, 0);
if (entry)
entry->proc_fops = &hpet_proc_fops;
sysctl_header = register_sysctl_table(dev_root, 0);
#ifdef CONFIG_TIME_INTERPOLATION
......@@ -1062,10 +987,8 @@ static void __exit hpet_exit(void)
{
acpi_bus_unregister_driver(&hpet_acpi_driver);
if (hpets) {
if (hpets)
unregister_sysctl_table(sysctl_header);
remove_proc_entry("driver/hpet", NULL);
}
return;
}
......
......@@ -115,6 +115,8 @@ struct hpet_task {
void *ht_opaque;
};
#define HD_STATE(HD, TIMER) (HD)->hd_state |= (1 << TIMER)
struct hpet_data {
unsigned long hd_address;
unsigned short hd_nirqs;
......
......@@ -33,9 +33,9 @@
#define SGI_STREAMS_KEYBOARD 150
/* drivers/sgi/char/usema.c */
#define SGI_USEMACLONE 151
#define HPET_MINOR 152
#define TUN_MINOR 200
#define HPET_MINOR 228
struct device;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment