ARC fixes for 4.10-rc6
- 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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJYi8faAAoJEGnX8d3iisJeU5wP/A1OM9S6TOCe4Ikguhp8UDgS UaGXboVpAAJNr6B+NfzvUbxi3VybgqooRM6tEU33A4eDzmfCTKBxMbvvE77rOuPC CC/8wxQ87wDqU+6GGL5DoTTc4rrxnNoEK6MOh2/Rv76idEi8Z2eo4INfm6FkBjGY +2WkuSpegBIxKrvFmBK9JC7cYaR3KBGSxW3rjLaK6xn0yt+LT1LQKJ/4OFLke7zy HWNVVnXnyJhn6z7v+Bum3hjnA8bhnDEVKAM0XgD/8TtjkhS6aod4HS2mjvcKnGc/ vyAk3B4fgq0EKFXX0IyHNnWI92gCnACWs8sHAQ/UBB4GHf0z1ScoihJeE4VAqRS4 kJ6SKAIHEtwY1nQV5GgVE2ddMgTDEXwAKCna99ejoUMMmQZFaRy80YuuSMLIjEuz H16oPkSzJDsR6Z9ocoC5mATWnHxsFZsCAX72u88X+ylaJmBziF2VmjaKRIXB8Psn YVz02U1YlONJTesEI7lnLD3fwx6pzu/XJjNTe4saiJFAoxaGuPbjRg6sJq3URDj6 3CJ89OFRbgx78jbk7QpYlc6m9SdTM2F5T7ICi6yxElok1dn+i+UQhnBXCinIvTcL 5w9IKA/9qeqjyT76vy1cPY2KlSDGj0kqjI+63IzpGtTScRuyflA5S1CvqyNeUbQq Vrtw/IRz5pvS7iaCDwuc =u+Jp -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
ef1dce990b
@ -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)
|
|||||||
" 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
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 {
|
|||||||
|
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user