diff options
| author | Robert Richter <robert.richter@amd.com> | 2010-10-25 10:28:14 -0400 |
|---|---|---|
| committer | Robert Richter <robert.richter@amd.com> | 2010-10-25 10:29:12 -0400 |
| commit | dbd1e66e04558a582e673bc4a9cd933ce0228d93 (patch) | |
| tree | 85f3633276282cde0a3ac558d988704eaa3e68af /arch/x86/kernel/apb_timer.c | |
| parent | 328b8f1ba50b708a1b3c0acd7c41ee1b356822f6 (diff) | |
| parent | 4a60cfa9457749f7987fd4f3c956dbba5a281129 (diff) | |
Merge commit 'linux-2.6/master' (early part) into oprofile/core
This branch depends on these apic patches:
apic, x86: Use BIOS settings for IBS and MCE threshold interrupt LVT offsets
apic, x86: Check if EILVT APIC registers are available (AMD only)
Signed-off-by: Robert Richter <robert.richter@amd.com>
Diffstat (limited to 'arch/x86/kernel/apb_timer.c')
| -rw-r--r-- | arch/x86/kernel/apb_timer.c | 60 |
1 files changed, 27 insertions, 33 deletions
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c index 8dd77800ff5d..92543c73cf8e 100644 --- a/arch/x86/kernel/apb_timer.c +++ b/arch/x86/kernel/apb_timer.c | |||
| @@ -231,34 +231,6 @@ static void apbt_restart_clocksource(struct clocksource *cs) | |||
| 231 | apbt_start_counter(phy_cs_timer_id); | 231 | apbt_start_counter(phy_cs_timer_id); |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | /* Setup IRQ routing via IOAPIC */ | ||
| 235 | #ifdef CONFIG_SMP | ||
| 236 | static void apbt_setup_irq(struct apbt_dev *adev) | ||
| 237 | { | ||
| 238 | struct irq_chip *chip; | ||
| 239 | struct irq_desc *desc; | ||
| 240 | |||
| 241 | /* timer0 irq has been setup early */ | ||
| 242 | if (adev->irq == 0) | ||
| 243 | return; | ||
| 244 | desc = irq_to_desc(adev->irq); | ||
| 245 | chip = get_irq_chip(adev->irq); | ||
| 246 | disable_irq(adev->irq); | ||
| 247 | desc->status |= IRQ_MOVE_PCNTXT; | ||
| 248 | irq_set_affinity(adev->irq, cpumask_of(adev->cpu)); | ||
| 249 | /* APB timer irqs are set up as mp_irqs, timer is edge triggerred */ | ||
| 250 | set_irq_chip_and_handler_name(adev->irq, chip, handle_edge_irq, "edge"); | ||
| 251 | enable_irq(adev->irq); | ||
| 252 | if (system_state == SYSTEM_BOOTING) | ||
| 253 | if (request_irq(adev->irq, apbt_interrupt_handler, | ||
| 254 | IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, | ||
| 255 | adev->name, adev)) { | ||
| 256 | printk(KERN_ERR "Failed request IRQ for APBT%d\n", | ||
| 257 | adev->num); | ||
| 258 | } | ||
| 259 | } | ||
| 260 | #endif | ||
| 261 | |||
| 262 | static void apbt_enable_int(int n) | 234 | static void apbt_enable_int(int n) |
| 263 | { | 235 | { |
| 264 | unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); | 236 | unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); |
| @@ -334,6 +306,27 @@ static int __init apbt_clockevent_register(void) | |||
| 334 | } | 306 | } |
| 335 | 307 | ||
| 336 | #ifdef CONFIG_SMP | 308 | #ifdef CONFIG_SMP |
| 309 | |||
| 310 | static void apbt_setup_irq(struct apbt_dev *adev) | ||
| 311 | { | ||
| 312 | /* timer0 irq has been setup early */ | ||
| 313 | if (adev->irq == 0) | ||
| 314 | return; | ||
| 315 | |||
| 316 | if (system_state == SYSTEM_BOOTING) { | ||
| 317 | irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT); | ||
| 318 | /* APB timer irqs are set up as mp_irqs, timer is edge type */ | ||
| 319 | __set_irq_handler(adev->irq, handle_edge_irq, 0, "edge"); | ||
| 320 | if (request_irq(adev->irq, apbt_interrupt_handler, | ||
| 321 | IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, | ||
| 322 | adev->name, adev)) { | ||
| 323 | printk(KERN_ERR "Failed request IRQ for APBT%d\n", | ||
| 324 | adev->num); | ||
| 325 | } | ||
| 326 | } else | ||
| 327 | enable_irq(adev->irq); | ||
| 328 | } | ||
| 329 | |||
| 337 | /* Should be called with per cpu */ | 330 | /* Should be called with per cpu */ |
| 338 | void apbt_setup_secondary_clock(void) | 331 | void apbt_setup_secondary_clock(void) |
| 339 | { | 332 | { |
| @@ -343,7 +336,7 @@ void apbt_setup_secondary_clock(void) | |||
| 343 | 336 | ||
| 344 | /* Don't register boot CPU clockevent */ | 337 | /* Don't register boot CPU clockevent */ |
| 345 | cpu = smp_processor_id(); | 338 | cpu = smp_processor_id(); |
| 346 | if (cpu == boot_cpu_id) | 339 | if (!cpu) |
| 347 | return; | 340 | return; |
| 348 | /* | 341 | /* |
| 349 | * We need to calculate the scaled math multiplication factor for | 342 | * We need to calculate the scaled math multiplication factor for |
| @@ -389,16 +382,17 @@ static int apbt_cpuhp_notify(struct notifier_block *n, | |||
| 389 | 382 | ||
| 390 | switch (action & 0xf) { | 383 | switch (action & 0xf) { |
| 391 | case CPU_DEAD: | 384 | case CPU_DEAD: |
| 385 | disable_irq(adev->irq); | ||
| 392 | apbt_disable_int(cpu); | 386 | apbt_disable_int(cpu); |
| 393 | if (system_state == SYSTEM_RUNNING) | 387 | if (system_state == SYSTEM_RUNNING) { |
| 394 | pr_debug("skipping APBT CPU %lu offline\n", cpu); | 388 | pr_debug("skipping APBT CPU %lu offline\n", cpu); |
| 395 | else if (adev) { | 389 | } else if (adev) { |
| 396 | pr_debug("APBT clockevent for cpu %lu offline\n", cpu); | 390 | pr_debug("APBT clockevent for cpu %lu offline\n", cpu); |
| 397 | free_irq(adev->irq, adev); | 391 | free_irq(adev->irq, adev); |
| 398 | } | 392 | } |
| 399 | break; | 393 | break; |
| 400 | default: | 394 | default: |
| 401 | pr_debug(KERN_INFO "APBT notified %lu, no action\n", action); | 395 | pr_debug("APBT notified %lu, no action\n", action); |
| 402 | } | 396 | } |
| 403 | return NOTIFY_OK; | 397 | return NOTIFY_OK; |
| 404 | } | 398 | } |
| @@ -552,7 +546,7 @@ bad_count: | |||
| 552 | pr_debug("APB CS going back %lx:%lx:%lx ", | 546 | pr_debug("APB CS going back %lx:%lx:%lx ", |
| 553 | t2, last_read, t2 - last_read); | 547 | t2, last_read, t2 - last_read); |
| 554 | bad_count_x3: | 548 | bad_count_x3: |
| 555 | pr_debug(KERN_INFO "tripple check enforced\n"); | 549 | pr_debug("triple check enforced\n"); |
| 556 | t0 = apbt_readl(phy_cs_timer_id, | 550 | t0 = apbt_readl(phy_cs_timer_id, |
| 557 | APBTMR_N_CURRENT_VALUE); | 551 | APBTMR_N_CURRENT_VALUE); |
| 558 | udelay(1); | 552 | udelay(1); |
