From 377692412f4e352c7c8457a05f8795a3f017cf61 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Fri, 30 Aug 2002 01:56:22 -0700 Subject: ACPI trivial cleanups (Kochi Takayoshi) --- include/linux/acpi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 9c619036dfb6..1bdcda4d36c8 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -354,11 +354,11 @@ void acpi_numa_arch_fixup(void); extern int acpi_mp_config; -#else /*!CONFIG_ACPI_BOOT*/ +#else #define acpi_mp_config 0 -#endif /*CONFIG_ACPI_BOOT*/ +#endif #ifdef CONFIG_ACPI_PCI -- cgit v1.2.3 From d9a2636316ef9695df0e7089b4f79f7a2661477c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 9 Sep 2002 00:34:37 -0700 Subject: PCI: hotplug core cleanup to get pci hotplug working again - removed pci_announce_device_to_drivers() prototype as the function is long gone - always call /sbin/hotplug when pci devices are added to the system if so configured (this includes during the system bring up.) --- drivers/pci/Makefile | 4 +--- drivers/pci/hotplug.c | 22 ++++++++++++++-------- drivers/pci/probe.c | 6 +++--- drivers/pci/proc.c | 9 +++++++++ include/linux/pci.h | 1 - 5 files changed, 27 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 579edc49e82a..14b5dcb183bf 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -6,10 +6,8 @@ export-objs := access.o hotplug.o pci-driver.o pci.o pool.o \ probe.o proc.o search.o compat.o obj-y += access.o probe.o pci.o pool.o quirks.o \ - compat.o names.o pci-driver.o search.o + compat.o names.o pci-driver.o search.o hotplug.o obj-$(CONFIG_PM) += power.o -obj-$(CONFIG_HOTPLUG) += hotplug.o - obj-$(CONFIG_PROC_FS) += proc.o ifndef CONFIG_SPARC64 diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c index 63dc49410dbc..c493d2f0216f 100644 --- a/drivers/pci/hotplug.c +++ b/drivers/pci/hotplug.c @@ -7,8 +7,8 @@ #define TRUE (!FALSE) #endif -static void -run_sbin_hotplug(struct pci_dev *pdev, int insert) +#ifdef CONFIG_HOTPLUG +static void run_sbin_hotplug(struct pci_dev *pdev, int insert) { int i; char *argv[3], *envp[8]; @@ -45,13 +45,18 @@ run_sbin_hotplug(struct pci_dev *pdev, int insert) call_usermodehelper (argv [0], argv, envp); } +#else +static void run_sbin_hotplug(struct pci_dev *pdev, int insert) { } +#endif /** - * pci_insert_device - insert a hotplug device + * pci_insert_device - insert a pci device * @dev: the device to insert * @bus: where to insert it * - * Add a new device to the device lists and notify userspace (/sbin/hotplug). + * Link the device to both the global PCI device chain and the + * per-bus list of devices, add the /proc entry, and notify + * userspace (/sbin/hotplug). */ void pci_insert_device(struct pci_dev *dev, struct pci_bus *bus) @@ -78,11 +83,11 @@ pci_free_resources(struct pci_dev *dev) } /** - * pci_remove_device - remove a hotplug device + * pci_remove_device - remove a pci device * @dev: the device to remove * - * Delete the device structure from the device lists and - * notify userspace (/sbin/hotplug). + * Delete the device structure from the device lists, + * remove the /proc entry, and notify userspace (/sbin/hotplug). */ void pci_remove_device(struct pci_dev *dev) @@ -94,10 +99,11 @@ pci_remove_device(struct pci_dev *dev) #ifdef CONFIG_PROC_FS pci_proc_detach_device(dev); #endif - /* notify userspace of hotplug device removal */ run_sbin_hotplug(dev, FALSE); } +#ifdef CONFIG_HOTPLUG EXPORT_SYMBOL(pci_insert_device); EXPORT_SYMBOL(pci_remove_device); +#endif diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6460e5f08eda..ffc65af0c438 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -479,10 +479,10 @@ struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp) /* * Link the device to both the global PCI device chain and - * the per-bus list of devices. + * the per-bus list of devices and call /sbin/hotplug if we + * should. */ - list_add_tail(&dev->global_list, &pci_devices); - list_add_tail(&dev->bus_list, &bus->devices); + pci_insert_device (dev, bus); /* Fix up broken headers */ pci_fixup_device(PCI_FIXUP_HEADER, dev); diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 67c7e1feb732..582fac9f16f7 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -18,6 +18,8 @@ #define PCI_CFG_SPACE_SIZE 256 +static int proc_initialized; /* = 0 */ + static loff_t proc_bus_pci_lseek(struct file *file, loff_t off, int whence) { @@ -410,6 +412,9 @@ int pci_proc_attach_device(struct pci_dev *dev) struct proc_dir_entry *de, *e; char name[16]; + if (!proc_initialized) + return -EACCES; + if (!(de = bus->procdir)) { sprintf(name, "%02x", bus->number); de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir); @@ -446,6 +451,9 @@ int pci_proc_attach_bus(struct pci_bus* bus) { struct proc_dir_entry *de = bus->procdir; + if (!proc_initialized) + return -EACCES; + if (!de) { char name[16]; sprintf(name, "%02x", bus->number); @@ -595,6 +603,7 @@ static int __init pci_proc_init(void) entry = create_proc_entry("devices", 0, proc_bus_pci_dir); if (entry) entry->proc_fops = &proc_bus_pci_dev_operations; + proc_initialized = 1; pci_for_each_dev(dev) { pci_proc_attach_device(dev); } diff --git a/include/linux/pci.h b/include/linux/pci.h index b82ec8e41174..79d909a8643a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -634,7 +634,6 @@ void pci_insert_device(struct pci_dev *, struct pci_bus *); void pci_remove_device(struct pci_dev *); struct pci_driver *pci_dev_driver(const struct pci_dev *); const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev); -void pci_announce_device_to_drivers(struct pci_dev *); unsigned int pci_do_scan_bus(struct pci_bus *bus); struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr); -- cgit v1.2.3 From 3843e047e902b4727a7d1f59c766da3f3b2989f0 Mon Sep 17 00:00:00 2001 From: Rolf Fokkens Date: Mon, 9 Sep 2002 03:26:06 -0700 Subject: [PATCH] USER_HZ & NTP problems I've been playing with different HZ values in the 2.4 kernel for a while now, and apparantly Linus also has decided to introduce a USER_HZ constant (I used CLOCKS_PER_SEC) while raising the HZ value on x86 to 1000. On x86 timekeeping has shown to be relative fragile when raising HZ (OK, I tried HZ=2048 which is quite high) because of the way the interrupt timer is configured to fire HZ times each second. This is done by configuring a divisor in the timer chip (LATCH) which divides a certain clock (1193180) and makes the chip fire interrupts at the resulting frequency. Now comes the catch: NTP requires a clock accuracy of 500 ppm. For some HZ values the clock is not accurate enough to meet this requirement, hence NTP won't work well. An example HZ value is 1020 which exceeds the 500 ppm requirement. In this case the best approximation is 1019.8 Hz. the xtime.tv_usec value is raised with a value of 980 each tick which means that after one second the tv_usec value has increased with 999404 (should be 1000000) which is an accuracy of 596 ppm. Some more examples: HZ Accuracy (ppm) ---- -------------- 100 17 1000 151 1024 632 2000 687 2008 343 2011 18 2048 1249 What I've been doing is replace tv_usec by tv_nsec, meaning xtime is now a timespec instead of a timeval. This allows the accuracy to be improved by a factor of 1000 for any (well ... any?) HZ value. Of course all kinds of calculations had te be improved as well. The ACTHZ constantant is introduced to approximate the actual HZ value, it's used to do some approximations of other related values. --- arch/i386/kernel/time.c | 13 +++++++------ fs/udf/udfdecl.h | 2 +- include/linux/time.h | 2 +- include/linux/timex.h | 25 ++++++++++++++++++++++++- kernel/time.c | 16 ++++++---------- kernel/timer.c | 26 ++++++++++++++------------ 6 files changed, 53 insertions(+), 31 deletions(-) (limited to 'include/linux') diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index a32314075d1d..ae3e803a5368 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -115,7 +115,7 @@ static inline unsigned long do_fast_gettimeoffset(void) return delay_at_last_interrupt + edx; } -#define TICK_SIZE tick +#define TICK_SIZE (tick_nsec / 1000) spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED; EXPORT_SYMBOL(i8253_lock); @@ -280,7 +280,7 @@ void do_gettimeofday(struct timeval *tv) usec += lost * (1000000 / HZ); } sec = xtime.tv_sec; - usec += xtime.tv_usec; + usec += (xtime.tv_nsec / 1000); read_unlock_irqrestore(&xtime_lock, flags); while (usec >= 1000000) { @@ -309,7 +309,8 @@ void do_settimeofday(struct timeval *tv) tv->tv_sec--; } - xtime = *tv; + xtime.tv_sec = tv->tv_sec; + xtime.tv_nsec = (tv->tv_usec * 1000); time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; @@ -437,8 +438,8 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg */ if ((time_status & STA_UNSYNC) == 0 && xtime.tv_sec > last_rtc_update + 660 && - xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 && - xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) { + (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && + (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { if (set_rtc_mmss(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else @@ -655,7 +656,7 @@ void __init time_init(void) extern int x86_udelay_tsc; xtime.tv_sec = get_cmos_time(); - xtime.tv_usec = 0; + xtime.tv_nsec = 0; /* * If we have APM enabled or the CPU clock speed is variable diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 4ee650d38e7c..c23edd0315b8 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -32,7 +32,7 @@ #define UDF_NAME_LEN 255 #define UDF_PATH_LEN 1023 -#define CURRENT_UTIME (xtime.tv_usec) +#define CURRENT_UTIME (xtime.tv_nsec / 1000) #define udf_file_entry_alloc_offset(inode)\ ((UDF_I_EXTENDED_FE(inode) ?\ diff --git a/include/linux/time.h b/include/linux/time.h index d9f9c6a340d8..088c52d09449 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -113,7 +113,7 @@ mktime (unsigned int year, unsigned int mon, )*60 + sec; /* finally seconds */ } -extern struct timeval xtime; +extern struct timespec xtime; #define CURRENT_TIME (xtime.tv_sec) diff --git a/include/linux/timex.h b/include/linux/timex.h index b82cbdc776f7..5b2b0ac18ae7 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -155,6 +155,28 @@ /* LATCH is used in the interval timer and ftape setup. */ #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ +/* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can + * improve accuracy by shifting LSH bits, hence calculating: + * (NOM << LSH) / DEN + * This however means trouble for large NOM, because (NOM << LSH) may no + * longer fit in 32 bits. The following way of calculating this gives us + * some slack, under the following onditions: + * - (NOM / DEN) fits in (32 - LSH) bits. + * - (NOM % DEN) fits in (32 - LSH) bits. + */ +#define SH_DIV(NOM,DEN,LSH) ( ((NOM / DEN) << LSH) \ + + (((NOM % DEN) << LSH) + DEN / 2) / DEN) + +/* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ +#define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) + +/* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ +#define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) + +/* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ and */ +/* a value TUSEC for TICK_USEC (can be set bij adjtimex) */ +#define TICK_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8)) + /* * syscall interface - used (mainly by NTP daemon) * to discipline kernel clock oscillator @@ -251,7 +273,8 @@ struct timex { * Note: maximum error = NTP synch distance = dispersion + delay / 2; * estimated error = NTP dispersion. */ -extern long tick; /* timer interrupt period */ +extern unsigned long tick_usec; /* USER_HZ period (usec) */ +extern unsigned long tick_nsec; /* ACTHZ period (nsec) */ extern int tickadj; /* amount of adjustment per tick */ /* diff --git a/kernel/time.c b/kernel/time.c index edb7eb7b8b73..716e0bbe071a 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -82,7 +82,7 @@ asmlinkage long sys_stime(int * tptr) return -EFAULT; write_lock_irq(&xtime_lock); xtime.tv_sec = value; - xtime.tv_usec = 0; + xtime.tv_nsec = 0; last_time_offset = 0; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; @@ -231,7 +231,8 @@ int do_adjtimex(struct timex *txc) /* if the quartz is off by more than 10% something is VERY wrong ! */ if (txc->modes & ADJ_TICK) - if (txc->tick < 900000/HZ || txc->tick > 1100000/HZ) + if (txc->tick < 900000/USER_HZ || + txc->tick > 1100000/USER_HZ) return -EINVAL; write_lock_irq(&xtime_lock); @@ -344,13 +345,8 @@ int do_adjtimex(struct timex *txc) } /* STA_PLL || STA_PPSTIME */ } /* txc->modes & ADJ_OFFSET */ if (txc->modes & ADJ_TICK) { - /* if the quartz is off by more than 10% something is - VERY wrong ! */ - if (txc->tick < 900000/HZ || txc->tick > 1100000/HZ) { - result = -EINVAL; - goto leave; - } - tick = txc->tick; + tick_usec = txc->tick; + tick_nsec = TICK_NSEC(tick_usec); } } /* txc->modes */ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0 @@ -380,7 +376,7 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0 txc->constant = time_constant; txc->precision = time_precision; txc->tolerance = time_tolerance; - txc->tick = tick; + txc->tick = tick_usec; txc->ppsfreq = pps_freq; txc->jitter = pps_jitter >> PPS_AVG; txc->shift = pps_shift; diff --git a/kernel/timer.c b/kernel/timer.c index d4efe5823e94..3b4be840f931 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -33,10 +33,11 @@ struct kernel_stat kstat; * Timekeeping variables */ -long tick = (1000000 + HZ/2) / HZ; /* timer interrupt period */ +unsigned long tick_usec = TICK_USEC; /* ACTHZ period (usec) */ +unsigned long tick_nsec = TICK_NSEC(TICK_USEC); /* USER_HZ period (nsec) */ /* The current time */ -struct timeval xtime __attribute__ ((aligned (16))); +struct timespec xtime __attribute__ ((aligned (16))); /* Don't completely fail for HZ > 500. */ int tickadj = 500/HZ ? : 1; /* microsecs */ @@ -63,7 +64,6 @@ long time_adj; /* tick adjust (scaled 1 / HZ) */ long time_reftime; /* time at last adjustment (s) */ long time_adjust; -long time_adjust_step; unsigned long event; @@ -465,6 +465,8 @@ static void second_overflow(void) /* in the NTP reference this is called "hardclock()" */ static void update_wall_time_one_tick(void) { + long time_adjust_step; + if ( (time_adjust_step = time_adjust) != 0 ) { /* We are doing an adjtime thing. * @@ -483,21 +485,21 @@ static void update_wall_time_one_tick(void) /* Reduce by this step the amount of time left */ time_adjust -= time_adjust_step; } - xtime.tv_usec += tick + time_adjust_step; + xtime.tv_nsec += tick_nsec + time_adjust_step * 1000; /* * Advance the phase, once it gets to one microsecond, then * advance the tick more. */ time_phase += time_adj; if (time_phase <= -FINEUSEC) { - long ltemp = -time_phase >> SHIFT_SCALE; - time_phase += ltemp << SHIFT_SCALE; - xtime.tv_usec -= ltemp; + long ltemp = -time_phase >> (SHIFT_SCALE - 10); + time_phase += ltemp << (SHIFT_SCALE - 10); + xtime.tv_nsec -= ltemp; } else if (time_phase >= FINEUSEC) { - long ltemp = time_phase >> SHIFT_SCALE; - time_phase -= ltemp << SHIFT_SCALE; - xtime.tv_usec += ltemp; + long ltemp = time_phase >> (SHIFT_SCALE - 10); + time_phase -= ltemp << (SHIFT_SCALE - 10); + xtime.tv_nsec += ltemp; } } @@ -515,8 +517,8 @@ static void update_wall_time(unsigned long ticks) update_wall_time_one_tick(); } while (ticks); - if (xtime.tv_usec >= 1000000) { - xtime.tv_usec -= 1000000; + if (xtime.tv_nsec >= 1000000000) { + xtime.tv_nsec -= 1000000000; xtime.tv_sec++; second_overflow(); } -- cgit v1.2.3