mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 05:02:12 +00:00
[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>
This commit is contained in:
parent
853265e588
commit
e8318d98e9
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user