linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [RFC][PATCH] PowerPC: 4xx PCIe indirect DCR spinlock fix.
@ 2008-02-04 18:27 Valentine Barshak
  2008-02-04 20:50 ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 4+ messages in thread
From: Valentine Barshak @ 2008-02-04 18:27 UTC (permalink / raw)
  To: linuxppc-dev

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 <vbarshak@ru.mvista.com>
---
 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 */

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC][PATCH] PowerPC: 4xx PCIe indirect DCR spinlock fix.
  2008-02-04 18:27 [RFC][PATCH] PowerPC: 4xx PCIe indirect DCR spinlock fix Valentine Barshak
@ 2008-02-04 20:50 ` Benjamin Herrenschmidt
  2008-02-05 18:36   ` Valentine Barshak
  0 siblings, 1 reply; 4+ messages in thread
From: Benjamin Herrenschmidt @ 2008-02-04 20:50 UTC (permalink / raw)
  To: Valentine Barshak; +Cc: linuxppc-dev


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 <vbarshak@ru.mvista.com>

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 */

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC][PATCH] PowerPC: 4xx PCIe indirect DCR spinlock fix.
  2008-02-04 20:50 ` Benjamin Herrenschmidt
@ 2008-02-05 18:36   ` Valentine Barshak
  2008-02-05 20:47     ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 4+ messages in thread
From: Valentine Barshak @ 2008-02-05 18:36 UTC (permalink / raw)
  To: linuxppc-dev

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>
---
 include/asm-powerpc/dcr-native.h |   49 +++++++++++++++++++++++----------------
 1 files changed, 30 insertions(+), 19 deletions(-)

diff -pruN linux-2.6.orig/include/asm-powerpc/dcr-native.h linux-2.6.bld/include/asm-powerpc/dcr-native.h
--- linux-2.6.orig/include/asm-powerpc/dcr-native.h	2008-02-05 16:44:54.000000000 +0300
+++ linux-2.6.bld/include/asm-powerpc/dcr-native.h	2008-02-05 19:11:55.000000000 +0300
@@ -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;						\
-})
-
-#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)
+static inline unsigned __mfdcri(int base_addr, int base_data, int reg)
+{
+	unsigned long flags;
+	unsigned int val;
+
+	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__ */

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC][PATCH] PowerPC: 4xx PCIe indirect DCR spinlock fix.
  2008-02-05 18:36   ` Valentine Barshak
@ 2008-02-05 20:47     ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 4+ messages in thread
From: Benjamin Herrenschmidt @ 2008-02-05 20:47 UTC (permalink / raw)
  To: Valentine Barshak; +Cc: linuxppc-dev


On Tue, 2008-02-05 at 21:36 +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 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>

> ---
>  include/asm-powerpc/dcr-native.h |   49 +++++++++++++++++++++++----------------
>  1 files changed, 30 insertions(+), 19 deletions(-)
> 
> diff -pruN linux-2.6.orig/include/asm-powerpc/dcr-native.h linux-2.6.bld/include/asm-powerpc/dcr-native.h
> --- linux-2.6.orig/include/asm-powerpc/dcr-native.h	2008-02-05 16:44:54.000000000 +0300
> +++ linux-2.6.bld/include/asm-powerpc/dcr-native.h	2008-02-05 19:11:55.000000000 +0300
> @@ -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;						\
> -})
> -
> -#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)
> +static inline unsigned __mfdcri(int base_addr, int base_data, int reg)
> +{
> +	unsigned long flags;
> +	unsigned int val;
> +
> +	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__ */

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-02-05 20:48 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-04 18:27 [RFC][PATCH] PowerPC: 4xx PCIe indirect DCR spinlock fix Valentine Barshak
2008-02-04 20:50 ` Benjamin Herrenschmidt
2008-02-05 18:36   ` Valentine Barshak
2008-02-05 20:47     ` Benjamin Herrenschmidt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).