patch-2.4.20 linux-2.4.20/arch/mips/sibyte/sb1250/bcm1250_tbprof.c

Next file: linux-2.4.20/arch/mips/sibyte/sb1250/bcm1250_tbprof.h
Previous file: linux-2.4.20/arch/mips/sibyte/sb1250/Makefile
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/arch/mips/sibyte/sb1250/bcm1250_tbprof.c linux-2.4.20/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
@@ -10,7 +10,7 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -50,20 +50,26 @@
  * overflow.
  *
  * We map the interrupt for trace_buffer_freeze to handle it on CPU 0.
- * 
+ *
  ************************************************************************/
 
-/* Once per second on a 500 Mhz 1250 */
-#define TB_PERIOD 250000000ULL
+/* 100 samples per second on a 500 Mhz 1250 */
+#define TB_PERIOD 2500000ULL
 
 static void arm_tb(void)
 {
+        unsigned long long scdperfcnt;
 	unsigned long long next = (1ULL << 40) - TB_PERIOD;
 	/* Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to
 	   trigger start of trace.  XXX vary sampling period */
 	out64(0, KSEG1 + A_SCD_PERF_CNT_1);
-	out64(in64(KSEG1 + A_SCD_PERF_CNT_CFG) | // keep counters 0,2,3 as is
+	scdperfcnt = in64(KSEG1 + A_SCD_PERF_CNT_CFG);
+	/* Unfortunately, in Pass 2 we must clear all counters to knock down
+	   a previous interrupt request.  This means that bus profiling
+	   requires ALL of the SCD perf counters. */
+	out64((scdperfcnt & ~M_SPC_CFG_SRC1) | // keep counters 0,2,3 as is
 		   M_SPC_CFG_ENABLE |		 // enable counting
+		   M_SPC_CFG_CLEAR |		 // clear all counters
 		   V_SPC_CFG_SRC1(1),		 // counter 1 counts cycles
 	      KSEG1 + A_SCD_PERF_CNT_CFG);
 	out64(next, KSEG1 + A_SCD_PERF_CNT_1);
@@ -150,17 +156,17 @@
 	out64(0, KSEG1 + A_ADDR_TRAP_UP_1);
 	out64(0, KSEG1 + A_ADDR_TRAP_UP_2);
 	out64(0, KSEG1 + A_ADDR_TRAP_UP_3);
-	
+
 	out64(0, KSEG1 + A_ADDR_TRAP_DOWN_0);
 	out64(0, KSEG1 + A_ADDR_TRAP_DOWN_1);
 	out64(0, KSEG1 + A_ADDR_TRAP_DOWN_2);
 	out64(0, KSEG1 + A_ADDR_TRAP_DOWN_3);
-	
+
 	out64(0, KSEG1 + A_ADDR_TRAP_CFG_0);
 	out64(0, KSEG1 + A_ADDR_TRAP_CFG_1);
 	out64(0, KSEG1 + A_ADDR_TRAP_CFG_2);
 	out64(0, KSEG1 + A_ADDR_TRAP_CFG_3);
-	
+
 	/* Initialize Trace Event 0-7 */
 	//				when interrupt
 	out64(M_SCD_TREVT_INTERRUPT, KSEG1 + A_SCD_TRACE_EVENT_0);
@@ -171,7 +177,7 @@
 	out64(0, KSEG1 + A_SCD_TRACE_EVENT_5);
 	out64(0, KSEG1 + A_SCD_TRACE_EVENT_6);
 	out64(0, KSEG1 + A_SCD_TRACE_EVENT_7);
-	
+
 	/* Initialize Trace Sequence 0-7 */
 	//				     Start on event 0 (interrupt)
 	out64(V_SCD_TRSEQ_FUNC_START|0x0fff,
@@ -252,7 +258,7 @@
 static int sbprof_tb_release(struct inode *inode, struct file *filp)
 {
 	int minor;
-	
+
 	minor = MINOR(inode->i_rdev);
 	if (minor != 0 || sbp == NULL) {
 		return -ENODEV;
@@ -269,7 +275,7 @@
 	return 0;
 }
 
-static ssize_t sbprof_tb_read(struct file *filp, char *buf, 
+static ssize_t sbprof_tb_read(struct file *filp, char *buf,
 			   size_t size, loff_t *offp)
 {
 	int cur_sample, sample_off, cur_count, sample_left;
@@ -309,9 +315,9 @@
 #define SBPROF_ZBSTOP	_IOW('s', 1, int)
 #define SBPROF_ZBFULL	_IOW('s', 2, int)
 
-static int sbprof_tb_ioctl(struct inode *inode, 
+static int sbprof_tb_ioctl(struct inode *inode,
 			struct file *filp,
-			unsigned int command, 
+			unsigned int command,
 			unsigned long arg)
 {
 	int error = 0;
@@ -346,7 +352,7 @@
 
 static devfs_handle_t devfs_handle;
 
-static int __init sbprof_tb_init(void) 
+static int __init sbprof_tb_init(void)
 {
 	if (devfs_register_chrdev(SBPROF_TB_MAJOR, DEVNAME, &sbprof_tb_fops)) {
 		printk(KERN_WARNING DEVNAME ": initialization failed (dev %d)\n",

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