patch-2.4.21 linux-2.4.21/include/asm-ia64/sn/bte_copy.h

Next file: linux-2.4.21/include/asm-ia64/sn/cdl.h
Previous file: linux-2.4.21/include/asm-ia64/sn/bte.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/include/asm-ia64/sn/bte_copy.h linux-2.4.21/include/asm-ia64/sn/bte_copy.h
@@ -1,9 +1,35 @@
 /*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
+ *
+ *
+ * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of version 2 of the GNU General Public License 
+ * as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * 
+ * Further, this software is distributed without any warranty that it is 
+ * free of the rightful claim of any third person regarding infringement 
+ * or the like.  Any license provided herein, whether implied or 
+ * otherwise, applies only to this software file.  Patent licenses, if 
+ * any, provided herein do not apply to combinations of this program with 
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write the Free Software 
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
  * 
- * Copyright (c) 2001-2002 Silicon Graphics, Inc.  All rights reserved.
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
  */
 
 #ifndef _ASM_IA64_SN_BTE_COPY_H
@@ -11,21 +37,40 @@
 
 #ident "$Revision: 1.1 $"
 
+#include <linux/timer.h>
 #include <asm/sn/bte.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/pda.h>
 #include <asm/delay.h>
 
 /*
- * BTE_LOCKING support - Undefining the following line will
- * adapt the bte_copy code to support one bte per cpu in
+ * BTE_LOCKING support - When CONFIG_IA64_SGI_BTE_LOCKING is
+ * not defined, the bte_copy code supports one bte per cpu in
  * synchronous mode.  Even if bte_copy is called with a
  * notify address, the bte will spin and wait for the transfer
  * to complete.  By defining the following, spin_locks and
  * busy checks are placed around the initiation of a BTE
  * transfer and multiple bte's per cpu are supported.
  */
+#if 0
 #define CONFIG_IA64_SGI_BTE_LOCKING 1
+#endif
+
+/*
+ * Handle locking of the bte interfaces.
+ *
+ * All transfers spinlock the interface before setting up the SHUB
+ * registers.  Sync transfers hold the lock until all processing is
+ * complete.  Async transfers release the lock as soon as the transfer
+ * is initiated.
+ *
+ * To determine if an interface is available, we must check both the
+ * busy bit and the spinlock for that interface.
+ */
+#define BTE_LOCK_IF_AVAIL(_x) (\
+	(*pda.cpu_bte_if[_x]->most_rcnt_na & IBLS_BUSY) && \
+	(!(spin_trylock(&(pda.cpu_bte_if[_x]->spinlock)))) \
+	)
 
 /*
  * Some macros to simplify reading.
@@ -33,39 +78,71 @@
  * Start with macros to locate the BTE control registers.
  */
 
-#define BTEREG_LNSTAT_ADDR (bte->bte_base_addr)
-#define BTEREG_SOURCE_ADDR (bte->bte_base_addr + IIO_IBSA0 - IIO_IBLS0)
-#define BTEREG_DEST_ADDR (bte->bte_base_addr + IIO_IBDA0 - IIO_IBLS0)
-#define BTEREG_CTRL_ADDR ((volatile char *)bte->bte_base_addr + IIO_IBCT0 - IIO_IBLS0)
-#define BTEREG_NOTIF_ADDR (bte->bte_base_addr + IIO_IBNA0 - IIO_IBLS0)
+#define BTEREG_LNSTAT_ADDR ((u64 *)(bte->bte_base_addr))
+#define BTEREG_SRC_ADDR ((u64 *)(bte->bte_base_addr + BTEOFF_SRC))
+#define BTEREG_DEST_ADDR ((u64 *)(bte->bte_base_addr + BTEOFF_DEST))
+#define BTEREG_CTRL_ADDR ((u64 *)(bte->bte_base_addr + BTEOFF_CTRL))
+#define BTEREG_NOTIF_ADDR ((u64 *)(bte->bte_base_addr + BTEOFF_NOTIFY))
 
 /* Some macros to force the IBCT0 value valid. */
 
 #define BTE_VALID_MODES BTE_NOTIFY
 #define BTE_VLD_MODE(x) (x & BTE_VALID_MODES)
 
