Commit ef1dce99 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'arc-4.10-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc

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
...@@ -15,6 +15,9 @@ Properties: ...@@ -15,6 +15,9 @@ Properties:
Second cell specifies the irq distribution mode to cores Second cell specifies the irq distribution mode to cores
0=Round Robin; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3 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 intc accessed via the special ARC AUX register interface, hence "reg" property
is not specified. is not specified.
......
...@@ -26,7 +26,9 @@ static inline void __delay(unsigned long loops) ...@@ -26,7 +26,9 @@ static inline void __delay(unsigned long loops)
" lp 1f \n" " lp 1f \n"
" nop \n" " nop \n"
"1: \n" "1: \n"
: : "r"(loops)); :
: "r"(loops)
: "lp_count");
} }
extern void __bad_udelay(void); extern void __bad_udelay(void);
......
...@@ -71,14 +71,14 @@ ENTRY(stext) ...@@ -71,14 +71,14 @@ ENTRY(stext)
GET_CPU_ID r5 GET_CPU_ID r5
cmp r5, 0 cmp r5, 0
mov.nz r0, r5 mov.nz r0, r5
#ifdef CONFIG_ARC_SMP_HALT_ON_RESET bz .Lmaster_proceed
; Non-Master can proceed as system would be booted sufficiently
jnz first_lines_of_secondary
#else
; Non-Masters wait for Master to boot enough and bring them up ; Non-Masters wait for Master to boot enough and bring them up
jnz arc_platform_smp_wait_to_boot ; when they resume, tail-call to entry point
#endif mov blink, @first_lines_of_secondary
; Master falls thru j arc_platform_smp_wait_to_boot
.Lmaster_proceed:
#endif #endif
; Clear BSS before updating any globals ; Clear BSS before updating any globals
......
...@@ -93,11 +93,10 @@ static void mcip_probe_n_setup(void) ...@@ -93,11 +93,10 @@ static void mcip_probe_n_setup(void)
READ_BCR(ARC_REG_MCIP_BCR, mp); READ_BCR(ARC_REG_MCIP_BCR, mp);
sprintf(smp_cpuinfo_buf, 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, mp.ver, mp.num_cores,
IS_AVAIL1(mp.ipi, "IPI "), IS_AVAIL1(mp.ipi, "IPI "),
IS_AVAIL1(mp.idu, "IDU "), IS_AVAIL1(mp.idu, "IDU "),
IS_AVAIL1(mp.llm, "LLM "),
IS_AVAIL1(mp.dbg, "DEBUG "), IS_AVAIL1(mp.dbg, "DEBUG "),
IS_AVAIL1(mp.gfrc, "GFRC")); IS_AVAIL1(mp.gfrc, "GFRC"));
...@@ -175,7 +174,6 @@ static void idu_irq_unmask(struct irq_data *data) ...@@ -175,7 +174,6 @@ static void idu_irq_unmask(struct irq_data *data)
raw_spin_unlock_irqrestore(&mcip_lock, flags); raw_spin_unlock_irqrestore(&mcip_lock, flags);
} }
#ifdef CONFIG_SMP
static int static int
idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask, idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
bool force) bool force)
...@@ -205,12 +203,27 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask, ...@@ -205,12 +203,27 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
return IRQ_SET_MASK_OK; 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 = { static struct irq_chip idu_irq_chip = {
.name = "MCIP IDU Intc", .name = "MCIP IDU Intc",
.irq_mask = idu_irq_mask, .irq_mask = idu_irq_mask,
.irq_unmask = idu_irq_unmask, .irq_unmask = idu_irq_unmask,
.irq_enable = idu_irq_enable,
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
.irq_set_affinity = idu_irq_set_affinity, .irq_set_affinity = idu_irq_set_affinity,
#endif #endif
...@@ -243,36 +256,14 @@ static int idu_irq_xlate(struct irq_domain *d, struct device_node *n, ...@@ -243,36 +256,14 @@ static int idu_irq_xlate(struct irq_domain *d, struct device_node *n,
const u32 *intspec, unsigned int intsize, const u32 *intspec, unsigned int intsize,
irq_hw_number_t *out_hwirq, unsigned int *out_type) irq_hw_number_t *out_hwirq, unsigned int *out_type)
{ {
irq_hw_number_t hwirq = *out_hwirq = intspec[0]; /*
int distri = intspec[1]; * Ignore value of interrupt distribution mode for common interrupts in
unsigned long flags; * IDU which resides in intspec[1] since setting an affinity using value
* from Device Tree is deprecated in ARC.
*/
*out_hwirq = intspec[0];
*out_type = IRQ_TYPE_NONE; *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
*/
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);
}
return 0; return 0;
} }
......
...@@ -90,22 +90,37 @@ void __init smp_cpus_done(unsigned int max_cpus) ...@@ -90,22 +90,37 @@ void __init smp_cpus_done(unsigned int max_cpus)
*/ */
static volatile int wake_flag; 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) static void arc_default_smp_cpu_kick(int cpu, unsigned long pc)
{ {
BUG_ON(cpu == 0); BUG_ON(cpu == 0);
wake_flag = cpu;
__boot_write(wake_flag, cpu);
} }
void arc_platform_smp_wait_to_boot(int 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; __boot_write(wake_flag, 0);
__asm__ __volatile__("j @first_lines_of_secondary \n");
} }
const char *arc_platform_smp_cpuinfo(void) const char *arc_platform_smp_cpuinfo(void)
{ {
return plat_smp_ops.info ? : ""; return plat_smp_ops.info ? : "";
......
...@@ -241,8 +241,9 @@ int misaligned_fixup(unsigned long address, struct pt_regs *regs, ...@@ -241,8 +241,9 @@ int misaligned_fixup(unsigned long address, struct pt_regs *regs,
if (state.fault) if (state.fault)
goto fault; goto fault;
/* clear any remanants of delay slot */
if (delay_mode(regs)) { if (delay_mode(regs)) {
regs->ret = regs->bta; regs->ret = regs->bta ~1U;
regs->status32 &= ~STATUS_DE_MASK; regs->status32 &= ~STATUS_DE_MASK;
} else { } else {
regs->ret += state.instr_len; regs->ret += state.instr_len;
......
...@@ -55,17 +55,17 @@ struct mcip_cmd { ...@@ -55,17 +55,17 @@ struct mcip_cmd {
struct mcip_bcr { struct mcip_bcr {
#ifdef CONFIG_CPU_BIG_ENDIAN #ifdef CONFIG_CPU_BIG_ENDIAN
unsigned int pad3:8, unsigned int pad4:6, pw_dom:1, pad3:1,
idu:1, llm:1, num_cores:6, idu:1, pad2:1, num_cores:6,
iocoh:1, gfrc:1, dbg:1, pad2:1, pad:1, gfrc:1, dbg:1, pw:1,
msg:1, sem:1, ipi:1, pad:1, msg:1, sem:1, ipi:1, slv:1,
ver:8; ver:8;
#else #else
unsigned int ver:8, unsigned int ver:8,
pad:1, ipi:1, sem:1, msg:1, slv:1, ipi:1, sem:1, msg:1,
pad2:1, dbg:1, gfrc:1, iocoh:1, pw:1, dbg:1, gfrc:1, pad:1,
num_cores:6, llm:1, idu:1, num_cores:6, pad2:1, idu:1,
pad3:8; pad3:1, pw_dom:1, pad4:6;
#endif #endif
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment