提交 6000fc4d 编写于 作者: S Stuart Menefy 提交者: Paul Mundt

sh: Fixes some write posting issues in the interrupt handling for SH

It is possible for the CPU to re-enable it's interrupt block bit
before the write to the interrupt controller has actually masked out
the external interupt at the controller. We get around this by
reading back from the interrupt controller which will ensure the
write has happened.
Signed-off-by: NStuart Menefy <stuart.menefy@st.com>
Signed-off-by: NPaul Mundt <lethal@linux-sh.org>
上级 bd4fb4d4
...@@ -35,6 +35,7 @@ static void disable_ipr_irq(unsigned int irq) ...@@ -35,6 +35,7 @@ static void disable_ipr_irq(unsigned int irq)
unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx]; unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
/* Set the priority in IPR to 0 */ /* Set the priority in IPR to 0 */
__raw_writew(__raw_readw(addr) & (0xffff ^ (0xf << p->shift)), addr); __raw_writew(__raw_readw(addr) & (0xffff ^ (0xf << p->shift)), addr);
(void)__raw_readw(addr); /* Read back to flush write posting */
} }
static void enable_ipr_irq(unsigned int irq) static void enable_ipr_irq(unsigned int irq)
......
...@@ -77,7 +77,7 @@ static unsigned long ack_handle[NR_IRQS]; ...@@ -77,7 +77,7 @@ static unsigned long ack_handle[NR_IRQS];
static inline struct intc_desc_int *get_intc_desc(unsigned int irq) static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
{ {
struct irq_chip *chip = get_irq_chip(irq); struct irq_chip *chip = get_irq_chip(irq);
return (void *)((char *)chip - offsetof(struct intc_desc_int, chip)); return container_of(chip, struct intc_desc_int, chip);
} }
static inline unsigned int set_field(unsigned int value, static inline unsigned int set_field(unsigned int value,
...@@ -95,16 +95,19 @@ static inline unsigned int set_field(unsigned int value, ...@@ -95,16 +95,19 @@ static inline unsigned int set_field(unsigned int value,
static void write_8(unsigned long addr, unsigned long h, unsigned long data) static void write_8(unsigned long addr, unsigned long h, unsigned long data)
{ {
__raw_writeb(set_field(0, data, h), addr); __raw_writeb(set_field(0, data, h), addr);
(void)__raw_readb(addr); /* Defeat write posting */
} }
static void write_16(unsigned long addr, unsigned long h, unsigned long data) static void write_16(unsigned long addr, unsigned long h, unsigned long data)
{ {
__raw_writew(set_field(0, data, h), addr); __raw_writew(set_field(0, data, h), addr);
(void)__raw_readw(addr); /* Defeat write posting */
} }
static void write_32(unsigned long addr, unsigned long h, unsigned long data) static void write_32(unsigned long addr, unsigned long h, unsigned long data)
{ {
__raw_writel(set_field(0, data, h), addr); __raw_writel(set_field(0, data, h), addr);
(void)__raw_readl(addr); /* Defeat write posting */
} }
static void modify_8(unsigned long addr, unsigned long h, unsigned long data) static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
...@@ -112,6 +115,7 @@ static void modify_8(unsigned long addr, unsigned long h, unsigned long data) ...@@ -112,6 +115,7 @@ static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
__raw_writeb(set_field(__raw_readb(addr), data, h), addr); __raw_writeb(set_field(__raw_readb(addr), data, h), addr);
(void)__raw_readb(addr); /* Defeat write posting */
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -120,6 +124,7 @@ static void modify_16(unsigned long addr, unsigned long h, unsigned long data) ...@@ -120,6 +124,7 @@ static void modify_16(unsigned long addr, unsigned long h, unsigned long data)
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
__raw_writew(set_field(__raw_readw(addr), data, h), addr); __raw_writew(set_field(__raw_readw(addr), data, h), addr);
(void)__raw_readw(addr); /* Defeat write posting */
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -128,6 +133,7 @@ static void modify_32(unsigned long addr, unsigned long h, unsigned long data) ...@@ -128,6 +133,7 @@ static void modify_32(unsigned long addr, unsigned long h, unsigned long data)
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
__raw_writel(set_field(__raw_readl(addr), data, h), addr); __raw_writel(set_field(__raw_readl(addr), data, h), addr);
(void)__raw_readl(addr); /* Defeat write posting */
local_irq_restore(flags); local_irq_restore(flags);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册