yet another bug in atyfb.c

Wulf Hofbauer wh at echo.chem.tu-berlin.de
Tue Aug 3 12:21:54 EST 1999


ABSTRACT: atyfb.c doesn't work when compiled with gcc-2.95 due to incorrect
inline assembly code.

EXPLANATION: atyfb.c - as of Kernel 2.2.10 - uses the following constructs
for accessing little-endian words in Mach32 controller space:

    asm("lwbrx %0,%1,%2" : "=r"(val) : "r" (regindex), "r" (temp));

and

    asm("stwbrx %0,%1,%2" : : "r" (val), "r" (regindex), "r" (temp) :
        "memory");

This is meant to access a word at address regindex+temp. If regindex
happens to be held in register r0, the address calculation is off as
r0 is defined as a null operand. This problem shows up with gcc-2.95 which
seems to use better register allocation code and _does_ keep regindex in
r0 at times.

The way of how the respective functions aty_ld_le32 and aty_st_le32
seems also strange to me, and I suspect it is incorrect.

Here's a proposed fix that works for me. I also changed the sparc code
to honour volatility of IO space, but couldn't check if this affects
the kernel. It would be nice if someone familiar with sparc could have a
look at this.

Here's the fix:

--- atyfb.c.orig        Wed Jul 21 00:04:40 1999
+++ atyfb.c     Tue Aug  3 12:13:42 1999
@@ -466,18 +466,18 @@
 };
 
 
-static inline u32 aty_ld_le32(volatile unsigned int regindex,
+static inline u32 aty_ld_le32(unsigned int regindex,
                              const struct fb_info_aty *info)
 {
     unsigned long temp;
     u32 val;
 
 #if defined(__powerpc__)
-    temp = info->ati_regbase;
-    asm("lwbrx %0,%1,%2" : "=r"(val) : "r" (regindex), "r" (temp));
+    temp = info->ati_regbase+regindex;
+    asm("lwbrx %0,0,%1" : "=r" (val) : "r" ((volatile u32*)temp), "m" (*(volatile u32*)temp));
 #elif defined(__sparc_v9__)
     temp = info->ati_regbase + regindex;
-    asm("lduwa [%1] %2, %0" : "=r" (val) : "r" (temp), "i" (ASI_PL));
+    asm("lduwa [%1] %2, %0" : "=r" (val) : "r" ((volatile u32*)temp), "i" (ASI_PL));
 #else
     temp = info->ati_regbase+regindex;
     val = le32_to_cpu(*((volatile u32 *)(temp)));
@@ -485,18 +485,17 @@
     return val;
 }
 
-static inline void aty_st_le32(volatile unsigned int regindex, u32 val,
+static inline void aty_st_le32(unsigned int regindex, u32 val,
                               const struct fb_info_aty *info)
 {
     unsigned long temp;
 
 #if defined(__powerpc__)
-    temp = info->ati_regbase;
-    asm("stwbrx %0,%1,%2" : : "r" (val), "r" (regindex), "r" (temp) :
-       "memory");
+    temp = info->ati_regbase+regindex;
+    asm("stwbrx %1,0,%2" : "=m" (*(volatile u32*)temp) : "r" (val) , "r" ((volatile u32*)temp));
 #elif defined(__sparc_v9__)
     temp = info->ati_regbase + regindex;
-    asm("stwa %0, [%1] %2" : : "r" (val), "r" (temp), "i" (ASI_PL) : "memory");
+    asm("stwa %0, [%1] %2" : : "r" (val), "r" ((volatile u32*)temp), "i" (ASI_PL) : "memory");
 #else
     temp = info->ati_regbase+regindex;
     *((volatile u32 *)(temp)) = cpu_to_le32(val);


- Wulf

--
 ________________________________________________________
! Dipl. Phys. Wulf Hofbauer  (wh at echo.chem.tu-berlin.de) !
! Max-Volmer-Institut     Technische Universitaet Berlin !
! Strasse des 17. Juni 135     10623 Berlin      Germany !
!________________________________________________________!

[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]





More information about the Linuxppc-dev mailing list