-// #define DEBUG_BTE
-// #define DEBUG_BTE_VERBOSE
-// #define DEBUG_TIME_BTE
-
-#ifdef DEBUG_BTE
-#  define DPRINTK(x) printk x	// Terse
-#  ifdef DEBUG_BTE_VERBOSE
-#    define DPRINTKV(x) printk x	// Verbose
+// #define BTE_DEBUG
+// #define BTE_DEBUG_VERBOSE
+// #define BTE_TIME
+
+#ifdef BTE_DEBUG
+#  define BTE_PRINTK(x) printk x	/* Terse */
+#  ifdef BTE_DEBUG_VERBOSE
+#    define BTE_PRINTKV(x) printk x	/* Verbose */
 #  else
-#    define DPRINTKV(x)
-#  endif
+#    define BTE_PRINTKV(x)
+#  endif /* BTE_DEBUG_VERBOSE */
 #else
-#  define DPRINTK(x)
-#  define DPRINTKV(x)
-#endif
-
-#ifdef DEBUG_TIME_BTE
-extern u64 BteSetupTime;
-extern u64 BteTransferTime;
-extern u64 BteTeardownTime;
-extern u64 BteExecuteTime;
-#endif
+#  define BTE_PRINTK(x)
+#  define BTE_PRINTKV(x)
+#endif /* BTE_DEBUG */
+
+#define BTE_IDEAL_TMO(x) (jiffies + \
+	(HZ / BTE_MAXT_LINES_PER_SECOND * x))
+
+#ifdef BTE_TIME
+volatile extern u64 bte_setup_time;
+volatile extern u64 bte_transfer_time;
+volatile extern u64 bte_tear_down_time;
+volatile extern u64 bte_execute_time;
+
+#define BTE_TIME_DECLARE() \
+	u64 btcp_strt_tm = 0; \
+	u64 btcp_cplt_tm = 0; \
+	u64 xfr_strt_tm = 0; \
+	u64 xfr_cplt_tm = 0; \
+
+#define BTE_TIME_START() \
+	btcp_strt_tm = xfr_strt_tm = xfr_cplt_tm = ia64_get_itc();
+
+#define BTE_TIME_XFR_START() \
+	xfr_strt_tm = ia64_get_itc();
+
+#define BTE_TIME_XFR_STOP() \
+	xfr_cplt_tm = ia64_get_itc();
+
+#define BTE_TIME_STOP() \
+	btcp_cplt_tm = ia64_get_itc(); \
+	bte_setup_time = xfr_strt_tm - btcp_strt_tm; \
+	bte_transfer_time = xfr_cplt_tm - xfr_strt_tm; \
+	bte_tear_down_time = btcp_cplt_tm - xfr_cplt_tm; \
+	bte_execute_time = btcp_cplt_tm - btcp_strt_tm; \
+
+#else /* BTE_TIME */
+#define BTE_TIME_DECLARE()
+#define BTE_TIME_START()
+#define BTE_TIME_XFR_START()
+#define BTE_TIME_XFR_STOP()
+#define BTE_TIME_STOP()
+#endif /* BTE_TIME */
 
 /*
  * bte_copy(src, dest, len, mode, notification)
@@ -91,25 +168,19 @@
 {
 #ifdef CONFIG_IA64_SGI_BTE_LOCKING
 	int bte_to_use;
-#endif
-
-#ifdef DEBUG_TIME_BTE
-	u64 invokeTime = 0;
-	u64 completeTime = 0;
-	u64 xferStartTime = 0;
-	u64 xferCompleteTime = 0;
-#endif
-	u64 transferSize;
+#endif /* CONFIG_IA64_SGI_BTE_LOCKING */
+	u64 transfer_size;
+	u64 lines_remaining;
 	bteinfo_t *bte;
+	BTE_TIME_DECLARE();
 
-#ifdef DEBUG_TIME_BTE
-	invokeTime = ia64_get_itc();
-#endif
+	BTE_TIME_START();
 
-	DPRINTK(("bte_copy (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
-		 src, dest, len, mode, notification));
+	BTE_PRINTK(("bte_copy (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
+		    src, dest, len, mode, notification));
 
 	if (len == 0) {
+		BTE_TIME_STOP();
 		return (BTE_SUCCESS);
 	}
 
