diff mbox series

[01/28] char: remove the SGI snsc driver

Message ID 20190813072514.23299-2-hch@lst.de
State Not Applicable
Delegated to: David Miller
Headers show
Series [01/28] char: remove the SGI snsc driver | expand

Commit Message

Christoph Hellwig Aug. 13, 2019, 7:24 a.m. UTC
The SGI SN2 support is about to be removed.  Remove this driver that
depends on the SN2 support.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/ia64/configs/generic_defconfig   |   1 -
 arch/ia64/configs/gensparse_defconfig |   1 -
 drivers/char/Kconfig                  |   8 -
 drivers/char/Makefile                 |   1 -
 drivers/char/snsc.c                   | 469 --------------------------
 drivers/char/snsc.h                   |  92 -----
 drivers/char/snsc_event.c             | 303 -----------------
 7 files changed, 875 deletions(-)
 delete mode 100644 drivers/char/snsc.c
 delete mode 100644 drivers/char/snsc.h
 delete mode 100644 drivers/char/snsc_event.c
diff mbox series

Patch

diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
index 81f686dee53c..22b98ddc9913 100644
--- a/arch/ia64/configs/generic_defconfig
+++ b/arch/ia64/configs/generic_defconfig
@@ -90,7 +90,6 @@  CONFIG_IGB=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_GAMEPORT=m
 CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_SGI_SNSC=y
 CONFIG_SGI_TIOCX=y
 CONFIG_SGI_MBCS=m
 CONFIG_SERIAL_8250=y
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index 5b4fcdd51457..1d230c0a90bd 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -79,7 +79,6 @@  CONFIG_E1000=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_GAMEPORT=m
 CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_SGI_SNSC=y
 CONFIG_SGI_TIOCX=y
 CONFIG_SGI_MBCS=m
 CONFIG_SERIAL_8250=y
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3e866885a405..c9fbbc6a3967 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -26,14 +26,6 @@  config DEVKMEM
 	  kind of kernel debugging operations.
 	  When in doubt, say "N".
 
-config SGI_SNSC
-	bool "SGI Altix system controller communication support"
-	depends on (IA64_SGI_SN2 || IA64_GENERIC)
-	help
-	  If you have an SGI Altix and you want to enable system
-	  controller communication from user space (you want this!),
-	  say Y.  Otherwise, say N.
-
 config SGI_TIOCX
        bool "SGI TIO CX driver support"
        depends on (IA64_SGI_SN2 || IA64_GENERIC)
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index fbea7dd12932..50835d420471 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -9,7 +9,6 @@  obj-y				+= misc.o
 obj-$(CONFIG_ATARI_DSP56K)	+= dsp56k.o
 obj-$(CONFIG_VIRTIO_CONSOLE)	+= virtio_console.o
 obj-$(CONFIG_RAW_DRIVER)	+= raw.o
