On Mon, 2008-02-04 at 21:27 +0300, Valentine Barshak wrote: > 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 mtdcr() macro and we have > the dcr_ind_lock spinlock acquired twice. To avoid this error, I've added > set_dcri() and clr_dcri() macros which set/clear the specified bits. > > Signed-off-by: Valentine Barshak <[EMAIL PROTECTED]>
No, better is to fix the macros to use functions. Make mfdcri/mtdcri call into __mfdcri/__mtdcri functions after fixing up the macro register names, and have those be inlines that take the lock. Ben. > arch/powerpc/sysdev/ppc4xx_pci.c | 13 +++++-------- > include/asm-powerpc/dcr-native.h | 22 ++++++++++++++++++++++ > 2 files changed, 27 insertions(+), 8 deletions(-) > > diff -pruN linux-2.6.orig/arch/powerpc/sysdev/ppc4xx_pci.c > linux-2.6/arch/powerpc/sysdev/ppc4xx_pci.c > --- linux-2.6.orig/arch/powerpc/sysdev/ppc4xx_pci.c 2008-02-04 > 20:05:37.000000000 +0300 > +++ linux-2.6/arch/powerpc/sysdev/ppc4xx_pci.c 2008-02-04 > 20:16:33.000000000 +0300 > @@ -645,7 +645,7 @@ static int __init ppc440spe_pciex_core_i > int time_out = 20; > > /* Set PLL clock receiver to LVPECL */ > - mtdcri(SDR0, PESDR0_PLLLCT1, mfdcri(SDR0, PESDR0_PLLLCT1) | 1 << 28); > + set_dcri(SDR0, PESDR0_PLLLCT1, 1 << 28); > > /* Shouldn't we do all the calibration stuff etc... here ? */ > if (ppc440spe_pciex_check_reset(np)) > @@ -659,8 +659,7 @@ static int __init ppc440spe_pciex_core_i > } > > /* De-assert reset of PCIe PLL, wait for lock */ > - mtdcri(SDR0, PESDR0_PLLLCT1, > - mfdcri(SDR0, PESDR0_PLLLCT1) & ~(1 << 24)); > + clr_dcri(SDR0, PESDR0_PLLLCT1, 1 << 24); > udelay(3); > > while (time_out) { > @@ -712,9 +711,8 @@ static int ppc440spe_pciex_init_port_hw( > mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL7SET1, > 0x35000000); > } > - val = mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET); > - mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, > - (val & ~(1 << 24 | 1 << 16)) | 1 << 12); > + clr_dcri(SDR0, port->sdr_base + PESDRn_RCSSET, 1 << 24 | 1 << 16) > + set_dcri(SDR0, port->sdr_base + PESDRn_RCSSET, 1 << 12); > > return 0; > } > @@ -1042,8 +1040,7 @@ static int __init ppc4xx_pciex_port_init > port->link = 0; > } > > - mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, > - mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) | 1 << 20); > + set_dcri(SDR0, port->sdr_base + PESDRn_RCSSET, 1 << 20); > msleep(100); > > return 0; > diff -pruN linux-2.6.orig/include/asm-powerpc/dcr-native.h > linux-2.6/include/asm-powerpc/dcr-native.h > --- linux-2.6.orig/include/asm-powerpc/dcr-native.h 2008-02-04 > 20:06:34.000000000 +0300 > +++ linux-2.6/include/asm-powerpc/dcr-native.h 2008-02-04 > 20:16:33.000000000 +0300 > @@ -79,6 +79,28 @@ do { > \ > spin_unlock_irqrestore(&dcr_ind_lock, flags); \ > } while (0) > > +#define set_dcri(base, reg, data) \ > +do { \ > + 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); \ > + mtdcr(DCRN_ ## base ## _CONFIG_DATA, val | (data)); \ > + spin_unlock_irqrestore(&dcr_ind_lock, flags); \ > +} while (0) > + > +#define clr_dcri(base, reg, data) \ > +do { \ > + 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); \ > + mtdcr(DCRN_ ## base ## _CONFIG_DATA, val & ~(data)); \ > + spin_unlock_irqrestore(&dcr_ind_lock, flags); \ > +} while (0) > + > #endif /* __ASSEMBLY__ */ > #endif /* __KERNEL__ */ > #endif /* _ASM_POWERPC_DCR_NATIVE_H */ _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev