[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[microblaze-uclinux] Patch for SystemACE to fix spurius write interrupt



Hi John,
I prepared two patch files.

The xilinx_sysace_patch.txt fixes the write problem with systemACE due to a 
spurius interrupt that hangs the kernel and add a printk with error code in 
case of initialization failed
(have to be applied to uClinux-2.4.x/drivers/block/xilinx_sysace).

The vendors_patch.txt adds systemace devices to the uclinux vendor Makefile 
only if DEVFS is not enabled and systemace drived is enabled
(have to be applied to uClinux-dist/vendors/Xilinx/uclinux-auto).

Specially the first one is a MUST to avoid kernel hang when mounting the 
systemace device read/write.

Include them in your official version, please.

Cheers,
Claudio Lanconelli

Attachment: patch.tar.gz
Description: application/tgz

*** Makefile	22 Dec 2004 12:00:47 -0000	1.1.1.1
--- Makefile	30 Mar 2005 08:10:17 -0000
***************
*** 56,61 ****
--- 56,68 ----
  	mtd6,c,90,12 	mtdr6,c,90,13	mtdblock6,b,31,6	\
  	mtd7,c,90,14 	mtdr7,c,90,15	mtdblock7,b,31,7
  
+ SYSACE_DEVICES = \
+ 	xsysacea,b,254,0	xsysacea1,b,254,1	xsysacea2,b,254,2  \
+ 	xsysacea3,b,254,3	xsysacea4,b,254,4	xsysacea5,b,254,5  \
+ 	xsysacea6,b,254,6	xsysacea7,b,254,7 	xsysacea8,b,254,8  \
+ 	xsysacea9,b,254,9	xsysacea10,b,254,10	xsysacea11,b,254,11 \
+ 	xsysacea12,b,254,12	xsysacea12,b,254,13	xsysacea14,b,254,14 \
+ 	xsysacea15,b,254,15
  
  FLASH_DEVICES = \
  	boot,c,90,0     \
***************
*** 122,127 ****
--- 129,141 ----
  	# these permissions are needed for openpty and family to work
  	# on non-ptmx ptys
  	chmod 620 $(ROMFSDIR)/dev/@[pt]ty[pqrsPQRS][0-9a-f],*
+ 	if [ "$(CONFIG_XILINX_SYSACE)" = "y" ]; then \
+ 		if [ "$(CONFIG_DEVFS_FS)" != "y" ]; then \
+ 			for i in $(SYSACE_DEVICES); do \
+ 				touch $(ROMFSDIR)/dev/@$$i; \
+ 			done; \
+ 		fi; \
+ 	fi
  	for i in $(FLASH_DEVICES); do \
  		touch $(ROMFSDIR)/dev/flash/@$$i; \
  	done


*** adapter.c	15 Feb 2005 22:44:29 -0000	1.2
--- adapter.c	30 Mar 2005 08:05:54 -0000
***************
*** 303,308 ****
--- 303,314 ----
  {
  	unsigned long flags;
  
+ 	if ( req_active == 0 )
+ 	{
+ 		printk(KERN_ERR "%s: spurius interrupt\n", DEVICE_NAME);
+ 		return;
+ 	}
+ 
  	XSysAce_Unlock(&SysAce);
  	spin_lock_irqsave(&io_request_lock, flags);
  	end_request(uptodate);
***************
*** 331,350 ****
  	XSysAce_InterruptHandler(&SysAce);
  }
  
- /* Called by the Xilinx interrupt handler to give us an event. */
  static void
! EventHandler(void *CallbackRef, int Event)
  {
- 	u32 ErrorMask;
- 
- 	switch (Event) {
- 	case XSA_EVENT_DATA_DONE:
- 		xsa_complete_request(1);	/* The request succeeded. */
- 		break;
- 
- 	case XSA_EVENT_ERROR:
- 		ErrorMask = XSysAce_GetErrors(&SysAce);
- 
  		/* Print out what went wrong. */
  		if (ErrorMask & XSA_ER_CARD_RESET)
  			printk(KERN_ERR "CompactFlash failed to reset\n");
--- 337,345 ----
  	XSysAce_InterruptHandler(&SysAce);
  }
  
  static void
! xsysace_printerrcode(u32 ErrorMask)
  {
  		/* Print out what went wrong. */
  		if (ErrorMask & XSA_ER_CARD_RESET)
  			printk(KERN_ERR "CompactFlash failed to reset\n");
***************
*** 382,387 ****
--- 377,399 ----
  			       "Invalid instruction during JTAG configuration\n");
  		if (ErrorMask & XSA_ER_CFG_INIT)
  			printk(KERN_ERR "JTAG CFGINIT pin error\n");
+ }
+ 
+ /* Called by the Xilinx interrupt handler to give us an event. */
+ static void
+ EventHandler(void *CallbackRef, int Event)
+ {
+ 	u32 ErrorMask;
+ 
+ 	switch (Event) {
+ 	case XSA_EVENT_DATA_DONE:
+ 		xsa_complete_request(1);	/* The request succeeded. */
+ 		break;
+ 
+ 	case XSA_EVENT_ERROR:
+ 		ErrorMask = XSysAce_GetErrors(&SysAce);
+ 
+ 		xsysace_printerrcode(ErrorMask);
  
  		/* Check for errors that should reset the CompactFlash */
  		if (ErrorMask & (XSA_ER_CARD_RESET |
***************
*** 741,746 ****
--- 753,759 ----
  	//		ppc_md.restart = old_restart; 
  }
  
+ 
  static int __init
  xsysace_init(void)
  {
***************
*** 790,795 ****
--- 803,810 ----
  	if (stat != XST_SUCCESS) {
  		printk(KERN_ERR "%s: Could not send identify command.\n",
  		       DEVICE_NAME);
+ 		if ( stat == XST_FAILURE )
+ 			xsysace_printerrcode( XSysAce_GetErrors(&SysAce) );
  		cleanup();
  		return -ENODEV;
  	}


*** xsysace_intr.c	28 Nov 2003 05:11:30 -0000	1.1
--- xsysace_intr.c	30 Mar 2005 08:05:57 -0000
***************
*** 58,64 ****
  /************************** Function Prototypes ******************************/
  
  static void HandleDataBuffer(XSysAce *InstancePtr, u32 StatusReg);
! static void DataComplete(XSysAce *InstancePtr);
  
  
  /*****************************************************************************/
--- 58,64 ----
  /************************** Function Prototypes ******************************/
  
  static void HandleDataBuffer(XSysAce *InstancePtr, u32 StatusReg);
! static void DataComplete(XSysAce *InstancePtr, int notify);
  
  
  /*****************************************************************************/
***************
*** 303,325 ****
  static void HandleDataBuffer(XSysAce *InstancePtr, u32 StatusReg)
  {
      /* By default, transfer a whole data buffer */
!     int BytesToTransfer = XSA_DATA_BUFFER_SIZE;
  
      /*
       * Check to see if number of bytes remaining is less than the data buffer
       * size. If it is, we need to adjust the remaining bytes to transfer.
       */
!     if (InstancePtr->NumRemaining < XSA_DATA_BUFFER_SIZE)
      {
          BytesToTransfer = InstancePtr->NumRemaining;
      }
  
      /*
       * Transfer only one data buffer at a time, which is 32 bytes. Note that
       * errors will be handled by an error interrupt occurring, so no need to
       * check for them here.
       */
!     if (StatusReg & XSA_SR_DATABUFMODE_MASK)
      {
          /*
           * A write operation in progress, so if there is data remaining then
--- 303,332 ----
  static void HandleDataBuffer(XSysAce *InstancePtr, u32 StatusReg)
  {
      /* By default, transfer a whole data buffer */
!     int BytesToTransfer;
! 	int last_transfer;
  
      /*
       * Check to see if number of bytes remaining is less than the data buffer
       * size. If it is, we need to adjust the remaining bytes to transfer.
       */
!     if (InstancePtr->NumRemaining <= XSA_DATA_BUFFER_SIZE)
      {
          BytesToTransfer = InstancePtr->NumRemaining;
+ 		last_transfer = TRUE;
      }
+ 	else
+ 	{
+ 		BytesToTransfer = XSA_DATA_BUFFER_SIZE;
+ 		last_transfer = FALSE;
+ 	}
  
      /*
       * Transfer only one data buffer at a time, which is 32 bytes. Note that
       * errors will be handled by an error interrupt occurring, so no need to
       * check for them here.
       */
!     if ( (StatusReg & XSA_SR_DATABUFMODE_MASK) != 0 )
      {
          /*
           * A write operation in progress, so if there is data remaining then
***************
*** 337,347 ****
               */
              InstancePtr->NumRemaining -= BytesToTransfer;
              InstancePtr->BufferPtr += BytesToTransfer;
          }
          else
!         {
!             /* Done writing data, so clean up */
!             DataComplete(InstancePtr);
          }
      }
      else
--- 344,358 ----
               */
              InstancePtr->NumRemaining -= BytesToTransfer;
              InstancePtr->BufferPtr += BytesToTransfer;
+ 
+             if ( last_transfer )
+             {   /* Done writing data, so clean up */
+                 DataComplete(InstancePtr, TRUE);
+             }
          }
          else
!         {   /* Spurius interrupt! It should never happens */
!             DataComplete(InstancePtr, FALSE);
          }
      }
      else
***************
*** 362,368 ****
          if (InstancePtr->NumRemaining == 0)
          {
              /* Done reading data, so clean up */
!             DataComplete(InstancePtr);
          }
      }
  }
--- 373,379 ----
          if (InstancePtr->NumRemaining == 0)
          {
              /* Done reading data, so clean up */
!             DataComplete(InstancePtr, TRUE);
          }
      }
  }
