* published by the Free Software Foundation.
*/
-#include <linux/config.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/poll.h>
+#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/sysctl.h>
}
#endif
-static irqreturn_t hpet_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t hpet_interrupt(int irq, void *data)
{
struct hpet_dev *devp;
unsigned long isr;
if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot)) {
- printk(KERN_ERR "remap_pfn_range failed in hpet.c\n");
+ printk(KERN_ERR "%s: io_remap_pfn_range failed\n",
+ __FUNCTION__);
return -EAGAIN;
}
sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
irq_flags = devp->hd_flags & HPET_SHARED_IRQ
- ? SA_SHIRQ : SA_INTERRUPT;
+ ? IRQF_SHARED : IRQF_DISABLED;
if (request_irq(irq, hpet_interrupt, irq_flags,
devp->hd_name, (void *)devp)) {
printk(KERN_ERR "hpet: IRQ %d is not free\n", irq);
return err;
}
-static struct file_operations hpet_fops = {
+static const struct file_operations hpet_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = hpet_read,
.mmap = hpet_mmap,
};
+static int hpet_is_known(struct hpet_data *hdp)
+{
+ struct hpets *hpetp;
+
+ for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
+ if (hpetp->hp_hpet_phys == hdp->hd_phys_address)
+ return 1;
+
+ return 0;
+}
+
EXPORT_SYMBOL(hpet_alloc);
EXPORT_SYMBOL(hpet_register);
EXPORT_SYMBOL(hpet_unregister);
static ctl_table hpet_table[] = {
{
- .ctl_name = 1,
+ .ctl_name = CTL_UNNUMBERED,
.procname = "max-user-freq",
.data = &hpet_max_freq,
.maxlen = sizeof(int),
static ctl_table hpet_root[] = {
{
- .ctl_name = 1,
+ .ctl_name = CTL_UNNUMBERED,
.procname = "hpet",
.maxlen = 0,
.mode = 0555,
#ifdef CONFIG_TIME_INTERPOLATION
struct time_interpolator *ti;
- ti = kmalloc(sizeof(*ti), GFP_KERNEL);
+ ti = kzalloc(sizeof(*ti), GFP_KERNEL);
if (!ti)
return;
- memset(ti, 0, sizeof(*ti));
ti->source = TIME_SOURCE_MMIO64;
ti->shift = 10;
ti->addr = &hpetp->hp_hpet->hpet_mc;
struct hpets *hpetp;
size_t siz;
struct hpet __iomem *hpet;
- static struct hpets *last = (struct hpets *)0;
+ static struct hpets *last = NULL;
unsigned long period;
unsigned long long temp;
/*
* hpet_alloc can be called by platform dependent code.
- * if platform dependent code has allocated the hpet
- * ACPI also reports hpet, then we catch it here.
+ * If platform dependent code has allocated the hpet that
+ * ACPI has also reported, then we catch it here.
*/
- for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
- if (hpetp->hp_hpet == hdp->hd_address)
- return 0;
+ if (hpet_is_known(hdp)) {
+ printk(KERN_DEBUG "%s: duplicate HPET ignored\n",
+ __FUNCTION__);
+ return 0;
+ }
siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) *
sizeof(struct hpet_dev));
- hpetp = kmalloc(siz, GFP_KERNEL);
+ hpetp = kzalloc(siz, GFP_KERNEL);
if (!hpetp)
return -ENOMEM;
- memset(hpetp, 0, siz);
-
hpetp->hp_which = hpet_nhpet++;
hpetp->hp_hpet = hdp->hd_address;
hpetp->hp_hpet_phys = hdp->hd_phys_address;
struct hpet_data *hdp;
acpi_status status;
struct acpi_resource_address64 addr;
- struct hpets *hpetp;
hdp = data;
status = acpi_resource_to_address64(res, &addr);
if (ACPI_SUCCESS(status)) {
- unsigned long size;
-
- size = addr.max_address_range - addr.min_address_range + 1;
- hdp->hd_phys_address = addr.min_address_range;
- hdp->hd_address = ioremap(addr.min_address_range, size);
-
- for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
- if (hpetp->hp_hpet == hdp->hd_address)
- return -EBUSY;
- } else if (res->id == ACPI_RSTYPE_FIXED_MEM32) {
- struct acpi_resource_fixed_mem32 *fixmem32;
+ hdp->hd_phys_address = addr.minimum;
+ hdp->hd_address = ioremap(addr.minimum, addr.address_length);
+
+ if (hpet_is_known(hdp)) {
+ printk(KERN_DEBUG "%s: 0x%lx is busy\n",
+ __FUNCTION__, hdp->hd_phys_address);
+ iounmap(hdp->hd_address);
+ return -EBUSY;
+ }
+ } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
+ struct acpi_resource_fixed_memory32 *fixmem32;
fixmem32 = &res->data.fixed_memory32;
if (!fixmem32)
return -EINVAL;
- hdp->hd_phys_address = fixmem32->range_base_address;
- hdp->hd_address = ioremap(fixmem32->range_base_address,
+ hdp->hd_phys_address = fixmem32->address;
+ hdp->hd_address = ioremap(fixmem32->address,
HPET_RANGE_SIZE);
- for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
- if (hpetp->hp_hpet == hdp->hd_address) {
- return -EBUSY;
- }
- } else if (res->id == ACPI_RSTYPE_EXT_IRQ) {
- struct acpi_resource_ext_irq *irqp;
- int i;
+ if (hpet_is_known(hdp)) {
+ printk(KERN_DEBUG "%s: 0x%lx is busy\n",
+ __FUNCTION__, hdp->hd_phys_address);
+ iounmap(hdp->hd_address);
+ return -EBUSY;
+ }
+ } else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
+ struct acpi_resource_extended_irq *irqp;
+ int i, irq;
irqp = &res->data.extended_irq;
- if (irqp->number_of_interrupts > 0) {
- hdp->hd_nirqs = irqp->number_of_interrupts;
-
- for (i = 0; i < hdp->hd_nirqs; i++) {
- int rc =
- acpi_register_gsi(irqp->interrupts[i],
- irqp->edge_level,
- irqp->active_high_low);
- if (rc < 0)
- return AE_ERROR;
- hdp->hd_irq[i] = rc;
- }
+ for (i = 0; i < irqp->interrupt_count; i++) {
+ irq = acpi_register_gsi(irqp->interrupts[i],
+ irqp->triggering, irqp->polarity);
+ if (irq < 0)
+ return AE_ERROR;
+
+ hdp->hd_irq[hdp->hd_nirqs] = irq;
+ hdp->hd_nirqs++;
}
}
if (result < 0)
return -ENODEV;
- sysctl_header = register_sysctl_table(dev_root, 0);
+ sysctl_header = register_sysctl_table(dev_root);
result = acpi_bus_register_driver(&hpet_acpi_driver);
if (result < 0) {