Index: linux-2.6.4/arch/ia64/sn/io/sn2/shub.c =================================================================== --- linux-2.6.4.orig/arch/ia64/sn/io/sn2/shub.c Thu Mar 11 13:55:28 2004 +++ linux-2.6.4/arch/ia64/sn/io/sn2/shub.c Tue Mar 23 14:45:27 2004 @@ -160,11 +160,13 @@ shubstats_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - cnodeid_t cnode; - uint64_t longarg; + cnodeid_t cnode; + uint64_t longarg; + uint64_t intarg; + uint64_t regval[2]; int nasid; - cnode = (cnodeid_t)file->f_dentry->d_fsdata; + cnode = (cnodeid_t)(u64)file->f_dentry->d_fsdata; if (cnode < 0 || cnode >= numnodes) return -ENODEV; @@ -200,6 +202,38 @@ } break; + case SNDRV_SHUB_GETMMR32: + intarg = shub_mmr_read32(cnode, arg); + if (copy_to_user((void *)arg, &intarg, + sizeof(intarg))) { + return -EFAULT; + } + break; + + case SNDRV_SHUB_GETMMR64: + case SNDRV_SHUB_GETMMR64_IO: + if (cmd == SNDRV_SHUB_GETMMR64) + longarg = shub_mmr_read(cnode, arg); + else + longarg = shub_mmr_read_iospace(cnode, arg); + if (copy_to_user((void *)arg, &longarg, sizeof(longarg))) + return -EFAULT; + break; + + case SNDRV_SHUB_PUTMMR64: + case SNDRV_SHUB_PUTMMR64_IO: + if (copy_from_user((void *)regval, (void *)arg, sizeof(regval))) + return -EFAULT; + if (regval[0] & 0x7) { + printk("Error: configure_shub_stats: unaligned address 0x%016lx\n", regval[0]); + return -EINVAL; + } + if (cmd == SNDRV_SHUB_PUTMMR64) + shub_mmr_write(cnode, (shubreg_t)regval[0], regval[1]); + else + shub_mmr_write_iospace(cnode, (shubreg_t)regval[0], regval[1]); + break; + default: return -EINVAL; } @@ -210,255 +244,3 @@ struct file_operations shub_mon_fops = { .ioctl = shubstats_ioctl, }; - -/* - * "linkstatd" kernel thread to export SGI Numalink - * stats via /proc/sgi_sn/linkstats - */ -static struct s_linkstats { - uint64_t hs_ni_sn_errors[2]; - uint64_t hs_ni_cb_errors[2]; - uint64_t hs_ni_retry_errors[2]; - int hs_ii_up; - uint64_t hs_ii_sn_errors; - uint64_t hs_ii_cb_errors; - uint64_t hs_ii_retry_errors; -} *sn_linkstats; - -static spinlock_t sn_linkstats_lock; -static unsigned long sn_linkstats_starttime; -static unsigned long sn_linkstats_samples; -static unsigned long sn_linkstats_overflows; -static unsigned long sn_linkstats_update_msecs; - -void -sn_linkstats_reset(unsigned long msecs) -{ - int cnode; - uint64_t iio_wstat; - uint64_t llp_csr_reg; - - spin_lock(&sn_linkstats_lock); - memset(sn_linkstats, 0, numnodes * sizeof(struct s_linkstats)); - for (cnode=0; cnode < numnodes; cnode++) { - shub_mmr_write(cnode, SH_NI0_LLP_ERR, 0L); - shub_mmr_write(cnode, SH_NI1_LLP_ERR, 0L); - shub_mmr_write_iospace(cnode, IIO_LLP_LOG, 0L); - - /* zero the II retry counter */ - iio_wstat = shub_mmr_read_iospace(cnode, IIO_WSTAT); - iio_wstat &= 0xffffffffff00ffff; /* bits 23:16 */ - shub_mmr_write_iospace(cnode, IIO_WSTAT, iio_wstat); - - /* Check if the II xtalk link is working */ - llp_csr_reg = shub_mmr_read_iospace(cnode, IIO_LLP_CSR); - if (llp_csr_reg & IIO_LLP_CSR_IS_UP) - sn_linkstats[cnode].hs_ii_up = 1; - } - - sn_linkstats_update_msecs = msecs; - sn_linkstats_samples = 0; - sn_linkstats_overflows = 0; - sn_linkstats_starttime = jiffies; - spin_unlock(&sn_linkstats_lock); -} - -int -linkstatd_thread(void *unused) -{ - int cnode; - int overflows; - uint64_t reg[2]; - uint64_t iio_wstat = 0L; - ii_illr_u_t illr; - struct s_linkstats *lsp; - struct task_struct *tsk = current; - - daemonize("linkstatd"); - set_user_nice(tsk, 19); - sigfillset(&tsk->blocked); - strcpy(tsk->comm, "linkstatd"); - - while(1) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(sn_linkstats_update_msecs * HZ / 1000); - - spin_lock(&sn_linkstats_lock); - - overflows = 0; - for (lsp=sn_linkstats, cnode=0; cnode < numnodes; cnode++, lsp++) { - reg[0] = shub_mmr_read(cnode, SH_NI0_LLP_ERR); - reg[1] = shub_mmr_read(cnode, SH_NI1_LLP_ERR); - if (lsp->hs_ii_up) { - illr = (ii_illr_u_t)shub_mmr_read_iospace(cnode, IIO_LLP_LOG); - iio_wstat = shub_mmr_read_iospace(cnode, IIO_WSTAT); - } - - if (!overflows && ( - (reg[0] & SH_NI0_LLP_ERR_RX_SN_ERR_COUNT_MASK) == - SH_NI0_LLP_ERR_RX_SN_ERR_COUNT_MASK || - (reg[0] & SH_NI0_LLP_ERR_RX_CB_ERR_COUNT_MASK) == - SH_NI0_LLP_ERR_RX_CB_ERR_COUNT_MASK || - (reg[1] & SH_NI1_LLP_ERR_RX_SN_ERR_COUNT_MASK) == - SH_NI1_LLP_ERR_RX_SN_ERR_COUNT_MASK || - (reg[1] & SH_NI1_LLP_ERR_RX_CB_ERR_COUNT_MASK) == - SH_NI1_LLP_ERR_RX_CB_ERR_COUNT_MASK || - (lsp->hs_ii_up && illr.ii_illr_fld_s.i_sn_cnt == IIO_LLP_SN_MAX) || - (lsp->hs_ii_up && illr.ii_illr_fld_s.i_cb_cnt == IIO_LLP_CB_MAX))) { - overflows = 1; - } - -#define LINKSTAT_UPDATE(reg, cnt, mask, shift) cnt += (reg & mask) >> shift - - LINKSTAT_UPDATE(reg[0], lsp->hs_ni_sn_errors[0], - SH_NI0_LLP_ERR_RX_SN_ERR_COUNT_MASK, - SH_NI0_LLP_ERR_RX_SN_ERR_COUNT_SHFT); - - LINKSTAT_UPDATE(reg[1], lsp->hs_ni_sn_errors[1], - SH_NI1_LLP_ERR_RX_SN_ERR_COUNT_MASK, - SH_NI1_LLP_ERR_RX_SN_ERR_COUNT_SHFT); - - LINKSTAT_UPDATE(reg[0], lsp->hs_ni_cb_errors[0], - SH_NI0_LLP_ERR_RX_CB_ERR_COUNT_MASK, - SH_NI0_LLP_ERR_RX_CB_ERR_COUNT_SHFT); - - LINKSTAT_UPDATE(reg[1], lsp->hs_ni_cb_errors[1], - SH_NI1_LLP_ERR_RX_CB_ERR_COUNT_MASK, - SH_NI1_LLP_ERR_RX_CB_ERR_COUNT_SHFT); - - LINKSTAT_UPDATE(reg[0], lsp->hs_ni_retry_errors[0], - SH_NI0_LLP_ERR_RETRY_COUNT_MASK, - SH_NI0_LLP_ERR_RETRY_COUNT_SHFT); - - LINKSTAT_UPDATE(reg[1], lsp->hs_ni_retry_errors[1], - SH_NI1_LLP_ERR_RETRY_COUNT_MASK, - SH_NI1_LLP_ERR_RETRY_COUNT_SHFT); - - if (lsp->hs_ii_up) { - /* II sn and cb errors */ - lsp->hs_ii_sn_errors += illr.ii_illr_fld_s.i_sn_cnt; - lsp->hs_ii_cb_errors += illr.ii_illr_fld_s.i_cb_cnt; - lsp->hs_ii_retry_errors += (iio_wstat & 0x0000000000ff0000) >> 16; - - shub_mmr_write(cnode, SH_NI0_LLP_ERR, 0L); - shub_mmr_write(cnode, SH_NI1_LLP_ERR, 0L); - shub_mmr_write_iospace(cnode, IIO_LLP_LOG, 0L); - - /* zero the II retry counter */ - iio_wstat = shub_mmr_read_iospace(cnode, IIO_WSTAT); - iio_wstat &= 0xffffffffff00ffff; /* bits 23:16 */ - shub_mmr_write_iospace(cnode, IIO_WSTAT, iio_wstat); - } - } - - sn_linkstats_samples++; - if (overflows) - sn_linkstats_overflows++; - - spin_unlock(&sn_linkstats_lock); - } -} - -static char * -rate_per_minute(uint64_t val, uint64_t secs) -{ - static char buf[16]; - uint64_t a=0, b=0, c=0, d=0; - - if (secs) { - a = 60 * val / secs; - b = 60 * 10 * val / secs - (10 * a); - c = 60 * 100 * val / secs - (100 * a) - (10 * b); - d = 60 * 1000 * val / secs - (1000 * a) - (100 * b) - (10 * c); - } - sprintf(buf, "%4lu.%lu%lu%lu", a, b, c, d); - - return buf; -} - -int -sn_linkstats_get(char *page) -{ - int n = 0; - int cnode; - int nlport; - struct s_linkstats *lsp; - nodepda_t *npda; - uint64_t snsum = 0; - uint64_t cbsum = 0; - uint64_t retrysum = 0; - uint64_t snsum_ii = 0; - uint64_t cbsum_ii = 0; - uint64_t retrysum_ii = 0; - uint64_t secs; - - spin_lock(&sn_linkstats_lock); - secs = (jiffies - sn_linkstats_starttime) / HZ; - - n += sprintf(page, "# SGI Numalink stats v1 : %lu samples, %lu o/flows, update %lu msecs\n", - sn_linkstats_samples, sn_linkstats_overflows, sn_linkstats_update_msecs); - - n += sprintf(page+n, "%-37s %8s %8s %8s %8s\n", - "# Numalink", "sn errs", "cb errs", "cb/min", "retries"); - - for (lsp=sn_linkstats, cnode=0; cnode < numnodes; cnode++, lsp++) { - npda = NODEPDA(cnode); - - /* two NL links on each SHub */ - for (nlport=0; nlport < 2; nlport++) { - cbsum += lsp->hs_ni_cb_errors[nlport]; - snsum += lsp->hs_ni_sn_errors[nlport]; - retrysum += lsp->hs_ni_retry_errors[nlport]; - - /* avoid buffer overrun (should be using seq_read API) */ - if (numnodes > 64) - continue; - - n += sprintf(page + n, "/%s/link/%d %8lu %8lu %8s %8lu\n", - npda->hwg_node_name, nlport+1, lsp->hs_ni_sn_errors[nlport], - lsp->hs_ni_cb_errors[nlport], - rate_per_minute(lsp->hs_ni_cb_errors[nlport], secs), - lsp->hs_ni_retry_errors[nlport]); - } - - /* one II port on each SHub (may not be connected) */ - if (lsp->hs_ii_up) { - n += sprintf(page + n, "/%s/xtalk %8lu %8lu %8s %8lu\n", - npda->hwg_node_name, lsp->hs_ii_sn_errors, - lsp->hs_ii_cb_errors, rate_per_minute(lsp->hs_ii_cb_errors, secs), - lsp->hs_ii_retry_errors); - - snsum_ii += lsp->hs_ii_sn_errors; - cbsum_ii += lsp->hs_ii_cb_errors; - retrysum_ii += lsp->hs_ii_retry_errors; - } - } - - n += sprintf(page + n, "%-37s %8lu %8lu %8s %8lu\n", - "System wide NL totals", snsum, cbsum, - rate_per_minute(cbsum, secs), retrysum); - - n += sprintf(page + n, "%-37s %8lu %8lu %8s %8lu\n", - "System wide II totals", snsum_ii, cbsum_ii, - rate_per_minute(cbsum_ii, secs), retrysum_ii); - - spin_unlock(&sn_linkstats_lock); - - return n; -} - -static int __init -linkstatd_init(void) -{ - if (!ia64_platform_is("sn2")) - return -ENODEV; - - spin_lock_init(&sn_linkstats_lock); - sn_linkstats = kmalloc(numnodes * sizeof(struct s_linkstats), GFP_KERNEL); - sn_linkstats_reset(60000UL); /* default 60 second update interval */ - kernel_thread(linkstatd_thread, NULL, CLONE_KERNEL); - - return 0; -} - -__initcall(linkstatd_init); Index: linux-2.6.4/arch/ia64/sn/kernel/sn2/sn_proc_fs.c =================================================================== --- linux-2.6.4.orig/arch/ia64/sn/kernel/sn2/sn_proc_fs.c Thu Mar 11 13:55:51 2004 +++ linux-2.6.4/arch/ia64/sn/kernel/sn2/sn_proc_fs.c Tue Mar 23 14:36:53 2004 @@ -113,59 +113,11 @@ } } -extern int sn_linkstats_get(char *); -extern int sn_linkstats_reset(unsigned long); - -static int -sn_linkstats_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) { - - return sn_linkstats_get(page); -} - -static int -sn_linkstats_write_proc(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - char s[64]; - unsigned long msecs; - int e = count; - - if (copy_from_user(s, buffer, count < sizeof(s) ? count : sizeof(s))) - e = -EFAULT; - else { - if (sscanf(s, "%lu", &msecs) != 1 || msecs < 5) - /* at least 5 milliseconds between updates */ - e = -EINVAL; - else - sn_linkstats_reset(msecs); - } - - return e; -} - -void -register_sn_linkstats(void) { - struct proc_dir_entry *entry; - - if (!sgi_proc_dir) { - sgi_proc_dir = proc_mkdir("sgi_sn", 0); - } - entry = create_proc_entry("linkstats", 0444, sgi_proc_dir); - if (entry) { - entry->nlink = 1; - entry->data = 0; - entry->read_proc = sn_linkstats_read_proc; - entry->write_proc = sn_linkstats_write_proc; - } -} - void register_sn_procfs(void) { register_sn_partition_id(); register_sn_serial_numbers(); register_sn_force_interrupt(); - register_sn_linkstats(); } #endif /* CONFIG_PROC_FS */ Index: linux-2.6.4/include/asm-ia64/sn/sndrv.h =================================================================== --- linux-2.6.4.orig/include/asm-ia64/sn/sndrv.h Thu Mar 11 13:55:28 2004 +++ linux-2.6.4/include/asm-ia64/sn/sndrv.h Tue Mar 23 14:36:53 2004 @@ -41,6 +41,11 @@ #define SNDRV_SHUB_RESETSTATS 42 #define SNDRV_SHUB_GETSTATS 43 #define SNDRV_SHUB_GETNASID 44 +#define SNDRV_SHUB_GETMMR32 45 +#define SNDRV_SHUB_GETMMR64 46 +#define SNDRV_SHUB_GETMMR64_IO 47 +#define SNDRV_SHUB_PUTMMR64 48 +#define SNDRV_SHUB_PUTMMR64_IO 49 /* Devices */ #define SNDRV_UKNOWN_DEVICE -1