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 /include | |
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>
Diffstat (limited to 'include')
-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__ */ |