@@ -123,17 +194,15 @@
 		bte_to_use = 0;
 
 		/* Attempt to lock one of the BTE interfaces */
-		while ((*pda.cpubte[bte_to_use]->
-			mostRecentNotification & IBLS_BUSY)
-		       &&
-		       (!(spin_trylock
-			  (&(pda.cpubte[bte_to_use]->spinlock))))
-		       && (bte_to_use < BTES_PER_NODE)) {
+		while ((bte_to_use < BTES_PER_NODE) &&
+		       BTE_LOCK_IF_AVAIL(bte_to_use)) {
+
 			bte_to_use++;
 		}
 
 		if ((bte_to_use >= BTES_PER_NODE) &&
 		    !(mode & BTE_WACQUIRE)) {
+			BTE_TIME_STOP();
 			return (BTEFAIL_NOTAVAIL);
 		}
 
@@ -141,12 +210,12 @@
 	}
 	while (bte_to_use >= BTES_PER_NODE);
 
-	bte = pda.cpubte[bte_to_use];
-	DPRINTKV(("Got a lock on bte %d\n", bte_to_use));
+	bte = pda.cpu_bte_if[bte_to_use];
+	BTE_PRINTKV(("Got a lock on bte %d\n", bte_to_use));
 #else
 	/* Assuming one BTE per CPU. */
-	bte = pda.cpubte[0];
-#endif
+	bte = pda.cpu_bte_if[0];
+#endif /* CONFIG_IA64_SGI_BTE_LOCKING */
 
 	/*
 	 * The following are removed for optimization but is
@@ -160,65 +229,51 @@
 	 */
 	if (notification == NULL) {
 		/* User does not want to be notified. */
-		bte->mostRecentNotification = &bte->notify;
+		bte->most_rcnt_na = &bte->notify;
 	} else {
-		bte->mostRecentNotification = notification;
+		bte->most_rcnt_na = notification;
 	}
 
 	/* Calculate the number of cache lines to transfer. */
-	transferSize = ((len >> L1_CACHE_SHIFT) & BTE_LEN_MASK);
+	transfer_size = ((len >> L1_CACHE_SHIFT) & BTE_LEN_MASK);
 
-	DPRINTKV(("Calculated transfer size of %d cache lines\n",
-		  transferSize));
+	BTE_PRINTKV(("Calculated transfer size of %d cache lines\n",
+		     transfer_size));
 
 	/* Initialize the notification to a known value. */
-	*bte->mostRecentNotification = -1L;
+	*bte->most_rcnt_na = -1L;
 
 
-	DPRINTKV(("Before, status is 0x%lx and notify is 0x%lx\n",
-		  HUB_L(BTEREG_LNSTAT_ADDR),
-		  *bte->mostRecentNotification));
+	BTE_PRINTKV(("Before, status is 0x%lx and notify is 0x%lx\n",
+		     HUB_L(BTEREG_LNSTAT_ADDR),
+		     *bte->most_rcnt_na));
 
 	/* Set the status reg busy bit and transfer length */
-	DPRINTKV(("IBLS - HUB_S(0x%lx, 0x%lx)\n",
-		  BTEREG_LNSTAT_ADDR, IBLS_BUSY | transferSize));
-	HUB_S(BTEREG_LNSTAT_ADDR, IBLS_BUSY | transferSize);
-
-
-	DPRINTKV(("After setting status, status is 0x%lx and notify is 0x%lx\n", HUB_L(BTEREG_LNSTAT_ADDR), *bte->mostRecentNotification));
+	BTE_PRINTKV(("IBLS - HUB_S(0x%lx, 0x%lx)\n",
+		     BTEREG_LNSTAT_ADDR, IBLS_BUSY | transfer_size));
+	HUB_S(BTEREG_LNSTAT_ADDR, (IBLS_BUSY | transfer_size));
 
 	/* Set the source and destination registers */
