linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 1/1] SCSI: improve endian handling in LSI fusion firmware mpt_downloadboot
@ 2006-08-30 17:32 Erik Habbinga
  2006-08-31 20:08 ` Andrew Morton
  0 siblings, 1 reply; 3+ messages in thread
From: Erik Habbinga @ 2006-08-30 17:32 UTC (permalink / raw)
  To: eric.moore
  Cc: james.bottomley, trivial, 'Erik Habbinga', linux-kernel

The mpt_downloadboot function in drivers/message/fusion/mptbase.c doesn't work correctly on big endian systems (powerpc in my case).
I've added appropriate le32_to_cpu calls to correctly translate little endian firmware file data into cpu endian format before
getting written to little endian PCI registers.  This patch has been tested successfully on a powerpc target and an Intel target.

Signed-off-by: Erik Habbinga <erikhabbinga@inphase-tech.com>

--- a/drivers/message/fusion/mptbase.c.orig	2006-08-23 15:16:33.000000000 -0600
+++ b/drivers/message/fusion/mptbase.c	2006-08-30 10:28:39.000000000 -0600
@@ -2915,7 +2915,7 @@
 	u32 			 ioc_state=0;
 
 	ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
-				ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
+				ioc->name, le32_to_cpu(pFwHeader->ImageSize), le32_to_cpu(pFwHeader->ImageSize), pFwHeader));
 
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
@@ -2968,7 +2968,7 @@
 	/* Set the DiagRwEn and Disable ARM bits */
 	CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
 
-	fwSize = (pFwHeader->ImageSize + 3)/4;
+	fwSize = (le32_to_cpu(pFwHeader->ImageSize) + 3)/4;
 	ptrFw = (u32 *) pFwHeader;
 
 	/* Write the LoadStartAddress to the DiagRw Address Register
@@ -2977,23 +2977,23 @@
 	if (ioc->errata_flag_1064)
 		pci_enable_io_access(ioc->pcidev);
 
-	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
+	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, le32_to_cpu(pFwHeader->LoadStartAddress));
 	ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
-		ioc->name, pFwHeader->LoadStartAddress));
+		ioc->name, le32_to_cpu(pFwHeader->LoadStartAddress)));
 
 	ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
 				ioc->name, fwSize*4, ptrFw));
 	while (fwSize--) {
-		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
+		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, le32_to_cpu(*ptrFw++));
 	}
 
-	nextImage = pFwHeader->NextImageHeaderOffset;
+	nextImage = le32_to_cpu(pFwHeader->NextImageHeaderOffset);
 	while (nextImage) {
 		pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
 
-		load_addr = pExtImage->LoadStartAddress;
+		load_addr = le32_to_cpu(pExtImage->LoadStartAddress);
 
-		fwSize = (pExtImage->ImageSize + 3) >> 2;
+		fwSize = (le32_to_cpu(pExtImage->ImageSize) + 3) >> 2;
 		ptrFw = (u32 *)pExtImage;
 
 		ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
@@ -3001,18 +3001,18 @@
 		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
 
 		while (fwSize--) {
-			CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
+			CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, le32_to_cpu(*ptrFw++));
 		}
-		nextImage = pExtImage->NextImageHeaderOffset;
+		nextImage = le32_to_cpu(pExtImage->NextImageHeaderOffset);
 	}
 
 	/* Write the IopResetVectorRegAddr */
-	ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, 	pFwHeader->IopResetRegAddr));
-	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
+	ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, 	le32_to_cpu(pFwHeader->IopResetRegAddr)));
+	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, le32_to_cpu(pFwHeader->IopResetRegAddr));
 
 	/* Write the IopResetVectorValue */
-	ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
-	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
+	ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, le32_to_cpu(pFwHeader->IopResetVectorValue)));
+	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, le32_to_cpu(pFwHeader->IopResetVectorValue));
 
 	/* Clear the internal flash bad bit - autoincrementing register,
 	 * so must do two writes.


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

* Re: [patch 1/1] SCSI: improve endian handling in LSI fusion firmware mpt_downloadboot
  2006-08-30 17:32 [patch 1/1] SCSI: improve endian handling in LSI fusion firmware mpt_downloadboot Erik Habbinga
@ 2006-08-31 20:08 ` Andrew Morton
  0 siblings, 0 replies; 3+ messages in thread
From: Andrew Morton @ 2006-08-31 20:08 UTC (permalink / raw)
  To: Erik Habbinga; +Cc: eric.moore, james.bottomley, trivial, linux-kernel

