diff options
| author | Valentine Barshak <vbarshak@ru.mvista.com> | 2008-02-05 13:36:49 -0500 |
|---|---|---|
| committer | Josh Boyer <jwboyer@linux.vnet.ibm.com> | 2008-02-06 22:02:57 -0500 |
| commit | e8318d98e95ddd3969c0701b5d15ec961ce786b2 (patch) | |
| tree | f395df1ecab6962ece80b9082d0b953e55c9273a | |
| parent | 853265e588153dca22c82b84df39bbb40abd7ad0 (diff) | |
[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>
| -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 { \ | |||
| 59 | /* R/W of indirect DCRs make use of standard naming conventions for DCRs */ | 59 | /* R/W of indirect DCRs make use of standard naming conventions for DCRs */ |
| 60 | extern spinlock_t dcr_ind_lock; | 60 | extern spinlock_t dcr_ind_lock; |
| 61 | 61 | ||
| 62 | #define mfdcri(base, reg) \ | 62 | static inline unsigned __mfdcri(int base_addr, int base_data, int reg) |
| 63 | ({ \ | 63 | { |
| 64 | unsigned long flags; \ | 64 | unsigned long flags; |
| 65 | unsigned int val; \ | 65 | unsigned int val; |
| 66 | spin_lock_irqsave(&dcr_ind_lock, flags); \ | ||
| 67 | mtdcr(DCRN_ ## base ## _CONFIG_ADDR, reg); \ | ||
| 68 | val = mfdcr(DCRN_ ## base ## _CONFIG_DATA); \ | ||
| 69 | spin_unlock_irqrestore(&dcr_ind_lock, flags); \ | ||
| 70 | val; \ | ||
| 71 | }) | ||
| 72 | 66 | ||
| 73 | #define mtdcri(base, reg, data) \ | 67 | spin_lock_irqsave(&dcr_ind_lock, flags); |
| 74 | do { \ | 68 | __mtdcr(base_addr, reg); |
| 75 | unsigned long flags; \ | 69 | val = __mfdcr(base_data); |
| 76 | spin_lock_irqsave(&dcr_ind_lock, flags); \ | 70 | spin_unlock_irqrestore(&dcr_ind_lock, flags); |
| 77 | mtdcr(DCRN_ ## base ## _CONFIG_ADDR, reg); \ | 71 | return val; |
| 78 | mtdcr(DCRN_ ## base ## _CONFIG_DATA, data); \ | 72 | } |
| 79 | spin_unlock_irqrestore(&dcr_ind_lock, flags); \ | 73 | |
| 80 | } while (0) | 74 | static inline void __mtdcri(int base_addr, int base_data, int reg, |
| 75 | unsigned val) | ||
| 76 | { | ||
| 77 | unsigned long flags; | ||
| 78 | |||
| 79 | spin_lock_irqsave(&dcr_ind_lock, flags); | ||
| 80 | __mtdcr(base_addr, reg); | ||
| 81 | __mtdcr(base_data, val); | ||
| 82 | spin_unlock_irqrestore(&dcr_ind_lock, flags); | ||
| 83 | } | ||
| 84 | |||
| 85 | #define mfdcri(base, reg) __mfdcri(DCRN_ ## base ## _CONFIG_ADDR, \ | ||
| 86 | DCRN_ ## base ## _CONFIG_DATA, \ | ||
| 87 | reg) | ||
| 88 | |||
| 89 | #define mtdcri(base, reg, data) __mtdcri(DCRN_ ## base ## _CONFIG_ADDR, \ | ||
| 90 | DCRN_ ## base ## _CONFIG_DATA, \ | ||
| 91 | reg, data) | ||
| 81 | 92 | ||
| 82 | #endif /* __ASSEMBLY__ */ | 93 | #endif /* __ASSEMBLY__ */ |
| 83 | #endif /* __KERNEL__ */ | 94 | #endif /* __KERNEL__ */ |