-	DPRINTKV(("IBSA - HUB_S(0x%lx, 0x%lx)\n", BTEREG_SOURCE_ADDR,
-		  src));
-	HUB_S(BTEREG_SOURCE_ADDR, src);
-	DPRINTKV(("IBDA - HUB_S(0x%lx, 0x%lx)\n", BTEREG_DEST_ADDR, dest));
-	HUB_S(BTEREG_DEST_ADDR, dest);
-
+	BTE_PRINTKV(("IBSA - HUB_S(0x%lx, 0x%lx)\n", BTEREG_SRC_ADDR,
+		     (TO_PHYS(src))));
+	HUB_S(BTEREG_SRC_ADDR, (TO_PHYS(src)));
+	BTE_PRINTKV(("IBDA - HUB_S(0x%lx, 0x%lx)\n", BTEREG_DEST_ADDR,
+		     (TO_PHYS(dest))));
+	HUB_S(BTEREG_DEST_ADDR, (TO_PHYS(dest)));
 
 	/* Set the notification register */
-	DPRINTKV(("IBNA - HUB_S(0x%lx, 0x%lx)\n", BTEREG_NOTIF_ADDR,
-		  __pa(bte->mostRecentNotification)));
-	HUB_S(BTEREG_NOTIF_ADDR, (__pa(bte->mostRecentNotification)));
-
-
-	DPRINTKV(("Set Notify, status is 0x%lx and notify is 0x%lx\n",
-		  HUB_L(BTEREG_LNSTAT_ADDR),
-		  *bte->mostRecentNotification));
+	BTE_PRINTKV(("IBNA - HUB_S(0x%lx, 0x%lx)\n", BTEREG_NOTIF_ADDR,
+		     (TO_PHYS(__pa(bte->most_rcnt_na)))));
+	HUB_S(BTEREG_NOTIF_ADDR, (TO_PHYS(__pa(bte->most_rcnt_na))));
 
 	/* Initiate the transfer */
-	DPRINTKV(("IBCT - HUB_S(0x%lx, 0x%lx)\n", BTEREG_CTRL_ADDR, mode));
-#ifdef DEBUG_TIME_BTE
-	xferStartTime = ia64_get_itc();
-#endif
+	BTE_PRINTKV(("IBCT - HUB_S(0x%lx, 0x%lx)\n", BTEREG_CTRL_ADDR, mode));
+	BTE_TIME_XFR_START();
 	HUB_S(BTEREG_CTRL_ADDR, BTE_VLD_MODE(mode));
 