-obj-$(CONFIG_SGI_SNSC)		+= snsc.o snsc_event.o
 obj-$(CONFIG_MSPEC)		+= mspec.o
 obj-$(CONFIG_UV_MMTIMER)	+= uv_mmtimer.o
 obj-$(CONFIG_IBM_BSR)		+= bsr.o
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
deleted file mode 100644
index 5918ea7499bb..000000000000
--- a/drivers/char/snsc.c
+++ /dev/null
@@ -1,469 +0,0 @@ 
-/*
- * SN Platform system controller communication support
- *
- * 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) 2004, 2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-/*
- * System controller communication driver
- *
- * This driver allows a user process to communicate with the system
- * controller (a.k.a. "IRouter") network in an SGI SN system.
- */
-
-#include <linux/interrupt.h>
-#include <linux/sched/signal.h>
-#include <linux/device.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <asm/sn/io.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/sn/module.h>
-#include <asm/sn/geo.h>
-#include <asm/sn/nodepda.h>
-#include "snsc.h"
-
-#define SYSCTL_BASENAME	"snsc"
-
-#define SCDRV_BUFSZ	2048
-#define SCDRV_TIMEOUT	1000
-
-static DEFINE_MUTEX(scdrv_mutex);
-static irqreturn_t
-scdrv_interrupt(int irq, void *subch_data)
-{
-	struct subch_data_s *sd = subch_data;
-	unsigned long flags;
-	int status;
-
-	spin_lock_irqsave(&sd->sd_rlock, flags);
-	spin_lock(&sd->sd_wlock);
-	status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
-
-	if (status > 0) {
-		if (status & SAL_IROUTER_INTR_RECV) {
-			wake_up(&sd->sd_rq);
-		}
-		if (status & SAL_IROUTER_INTR_XMIT) {
-			ia64_sn_irtr_intr_disable
-			    (sd->sd_nasid, sd->sd_subch,
-			     SAL_IROUTER_INTR_XMIT);
-			wake_up(&sd->sd_wq);
-		}
-	}
-	spin_unlock(&sd->sd_wlock);
-	spin_unlock_irqrestore(&sd->sd_rlock, flags);
-	return IRQ_HANDLED;
-}
-
-/*
- * scdrv_open
- *
- * Reserve a subchannel for system controller communication.
- */
-
-static int
-scdrv_open(struct inode *inode, struct file *file)
-{
-	struct sysctl_data_s *scd;
-	struct subch_data_s *sd;
-	int rv;
-
-	/* look up device info for this device file */
-	scd = container_of(inode->i_cdev, struct sysctl_data_s, scd_cdev);
-
-	/* allocate memory for subchannel data */
-	sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL);
-	if (sd == NULL) {
-		printk("%s: couldn't allocate subchannel data\n",
-		       __func__);
-		return -ENOMEM;
-	}
-
-	/* initialize subch_data_s fields */
-	sd->sd_nasid = scd->scd_nasid;
-	sd->sd_subch = ia64_sn_irtr_open(scd->scd_nasid);
-
-	if (sd->sd_subch < 0) {
-		kfree(sd);
-		printk("%s: couldn't allocate subchannel\n", __func__);
-		return -EBUSY;
-	}
-
-	spin_lock_init(&sd->sd_rlock);
-	spin_lock_init(&sd->sd_wlock);
-	init_waitqueue_head(&sd->sd_rq);
-	init_waitqueue_head(&sd->sd_wq);
-	sema_init(&sd->sd_rbs, 1);
-	sema_init(&sd->sd_wbs, 1);
-
-	file->private_data = sd;
-
-	/* hook this subchannel up to the system controller interrupt */
-	mutex_lock(&scdrv_mutex);
-	rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
-			 IRQF_SHARED, SYSCTL_BASENAME, sd);
-	if (rv) {
-		ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
-		kfree(sd);
-		printk("%s: irq request failed (%d)\n", __func__, rv);
-		mutex_unlock(&scdrv_mutex);
-		return -EBUSY;
-	}
-	mutex_unlock(&scdrv_mutex);
-	return 0;
-}
-
-/*
- * scdrv_release
- *
- * Release a previously-reserved subchannel.
- */
-
-static int
-scdrv_release(struct inode *inode, struct file *file)
-{
-	struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
-	int rv;
-
-	/* free the interrupt */
-	free_irq(SGI_UART_VECTOR, sd);
-
-	/* ask SAL to close the subchannel */
-	rv = ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
-
-	kfree(sd);
-	return rv;
-}
-
-/*
- * scdrv_read
- *
- * Called to read bytes from the open IRouter pipe.
- *
- */
-
-static inline int
-read_status_check(struct subch_data_s *sd, int *len)
-{
-	return ia64_sn_irtr_recv(sd->sd_nasid, sd->sd_subch, sd->sd_rb, len);
-}
-
-static ssize_t
-scdrv_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
-{
-	int status;
-	int len;
-	unsigned long flags;
-	struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
-
-	/* try to get control of the read buffer */
-	if (down_trylock(&sd->sd_rbs)) {
-		/* somebody else has it now;
-		 * if we're non-blocking, then exit...
-		 */
-		if (file->f_flags & O_NONBLOCK) {
-			return -EAGAIN;
-		}
-		/* ...or if we want to block, then do so here */
-		if (down_interruptible(&sd->sd_rbs)) {
-			/* something went wrong with wait */
-			return -ERESTARTSYS;
-		}
-	}
-
-	/* anything to read? */
-	len = CHUNKSIZE;
-	spin_lock_irqsave(&sd->sd_rlock, flags);
-	status = read_status_check(sd, &len);
-
-	/* if not, and we're blocking I/O, loop */
-	while (status < 0) {
-		DECLARE_WAITQUEUE(wait, current);
-
-		if (file->f_flags & O_NONBLOCK) {
-			spin_unlock_irqrestore(&sd->sd_rlock, flags);
-			up(&sd->sd_rbs);
-			return -EAGAIN;
-		}
-
-		len = CHUNKSIZE;
-		set_current_state(TASK_INTERRUPTIBLE);
-		add_wait_queue(&sd->sd_rq, &wait);
-		spin_unlock_irqrestore(&sd->sd_rlock, flags);
-
-		schedule_timeout(msecs_to_jiffies(SCDRV_TIMEOUT));
-
-		remove_wait_queue(&sd->sd_rq, &wait);
-		if (signal_pending(current)) {
-			/* wait was interrupted */
-			up(&sd->sd_rbs);
-			return -ERESTARTSYS;
-		}
-
-		spin_lock_irqsave(&sd->sd_rlock, flags);
-		status = read_status_check(sd, &len);
-	}
-	spin_unlock_irqrestore(&sd->sd_rlock, flags);
-
-	if (len > 0) {
-		/* we read something in the last read_status_check(); copy
-		 * it out to user space
-		 */
-		if (count < len) {
-			pr_debug("%s: only accepting %d of %d bytes\n",
-				 __func__, (int) count, len);
-		}
-		len = min((int) count, len);
-		if (copy_to_user(buf, sd->sd_rb, len))
-			len = -EFAULT;
-	}
-
-	/* release the read buffer and wake anyone who might be
-	 * waiting for it
-	 */
-	up(&sd->sd_rbs);
-
-	/* return the number of characters read in */
-	return len;
-}
-
-/*
- * scdrv_write
- *
- * Writes a chunk of an IRouter packet (or other system controller data)
- * to the system controller.
- *
- */
-static inline int
-write_status_check(struct subch_data_s *sd, int count)
-{
-	return ia64_sn_irtr_send(sd->sd_nasid, sd->sd_subch, sd->sd_wb, count);
-}
-
-static ssize_t
-scdrv_write(struct file *file, const char __user *buf,
-	    size_t count, loff_t *f_pos)
-{
-	unsigned long flags;
-	int status;
-	struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
-
-	/* try to get control of the write buffer */
-	if (down_trylock(&sd->sd_wbs)) {
-		/* somebody else has it now;
-		 * if we're non-blocking, then exit...
-		 */
-		if (file->f_flags & O_NONBLOCK) {
-			return -EAGAIN;
-		}
-		/* ...or if we want to block, then do so here */
-		if (down_interruptible(&sd->sd_wbs)) {
-			/* something went wrong with wait */
-			return -ERESTARTSYS;
-		}
-	}
-
-	count = min((int) count, CHUNKSIZE);
-	if (copy_from_user(sd->sd_wb, buf, count)) {
-		up(&sd->sd_wbs);
-		return -EFAULT;
-	}
-
-	/* try to send the buffer */
-	spin_lock_irqsave(&sd->sd_wlock, flags);
-	status = write_status_check(sd, count);
-
-	/* if we failed, and we want to block, then loop */
-	while (status <= 0) {
-		DECLARE_WAITQUEUE(wait, current);
-
-		if (file->f_flags & O_NONBLOCK) {
-			spin_unlock_irqrestore(&sd->sd_wlock, flags);
-			up(&sd->sd_wbs);
-			return -EAGAIN;
-		}
-
-		set_current_state(TASK_INTERRUPTIBLE);
-		add_wait_queue(&sd->sd_wq, &wait);
-		spin_unlock_irqrestore(&sd->sd_wlock, flags);
-
-		schedule_timeout(msecs_to_jiffies(SCDRV_TIMEOUT));
-
-		remove_wait_queue(&sd->sd_wq, &wait);
-		if (signal_pending(current)) {
-			/* wait was interrupted */
-			up(&sd->sd_wbs);
-			return -ERESTARTSYS;
-		}
-
-		spin_lock_irqsave(&sd->sd_wlock, flags);
-		status = write_status_check(sd, count);
-	}
-	spin_unlock_irqrestore(&sd->sd_wlock, flags);
-
-	/* release the write buffer and wake anyone who's waiting for it */
-	up(&sd->sd_wbs);
-
-	/* return the number of characters accepted (should be the complete
-	 * "chunk" as requested)
-	 */
-	if ((status >= 0) && (status < count)) {
-		pr_debug("Didn't accept the full chunk; %d of %d\n",
-			 status, (int) count);
-	}
-	return status;
-}
-
-static __poll_t
-scdrv_poll(struct file *file, struct poll_table_struct *wait)
-{
-	__poll_t mask = 0;
-	int status = 0;
-	struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
-	unsigned long flags;
-
-	poll_wait(file, &sd->sd_rq, wait);
-	poll_wait(file, &sd->sd_wq, wait);
-
-	spin_lock_irqsave(&sd->sd_rlock, flags);
-	spin_lock(&sd->sd_wlock);
-	status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
-	spin_unlock(&sd->sd_wlock);
-	spin_unlock_irqrestore(&sd->sd_rlock, flags);
-
-	if (status > 0) {
-		if (status & SAL_IROUTER_INTR_RECV) {
-			mask |= EPOLLIN | EPOLLRDNORM;
-		}
-		if (status & SAL_IROUTER_INTR_XMIT) {
-			mask |= EPOLLOUT | EPOLLWRNORM;
-		}
-	}
-
-	return mask;
-}
-
-static const struct file_operations scdrv_fops = {
-	.owner =	THIS_MODULE,
-	.read =		scdrv_read,
-	.write =	scdrv_write,
-	.poll =		scdrv_poll,
-	.open =		scdrv_open,
-	.release =	scdrv_release,
-	.llseek =	noop_llseek,
-};
-
-static struct class *snsc_class;
-
-/*
- * scdrv_init
- *
- * Called at boot time to initialize the system controller communication
- * facility.
- */
-int __init
-scdrv_init(void)
-{
-	geoid_t geoid;
-	cnodeid_t cnode;
-	char devname[32];
-	char *devnamep;
-	struct sysctl_data_s *scd;
-	void *salbuf;
-	dev_t first_dev, dev;
-	nasid_t event_nasid;
-
-	if (!ia64_platform_is("sn2"))
-		return -ENODEV;
-
-	event_nasid = ia64_sn_get_console_nasid();
-
-	snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
-	if (IS_ERR(snsc_class)) {
-		printk("%s: failed to allocate class\n", __func__);
-		return PTR_ERR(snsc_class);
-	}
-
-	if (alloc_chrdev_region(&first_dev, 0, num_cnodes,
-				SYSCTL_BASENAME) < 0) {
-		printk("%s: failed to register SN system controller device\n",
-		       __func__);
-		return -ENODEV;
-	}
-
-	for (cnode = 0; cnode < num_cnodes; cnode++) {
-			geoid = cnodeid_get_geoid(cnode);
-			devnamep = devname;
-			format_module_id(devnamep, geo_module(geoid),
-					 MODULE_FORMAT_BRIEF);
-			devnamep = devname + strlen(devname);
-			sprintf(devnamep, "^%d#%d", geo_slot(geoid),
-				geo_slab(geoid));
-
-			/* allocate sysctl device data */
-			scd = kzalloc(sizeof (struct sysctl_data_s),
-				      GFP_KERNEL);
-			if (!scd) {
-				printk("%s: failed to allocate device info"
-				       "for %s/%s\n", __func__,
-				       SYSCTL_BASENAME, devname);
-				continue;
-			}
-
-			/* initialize sysctl device data fields */
-			scd->scd_nasid = cnodeid_to_nasid(cnode);
-			if (!(salbuf = kmalloc(SCDRV_BUFSZ, GFP_KERNEL))) {
-				printk("%s: failed to allocate driver buffer"
-				       "(%s%s)\n", __func__,
-				       SYSCTL_BASENAME, devname);
-				kfree(scd);
-				continue;
-			}
-
-			if (ia64_sn_irtr_init(scd->scd_nasid, salbuf,
-					      SCDRV_BUFSZ) < 0) {
-				printk
-				    ("%s: failed to initialize SAL for"
-				     " system controller communication"
-				     " (%s/%s): outdated PROM?\n",
-				     __func__, SYSCTL_BASENAME, devname);
-				kfree(scd);
-				kfree(salbuf);
-				continue;
-			}
-
-			dev = first_dev + cnode;
-			cdev_init(&scd->scd_cdev, &scdrv_fops);
-			if (cdev_add(&scd->scd_cdev, dev, 1)) {
-				printk("%s: failed to register system"
-				       " controller device (%s%s)\n",
-				       __func__, SYSCTL_BASENAME, devname);
-				kfree(scd);
-				kfree(salbuf);
-				continue;
-			}
-
-			device_create(snsc_class, NULL, dev, NULL,
-				      "%s", devname);
-
-			ia64_sn_irtr_intr_enable(scd->scd_nasid,
-						 0 /*ignored */ ,
-						 SAL_IROUTER_INTR_RECV);
-
-                        /* on the console nasid, prepare to receive
-                         * system controller environmental events
-                         */
-                        if(scd->scd_nasid == event_nasid) {
-                                scdrv_event_init(scd);
-                        }
-	}
-	return 0;
-}
-device_initcall(scdrv_init);
diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h
deleted file mode 100644
index e8c52c882b21..000000000000
--- a/drivers/char/snsc.h
+++ /dev/null
@@ -1,92 +0,0 @@ 
-/*
- * SN Platform system controller communication support
- *
- * 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) 2004-2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-/*
- * This file contains macros and data types for communication with the
- * system controllers in SGI SN systems.
- */
-
-#ifndef _SN_SYSCTL_H_
-#define _SN_SYSCTL_H_
-
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/semaphore.h>
-#include <asm/sn/types.h>
-
-#define CHUNKSIZE 127
-
-/* This structure is used to track an open subchannel. */
-struct subch_data_s {
-	nasid_t sd_nasid;	/* node on which the subchannel was opened */
-	int sd_subch;		/* subchannel number */
-	spinlock_t sd_rlock;	/* monitor lock for rsv */
-	spinlock_t sd_wlock;	/* monitor lock for wsv */
-	wait_queue_head_t sd_rq;	/* wait queue for readers */
-	wait_queue_head_t sd_wq;	/* wait queue for writers */
-	struct semaphore sd_rbs;	/* semaphore for read buffer */
-	struct semaphore sd_wbs;	/* semaphore for write buffer */
-
-	char sd_rb[CHUNKSIZE];	/* read buffer */
-	char sd_wb[CHUNKSIZE];	/* write buffer */
-};
-
-struct sysctl_data_s {
-	struct cdev scd_cdev;	/* Character device info */
-	nasid_t scd_nasid;	/* Node on which subchannels are opened. */
-};
-
-
-/* argument types */
-#define IR_ARG_INT              0x00    /* 4-byte integer (big-endian)  */
-#define IR_ARG_ASCII            0x01    /* null-terminated ASCII string */
-#define IR_ARG_UNKNOWN          0x80    /* unknown data type.  The low
-                                         * 7 bits will contain the data
-                                         * length.                      */
-#define IR_ARG_UNKNOWN_LENGTH_MASK	0x7f
-
-
-/* system controller event codes */
-#define EV_CLASS_MASK		0xf000ul
-#define EV_SEVERITY_MASK	0x0f00ul
-#define EV_COMPONENT_MASK	0x00fful
-
-#define EV_CLASS_POWER		0x1000ul
-#define EV_CLASS_FAN		0x2000ul
-#define EV_CLASS_TEMP		0x3000ul
-#define EV_CLASS_ENV		0x4000ul
-#define EV_CLASS_TEST_FAULT	0x5000ul
-#define EV_CLASS_TEST_WARNING	0x6000ul
-#define EV_CLASS_PWRD_NOTIFY	0x8000ul
-
-/* ENV class codes */
-#define ENV_PWRDN_PEND		0x4101ul
-
-#define EV_SEVERITY_POWER_STABLE	0x0000ul
-#define EV_SEVERITY_POWER_LOW_WARNING	0x0100ul
-#define EV_SEVERITY_POWER_HIGH_WARNING	0x0200ul
-#define EV_SEVERITY_POWER_HIGH_FAULT	0x0300ul
-#define EV_SEVERITY_POWER_LOW_FAULT	0x0400ul
-
-#define EV_SEVERITY_FAN_STABLE		0x0000ul
-#define EV_SEVERITY_FAN_WARNING		0x0100ul
-#define EV_SEVERITY_FAN_FAULT		0x0200ul
-
-#define EV_SEVERITY_TEMP_STABLE		0x0000ul
-#define EV_SEVERITY_TEMP_ADVISORY	0x0100ul
-#define EV_SEVERITY_TEMP_CRITICAL	0x0200ul
-#define EV_SEVERITY_TEMP_FAULT		0x0300ul
-
-void scdrv_event_init(struct sysctl_data_s *);
-
-#endif /* _SN_SYSCTL_H_ */
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c
deleted file mode 100644
index e452673dff66..000000000000
--- a/drivers/char/snsc_event.c
+++ /dev/null
@@ -1,303 +0,0 @@ 
-/*
- * SN Platform system controller communication support
- *
- * 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) 2004-2006 Silicon Graphics, Inc. All rights reserved.
- */
-
-/*
- * System controller event handler
- *
- * These routines deal with environmental events arriving from the
- * system controllers.
- */
-
-#include <linux/interrupt.h>
-#include <linux/sched/signal.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/unaligned.h>
-#include "snsc.h"
-
-static struct subch_data_s *event_sd;
-
-void scdrv_event(unsigned long);
-DECLARE_TASKLET(sn_sysctl_event, scdrv_event, 0);
-
-/*
- * scdrv_event_interrupt
- *
- * Pull incoming environmental events off the physical link to the
- * system controller and put them in a temporary holding area in SAL.
- * Schedule scdrv_event() to move them along to their ultimate
- * destination.
- */
-static irqreturn_t
-scdrv_event_interrupt(int irq, void *subch_data)
-{
-	struct subch_data_s *sd = subch_data;
-	unsigned long flags;
-	int status;
-
-	spin_lock_irqsave(&sd->sd_rlock, flags);
-	status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
-
-	if ((status > 0) && (status & SAL_IROUTER_INTR_RECV)) {
-		tasklet_schedule(&sn_sysctl_event);
-	}
-	spin_unlock_irqrestore(&sd->sd_rlock, flags);
-	return IRQ_HANDLED;
-}
-
-
-/*
- * scdrv_parse_event
- *
- * Break an event (as read from SAL) into useful pieces so we can decide
- * what to do with it.
- */
-static int
-scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc)
-{
-	char *desc_end;
-
-	/* record event source address */
-	*src = get_unaligned_be32(event);
-	event += 4; 			/* move on to event code */
-
-	/* record the system controller's event code */
-	*code = get_unaligned_be32(event);
-	event += 4;			/* move on to event arguments */
-
-	/* how many arguments are in the packet? */
-	if (*event++ != 2) {
-		/* if not 2, give up */
-		return -1;
-	}
-
-	/* parse out the ESP code */
-	if (*event++ != IR_ARG_INT) {
-		/* not an integer argument, so give up */
-		return -1;
-	}
-	*esp_code = get_unaligned_be32(event);
-	event += 4;
-
-	/* parse out the event description */
-	if (*event++ != IR_ARG_ASCII) {
-		/* not an ASCII string, so give up */
-		return -1;
-	}
-	event[CHUNKSIZE-1] = '\0';	/* ensure this string ends! */
-	event += 2; 			/* skip leading CR/LF */
-	desc_end = desc + sprintf(desc, "%s", event);
-
-	/* strip trailing CR/LF (if any) */
-	for (desc_end--;
-	     (desc_end != desc) && ((*desc_end == 0xd) || (*desc_end == 0xa));
-	     desc_end--) {
-		*desc_end = '\0';
-	}
-
-	return 0;
-}
-
-
-/*
- * scdrv_event_severity
- *
- * Figure out how urgent a message we should write to the console/syslog
- * via printk.
- */
-static char *
-scdrv_event_severity(int code)
-{
-	int ev_class = (code & EV_CLASS_MASK);
-	int ev_severity = (code & EV_SEVERITY_MASK);
-	char *pk_severity = KERN_NOTICE;
-
-	switch (ev_class) {
-	case EV_CLASS_POWER:
-		switch (ev_severity) {
-		case EV_SEVERITY_POWER_LOW_WARNING:
-		case EV_SEVERITY_POWER_HIGH_WARNING:
-			pk_severity = KERN_WARNING;
-			break;
-		case EV_SEVERITY_POWER_HIGH_FAULT:
-		case EV_SEVERITY_POWER_LOW_FAULT:
-			pk_severity = KERN_ALERT;
-			break;
-		}
-		break;
-	case EV_CLASS_FAN:
-		switch (ev_severity) {
-		case EV_SEVERITY_FAN_WARNING:
-			pk_severity = KERN_WARNING;
-			break;
-		case EV_SEVERITY_FAN_FAULT:
-			pk_severity = KERN_CRIT;
-			break;
-		}
-		break;
-	case EV_CLASS_TEMP:
-		switch (ev_severity) {
-		case EV_SEVERITY_TEMP_ADVISORY:
-			pk_severity = KERN_WARNING;
-			break;
-		case EV_SEVERITY_TEMP_CRITICAL:
-			pk_severity = KERN_CRIT;
-			break;
-		case EV_SEVERITY_TEMP_FAULT:
-			pk_severity = KERN_ALERT;
-			break;
-		}
-		break;
-	case EV_CLASS_ENV:
-		pk_severity = KERN_ALERT;
-		break;
-	case EV_CLASS_TEST_FAULT:
-		pk_severity = KERN_ALERT;
-		break;
-	case EV_CLASS_TEST_WARNING:
-		pk_severity = KERN_WARNING;
-		break;
-	case EV_CLASS_PWRD_NOTIFY:
-		pk_severity = KERN_ALERT;
-		break;
-	}
-
-	return pk_severity;
-}
-
-
-/*
- * scdrv_dispatch_event
- *
- * Do the right thing with an incoming event.  That's often nothing
- * more than printing it to the system log.  For power-down notifications
- * we start a graceful shutdown.
- */
-static void
-scdrv_dispatch_event(char *event, int len)
-{
-	static int snsc_shutting_down = 0;
-	int code, esp_code, src, class;
-	char desc[CHUNKSIZE];
-	char *severity;
-
-	if (scdrv_parse_event(event, &src, &code, &esp_code, desc) < 0) {
-		/* ignore uninterpretible event */
-		return;
-	}
-
-	/* how urgent is the message? */
-	severity = scdrv_event_severity(code);
-
-	class = (code & EV_CLASS_MASK);
-
-	if (class == EV_CLASS_PWRD_NOTIFY || code == ENV_PWRDN_PEND) {
-		if (snsc_shutting_down)
-			return;
-
-		snsc_shutting_down = 1;
-
-		/* give a message for each type of event */
-		if (class == EV_CLASS_PWRD_NOTIFY)
-			printk(KERN_NOTICE "Power off indication received."
-			       " Sending SIGPWR to init...\n");
-		else if (code == ENV_PWRDN_PEND)
-			printk(KERN_CRIT "WARNING: Shutting down the system"
-			       " due to a critical environmental condition."
-			       " Sending SIGPWR to init...\n");
-
-		/* give a SIGPWR signal to init proc */
-		kill_cad_pid(SIGPWR, 0);
-	} else {
-		/* print to system log */
-		printk("%s|$(0x%x)%s\n", severity, esp_code, desc);
-	}
-}
-
-
-/*
- * scdrv_event
- *
- * Called as a tasklet when an event arrives from the L1.  Read the event
- * from where it's temporarily stored in SAL and call scdrv_dispatch_event()
- * to send it on its way.  Keep trying to read events until SAL indicates
- * that there are no more immediately available.
- */
-void
-scdrv_event(unsigned long dummy)
-{
-	int status;
-	int len;
-	unsigned long flags;
-	struct subch_data_s *sd = event_sd;
-
-	/* anything to read? */
-	len = CHUNKSIZE;
-	spin_lock_irqsave(&sd->sd_rlock, flags);
-	status = ia64_sn_irtr_recv(sd->sd_nasid, sd->sd_subch,
-				   sd->sd_rb, &len);
-
-	while (!(status < 0)) {
-		spin_unlock_irqrestore(&sd->sd_rlock, flags);
-		scdrv_dispatch_event(sd->sd_rb, len);
-		len = CHUNKSIZE;
-		spin_lock_irqsave(&sd->sd_rlock, flags);
-		status = ia64_sn_irtr_recv(sd->sd_nasid, sd->sd_subch,
-					   sd->sd_rb, &len);
-	}
-	spin_unlock_irqrestore(&sd->sd_rlock, flags);
-}
-
-
-/*
- * scdrv_event_init
- *
- * Sets up a system controller subchannel to begin receiving event
- * messages. This is sort of a specialized version of scdrv_open()
- * in drivers/char/sn_sysctl.c.
- */
-void
-scdrv_event_init(struct sysctl_data_s *scd)
-{
-	int rv;
-
-	event_sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL);
-	if (event_sd == NULL) {
-		printk(KERN_WARNING "%s: couldn't allocate subchannel info"
-		       " for event monitoring\n", __func__);
-		return;
-	}
-
-	/* initialize subch_data_s fields */
-	event_sd->sd_nasid = scd->scd_nasid;
-	spin_lock_init(&event_sd->sd_rlock);
-
-	/* ask the system controllers to send events to this node */
-	event_sd->sd_subch = ia64_sn_sysctl_event_init(scd->scd_nasid);
-
-	if (event_sd->sd_subch < 0) {
-		kfree(event_sd);
-		printk(KERN_WARNING "%s: couldn't open event subchannel\n",
-		       __func__);
-		return;
-	}
-
-	/* hook event subchannel up to the system controller interrupt */
-	rv = request_irq(SGI_UART_VECTOR, scdrv_event_interrupt,
-			 IRQF_SHARED, "system controller events", event_sd);
-	if (rv) {
-		printk(KERN_WARNING "%s: irq request failed (%d)\n",
-		       __func__, rv);
-		ia64_sn_irtr_close(event_sd->sd_nasid, event_sd->sd_subch);
-		kfree(event_sd);
-		return;
-	}
-}