From: Robert Picco There hasn't been any response to your emails by Al other than the redesign suggestion. I have arrived at a solution for HPET driver with miscdevice. The patch is below and removes the HPET definition in include/linux/major.h. Signed-off-by: Andrew Morton --- 25-akpm/drivers/char/hpet.c | 99 +++++++------------------------------ 25-akpm/include/linux/hpet.h | 2 25-akpm/include/linux/major.h | 2 25-akpm/include/linux/miscdevice.h | 1 4 files changed, 24 insertions(+), 80 deletions(-) diff -puN drivers/char/hpet.c~hpet-dont-use-new-major drivers/char/hpet.c --- 25/drivers/char/hpet.c~hpet-dont-use-new-major Wed Jun 9 14:36:45 2004 +++ 25-akpm/drivers/char/hpet.c Wed Jun 9 14:36:45 2004 @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -44,7 +44,6 @@ #define HPET_DRIFT (500) static u32 hpet_ntimer, hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; -static char hpetname[] = "hpet/XX"; /* A lock for concurrent access by app and isr hpet activity. */ static spinlock_t hpet_lock = SPIN_LOCK_UNLOCKED; @@ -63,7 +62,6 @@ struct hpet_dev { unsigned int hd_flags; unsigned int hd_irq; unsigned int hd_hdwirq; - int hd_minor; }; struct hpets { @@ -144,29 +142,25 @@ static irqreturn_t hpet_interrupt(int ir return IRQ_HANDLED; } -static struct hpet_dev *hpet_minor_to_dev(int minor) -{ - struct hpets *hpetp; - int i; - - for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) - for (i = 0; i < hpetp->hp_ntimer; i++) - if (hpetp->hp_dev[i].hd_minor == minor) - return &hpetp->hp_dev[i]; - return 0; -} - static int hpet_open(struct inode *inode, struct file *file) { struct hpet_dev *devp; + struct hpets *hpetp; + int i; - devp = hpet_minor_to_dev(MINOR(inode->i_rdev)); + spin_lock_irq(&hpet_lock); - if (!devp) - return -ENODEV; + for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) + for (i = 0; i < hpetp->hp_ntimer; i++) + if (hpetp->hp_dev[i].hd_flags & HPET_OPEN + || hpetp->hp_dev[i].hd_task) + continue; + else { + devp = &hpetp->hp_dev[i]; + break; + } - spin_lock_irq(&hpet_lock); - if (devp->hd_flags & HPET_OPEN || devp->hd_task) { + if (!devp) { spin_unlock_irq(&hpet_lock); return -EBUSY; } @@ -481,6 +475,8 @@ hpet_ioctl_common(struct hpet_dev *devp, devp->hd_ireqfreq); info.hi_flags = readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; + info.hi_hpet = devp->hd_hpets->hp_which; + info.hi_timer = devp - devp->hd_hpets->hp_dev; if (copy_to_user((void *)arg, &info, sizeof(info))) err = -EFAULT; break; @@ -847,40 +843,6 @@ static unsigned long __init hpet_calibra return (m - start) / i; } -static void __init hpet_init_chrdev(void) -{ - static int once; - - if (!once++ && register_chrdev(HPET_MAJOR, "hpet", &hpet_fops)) - panic("unable to to major %d for hpet device", HPET_MAJOR); - - return; -} - -static void __init hpet_post_platform(void) -{ - struct hpets *hpetp; - u32 i, ntimer; - struct hpet_dev *devp; - - hpet_init_chrdev(); - - for (ntimer = 0, hpetp = hpets; hpetp; hpetp = hpetp->hp_next, ntimer++) - for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; - i++, devp++) { - - if (devp->hd_flags & HPET_OPEN) - continue; - - sprintf(&hpetname[5], "%d", ntimer); - devfs_mk_cdev(MKDEV(HPET_MAJOR, ntimer), - S_IFCHR | S_IRUSR | S_IWUSR, hpetname); - init_waitqueue_head(&devp->hd_waitqueue); - } - - return; -} - int __init hpet_alloc(struct hpet_data *hdp) { u64 cap, mcfg; @@ -948,14 +910,6 @@ int __init hpet_alloc(struct hpet_data * writeq(mcfg, &hpet->hpet_config); } - /* - * Create character devices and init wait queue. - * If this is a platform call, then device initialization - * occurs during startup call to hpet_init. - */ - if (hdp->hd_flags ^ HPET_DATA_PLATFORM) - hpet_init_chrdev(); - for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; i++, hpet_ntimer++, devp++) { unsigned long v; @@ -968,8 +922,6 @@ int __init hpet_alloc(struct hpet_data * devp->hd_hpet = hpet; devp->hd_timer = timer; - devp->hd_minor = hpet_ntimer; - /* * If the timer was reserved by platform code, * then make timer unavailable for opens. @@ -979,12 +931,6 @@ int __init hpet_alloc(struct hpet_data * continue; } - if (hdp->hd_flags & HPET_DATA_PLATFORM) - continue; - - sprintf(&hpetname[5], "%d", hpet_ntimer); - devfs_mk_cdev(MKDEV(HPET_MAJOR, hpet_ntimer), - S_IFCHR | S_IRUSR | S_IWUSR, hpetname); init_waitqueue_head(&devp->hd_waitqueue); } @@ -1075,21 +1021,18 @@ static struct acpi_driver hpet_acpi_driv }, }; +static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops }; + static int __init hpet_init(void) { struct proc_dir_entry *entry; - /* - * If platform dependent code allocated hpet, - * then do the rest of post boot initialization - * of these hpets. - */ - if (hpets) - hpet_post_platform(); - (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) diff -puN include/linux/hpet.h~hpet-dont-use-new-major include/linux/hpet.h --- 25/include/linux/hpet.h~hpet-dont-use-new-major Wed Jun 9 14:36:45 2004 +++ 25-akpm/include/linux/hpet.h Wed Jun 9 14:36:45 2004 @@ -92,6 +92,8 @@ struct hpet { struct hpet_info { unsigned long hi_ireqfreq; /* Hz */ unsigned long hi_flags; /* information */ + unsigned short hi_hpet; + unsigned short hi_timer; }; #define HPET_INFO_PERIODIC 0x0001 /* timer is periodic */ diff -puN include/linux/major.h~hpet-dont-use-new-major include/linux/major.h --- 25/include/linux/major.h~hpet-dont-use-new-major Wed Jun 9 14:36:45 2004 +++ 25-akpm/include/linux/major.h Wed Jun 9 14:36:45 2004 @@ -165,6 +165,4 @@ #define VIOTAPE_MAJOR 230 -#define HPET_MAJOR 229 /* High Precision Event Timer */ - #endif diff -puN include/linux/miscdevice.h~hpet-dont-use-new-major include/linux/miscdevice.h --- 25/include/linux/miscdevice.h~hpet-dont-use-new-major Wed Jun 9 14:36:45 2004 +++ 25-akpm/include/linux/miscdevice.h Wed Jun 9 14:36:45 2004 @@ -33,6 +33,7 @@ #define SGI_STREAMS_KEYBOARD 150 /* drivers/sgi/char/usema.c */ #define SGI_USEMACLONE 151 +#define HPET_MINOR 152 #define TUN_MINOR 200 _