-	DPRINTKV(("Initiated, status is 0x%lx and notify is 0x%lx\n",
-		  HUB_L(BTEREG_LNSTAT_ADDR),
-		  *bte->mostRecentNotification));
-
-	// >>> Temporarily work around not getting a notification
-	// from medusa.
-	// *bte->mostRecentNotification = HUB_L(bte->bte_base_addr);
+	BTE_PRINTKV(("Initiated, status is 0x%lx and notify is 0x%lx\n",
+		     HUB_L(BTEREG_LNSTAT_ADDR),
+		     *bte->most_rcnt_na));
 
 	if (notification == NULL) {
 		/*
@@ -240,56 +295,75 @@
 		 * delay from hardware completing our request and
 		 * our detecting the failure.
 		 */
-		bte->idealTransferTimeout = jiffies +
-		    (HZ / BTE_MAXT_LINES_PER_SECOND * transferSize);
+		bte->ideal_xfr_tmo = BTE_IDEAL_TMO(transfer_size);
 
-		while ((IBLS_BUSY & bte->notify)) {
+		while (bte->notify == -1UL) {
 			/*
 			 * Notification Workaround: When the max
 			 * theoretical time has elapsed, read the hub
 			 * status register into the notification area.
 			 * This fakes the shub performing the copy.
 			 */
-			if (jiffies > bte->idealTransferTimeout) {
-				bte->notify = HUB_L(bte->bte_base_addr);
-				bte->idealTransferTimeoutReached++;
-				bte->idealTransferTimeout = jiffies +
-				    (HZ / BTE_MAXT_LINES_PER_SECOND *
-				     (bte->notify & BTE_LEN_MASK));
+			BTE_PRINTKV(("  Timing.  IBLS = 0x%lx, "
+				     "notify= 0x%lx\n",
+				     HUB_L(BTEREG_LNSTAT_ADDR),
+				     bte->notify));
+			if (time_after(jiffies, bte->ideal_xfr_tmo)) {
+				lines_remaining = HUB_L(BTEREG_LNSTAT_ADDR) &
+					BTE_LEN_MASK;
+				bte->ideal_xfr_tmo_cnt++;
+				bte->ideal_xfr_tmo =
+					BTE_IDEAL_TMO(lines_remaining);
+
+				BTE_PRINTKV(("  Timeout.  cpu %d "
+					     "IBLS = 0x%lx, "
+					     "notify= 0x%lx, "
+					     "Lines remaining = %d. "
+					     "New timeout = %d.\n",
+					     smp_processor_id(),
+					     HUB_L(BTEREG_LNSTAT_ADDR),
+					     bte->notify,
+					     lines_remaining,
+					     bte->ideal_xfr_tmo));
 			}
 		}
-#ifdef DEBUG_TIME_BTE
-		xferCompleteTime = ia64_get_itc();
-#endif
+		BTE_PRINTKV((" Delay Done.  IBLS = 0x%lx, notify= 0x%lx\n",
+			     HUB_L(BTEREG_LNSTAT_ADDR),
+			  bte->notify));
+		BTE_TIME_XFR_STOP();
 		if (bte->notify & IBLS_ERROR) {
 			/* >>> Need to do real error checking. */
-			transferSize = 0;
+			transfer_size = 0;
 
 #ifdef CONFIG_IA64_SGI_BTE_LOCKING
 			spin_unlock(&(bte->spinlock));
-#endif
+#endif /* CONFIG_IA64_SGI_BTE_LOCKING */
+			BTE_PRINTKV(("Erroring status is 0x%lx and "
+				     "notify is 0x%lx\n",
+				     HUB_L(BTEREG_LNSTAT_ADDR),
+				     bte->notify));
+
+			BTE_TIME_STOP();
+			bte->notify = 0L;
 			return (BTEFAIL_ERROR);
 		}
 
 	}
 #ifdef CONFIG_IA64_SGI_BTE_LOCKING
 	spin_unlock(&(bte->spinlock));
-#endif
-#ifdef DEBUG_TIME_BTE
-	completeTime = ia64_get_itc();
+#endif /* CONFIG_IA64_SGI_BTE_LOCKING */
+	BTE_TIME_STOP();
+	BTE_PRINTKV(("Returning status is 0x%lx and notify is 0x%lx\n",
+		     HUB_L(BTEREG_LNSTAT_ADDR),
+		     *bte->most_rcnt_na));
 
-	BteSetupTime = xferStartTime - invokeTime;
-	BteTransferTime = xferCompleteTime - xferStartTime;
-	BteTeardownTime = completeTime - xferCompleteTime;
-	BteExecuteTime = completeTime - invokeTime;
-#endif
 	return (BTE_SUCCESS);
 }
 
 /*
  * Define the bte_unaligned_copy as an extern.
  */
-extern bte_result_t bte_unaligned_copy(u64, u64, u64, u64, char *);
+extern bte_result_t bte_unaligned_copy(u64, u64, u64, u64);
 
 /*
  * The following is the prefered way of calling bte_unaligned_copy
@@ -299,13 +373,10 @@
  * until the transfer is complete.  In order to get the asynch
  * version of bte_copy, you must perform this check yourself.
  */
-#define BTE_UNALIGNED_COPY(src, dest, len, mode, bteBlock) \
-	if ((len & L1_CACHE_MASK) || \
-	    (src & L1_CACHE_MASK) || \
-	    (dest & L1_CACHE_MASK)) { \
-		bte_unaligned_copy (src, dest, len, mode, bteBlock); \
-	} else { \
-		bte_copy(src, dest, len, mode, NULL); \
-	}
+#define BTE_UNALIGNED_COPY(src, dest, len, mode)			\
+	(((len & L1_CACHE_MASK) || (src & L1_CACHE_MASK) ||		\
+	  (dest & L1_CACHE_MASK)) ?					\
+		bte_unaligned_copy(src, dest, len, mode) :		\
+		bte_copy(src, dest, len, mode, NULL))
 
-#endif				/* _ASM_IA64_SN_BTE_COPY_H */
+#endif /* _ASM_IA64_SN_BTE_COPY_H */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)