[PATCH 6/14] ps3: smp interrupt fixes

Benjamin Herrenschmidt benh at kernel.crashing.org
Thu Jan 25 14:51:37 EST 2007


On Wed, 2007-01-24 at 18:40 -0800, Geoff Levand wrote:
> PS3 fixups for interrups on SMP.
> 
> Fixes the alignment of the interrupt status bitmap, changes the hypervisor
> interrupt calls to the '_ext' versions that take an explicit processor
> thread ID, and sets the cpu_features flag CPU_FTR_SMT.
> 
> 
> Signed-off-by: Geoff Levand <geoffrey.levand at am.sony.com>

Looks good.

Acked-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>

> ---
>  arch/powerpc/platforms/ps3/interrupt.c |   64 +++++++++++++++------------------
>  arch/powerpc/platforms/ps3/setup.c     |    1 
>  2 files changed, 32 insertions(+), 33 deletions(-)
> 
> --- ps3-linux-dev.orig/arch/powerpc/platforms/ps3/interrupt.c
> +++ ps3-linux-dev/arch/powerpc/platforms/ps3/interrupt.c
> @@ -317,22 +317,23 @@ struct ps3_bmp {
>  		unsigned long unused_1[3];
>  		unsigned long mask;
>  		unsigned long unused_2[3];
> -	} __attribute__ ((packed));
> +	} __attribute__ ((aligned (64)));
> +
>  	spinlock_t lock;
>  	unsigned long ipi_debug_brk_mask;
>  };
>  
>  /**
>   * struct ps3_private - a per cpu data structure
> - * @node: HV node id
> - * @cpu: HV thread id
> - * @bmp: an HV ps3_bmp structure
> + * @bmp: ps3_bmp structure
> + * @node: HV logical_ppe_id
> + * @cpu: HV thread_id
>   */
>  
>  struct ps3_private {
> +	struct ps3_bmp bmp;
>  	unsigned long node;
>  	unsigned int cpu;
> -	struct ps3_bmp bmp;
>  };
>  
>  #if defined(DEBUG)
> @@ -389,9 +390,8 @@ static void ps3_chip_mask(unsigned int v
>  
>  	spin_lock_irqsave(&pd->bmp.lock, flags);
>  	pd->bmp.mask &= ~(0x8000000000000000UL >> virq);
> -	spin_unlock_irqrestore(&pd->bmp.lock, flags);
> -
>  	lv1_did_update_interrupt_mask(pd->node, pd->cpu);
> +	spin_unlock_irqrestore(&pd->bmp.lock, flags);
>  }
>  
>  static void ps3_chip_unmask(unsigned int virq)
> @@ -406,14 +406,14 @@ static void ps3_chip_unmask(unsigned int
>  
>  	spin_lock_irqsave(&pd->bmp.lock, flags);
>  	pd->bmp.mask |= (0x8000000000000000UL >> virq);
> -	spin_unlock_irqrestore(&pd->bmp.lock, flags);
> -
>  	lv1_did_update_interrupt_mask(pd->node, pd->cpu);
> +	spin_unlock_irqrestore(&pd->bmp.lock, flags);
>  }
>  
>  static void ps3_chip_eoi(unsigned int virq)
>  {
> -	lv1_end_of_interrupt(virq);
> +	const struct ps3_private *pd = get_irq_chip_data(virq);
> +	lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq);
>  }
>  
>  static struct irq_chip irq_chip = {
> @@ -426,10 +426,12 @@ static struct irq_chip irq_chip = {
>  static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
>  {
>  	int result;
> +	const struct ps3_private *pd = get_irq_chip_data(virq);
>  
> -	pr_debug("%s:%d: virq %d\n", __func__, __LINE__, virq);
> +	pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
> +		pd->node, pd->cpu, virq);
>  
> -	lv1_disconnect_irq_plug(virq);
> +	lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
>  
>  	result = set_irq_chip_data(virq, NULL);
>  	BUG_ON(result);
> @@ -441,31 +443,26 @@ static int ps3_host_map(struct irq_host 
>  	irq_hw_number_t hwirq)
>  {
>  	int result;
> -	unsigned int cpu;
> +	struct ps3_private *pd = &__get_cpu_var(ps3_private);
> +
> +	pr_debug("%s:%d: node %lu, cpu %d, hwirq %lu => virq %u\n", __func__,
> +		__LINE__, pd->node, pd->cpu, hwirq, virq);
>  
> -	pr_debug(" -> %s:%d\n", __func__, __LINE__);
> -	pr_debug("%s:%d: hwirq %lu => virq %u\n", __func__, __LINE__, hwirq,
> -		virq);
> -
> -	/* bind this virq to a cpu */
> -
> -	preempt_disable();
> -	cpu = smp_processor_id();
> -	result = lv1_connect_irq_plug(virq, hwirq);
> -	preempt_enable();
> +	/* Binds this virq to pd->cpu (current cpu) */
> +
> +	result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, virq, hwirq, 0);
>  
>  	if (result) {
> -		pr_info("%s:%d: lv1_connect_irq_plug failed:"
> +		pr_info("%s:%d: lv1_connect_irq_plug_ext failed:"
>  			" %s\n", __func__, __LINE__, ps3_result(result));
>  		return -EPERM;
>  	}
>  
> -	result = set_irq_chip_data(virq, &per_cpu(ps3_private, cpu));
> +	result = set_irq_chip_data(virq, pd);
>  	BUG_ON(result);
>  
>  	set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq);
>  
> -	pr_debug(" <- %s:%d\n", __func__, __LINE__);
>  	return result;
>  }
>  
> @@ -544,12 +541,9 @@ unsigned int ps3_get_irq(void)
>  void __init ps3_init_IRQ(void)
>  {
>  	int result;
> -	unsigned long node;
>  	unsigned cpu;
>  	struct irq_host *host;
>  
> -	lv1_get_logical_ppe_id(&node);
> -
>  	host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops,
>  		PS3_INVALID_OUTLET);
>  	irq_set_default_host(host);
> @@ -558,12 +552,16 @@ void __init ps3_init_IRQ(void)
>  	for_each_possible_cpu(cpu) {
>  		struct ps3_private *pd = &per_cpu(ps3_private, cpu);
>  
> -		pd->node = node;
> -		pd->cpu = cpu;
> +		lv1_get_logical_ppe_id(&pd->node);
> +		pd->cpu = get_hard_smp_processor_id(cpu);
>  		spin_lock_init(&pd->bmp.lock);
>  
> -		result = lv1_configure_irq_state_bitmap(node, cpu,
> -			ps3_mm_phys_to_lpar(__pa(&pd->bmp.status)));
> +		pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__,
> +			__LINE__, pd->node, pd->cpu,
> +			ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
> +
> +		result = lv1_configure_irq_state_bitmap(pd->node, pd->cpu,
> +			ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
>  
>  		if (result)
>  			pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:"
> --- ps3-linux-dev.orig/arch/powerpc/platforms/ps3/setup.c
> +++ ps3-linux-dev/arch/powerpc/platforms/ps3/setup.c
> @@ -109,6 +109,7 @@ static int __init ps3_probe(void)
>  		return 0;
>  
>  	powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE;
> +	cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
>  
>  	ps3_os_area_init();
>  	ps3_mm_init();
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev




More information about the Linuxppc-dev mailing list