2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
9 #include <linux/types.h>
10 #include <linux/slab.h>
11 #include <linux/interrupt.h>
12 #include <linux/seq_file.h>
13 #include <linux/sched.h>
16 #include <asm/hw_irq.h>
17 #include <asm/system.h>
18 #include <asm/sn/sgi.h>
19 #include <asm/uaccess.h>
20 #include <asm/sn/hcl.h>
21 #include <asm/sn/labelcl.h>
22 #include <asm/sn/io.h>
23 #include <asm/sn/sn_private.h>
24 #include <asm/sn/klconfig.h>
25 #include <asm/sn/sn_cpuid.h>
26 #include <asm/sn/pci/pciio.h>
27 #include <asm/sn/pci/pcibr.h>
28 #include <asm/sn/xtalk/xtalk.h>
29 #include <asm/sn/pci/pcibr_private.h>
30 #include <asm/sn/intr.h>
31 #include <asm/sn/sn2/shub_mmr.h>
32 #include <asm/sn/sn2/shub_mmr_t.h>
34 #include <asm/sn/sn_sal.h>
35 #include <asm/sn/sndrv.h>
36 #include <asm/sn/sn2/shubio.h>
38 #define SHUB_NUM_ECF_REGISTERS 8
40 static uint32_t shub_perf_counts[SHUB_NUM_ECF_REGISTERS];
42 static shubreg_t shub_perf_counts_regs[SHUB_NUM_ECF_REGISTERS] = {
43 SH_PERFORMANCE_COUNTER0,
44 SH_PERFORMANCE_COUNTER1,
45 SH_PERFORMANCE_COUNTER2,
46 SH_PERFORMANCE_COUNTER3,
47 SH_PERFORMANCE_COUNTER4,
48 SH_PERFORMANCE_COUNTER5,
49 SH_PERFORMANCE_COUNTER6,
50 SH_PERFORMANCE_COUNTER7
54 shub_mmr_write(cnodeid_t cnode, shubreg_t reg, uint64_t val)
56 int nasid = cnodeid_to_nasid(cnode);
57 volatile uint64_t *addr = (uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg));
64 shub_mmr_write_iospace(cnodeid_t cnode, shubreg_t reg, uint64_t val)
66 int nasid = cnodeid_to_nasid(cnode);
68 REMOTE_HUB_S(nasid, reg, val);
72 shub_mmr_write32(cnodeid_t cnode, shubreg_t reg, uint32_t val)
74 int nasid = cnodeid_to_nasid(cnode);
75 volatile uint32_t *addr = (uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg));
81 static inline uint64_t
82 shub_mmr_read(cnodeid_t cnode, shubreg_t reg)
84 int nasid = cnodeid_to_nasid(cnode);
85 volatile uint64_t val;
87 val = *(uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg));
93 static inline uint64_t
94 shub_mmr_read_iospace(cnodeid_t cnode, shubreg_t reg)
96 int nasid = cnodeid_to_nasid(cnode);
98 return REMOTE_HUB_L(nasid, reg);
101 static inline uint32_t
102 shub_mmr_read32(cnodeid_t cnode, shubreg_t reg)
104 int nasid = cnodeid_to_nasid(cnode);
105 volatile uint32_t val;
107 val = *(uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg));
114 reset_shub_stats(cnodeid_t cnode)
118 for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) {
119 shub_perf_counts[i] = 0;
120 shub_mmr_write32(cnode, shub_perf_counts_regs[i], 0);
126 configure_shub_stats(cnodeid_t cnode, unsigned long arg)
128 uint64_t *p = (uint64_t *)arg;
133 if (copy_from_user((void *)®cnt, p, sizeof(regcnt)))
136 for (p++, i=0; i < regcnt; i++, p += 2) {
137 if (copy_from_user((void *)regval, (void *)p, sizeof(regval)))
139 if (regval[0] & 0x7) {
140 printk("Error: configure_shub_stats: unaligned address 0x%016lx\n", regval[0]);
143 shub_mmr_write(cnode, (shubreg_t)regval[0], regval[1]);
149 capture_shub_stats(cnodeid_t cnode, uint32_t *counts)
153 for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) {
154 counts[i] = shub_mmr_read32(cnode, shub_perf_counts_regs[i]);
160 shubstats_ioctl(struct inode *inode, struct file *file,
161 unsigned int cmd, unsigned long arg)
169 cnode = (cnodeid_t)(u64)file->f_dentry->d_fsdata;
170 if (cnode < 0 || cnode >= numnodes)
174 case SNDRV_SHUB_CONFIGURE:
175 return configure_shub_stats(cnode, arg);
178 case SNDRV_SHUB_RESETSTATS:
179 reset_shub_stats(cnode);
182 case SNDRV_SHUB_INFOSIZE:
183 longarg = sizeof(shub_perf_counts);
184 if (copy_to_user((void *)arg, &longarg, sizeof(longarg))) {
189 case SNDRV_SHUB_GETSTATS:
190 capture_shub_stats(cnode, shub_perf_counts);
191 if (copy_to_user((void *)arg, shub_perf_counts,
192 sizeof(shub_perf_counts))) {
197 case SNDRV_SHUB_GETNASID:
198 nasid = cnodeid_to_nasid(cnode);
199 if (copy_to_user((void *)arg, &nasid,
205 case SNDRV_SHUB_GETMMR32:
206 intarg = shub_mmr_read32(cnode, arg);
207 if (copy_to_user((void *)arg, &intarg,
213 case SNDRV_SHUB_GETMMR64:
214 case SNDRV_SHUB_GETMMR64_IO:
215 if (cmd == SNDRV_SHUB_GETMMR64)
216 longarg = shub_mmr_read(cnode, arg);
218 longarg = shub_mmr_read_iospace(cnode, arg);
219 if (copy_to_user((void *)arg, &longarg, sizeof(longarg)))
223 case SNDRV_SHUB_PUTMMR64:
224 case SNDRV_SHUB_PUTMMR64_IO:
225 if (copy_from_user((void *)regval, (void *)arg, sizeof(regval)))
227 if (regval[0] & 0x7) {
228 printk("Error: configure_shub_stats: unaligned address 0x%016lx\n", regval[0]);
231 if (cmd == SNDRV_SHUB_PUTMMR64)
232 shub_mmr_write(cnode, (shubreg_t)regval[0], regval[1]);
234 shub_mmr_write_iospace(cnode, (shubreg_t)regval[0], regval[1]);
244 struct file_operations shub_mon_fops = {
245 .ioctl = shubstats_ioctl,