Pull sparc fixes from David Miller: 1) Fix NULL oops in Schizo PCI controller error handler. 2) Fix race between xchg and other operations on 32-bit sparc, from Andreas Larsson. 3) swab*() helpers need a dummy memory input operand to show data flow on 64-bit sparc. 4) Fix RCU warnings due to missing irq_{enter,exit}() around generic_smp_call_function*() calls. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc: sparc64: Fix constraints on swab helpers. sparc32: Implement xchg and atomic_xchg using ATOMIC_HASH locks sparc64: Do irq_{enter,exit}() around generic_smp_call_function*(). sparc64: Fix crashes in schizo_pcierr_intr_other().
Unified · Split
| @@ -22,7 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | int atomic_add_return(int, atomic_t *); |
| 24 | 24 | int atomic_cmpxchg(atomic_t *, int, int); |
| 25 | −#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) | |
| 25 | +int atomic_xchg(atomic_t *, int); | |
| 26 | 26 | int __atomic_add_unless(atomic_t *, int, int); |
| 27 | 27 | void atomic_set(atomic_t *, int); |
| 28 | 28 | |
| @@ -11,22 +11,14 @@ · 10 unmodified lines | ||
| 11 | 11 | #ifndef __ARCH_SPARC_CMPXCHG__ |
| 12 | 12 | #define __ARCH_SPARC_CMPXCHG__ |
| 13 | 13 | |
| 14 | −static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val) | |
| 15 | −{ | |
| 16 | − __asm__ __volatile__("swap [%2], %0" | |
| 17 | − : "=&r" (val) | |
| 18 | − : "0" (val), "r" (m) | |
| 19 | − : "memory"); | |
| 20 | − return val; | |
| 21 | −} | |
| 22 | − | |
| 14 | +unsigned long __xchg_u32(volatile u32 *m, u32 new); | |
| 23 | 15 | void __xchg_called_with_bad_pointer(void); |
| 24 | 16 | |
| 25 | 17 | static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size) |
| 26 | 18 | { |
| 27 | 19 | switch (size) { |
| 28 | 20 | case 4: |
| 29 | − return xchg_u32(ptr, x); | |
| 21 | + return __xchg_u32(ptr, x); | |
| 30 | 22 | } |
| 31 | 23 | __xchg_called_with_bad_pointer(); |
| 32 | 24 | return x; |
| @@ -9,9 +9,9 @@ static inline __u16 __arch_swab16p(const __u16 *addr) · 8 unmodified lines | ||
| 9 | 9 | { |
| 10 | 10 | __u16 ret; |
| 11 | 11 | |
| 12 | − __asm__ __volatile__ ("lduha [%1] %2, %0" | |
| 12 | + __asm__ __volatile__ ("lduha [%2] %3, %0" | |
| 13 | 13 | : "=r" (ret) |
| 14 | − : "r" (addr), "i" (ASI_PL)); | |
| 14 | + : "m" (*addr), "r" (addr), "i" (ASI_PL)); | |
| 15 | 15 | return ret; |
| 16 | 16 | } |
| 17 | 17 | #define __arch_swab16p __arch_swab16p |
| @@ -20,9 +20,9 @@ static inline __u32 __arch_swab32p(const __u32 *addr) · 2 unmodified lines | ||
| 20 | 20 | { |
| 21 | 21 | __u32 ret; |
| 22 | 22 | |
| 23 | − __asm__ __volatile__ ("lduwa [%1] %2, %0" | |
| 23 | + __asm__ __volatile__ ("lduwa [%2] %3, %0" | |
| 24 | 24 | : "=r" (ret) |
| 25 | − : "r" (addr), "i" (ASI_PL)); | |
| 25 | + : "m" (*addr), "r" (addr), "i" (ASI_PL)); | |
| 26 | 26 | return ret; |
| 27 | 27 | } |
| 28 | 28 | #define __arch_swab32p __arch_swab32p |
| @@ -31,9 +31,9 @@ static inline __u64 __arch_swab64p(const __u64 *addr) · 2 unmodified lines | ||
| 31 | 31 | { |
| 32 | 32 | __u64 ret; |
| 33 | 33 | |
| 34 | − __asm__ __volatile__ ("ldxa [%1] %2, %0" | |
| 34 | + __asm__ __volatile__ ("ldxa [%2] %3, %0" | |
| 35 | 35 | : "=r" (ret) |
| 36 | − : "r" (addr), "i" (ASI_PL)); | |
| 36 | + : "m" (*addr), "r" (addr), "i" (ASI_PL)); | |
| 37 | 37 | return ret; |
| 38 | 38 | } |
| 39 | 39 | #define __arch_swab64p __arch_swab64p |
| @@ -581,7 +581,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) · 580 unmodified lines | ||
| 581 | 581 | { |
| 582 | 582 | unsigned long csr_reg, csr, csr_error_bits; |
| 583 | 583 | irqreturn_t ret = IRQ_NONE; |
| 584 | − u16 stat; | |
| 584 | + u32 stat; | |
| 585 | 585 | |
| 586 | 586 | csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL; |
| 587 | 587 | csr = upa_readq(csr_reg); |
| @@ -617,7 +617,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) · 29 unmodified lines | ||
| 617 | 617 | pbm->name); |
| 618 | 618 | ret = IRQ_HANDLED; |
| 619 | 619 | } |
| 620 | − pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); | |
| 620 | + pbm->pci_ops->read(pbm->pci_bus, 0, PCI_STATUS, 2, &stat); | |
| 621 | 621 | if (stat & (PCI_STATUS_PARITY | |
| 622 | 622 | PCI_STATUS_SIG_TARGET_ABORT | |
| 623 | 623 | PCI_STATUS_REC_TARGET_ABORT | |
| @@ -625,7 +625,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) · 1 unmodified line | ||
| 625 | 625 | PCI_STATUS_SIG_SYSTEM_ERROR)) { |
| 626 | 626 | printk("%s: PCI bus error, PCI_STATUS[%04x]\n", |
| 627 | 627 | pbm->name, stat); |
| 628 | − pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); | |
| 628 | + pbm->pci_ops->write(pbm->pci_bus, 0, PCI_STATUS, 2, 0xffff); | |
| 629 | 629 | ret = IRQ_HANDLED; |
| 630 | 630 | } |
| 631 | 631 | return ret; |
| @@ -816,13 +816,17 @@ void arch_send_call_function_single_ipi(int cpu) · 815 unmodified lines | ||
| 816 | 816 | void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs) |
| 817 | 817 | { |
| 818 | 818 | clear_softint(1 << irq); |
| 819 | + irq_enter(); | |
| 819 | 820 | generic_smp_call_function_interrupt(); |
| 821 | + irq_exit(); | |
| 820 | 822 | } |
| 821 | 823 | |
| 822 | 824 | void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs) |
| 823 | 825 | { |
| 824 | 826 | clear_softint(1 << irq); |
| 827 | + irq_enter(); | |
| 825 | 828 | generic_smp_call_function_single_interrupt(); |
| 829 | + irq_exit(); | |
| 826 | 830 | } |
| 827 | 831 | |
| 828 | 832 | static void tsb_sync(void *info) |
| @@ -45,6 +45,19 @@ ATOMIC_OP(add, +=) · 44 unmodified lines | ||
| 45 | 45 | |
| 46 | 46 | #undef ATOMIC_OP |
| 47 | 47 | |
| 48 | +int atomic_xchg(atomic_t *v, int new) | |
| 49 | +{ | |
| 50 | + int ret; | |
| 51 | + unsigned long flags; | |
| 52 | + | |
| 53 | + spin_lock_irqsave(ATOMIC_HASH(v), flags); | |
| 54 | + ret = v->counter; | |
| 55 | + v->counter = new; | |
| 56 | + spin_unlock_irqrestore(ATOMIC_HASH(v), flags); | |
| 57 | + return ret; | |
| 58 | +} | |
| 59 | +EXPORT_SYMBOL(atomic_xchg); | |
| 60 | + | |
| 48 | 61 | int atomic_cmpxchg(atomic_t *v, int old, int new) |
| 49 | 62 | { |
| 50 | 63 | int ret; |
| @@ -137,3 +150,17 @@ unsigned long __cmpxchg_u32(volatile u32 *ptr, u32 old, u32 new) · 86 unmodified lines | ||
| 137 | 150 | return (unsigned long)prev; |
| 138 | 151 | } |
| 139 | 152 | EXPORT_SYMBOL(__cmpxchg_u32); |
| 153 | + | |
| 154 | +unsigned long __xchg_u32(volatile u32 *ptr, u32 new) | |
| 155 | +{ | |
| 156 | + unsigned long flags; | |
| 157 | + u32 prev; | |
| 158 | + | |
| 159 | + spin_lock_irqsave(ATOMIC_HASH(ptr), flags); | |
| 160 | + prev = *ptr; | |
| 161 | + *ptr = new; | |
| 162 | + spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags); | |
| 163 | + | |
| 164 | + return (unsigned long)prev; | |
| 165 | +} | |
| 166 | +EXPORT_SYMBOL(__xchg_u32); | |