***************
*** 385,391 ****
  * None.
  *
  ******************************************************************************/
! static void DataComplete(XSysAce *InstancePtr)
  {
      InstancePtr->NumRequested = 0;
      InstancePtr->NumRemaining = 0;
--- 396,402 ----
  * None.
  *
  ******************************************************************************/
! static void DataComplete(XSysAce *InstancePtr, int notify)
  {
      InstancePtr->NumRequested = 0;
      InstancePtr->NumRemaining = 0;
***************
*** 408,415 ****
       * to determine if an MPU JTAG config process has just completed. The
       * CFG_DONE event is passed up later by the main interrupt handler.
       */
!     if ((XSysAce_mGetControlReg(InstancePtr->BaseAddress)
!         & XSA_CR_CFGSEL_MASK) == 0)
      {
          /* no JTAG configuration in progress */
          InstancePtr->EventHandler(InstancePtr->EventRef, XSA_EVENT_DATA_DONE);
--- 419,425 ----
       * to determine if an MPU JTAG config process has just completed. The
       * CFG_DONE event is passed up later by the main interrupt handler.
       */
!     if ( (XSysAce_mGetControlReg(InstancePtr->BaseAddress) & XSA_CR_CFGSEL_MASK) == 0 && notify )
      {
          /* no JTAG configuration in progress */
          InstancePtr->EventHandler(InstancePtr->EventRef, XSA_EVENT_DATA_DONE);


*** xsysace_l.c	15 Feb 2005 22:44:29 -0000	1.2
--- xsysace_l.c	30 Mar 2005 08:06:02 -0000
***************
*** 35,40 ****
--- 35,41 ----
  * Ver   Who  Date     Changes
  * ----- ---- -------- -----------------------------------------------
  * 1.00a rpm  06/14/02 work in progress
+ * 1.00a rpm  02/17/04 Fixed WriteSector function command
  * </pre>
  *
  ******************************************************************************/
***************
*** 367,373 ****
  
      /* Send a write command of one sector to the controller */
      XSysAce_RegWrite16(BaseAddress + XSA_SCCR_OFFSET,
!                         XSA_SCCR_READDATA_MASK | 1);
  
      /* Reset configuration controller (be sure to keep the lock) */
      XSysAce_mOrControlReg(BaseAddress, XSA_CR_CFGRESET_MASK);
--- 368,374 ----
  
      /* Send a write command of one sector to the controller */
      XSysAce_RegWrite16(BaseAddress + XSA_SCCR_OFFSET,
!                         XSA_SCCR_WRITEDATA_MASK | 1);
  
      /* Reset configuration controller (be sure to keep the lock) */
      XSysAce_mOrControlReg(BaseAddress, XSA_CR_CFGRESET_MASK);