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
- Lines: 464
- Date:
2003-06-13 07:51:38.000000000 -0700
- Orig file:
linux-2.4.20/include/asm-ia64/sn/bte_copy.h
- Orig date:
2002-08-02 17:39:45.000000000 -0700
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)