Skip to content

Commit

Permalink
[POWERPC] 4xx: PCIe indirect DCR spinlock fix.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Valentine Barshak authored and Josh Boyer committed Feb 7, 2008
1 parent 853265e commit e8318d9
Showing 1 changed file with 29 additions and 18 deletions.
47 changes: 29 additions & 18 deletions include/asm-powerpc/dcr-native.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
Expand Down

0 comments on commit e8318d9

Please sign in to comment.