diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-11-03 02:57:41 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-03 02:57:41 -0500 |
commit | db5935001a43528e673ad26ffec9d98c60a496a9 (patch) | |
tree | 8e735327a97beccabb5d94ef93df25d2bacda705 /arch/powerpc/sysdev | |
parent | 34f3a814eef8069a24e5b3ebcf27aba9dabac2ea (diff) | |
parent | 45beca08dd8b6d6a65c5ffd730af2eac7a2c7a03 (diff) |
Merge commit 'v2.6.28-rc3' into sched/core
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/fsl_soc.c | 26 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 59 |
2 files changed, 81 insertions, 4 deletions
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 01b884b25696..26ecb96f9731 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -223,6 +223,8 @@ static int gfar_mdio_of_init_one(struct device_node *np) | |||
223 | if (ret) | 223 | if (ret) |
224 | return ret; | 224 | return ret; |
225 | 225 | ||
226 | /* The gianfar device will try to use the same ID created below to find | ||
227 | * this bus, to coordinate register access (since they share). */ | ||
226 | mdio_dev = platform_device_register_simple("fsl-gianfar_mdio", | 228 | mdio_dev = platform_device_register_simple("fsl-gianfar_mdio", |
227 | res.start&0xfffff, &res, 1); | 229 | res.start&0xfffff, &res, 1); |
228 | if (IS_ERR(mdio_dev)) | 230 | if (IS_ERR(mdio_dev)) |
@@ -394,6 +396,30 @@ static int __init gfar_of_init(void) | |||
394 | of_node_put(mdio); | 396 | of_node_put(mdio); |
395 | } | 397 | } |
396 | 398 | ||
399 | /* Get MDIO bus controlled by this eTSEC, if any. Normally only | ||
400 | * eTSEC 1 will control an MDIO bus, not necessarily the same | ||
401 | * bus that its PHY is on ('mdio' above), so we can't just use | ||
402 | * that. What we do is look for a gianfar mdio device that has | ||
403 | * overlapping registers with this device. That's really the | ||
404 | * whole point, to find the device sharing our registers to | ||
405 | * coordinate access with it. | ||
406 | */ | ||
407 | for_each_compatible_node(mdio, NULL, "fsl,gianfar-mdio") { | ||
408 | if (of_address_to_resource(mdio, 0, &res)) | ||
409 | continue; | ||
410 | |||
411 | if (res.start >= r[0].start && res.end <= r[0].end) { | ||
412 | /* Get the ID the mdio bus platform device was | ||
413 | * registered with. gfar_data.bus_id is | ||
414 | * different because it's for finding a PHY, | ||
415 | * while this is for finding a MII bus. | ||
416 | */ | ||
417 | gfar_data.mdio_bus = res.start&0xfffff; | ||
418 | of_node_put(mdio); | ||
419 | break; | ||
420 | } | ||
421 | } | ||
422 | |||
397 | ret = | 423 | ret = |
398 | platform_device_add_data(gfar_dev, &gfar_data, | 424 | platform_device_add_data(gfar_dev, &gfar_data, |
399 | sizeof(struct | 425 | sizeof(struct |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 8e3478c995ef..f6299cca7814 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -563,6 +563,51 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) | |||
563 | 563 | ||
564 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ | 564 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ |
565 | 565 | ||
566 | #ifdef CONFIG_SMP | ||
567 | static int irq_choose_cpu(unsigned int virt_irq) | ||
568 | { | ||
569 | cpumask_t mask = irq_desc[virt_irq].affinity; | ||
570 | int cpuid; | ||
571 | |||
572 | if (cpus_equal(mask, CPU_MASK_ALL)) { | ||
573 | static int irq_rover; | ||
574 | static DEFINE_SPINLOCK(irq_rover_lock); | ||
575 | unsigned long flags; | ||
576 | |||
577 | /* Round-robin distribution... */ | ||
578 | do_round_robin: | ||
579 | spin_lock_irqsave(&irq_rover_lock, flags); | ||
580 | |||
581 | while (!cpu_online(irq_rover)) { | ||
582 | if (++irq_rover >= NR_CPUS) | ||
583 | irq_rover = 0; | ||
584 | } | ||
585 | cpuid = irq_rover; | ||
586 | do { | ||
587 | if (++irq_rover >= NR_CPUS) | ||
588 | irq_rover = 0; | ||
589 | } while (!cpu_online(irq_rover)); | ||
590 | |||
591 | spin_unlock_irqrestore(&irq_rover_lock, flags); | ||
592 | } else { | ||
593 | cpumask_t tmp; | ||
594 | |||
595 | cpus_and(tmp, cpu_online_map, mask); | ||
596 | |||
597 | if (cpus_empty(tmp)) | ||
598 | goto do_round_robin; | ||
599 | |||
600 | cpuid = first_cpu(tmp); | ||
601 | } | ||
602 | |||
603 | return cpuid; | ||
604 | } | ||
605 | #else | ||
606 | static int irq_choose_cpu(unsigned int virt_irq) | ||
607 | { | ||
608 | return hard_smp_processor_id(); | ||
609 | } | ||
610 | #endif | ||
566 | 611 | ||
567 | #define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) | 612 | #define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) |
568 | 613 | ||
@@ -777,12 +822,18 @@ void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) | |||
777 | struct mpic *mpic = mpic_from_irq(irq); | 822 | struct mpic *mpic = mpic_from_irq(irq); |
778 | unsigned int src = mpic_irq_to_hw(irq); | 823 | unsigned int src = mpic_irq_to_hw(irq); |
779 | 824 | ||
780 | cpumask_t tmp; | 825 | if (mpic->flags & MPIC_SINGLE_DEST_CPU) { |
826 | int cpuid = irq_choose_cpu(irq); | ||
781 | 827 | ||
782 | cpus_and(tmp, cpumask, cpu_online_map); | 828 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); |
829 | } else { | ||
830 | cpumask_t tmp; | ||
783 | 831 | ||
784 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), | 832 | cpus_and(tmp, cpumask, cpu_online_map); |
785 | mpic_physmask(cpus_addr(tmp)[0])); | 833 | |
834 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), | ||
835 | mpic_physmask(cpus_addr(tmp)[0])); | ||
836 | } | ||
786 | } | 837 | } |
787 | 838 | ||
788 | static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type) | 839 | static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type) |