From: David Eger <eger@havoc.gtf.org>
To: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Linus Torvalds <torvalds@osdl.org>, Andrew Morton <akpm@osdl.org>,
Linux Fbdev development list
<linux-fbdev-devel@lists.sourceforge.net>
Subject: Re: [PATCH] radeonfb: remove reg_lock nonsense
Date: Wed, 7 Jul 2004 03:24:41 -0400 [thread overview]
Message-ID: <20040707072441.GA13160@havoc.gtf.org> (raw)
In-Reply-To: <1089115727.1899.27.camel@gaston>
On Tue, Jul 06, 2004 at 07:08:47AM -0500, Benjamin Herrenschmidt wrote:
>
> > I agree, the patch is horrid. In fact, now that I really look at it,
> > it seems that the spinlock is totally bogus. This patch removes it.
> > Details below.
> >
> > BenH: thoughts, objections?
>
> The lock is meant to keep writes to the PLL index register followed
> with a read/write of the PLL data register together. It is necessay
> for OUTPLL/INPLL as long as radeonfb can be re-entered.
Hmmm :-/
In that case, I have a patch which implements both of Linus's suggestions,
making OUTPLL()/INPLL() inlines and making the caller responsible for
taking the register lock when calling OUTPLL()/INPLL().
On the upside, the number of lockings goes down from 159 to 24.
On the downside, that means about 70 more lines of code via:
from 48 spin lock & unlock lines and 17 'flags' decls
I'll leave it up to your discretion whether to apply.
-dte
radeonfb: make the PLL locking the responsibility of the caller,
so as to avoid grabbing rinfo->reg_lock 100 times during
a sequence of OUTPLL()'s
Signed-off-by: David Eger <eger@havoc.gtf.org>
diff -Nru a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c
--- a/drivers/video/aty/radeon_accel.c 2004-07-07 09:11:50 +02:00
+++ b/drivers/video/aty/radeon_accel.c 2004-07-07 09:11:50 +02:00
@@ -147,6 +147,7 @@
{
u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
u32 host_path_cntl;
+ unsigned long flags;
radeon_engine_flush (rinfo);
@@ -156,6 +157,7 @@
* We don't do that on macs, things just work here with dynamic
* clocking... --BenH
*/
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
#ifdef CONFIG_ALL_PPC
if (_machine != _MACH_Pmac && rinfo->hasCRTC2)
#else
@@ -237,6 +239,7 @@
OUTPLL(MCLK_CNTL, mclk_cntl);
if (rinfo->R300_cg_workaround)
R300_cg_workardound(rinfo);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
void radeonfb_engine_init (struct radeonfb_info *rinfo)
diff -Nru a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
--- a/drivers/video/aty/radeon_base.c 2004-07-07 09:11:50 +02:00
+++ b/drivers/video/aty/radeon_base.c 2004-07-07 09:11:50 +02:00
@@ -466,6 +466,7 @@
struct timeval start_tv, stop_tv;
long total_secs, total_usecs;
int i;
+ unsigned long flags;
/* Ugh, we cut interrupts, bad bad bad, but we want some precision
* here, so... --BenH
@@ -507,6 +508,7 @@
vTotal = ((INREG(CRTC_V_TOTAL_DISP) & 0x3ff) + 1);
vclk = (long long)hTotal * (long long)vTotal * hz;
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
switch((INPLL(PPLL_REF_DIV) & 0x30000) >> 16) {
case 0:
default:
@@ -574,6 +576,7 @@
tmp = INPLL(X_MPLL_REF_FB_DIV);
ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
Ns = (tmp & 0xff0000) >> 16;
Nm = (tmp & 0xff00) >> 8;
@@ -595,13 +598,17 @@
*/
static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
{
+ unsigned long flags;
+
#ifdef CONFIG_PPC_OF
/*
* Retreive PLL infos from Open Firmware first
*/
if (!force_measure_pll && radeon_read_xtal_OF(rinfo) == 0) {
printk(KERN_INFO "radeonfb: Retreived PLL infos from Open Firmware\n");
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
/* FIXME: Max clock may be higher on newer chips */
rinfo->pll.ppll_min = 12000;
rinfo->pll.ppll_max = 35000;
@@ -695,7 +702,9 @@
rinfo->pll.ref_clk = 2700;
break;
}
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
printk(KERN_INFO "radeonfb: Used default PLL infos\n");
@@ -1004,6 +1013,7 @@
struct radeonfb_info *rinfo = info->par;
u32 pindex;
unsigned int i;
+ unsigned long flags;
if (regno > 255)
return 1;
@@ -1023,8 +1033,10 @@
radeon_fifo_wait(9);
if (rinfo->is_mobility) {
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
vclk_cntl = INPLL(VCLK_ECP_CNTL);
OUTPLL(VCLK_ECP_CNTL, vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
/* Make sure we are on first palette */
@@ -1055,8 +1067,11 @@
OUTREG(PALETTE_INDEX, pindex);
OUTREG(PALETTE_DATA, (red << 16) | (green << 8) | blue);
}
- if (rinfo->is_mobility)
+ if (rinfo->is_mobility) {
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+ }
}
if (regno < 16) {
u32 *pal = info->pseudo_palette;
@@ -1082,6 +1097,7 @@
static void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save)
{
+ unsigned long flags;
/* CRTC regs */
save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
save->crtc_ext_cntl = INREG(CRTC_EXT_CNTL);
@@ -1105,13 +1121,18 @@
save->lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
save->lvds_pll_cntl = INREG(LVDS_PLL_CNTL);
save->tmds_crc = INREG(TMDS_CRC); save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL);
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
{
int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
radeon_fifo_wait(20);
@@ -1192,6 +1213,7 @@
/* Switch back VCLK source to PPLL */
OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
/*
@@ -1199,8 +1221,10 @@
*/
static void radeon_lvds_timer_func(unsigned long data)
{
+ unsigned long flags;
struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
radeon_fifo_wait(3);
OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl);
@@ -1208,6 +1232,7 @@
OUTPLL(PIXCLKS_CNTL, rinfo->pending_pixclks_cntl);
rinfo->pending_pixclks_cntl = 0;
}
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
/*
@@ -1219,6 +1244,7 @@
{
int i;
int primary_mon = PRIMARY_MONITOR(rinfo);
+ unsigned long flags;
if (nomodeset)
return;
@@ -1279,9 +1305,11 @@
(mode->lvds_gen_cntl & (LVDS_ON | LVDS_BLON))) {
OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl);
} else {
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
rinfo->pending_pixclks_cntl = INPLL(PIXCLKS_CNTL);
if (rinfo->is_mobility || rinfo->is_IGP)
OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
if (!(tmp & (LVDS_ON | LVDS_BLON)))
OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl | LVDS_BLON);
rinfo->pending_lvds_gen_cntl = mode->lvds_gen_cntl;
@@ -1295,8 +1323,10 @@
radeon_screen_blank(rinfo, VESA_NO_BLANKING);
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
radeon_fifo_wait(2);
OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
return;
}
@@ -1845,12 +1875,17 @@
{
struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
unsigned int lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
- unsigned long tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
+ unsigned long tmpPixclksCntl;
int* conv_table;
+ unsigned long flags;
if (rinfo->mon1_type != MT_LCD)
return 0;
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
+ tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+
/* Pardon me for that hack... maybe some day we can figure
* out in what direction backlight should work on a given
* panel ?
@@ -1889,8 +1924,11 @@
/* Asic bug, when turning off LVDS_ON, we have to make sure
RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
*/
- if (rinfo->is_mobility || rinfo->is_IGP)
+ if (rinfo->is_mobility || rinfo->is_IGP) {
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+ }
lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
lvds_gen_cntl |= (conv_table[0] <<
LVDS_BL_MOD_LEVEL_SHIFT);
@@ -1901,8 +1939,11 @@
}
OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
- if (rinfo->is_mobility || rinfo->is_IGP)
+ if (rinfo->is_mobility || rinfo->is_IGP) {
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+ }
rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
diff -Nru a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
--- a/drivers/video/aty/radeon_monitor.c 2004-07-07 09:11:50 +02:00
+++ b/drivers/video/aty/radeon_monitor.c 2004-07-07 09:11:50 +02:00
@@ -293,7 +293,9 @@
unsigned long ulOrigCRTC_EXT_CNTL;
unsigned long ulData;
unsigned long ulMask;
+ unsigned long flags;
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
ulOrigVCLK_ECP_CNTL = INPLL(VCLK_ECP_CNTL);
ulData = ulOrigVCLK_ECP_CNTL;
@@ -342,6 +344,7 @@
OUTREG(DAC_CNTL, ulOrigDAC_CNTL );
OUTREG(DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL );
OUTREG(CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
return connected ? MT_CRT : MT_NONE;
diff -Nru a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
--- a/drivers/video/aty/radeon_pm.c 2004-07-07 09:11:51 +02:00
+++ b/drivers/video/aty/radeon_pm.c 2004-07-07 09:11:51 +02:00
@@ -38,13 +38,13 @@
void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
{
-
u32 sclk_cntl;
u32 mclk_cntl;
u32 sclk_more_cntl;
u32 vclk_ecp_cntl;
u32 pixclks_cntl;
+ unsigned long flags;
/* Mobility chips only, untested on M9+/M10/11 */
if (!rinfo->is_mobility)
@@ -52,6 +52,7 @@
if (rinfo->family > CHIP_FAMILY_RV250)
return;
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
/* Force Core Clocks */
sclk_cntl = INPLL( pllSCLK_CNTL_M6);
sclk_cntl |= SCLK_CNTL_M6__FORCE_CP|
@@ -106,6 +107,7 @@
MCLK_CNTL_M6__FORCE_YCLKA |
MCLK_CNTL_M6__FORCE_YCLKB );
OUTPLL( pllMCLK_CNTL_M6, mclk_cntl);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
@@ -118,6 +120,7 @@
u32 vclk_ecp_cntl;
u32 mclk_cntl;
u32 mclk_misc;
+ unsigned long flags;
/* Mobility chips only, untested on M9+/M10/11 */
if (!rinfo->is_mobility)
@@ -125,6 +128,7 @@
if (rinfo->family > CHIP_FAMILY_RV250)
return;
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
/* Set Latencies */
clk_pwrmgt_cntl = INPLL( pllCLK_PWRMGT_CNTL_M6);
@@ -202,6 +206,7 @@
MCLK_MISC__IO_MCLK_DYN_ENABLE;
OUTPLL(pllMCLK_MISC, mclk_misc);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
#ifdef CONFIG_PM
@@ -220,6 +225,9 @@
static void radeon_pm_save_regs(struct radeonfb_info *rinfo)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
rinfo->save_regs[0] = INPLL(PLL_PWRMGT_CNTL);
rinfo->save_regs[1] = INPLL(CLK_PWRMGT_CNTL);
rinfo->save_regs[2] = INPLL(MCLK_CNTL);
@@ -256,10 +264,14 @@
rinfo->save_regs[31] = INREG(DISPLAY_BASE_ADDR);
rinfo->save_regs[32] = INREG(MC_AGP_LOCATION);
rinfo->save_regs[33] = INREG(CRTC2_DISPLAY_BASE_ADDR);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
static void radeon_pm_restore_regs(struct radeonfb_info *rinfo)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
OUTPLL(P2PLL_CNTL, rinfo->save_regs[8] & 0xFFFFFFFE); /* First */
OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]);
@@ -301,6 +313,7 @@
OUTREG(GPIO_DVI_DDC, rinfo->save_regs[26]);
OUTREG(GPIO_MONID, rinfo->save_regs[27]);
OUTREG(GPIO_CRT2_DDC, rinfo->save_regs[28]);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
static void radeon_pm_disable_iopad(struct radeonfb_info *rinfo)
@@ -319,27 +332,26 @@
static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo)
{
- /* we use __INPLL and _OUTPLL and do the locking ourselves... */
unsigned long flags;
spin_lock_irqsave(&rinfo->reg_lock, flags);
/* Set v2clk to 65MHz */
- __OUTPLL(pllPIXCLKS_CNTL,
- __INPLL(rinfo, pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK);
+ OUTPLL(pllPIXCLKS_CNTL,
+ INPLL(pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK);
- __OUTPLL(pllP2PLL_REF_DIV, 0x0000000c);
- __OUTPLL(pllP2PLL_CNTL, 0x0000bf00);
- __OUTPLL(pllP2PLL_DIV_0, 0x00020074 | P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_W);
+ OUTPLL(pllP2PLL_REF_DIV, 0x0000000c);
+ OUTPLL(pllP2PLL_CNTL, 0x0000bf00);
+ OUTPLL(pllP2PLL_DIV_0, 0x00020074 | P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_W);
- __OUTPLL(pllP2PLL_CNTL,
- __INPLL(rinfo, pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_SLEEP);
+ OUTPLL(pllP2PLL_CNTL,
+ INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_SLEEP);
mdelay(1);
- __OUTPLL(pllP2PLL_CNTL,
- __INPLL(rinfo, pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_RESET);
+ OUTPLL(pllP2PLL_CNTL,
+ INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_RESET);
mdelay( 1);
- __OUTPLL(pllPIXCLKS_CNTL,
- (__INPLL(rinfo, pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK)
+ OUTPLL(pllPIXCLKS_CNTL,
+ (INPLL(pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK)
| (0x03 << PIXCLKS_CNTL__PIX2CLK_SRC_SEL__SHIFT));
mdelay( 1);
spin_unlock_irqrestore(&rinfo->reg_lock, flags);
@@ -348,18 +360,21 @@
static void radeon_pm_low_current(struct radeonfb_info *rinfo)
{
u32 reg;
+ unsigned long flags;
reg = INREG(BUS_CNTL1);
reg &= ~BUS_CNTL1_MOBILE_PLATFORM_SEL_MASK;
reg |= BUS_CNTL1_AGPCLK_VALID | (1<<BUS_CNTL1_MOBILE_PLATFORM_SEL_SHIFT);
OUTREG(BUS_CNTL1, reg);
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
reg = INPLL(PLL_PWRMGT_CNTL);
reg |= PLL_PWRMGT_CNTL_SPLL_TURNOFF | PLL_PWRMGT_CNTL_PPLL_TURNOFF |
PLL_PWRMGT_CNTL_P2PLL_TURNOFF | PLL_PWRMGT_CNTL_TVPLL_TURNOFF;
reg &= ~PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK;
reg &= ~PLL_PWRMGT_CNTL_MOBILE_SU;
OUTPLL(PLL_PWRMGT_CNTL, reg);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
reg = INREG(TV_DAC_CNTL);
reg &= ~(TV_DAC_CNTL_BGADJ_MASK |TV_DAC_CNTL_DACADJ_MASK);
@@ -397,8 +412,10 @@
u32 pixclks_cntl;
u32 disp_mis_cntl;
u32 disp_pwr_man;
- u32 tmp;
-
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
/* Force Core Clocks */
sclk_cntl = INPLL( pllSCLK_CNTL_M6);
sclk_cntl |= SCLK_CNTL_M6__IDCT_MAX_DYN_STOP_LAT|
@@ -503,9 +520,8 @@
clk_pin_cntl &= ~CLK_PIN_CNTL__ACCESS_REGS_IN_SUSPEND;
- /* because both INPLL and OUTPLL take the same lock, that's why. */
- tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND;
- OUTPLL( pllMCLK_MISC, tmp);
+ OUTPLL( pllMCLK_MISC,
+ INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND);
/* AGP PLL control */
OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID);
@@ -525,9 +541,8 @@
| (0x20<<AGP_CNTL__MAX_IDLE_CLK__SHIFT));
/* ACPI mode */
- /* because both INPLL and OUTPLL take the same lock, that's why. */
- tmp = INPLL( pllPLL_PWRMGT_CNTL) & ~PLL_PWRMGT_CNTL__PM_MODE_SEL;
- OUTPLL( pllPLL_PWRMGT_CNTL, tmp);
+ OUTPLL( pllPLL_PWRMGT_CNTL,
+ INPLL( pllPLL_PWRMGT_CNTL) & ~PLL_PWRMGT_CNTL__PM_MODE_SEL);
disp_mis_cntl = INREG(DISP_MISC_CNTL);
@@ -591,6 +606,8 @@
OUTREG( CRTC_GEN_CNTL, (INREG( CRTC_GEN_CNTL) & ~CRTC_GEN_CNTL__CRTC_EN) | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B);
OUTREG( CRTC2_GEN_CNTL, (INREG( CRTC2_GEN_CNTL) & ~CRTC2_GEN_CNTL__CRTC2_EN) | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+
mdelay(17);
}
@@ -648,6 +665,9 @@
u32 DLL_CKA_Value = INPLL(pllMDLL_RDCKA) | MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP | MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET;
u32 DLL_CKB_Value = INPLL(pllMDLL_RDCKB) | MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP | MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
/* Setting up the DLL range for write */
OUTPLL(pllMDLL_CKO, DLL_CKO_Value);
OUTPLL(pllMDLL_RDCKA, DLL_CKA_Value);
@@ -714,6 +734,7 @@
OUTPLL(pllMDLL_RDCKB, DLL_CKB_Value);
mdelay( DLL_RESET_DELAY);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
#undef DLL_RESET_DELAY
#undef DLL_SLEEP_DELAY
}
@@ -778,7 +799,7 @@
static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
{
u16 pwr_cmd;
- u32 tmp;
+ unsigned long flags;
if (!rinfo->pm_reg)
return;
@@ -814,9 +835,11 @@
radeon_pm_setup_for_suspend(rinfo);
/* Reset the MDLL */
- /* because both INPLL and OUTPLL take the same lock, that's why. */
- tmp = INPLL( pllMDLL_CKO) | MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET;
- OUTPLL( pllMDLL_CKO, tmp );
+
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
+ OUTPLL( pllMDLL_CKO,
+ INPLL( pllMDLL_CKO) | MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
/* Switch PCI power managment to D2. */
diff -Nru a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
--- a/drivers/video/aty/radeonfb.h 2004-07-07 09:11:51 +02:00
+++ b/drivers/video/aty/radeonfb.h 2004-07-07 09:11:51 +02:00
@@ -311,8 +311,8 @@
int asleep;
int lock_blank;
- /* Lock on register access */
- spinlock_t reg_lock;
+ /* Lock to keep PLL index + data register sequences together */
+ spinlock_t reg_lock;
/* Timer used for delayed LVDS operations */
struct timer_list lvds_timer;
@@ -363,11 +363,11 @@
OUTREG(CLOCK_CNTL_INDEX, save);
}
-#define __OUTPLL(addr,val) \
- do { \
- OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000003f) | 0x00000080); \
- OUTREG(CLOCK_CNTL_DATA, val); \
-} while(0)
+static inline void __OUTPLL(struct radeonfb_info *rinfo, u32 addr, u32 val)
+{
+ OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000003f) | 0x00000080);
+ OUTREG(CLOCK_CNTL_DATA, val);
+}
static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
@@ -380,49 +380,27 @@
return data;
}
-static inline u32 _INPLL(struct radeonfb_info *rinfo, u32 addr)
-{
- unsigned long flags;
- u32 data;
-
- spin_lock_irqsave(&rinfo->reg_lock, flags);
- data = __INPLL(rinfo, addr);
- spin_unlock_irqrestore(&rinfo->reg_lock, flags);
- return data;
-}
-
-#define INPLL(addr) _INPLL(rinfo, addr)
-
-#define OUTPLL(addr,val) \
- do { \
- unsigned long flags;\
- spin_lock_irqsave(&rinfo->reg_lock, flags); \
- __OUTPLL(addr, val); \
- spin_unlock_irqrestore(&rinfo->reg_lock, flags); \
- } while(0)
+/* WARNING: when calling INPLL() or OUTPLL(),
+ * you must hold rinfo->reg_lock so the sequencing is not interrupted */
+#define INPLL(addr) __INPLL(rinfo, addr)
+#define OUTPLL(addr, val) __OUTPLL(rinfo, addr, val)
#define OUTPLLP(addr,val,mask) \
do { \
- unsigned long flags; \
unsigned int _tmp; \
- spin_lock_irqsave(&rinfo->reg_lock, flags); \
_tmp = __INPLL(rinfo,addr); \
_tmp &= (mask); \
_tmp |= (val); \
- __OUTPLL(addr, _tmp); \
- spin_unlock_irqrestore(&rinfo->reg_lock, flags); \
+ __OUTPLL(rinfo, addr, _tmp); \
} while (0)
#define OUTREGP(addr,val,mask) \
do { \
- unsigned long flags; \
unsigned int _tmp; \
- spin_lock_irqsave(&rinfo->reg_lock, flags); \
_tmp = INREG(addr); \
_tmp &= (mask); \
_tmp |= (val); \
OUTREG(addr, _tmp); \
- spin_unlock_irqrestore(&rinfo->reg_lock, flags); \
} while (0)
#define MS_TO_HZ(ms) ((ms * HZ + 999) / 1000)
-------------------------------------------------------
This SF.Net email sponsored by Black Hat Briefings & Training.
Attend Black Hat Briefings & Training, Las Vegas July 24-29 -
digital self defense, top technical experts, no vendor pitches,
unmatched networking opportunities. Visit www.blackhat.com
next prev parent reply other threads:[~2004-07-07 7:25 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <200407051043.i65AhCG13509@mail.osdl.org>
[not found] ` <Pine.LNX.4.58.0407051028250.1764@ppc970.osdl.org>
2004-07-06 8:10 ` [PATCH] radeonfb: remove reg_lock nonsense David Eger
2004-07-06 12:08 ` Benjamin Herrenschmidt
2004-07-07 7:24 ` David Eger [this message]
2004-07-07 15:35 ` Benjamin Herrenschmidt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040707072441.GA13160@havoc.gtf.org \
--to=eger@havoc.gtf.org \
--cc=akpm@osdl.org \
--cc=benh@kernel.crashing.org \
--cc=linux-fbdev-devel@lists.sourceforge.net \
--cc=torvalds@osdl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).