Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef1dce99 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull ARC fixes from Vineet Gupta:
 "Hopefully last set of changes for ARC for 4.10:

   - fix for unaligned access emulation corner case

   - fix for udelay loop inline asm regression

   - fix irq affinity finally for AXS103 board [Yuriy]

   - final fixes for setting IO-coherency sanely in SMP"

* tag 'arc-4.10-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc:
  ARC: [arcompact] handle unaligned access delay slot corner case
  ARCv2: smp-boot: wake_flag polling by non-Masters needs to be uncached
  ARC: smp-boot: Decouple Non masters waiting API from jump to entry point
  ARCv2: MCIP: update the BCR per current changes
  ARC: udelay: fix inline assembler by adding LP_COUNT to clobber list
  ARCv2: MCIP: Deprecate setting of affinity in Device Tree
parents 1b1bc42c 9aed02fe
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@ Properties:
  Second cell specifies the irq distribution mode to cores
     0=Round Robin; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3

  The second cell in interrupts property is deprecated and may be ignored by
  the kernel.

  intc accessed via the special ARC AUX register interface, hence "reg" property
  is not specified.

+3 −1
Original line number Diff line number Diff line
@@ -26,7 +26,9 @@ static inline void __delay(unsigned long loops)
	"	lp  1f			\n"
	"	nop			\n"
	"1:				\n"
	: : "r"(loops));
	:
        : "r"(loops)
        : "lp_count");
}

extern void __bad_udelay(void);
+7 −7
Original line number Diff line number Diff line
@@ -71,14 +71,14 @@ ENTRY(stext)
	GET_CPU_ID  r5
	cmp	r5, 0
	mov.nz	r0, r5
#ifdef CONFIG_ARC_SMP_HALT_ON_RESET
	; Non-Master can proceed as system would be booted sufficiently
	jnz	first_lines_of_secondary
#else
	bz	.Lmaster_proceed

	; Non-Masters wait for Master to boot enough and bring them up
	jnz	arc_platform_smp_wait_to_boot
#endif
	; Master falls thru
	; when they resume, tail-call to entry point
	mov	blink, @first_lines_of_secondary
	j	arc_platform_smp_wait_to_boot

.Lmaster_proceed:
#endif

	; Clear BSS before updating any globals
+23 −32
Original line number Diff line number Diff line
@@ -93,11 +93,10 @@ static void mcip_probe_n_setup(void)
	READ_BCR(ARC_REG_MCIP_BCR, mp);

	sprintf(smp_cpuinfo_buf,
		"Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s%s\n",
		"Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s\n",
		mp.ver, mp.num_cores,
		IS_AVAIL1(mp.ipi, "IPI "),
		IS_AVAIL1(mp.idu, "IDU "),
		IS_AVAIL1(mp.llm, "LLM "),
		IS_AVAIL1(mp.dbg, "DEBUG "),
		IS_AVAIL1(mp.gfrc, "GFRC"));

@@ -175,7 +174,6 @@ static void idu_irq_unmask(struct irq_data *data)
	raw_spin_unlock_irqrestore(&mcip_lock, flags);
}

#ifdef CONFIG_SMP
static int
idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
		     bool force)
@@ -205,12 +203,27 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,

	return IRQ_SET_MASK_OK;
}
#endif

static void idu_irq_enable(struct irq_data *data)
{
	/*
	 * By default send all common interrupts to all available online CPUs.
	 * The affinity of common interrupts in IDU must be set manually since
	 * in some cases the kernel will not call irq_set_affinity() by itself:
	 *   1. When the kernel is not configured with support of SMP.
	 *   2. When the kernel is configured with support of SMP but upper
	 *      interrupt controllers does not support setting of the affinity
	 *      and cannot propagate it to IDU.
	 */
	idu_irq_set_affinity(data, cpu_online_mask, false);
	idu_irq_unmask(data);
}

static struct irq_chip idu_irq_chip = {
	.name			= "MCIP IDU Intc",
	.irq_mask		= idu_irq_mask,
	.irq_unmask		= idu_irq_unmask,
	.irq_enable		= idu_irq_enable,
#ifdef CONFIG_SMP
	.irq_set_affinity       = idu_irq_set_affinity,
#endif
@@ -243,35 +256,13 @@ static int idu_irq_xlate(struct irq_domain *d, struct device_node *n,
			 const u32 *intspec, unsigned int intsize,
			 irq_hw_number_t *out_hwirq, unsigned int *out_type)
{
	irq_hw_number_t hwirq = *out_hwirq = intspec[0];
	int distri = intspec[1];
	unsigned long flags;

	*out_type = IRQ_TYPE_NONE;

	/* XXX: validate distribution scheme again online cpu mask */
	if (distri == 0) {
		/* 0 - Round Robin to all cpus, otherwise 1 bit per core */
		raw_spin_lock_irqsave(&mcip_lock, flags);
		idu_set_dest(hwirq, BIT(num_online_cpus()) - 1);
		idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
		raw_spin_unlock_irqrestore(&mcip_lock, flags);
	} else {
	/*
		 * DEST based distribution for Level Triggered intr can only
		 * have 1 CPU, so generalize it to always contain 1 cpu
	 * Ignore value of interrupt distribution mode for common interrupts in
	 * IDU which resides in intspec[1] since setting an affinity using value
	 * from Device Tree is deprecated in ARC.
	 */
		int cpu = ffs(distri);

		if (cpu != fls(distri))
			pr_warn("IDU irq %lx distri mode set to cpu %x\n",
				hwirq, cpu);

		raw_spin_lock_irqsave(&mcip_lock, flags);
		idu_set_dest(hwirq, cpu);
		idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_DEST);
		raw_spin_unlock_irqrestore(&mcip_lock, flags);
	}
	*out_hwirq = intspec[0];
	*out_type = IRQ_TYPE_NONE;

	return 0;
}
+20 −5
Original line number Diff line number Diff line
@@ -90,22 +90,37 @@ void __init smp_cpus_done(unsigned int max_cpus)
 */
static volatile int wake_flag;

#ifdef CONFIG_ISA_ARCOMPACT

#define __boot_read(f)		f
#define __boot_write(f, v)	f = v

#else

#define __boot_read(f)		arc_read_uncached_32(&f)
#define __boot_write(f, v)	arc_write_uncached_32(&f, v)

#endif

static void arc_default_smp_cpu_kick(int cpu, unsigned long pc)
{
	BUG_ON(cpu == 0);
	wake_flag = cpu;

	__boot_write(wake_flag, cpu);
}

void arc_platform_smp_wait_to_boot(int cpu)
{
	while (wake_flag != cpu)
	/* for halt-on-reset, we've waited already */
	if (IS_ENABLED(CONFIG_ARC_SMP_HALT_ON_RESET))
		return;

	while (__boot_read(wake_flag) != cpu)
		;

	wake_flag = 0;
	__asm__ __volatile__("j @first_lines_of_secondary	\n");
	__boot_write(wake_flag, 0);
}


const char *arc_platform_smp_cpuinfo(void)
{
	return plat_smp_ops.info ? : "";
Loading