diff options
author | Valentine Barshak <vbarshak@ru.mvista.com> | 2008-02-06 05:36:49 +1100 |
---|---|---|
committer | Josh Boyer <jwboyer@linux.vnet.ibm.com> | 2008-02-06 21:02:57 -0600 |
commit | e8318d98e95ddd3969c0701b5d15ec961ce786b2 (patch) | |
tree | f395df1ecab6962ece80b9082d0b953e55c9273a /include/asm-powerpc | |
parent | 853265e588153dca22c82b84df39bbb40abd7ad0 (diff) | |
download | linux-e8318d98e95ddd3969c0701b5d15ec961ce786b2.tar.gz linux-e8318d98e95ddd3969c0701b5d15ec961ce786b2.tar.bz2 linux-e8318d98e95ddd3969c0701b5d15ec961ce786b2.zip |
[POWERPC] 4xx: PCIe indirect DCR spinlock fix.
Since we have mfdcri() and mtdcri() as macros, we can't use constructions,
such as "mtdcri(base, reg, mfdcri(base, reg) | val)". In this case the
mfdcri() stuff is not evaluated first. It's evaluated inside the mtdcri()
macro and we have the dcr_ind_lock spinlock acquired twice.
To avoid this error, I've added __mfdcri()/__mtdcri() inline functions that
take the lock after register name fix-up.
Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Diffstat (limited to 'include/asm-powerpc')
-rw-r--r-- | include/asm-powerpc/dcr-native.h | 47 |
1 files changed, 29 insertions, 18 deletions
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h index af5fb31af559..be6c879e8760 100644 --- a/include/asm-powerpc/dcr-native.h +++ b/include/asm-powerpc/dcr-native.h @@ -59,25 +59,36 @@ do { \ /* R/W of indirect DCRs make use of standard naming conventions for DCRs */ extern spinlock_t dcr_ind_lock; -#define mfdcri(base, reg) \ -({ \ - unsigned long flags; \ - unsigned int val; \ - spin_lock_irqsave(&dcr_ind_lock, flags); \ - mtdcr(DCRN_ ## base ## _CONFIG_ADDR, reg); \ - val = mfdcr(DCRN_ ## base ## _CONFIG_DATA); \ - spin_unlock_irqrestore(&dcr_ind_lock, flags); \ - val; \ -}) +static inline unsigned __mfdcri(int base_addr, int base_data, int reg) +{ + unsigned long flags; + unsigned int val; -#define mtdcri(base, reg, data) \ -do { \ - unsigned long flags; \ - spin_lock_irqsave(&dcr_ind_lock, flags); \ - mtdcr(DCRN_ ## base ## _CONFIG_ADDR, reg); \ - mtdcr(DCRN_ ## base ## _CONFIG_DATA, data); \ - spin_unlock_irqrestore(&dcr_ind_lock, flags); \ -} while (0) + spin_lock_irqsave(&dcr_ind_lock, flags); + __mtdcr(base_addr, reg); + val = __mfdcr(base_data); + spin_unlock_irqrestore(&dcr_ind_lock, flags); + return val; +} + +static inline void __mtdcri(int base_addr, int base_data, int reg, + unsigned val) +{ + unsigned long flags; + + spin_lock_irqsave(&dcr_ind_lock, flags); + __mtdcr(base_addr, reg); + __mtdcr(base_data, val); + spin_unlock_irqrestore(&dcr_ind_lock, flags); +} + +#define mfdcri(base, reg) __mfdcri(DCRN_ ## base ## _CONFIG_ADDR, \ + DCRN_ ## base ## _CONFIG_DATA, \ + reg) + +#define mtdcri(base, reg, data) __mtdcri(DCRN_ ## base ## _CONFIG_ADDR, \ + DCRN_ ## base ## _CONFIG_DATA, \ + reg, data) #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ |