Commit 823e911b authored by Mark Goodwin's avatar Mark Goodwin Committed by David Mosberger

[PATCH] ia64: deprecate SN2 linkstatd

This patch against 2.6.5-rc2 affects the SGI/SN platform only. It deprecates
a kernel daemon for our interconnect traffic statistics which has been
replaced by a userland tool.
parent 72de3708
......@@ -162,9 +162,11 @@ shubstats_ioctl(struct inode *inode, struct file *file,
{
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,265 +202,45 @@ shubstats_ioctl(struct inode *inode, struct file *file,
}
break;
default:
return -EINVAL;
}
return 0;
}
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);
case SNDRV_SHUB_GETMMR32:
intarg = shub_mmr_read32(cnode, arg);
if (copy_to_user((void *)arg, &intarg,
sizeof(intarg))) {
return -EFAULT;
}
sprintf(buf, "%4lu.%lu%lu%lu", a, b, c, d);
break;
return buf;
}
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;
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]);
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;
/* 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;
}
default:
return -EINVAL;
}
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);
struct file_operations shub_mon_fops = {
.ioctl = shubstats_ioctl,
};
......@@ -118,59 +118,11 @@ register_sn_force_interrupt(void) {
}
}
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 */
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment