void __init ia64_init_itm (void) { unsigned long platform_base_freq, itc_freq, drift; struct pal_freq_ratio itc_ratio, proc_ratio; long status; /* * According to SAL v2.6, we need to use a SAL call to determine the platform base * frequency and then a PAL call to determine the frequency ratio between the ITC * and the base frequency. */ status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM, &platform_base_freq, &drift); if (status != 0) { printk(KERN_ERR "SAL_FREQ_BASE_PLATFORM failed: %s\n", ia64_sal_strerror(status)); } else { status = ia64_pal_freq_ratios(&proc_ratio, 0, &itc_ratio); if (status != 0) printk(KERN_ERR "PAL_FREQ_RATIOS failed with status=%ld\n", status); } if (status != 0) { /* invent "random" values */ printk(KERN_ERR "SAL/PAL failed to obtain frequency info---inventing reasonably values\n"); platform_base_freq = 100000000; itc_ratio.num = 3; itc_ratio.den = 1; } if (platform_base_freq < 40000000) { printk(KERN_ERR "Platform base frequency %lu bogus---resetting to 75MHz!\n", platform_base_freq); platform_base_freq = 75000000; } if (!proc_ratio.den) proc_ratio.den = 1; /* avoid division by zero */ if (!itc_ratio.den) itc_ratio.den = 1; /* avoid division by zero */ itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den; local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ; printk(KERN_INFO "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, " "ITC freq=%lu.%03luMHz\n", smp_processor_id(), platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000, itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000); local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den; local_cpu_data->itc_freq = itc_freq; local_cpu_data->cyc_per_usec = (itc_freq + 500000) / 1000000; local_cpu_data->usec_per_cyc = ((1000000UL<<IA64_USEC_PER_CYC_SHIFT) + itc_freq/2)/itc_freq; /* Setup the CPU local timer tick */ ia64_cpu_local_tick(); }
/* * Assume that CPUs have been discovered by some platform-dependent interface. For * SoftSDV/Lion, that would be ACPI. * * Setup of the IPI irq handler is done in irq.c:init_IRQ_SMP(). */ void __init init_smp_config(void) { struct fptr { unsigned long fp; unsigned long gp; } *ap_startup; long sal_ret; /* Tell SAL where to drop the APs. */ ap_startup = (struct fptr *) start_ap; sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ, ia64_tpa(ap_startup->fp), ia64_tpa(ap_startup->gp), 0, 0, 0, 0); if (sal_ret < 0) printk(KERN_ERR "SMP: Can't set SAL AP Boot Rendezvous: %s\n", ia64_sal_strerror(sal_ret)); }
/* * Assume that CPU's have been discovered by some platform-dependant interface. For * SoftSDV/Lion, that would be ACPI. * * Setup of the IPI irq handler is done in irq.c:init_IRQ_SMP(). */ void __init init_smp_config(void) { struct fptr { unsigned long fp; unsigned long gp; } *ap_startup; long sal_ret; /* Tell SAL where to drop the AP's. */ ap_startup = (struct fptr *) start_ap; sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ, __pa(ap_startup->fp), __pa(ap_startup->gp), 0, 0, 0, 0); if (sal_ret < 0) { printk("SMP: Can't set SAL AP Boot Rendezvous: %s\n Forcing UP mode\n", ia64_sal_strerror(sal_ret)); max_cpus = 0; smp_num_cpus = 1; } }
void __devinit ia64_init_itm (void) { unsigned long platform_base_freq, itc_freq; struct pal_freq_ratio itc_ratio, proc_ratio; long status, platform_base_drift, itc_drift; /* * According to SAL v2.6, we need to use a SAL call to determine the platform base * frequency and then a PAL call to determine the frequency ratio between the ITC * and the base frequency. */ status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM, &platform_base_freq, &platform_base_drift); if (status != 0) { printk(KERN_ERR "SAL_FREQ_BASE_PLATFORM failed: %s\n", ia64_sal_strerror(status)); } else { status = ia64_pal_freq_ratios(&proc_ratio, NULL, &itc_ratio); if (status != 0) printk(KERN_ERR "PAL_FREQ_RATIOS failed with status=%ld\n", status); } if (status != 0) { /* invent "random" values */ printk(KERN_ERR "SAL/PAL failed to obtain frequency info---inventing reasonable values\n"); platform_base_freq = 100000000; platform_base_drift = -1; /* no drift info */ itc_ratio.num = 3; itc_ratio.den = 1; } if (platform_base_freq < 40000000) { printk(KERN_ERR "Platform base frequency %lu bogus---resetting to 75MHz!\n", platform_base_freq); platform_base_freq = 75000000; platform_base_drift = -1; } if (!proc_ratio.den) proc_ratio.den = 1; /* avoid division by zero */ if (!itc_ratio.den) itc_ratio.den = 1; /* avoid division by zero */ itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den; local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ; printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%u/%u, " "ITC freq=%lu.%03luMHz", smp_processor_id(), platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000, itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000); if (platform_base_drift != -1) { itc_drift = platform_base_drift*itc_ratio.num/itc_ratio.den; printk("+/-%ldppm\n", itc_drift); } else { itc_drift = -1; printk("\n"); } local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den; local_cpu_data->itc_freq = itc_freq; local_cpu_data->cyc_per_usec = (itc_freq + USEC_PER_SEC/2) / USEC_PER_SEC; local_cpu_data->nsec_per_cyc = ((NSEC_PER_SEC<<IA64_NSEC_PER_CYC_SHIFT) + itc_freq/2)/itc_freq; if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) { #ifdef CONFIG_SMP /* On IA64 in an SMP configuration ITCs are never accurately synchronized. * Jitter compensation requires a cmpxchg which may limit * the scalability of the syscalls for retrieving time. * The ITC synchronization is usually successful to within a few * ITC ticks but this is not a sure thing. If you need to improve * timer performance in SMP situations then boot the kernel with the * "nojitter" option. However, doing so may result in time fluctuating (maybe * even going backward) if the ITC offsets between the individual CPUs * are too large. */ if (!nojitter) itc_jitter_data.itc_jitter = 1; #endif } else /* * ITC is drifty and we have not synchronized the ITCs in smpboot.c. * ITC values may fluctuate significantly between processors. * Clock should not be used for hrtimers. Mark itc as only * useful for boot and testing. * * Note that jitter compensation is off! There is no point of * synchronizing ITCs since they may be large differentials * that change over time. * * The only way to fix this would be to repeatedly sync the * ITCs. Until that time we have to avoid ITC. */ clocksource_itc.rating = 50; paravirt_init_missing_ticks_accounting(smp_processor_id()); /* avoid softlock up message when cpu is unplug and plugged again. */ touch_softlockup_watchdog(); /* Setup the CPU local timer tick */ ia64_cpu_local_tick(); if (!itc_clocksource) { /* Sort out mult/shift values: */ clocksource_itc.mult = clocksource_hz2mult(local_cpu_data->itc_freq, clocksource_itc.shift); clocksource_register(&clocksource_itc); itc_clocksource = &clocksource_itc; } }
void __devinit ia64_init_itm (void) { unsigned long platform_base_freq, itc_freq; struct pal_freq_ratio itc_ratio, proc_ratio; long status, platform_base_drift, itc_drift; /* * According to SAL v2.6, we need to use a SAL call to determine the platform base * frequency and then a PAL call to determine the frequency ratio between the ITC * and the base frequency. */ status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM, &platform_base_freq, &platform_base_drift); if (status != 0) { printk(KERN_ERR "SAL_FREQ_BASE_PLATFORM failed: %s\n", ia64_sal_strerror(status)); } else { status = ia64_pal_freq_ratios(&proc_ratio, NULL, &itc_ratio); if (status != 0) printk(KERN_ERR "PAL_FREQ_RATIOS failed with status=%ld\n", status); } if (status != 0) { /* invent "random" values */ printk(KERN_ERR "SAL/PAL failed to obtain frequency info---inventing reasonable values\n"); platform_base_freq = 100000000; platform_base_drift = -1; /* no drift info */ itc_ratio.num = 3; itc_ratio.den = 1; } if (platform_base_freq < 40000000) { printk(KERN_ERR "Platform base frequency %lu bogus---resetting to 75MHz!\n", platform_base_freq); platform_base_freq = 75000000; platform_base_drift = -1; } if (!proc_ratio.den) proc_ratio.den = 1; /* avoid division by zero */ if (!itc_ratio.den) itc_ratio.den = 1; /* avoid division by zero */ itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den; local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ; printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%u/%u, " "ITC freq=%lu.%03luMHz", smp_processor_id(), platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000, itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000); if (platform_base_drift != -1) { itc_drift = platform_base_drift*itc_ratio.num/itc_ratio.den; printk("+/-%ldppm\n", itc_drift); } else { itc_drift = -1; printk("\n"); } local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den; local_cpu_data->itc_freq = itc_freq; local_cpu_data->cyc_per_usec = (itc_freq + USEC_PER_SEC/2) / USEC_PER_SEC; local_cpu_data->nsec_per_cyc = ((NSEC_PER_SEC<<IA64_NSEC_PER_CYC_SHIFT) + itc_freq/2)/itc_freq; if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) { itc_interpolator.frequency = local_cpu_data->itc_freq; itc_interpolator.drift = itc_drift; #ifdef CONFIG_SMP /* On IA64 in an SMP configuration ITCs are never accurately synchronized. * Jitter compensation requires a cmpxchg which may limit * the scalability of the syscalls for retrieving time. * The ITC synchronization is usually successful to within a few * ITC ticks but this is not a sure thing. If you need to improve * timer performance in SMP situations then boot the kernel with the * "nojitter" option. However, doing so may result in time fluctuating (maybe * even going backward) if the ITC offsets between the individual CPUs * are too large. */ if (!nojitter) itc_interpolator.jitter = 1; #endif register_time_interpolator(&itc_interpolator); } /* Setup the CPU local timer tick */ ia64_cpu_local_tick(); }