On Wed, 30 Aug 2006 11:32:47 -0600
"Erik Habbinga" <erikhabbinga@inphase-tech.com> wrote:

> The mpt_downloadboot function in drivers/message/fusion/mptbase.c doesn't work correctly on big endian systems (powerpc in my case).
> I've added appropriate le32_to_cpu calls to correctly translate little endian firmware file data into cpu endian format before
> getting written to little endian PCI registers.  This patch has been tested successfully on a powerpc target and an Intel target.
> 
> Signed-off-by: Erik Habbinga <erikhabbinga@inphase-tech.com>
> 
> --- a/drivers/message/fusion/mptbase.c.orig	2006-08-23 15:16:33.000000000 -0600
> +++ b/drivers/message/fusion/mptbase.c	2006-08-30 10:28:39.000000000 -0600
> @@ -2915,7 +2915,7 @@
>  	u32 			 ioc_state=0;
>  
>  	ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
> -				ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
> +				ioc->name, le32_to_cpu(pFwHeader->ImageSize), le32_to_cpu(pFwHeader->ImageSize), pFwHeader));
>  
>  	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
>  	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
> @@ -2968,7 +2968,7 @@
>  	/* Set the DiagRwEn and Disable ARM bits */
>  	CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
>  
> -	fwSize = (pFwHeader->ImageSize + 3)/4;
> +	fwSize = (le32_to_cpu(pFwHeader->ImageSize) + 3)/4;
>  	ptrFw = (u32 *) pFwHeader;
>  
>  	/* Write the LoadStartAddress to the DiagRw Address Register
> @@ -2977,23 +2977,23 @@
>  	if (ioc->errata_flag_1064)
>  		pci_enable_io_access(ioc->pcidev);
>  
> -	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
> +	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, le32_to_cpu(pFwHeader->LoadStartAddress));
>  	ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
> -		ioc->name, pFwHeader->LoadStartAddress));
> +		ioc->name, le32_to_cpu(pFwHeader->LoadStartAddress)));
>  
>  	ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
>  				ioc->name, fwSize*4, ptrFw));
>  	while (fwSize--) {
> -		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
> +		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, le32_to_cpu(*ptrFw++));

hm, I'd be a bit more comfortable if this didn't require that le32_to_cpu()
was sanely implemented.   include/linux/byteorder/swab.h has

#  define __swab32(x) \
(__builtin_constant_p((__u32)(x)) ? \
 ___swab32((x)) : \
 __fswab32((x)))

so if `x' is foo++, what value does `foo' end up with?  I guess it would be
pretty dumb if __builtin_constant_p(foo++) were to increment foo, but is
that guaranteed?

Anyway.  This is a moderately important fix, isn't it?  Eric (Moore), do
you want to proceed with this patch?

Thanks.


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

* RE: [patch 1/1] SCSI: improve endian handling in LSI fusion firmware mpt_downloadboot
@ 2006-09-01 16:12 Moore, Eric
  0 siblings, 0 replies; 3+ messages in thread
From: Moore, Eric @ 2006-09-01 16:12 UTC (permalink / raw)
  To: Erik Habbinga
  Cc: james.bottomley, trivial, linux-kernel, Shirron, Stephen,
	Hickerson, Roger

On Wednesday, August 30, 2006 11:33 AM, Erik Habbinga wrote: 

> The mpt_downloadboot function in 
> drivers/message/fusion/mptbase.c doesn't work correctly on 
> big endian systems (powerpc in my case).
> I've added appropriate le32_to_cpu calls to correctly 
> translate little endian firmware file data into cpu endian 
> format before
> getting written to little endian PCI registers.  This patch 
> has been tested successfully on a powerpc target and an Intel target.
> 

Rejected.

This will break all our customers on big-endian machines.

Our firmware is packaged in proper byte order on dword boundarys,
and doesn't need swapping at all.   Basically mpt_downloadboot, 
is reading from pFwHeader, and writing back out to doorbell
in proper byte order that doorbell expecting.  This code is working
for many LSI customers running on big-endian systems, such as pppc64.

Could you send your firmware image, copied to Stephen Shirron,
so he can determine if your firmware is properly packaged in correct
byte order?

Eric Moore
LSI Logic

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

end of thread, other threads:[~2006-09-01 16:13 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-08-30 17:32 [patch 1/1] SCSI: improve endian handling in LSI fusion firmware mpt_downloadboot Erik Habbinga
2006-08-31 20:08 ` Andrew Morton
2006-09-01 16:12 Moore, Eric

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).