cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pcwd_usb.c (21389B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 *	Berkshire USB-PC Watchdog Card Driver
      4 *
      5 *	(c) Copyright 2004-2007 Wim Van Sebroeck <wim@iguana.be>.
      6 *
      7 *	Based on source code of the following authors:
      8 *	  Ken Hollis <kenji@bitgate.com>,
      9 *	  Alan Cox <alan@lxorguk.ukuu.org.uk>,
     10 *	  Matt Domsch <Matt_Domsch@dell.com>,
     11 *	  Rob Radez <rob@osinvestor.com>,
     12 *	  Greg Kroah-Hartman <greg@kroah.com>
     13 *
     14 *	Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
     15 *	provide warranty for any of this software. This material is
     16 *	provided "AS-IS" and at no charge.
     17 *
     18 *	Thanks also to Simon Machell at Berkshire Products Inc. for
     19 *	providing the test hardware. More info is available at
     20 *	http://www.berkprod.com/ or http://www.pcwatchdog.com/
     21 */
     22
     23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     24
     25#include <linux/module.h>	/* For module specific items */
     26#include <linux/moduleparam.h>	/* For new moduleparam's */
     27#include <linux/types.h>	/* For standard types (like size_t) */
     28#include <linux/errno.h>	/* For the -ENODEV/... values */
     29#include <linux/kernel.h>	/* For printk/panic/... */
     30#include <linux/delay.h>	/* For mdelay function */
     31#include <linux/miscdevice.h>	/* For struct miscdevice */
     32#include <linux/watchdog.h>	/* For the watchdog specific items */
     33#include <linux/notifier.h>	/* For notifier support */
     34#include <linux/reboot.h>	/* For reboot_notifier stuff */
     35#include <linux/init.h>		/* For __init/__exit/... */
     36#include <linux/fs.h>		/* For file operations */
     37#include <linux/usb.h>		/* For USB functions */
     38#include <linux/slab.h>		/* For kmalloc, ... */
     39#include <linux/mutex.h>	/* For mutex locking */
     40#include <linux/hid.h>		/* For HID_REQ_SET_REPORT & HID_DT_REPORT */
     41#include <linux/uaccess.h>	/* For copy_to_user/put_user/... */
     42
     43
     44/* Module and Version Information */
     45#define DRIVER_VERSION "1.02"
     46#define DRIVER_AUTHOR "Wim Van Sebroeck <wim@iguana.be>"
     47#define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
     48#define DRIVER_NAME "pcwd_usb"
     49
     50MODULE_AUTHOR(DRIVER_AUTHOR);
     51MODULE_DESCRIPTION(DRIVER_DESC);
     52MODULE_LICENSE("GPL");
     53
     54#define WATCHDOG_HEARTBEAT 0	/* default heartbeat =
     55						delay-time from dip-switches */
     56static int heartbeat = WATCHDOG_HEARTBEAT;
     57module_param(heartbeat, int, 0);
     58MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. "
     59	"(0<heartbeat<65536 or 0=delay-time from dip-switches, default="
     60				__MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
     61
     62static bool nowayout = WATCHDOG_NOWAYOUT;
     63module_param(nowayout, bool, 0);
     64MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
     65				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
     66
     67/* The vendor and product id's for the USB-PC Watchdog card */
     68#define USB_PCWD_VENDOR_ID	0x0c98
     69#define USB_PCWD_PRODUCT_ID	0x1140
     70
     71/* table of devices that work with this driver */
     72static const struct usb_device_id usb_pcwd_table[] = {
     73	{ USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) },
     74	{ }					/* Terminating entry */
     75};
     76MODULE_DEVICE_TABLE(usb, usb_pcwd_table);
     77
     78/* according to documentation max. time to process a command for the USB
     79 * watchdog card is 100 or 200 ms, so we give it 250 ms to do it's job */
     80#define USB_COMMAND_TIMEOUT	250
     81
     82/* Watchdog's internal commands */
     83#define CMD_READ_TEMP			0x02	/* Read Temperature;
     84							Re-trigger Watchdog */
     85#define CMD_TRIGGER			CMD_READ_TEMP
     86#define CMD_GET_STATUS			0x04	/* Get Status Information */
     87#define CMD_GET_FIRMWARE_VERSION	0x08	/* Get Firmware Version */
     88#define CMD_GET_DIP_SWITCH_SETTINGS	0x0c	/* Get Dip Switch Settings */
     89#define CMD_READ_WATCHDOG_TIMEOUT	0x18	/* Read Current Watchdog Time */
     90#define CMD_WRITE_WATCHDOG_TIMEOUT	0x19	/* Write Current WatchdogTime */
     91#define CMD_ENABLE_WATCHDOG		0x30	/* Enable / Disable Watchdog */
     92#define CMD_DISABLE_WATCHDOG		CMD_ENABLE_WATCHDOG
     93
     94/* Watchdog's Dip Switch heartbeat values */
     95static const int heartbeat_tbl[] = {
     96	5,	/* OFF-OFF-OFF	=  5 Sec  */
     97	10,	/* OFF-OFF-ON	= 10 Sec  */
     98	30,	/* OFF-ON-OFF	= 30 Sec  */
     99	60,	/* OFF-ON-ON	=  1 Min  */
    100	300,	/* ON-OFF-OFF	=  5 Min  */
    101	600,	/* ON-OFF-ON	= 10 Min  */
    102	1800,	/* ON-ON-OFF	= 30 Min  */
    103	3600,	/* ON-ON-ON	=  1 hour */
    104};
    105
    106/* We can only use 1 card due to the /dev/watchdog restriction */
    107static int cards_found;
    108
    109/* some internal variables */
    110static unsigned long is_active;
    111static char expect_release;
    112
    113/* Structure to hold all of our device specific stuff */
    114struct usb_pcwd_private {
    115	/* save off the usb device pointer */
    116	struct usb_device	*udev;
    117	/* the interface for this device */
    118	struct usb_interface	*interface;
    119
    120	/* the interface number used for cmd's */
    121	unsigned int		interface_number;
    122
    123	/* the buffer to intr data */
    124	unsigned char		*intr_buffer;
    125	/* the dma address for the intr buffer */
    126	dma_addr_t		intr_dma;
    127	/* the size of the intr buffer */
    128	size_t			intr_size;
    129	/* the urb used for the intr pipe */
    130	struct urb		*intr_urb;
    131
    132	/* The command that is reported back */
    133	unsigned char		cmd_command;
    134	/* The data MSB that is reported back */
    135	unsigned char		cmd_data_msb;
    136	/* The data LSB that is reported back */
    137	unsigned char		cmd_data_lsb;
    138	/* true if we received a report after a command */
    139	atomic_t		cmd_received;
    140
    141	/* Wether or not the device exists */
    142	int			exists;
    143	/* locks this structure */
    144	struct mutex		mtx;
    145};
    146static struct usb_pcwd_private *usb_pcwd_device;
    147
    148/* prevent races between open() and disconnect() */
    149static DEFINE_MUTEX(disconnect_mutex);
    150
    151/* local function prototypes */
    152static int usb_pcwd_probe(struct usb_interface *interface,
    153						const struct usb_device_id *id);
    154static void usb_pcwd_disconnect(struct usb_interface *interface);
    155
    156/* usb specific object needed to register this driver with the usb subsystem */
    157static struct usb_driver usb_pcwd_driver = {
    158	.name =		DRIVER_NAME,
    159	.probe =	usb_pcwd_probe,
    160	.disconnect =	usb_pcwd_disconnect,
    161	.id_table =	usb_pcwd_table,
    162};
    163
    164
    165static void usb_pcwd_intr_done(struct urb *urb)
    166{
    167	struct usb_pcwd_private *usb_pcwd =
    168				(struct usb_pcwd_private *)urb->context;
    169	unsigned char *data = usb_pcwd->intr_buffer;
    170	struct device *dev = &usb_pcwd->interface->dev;
    171	int retval;
    172
    173	switch (urb->status) {
    174	case 0:			/* success */
    175		break;
    176	case -ECONNRESET:	/* unlink */
    177	case -ENOENT:
    178	case -ESHUTDOWN:
    179		/* this urb is terminated, clean up */
    180		dev_dbg(dev, "%s - urb shutting down with status: %d",
    181			__func__, urb->status);
    182		return;
    183	/* -EPIPE:  should clear the halt */
    184	default:		/* error */
    185		dev_dbg(dev, "%s - nonzero urb status received: %d",
    186			__func__, urb->status);
    187		goto resubmit;
    188	}
    189
    190	dev_dbg(dev, "received following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
    191		data[0], data[1], data[2]);
    192
    193	usb_pcwd->cmd_command  = data[0];
    194	usb_pcwd->cmd_data_msb = data[1];
    195	usb_pcwd->cmd_data_lsb = data[2];
    196
    197	/* notify anyone waiting that the cmd has finished */
    198	atomic_set(&usb_pcwd->cmd_received, 1);
    199
    200resubmit:
    201	retval = usb_submit_urb(urb, GFP_ATOMIC);
    202	if (retval)
    203		pr_err("can't resubmit intr, usb_submit_urb failed with result %d\n",
    204		       retval);
    205}
    206
    207static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd,
    208		unsigned char cmd, unsigned char *msb, unsigned char *lsb)
    209{
    210	int got_response, count;
    211	unsigned char *buf;
    212
    213	/* We will not send any commands if the USB PCWD device does
    214	 * not exist */
    215	if ((!usb_pcwd) || (!usb_pcwd->exists))
    216		return -1;
    217
    218	buf = kmalloc(6, GFP_KERNEL);
    219	if (buf == NULL)
    220		return 0;
    221
    222	/* The USB PC Watchdog uses a 6 byte report format.
    223	 * The board currently uses only 3 of the six bytes of the report. */
    224	buf[0] = cmd;			/* Byte 0 = CMD */
    225	buf[1] = *msb;			/* Byte 1 = Data MSB */
    226	buf[2] = *lsb;			/* Byte 2 = Data LSB */
    227	buf[3] = buf[4] = buf[5] = 0;	/* All other bytes not used */
    228
    229	dev_dbg(&usb_pcwd->interface->dev,
    230		"sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
    231		buf[0], buf[1], buf[2]);
    232
    233	atomic_set(&usb_pcwd->cmd_received, 0);
    234
    235	if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0),
    236			HID_REQ_SET_REPORT, HID_DT_REPORT,
    237			0x0200, usb_pcwd->interface_number, buf, 6,
    238			USB_COMMAND_TIMEOUT) != 6) {
    239		dev_dbg(&usb_pcwd->interface->dev,
    240			"usb_pcwd_send_command: error in usb_control_msg for cmd 0x%x 0x%x 0x%x\n",
    241			cmd, *msb, *lsb);
    242	}
    243	/* wait till the usb card processed the command,
    244	 * with a max. timeout of USB_COMMAND_TIMEOUT */
    245	got_response = 0;
    246	for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response);
    247								count++) {
    248		mdelay(1);
    249		if (atomic_read(&usb_pcwd->cmd_received))
    250			got_response = 1;
    251	}
    252
    253	if ((got_response) && (cmd == usb_pcwd->cmd_command)) {
    254		/* read back response */
    255		*msb = usb_pcwd->cmd_data_msb;
    256		*lsb = usb_pcwd->cmd_data_lsb;
    257	}
    258
    259	kfree(buf);
    260
    261	return got_response;
    262}
    263
    264static int usb_pcwd_start(struct usb_pcwd_private *usb_pcwd)
    265{
    266	unsigned char msb = 0x00;
    267	unsigned char lsb = 0x00;
    268	int retval;
    269
    270	/* Enable Watchdog */
    271	retval = usb_pcwd_send_command(usb_pcwd, CMD_ENABLE_WATCHDOG,
    272								&msb, &lsb);
    273
    274	if ((retval == 0) || (lsb == 0)) {
    275		pr_err("Card did not acknowledge enable attempt\n");
    276		return -1;
    277	}
    278
    279	return 0;
    280}
    281
    282static int usb_pcwd_stop(struct usb_pcwd_private *usb_pcwd)
    283{
    284	unsigned char msb = 0xA5;
    285	unsigned char lsb = 0xC3;
    286	int retval;
    287
    288	/* Disable Watchdog */
    289	retval = usb_pcwd_send_command(usb_pcwd, CMD_DISABLE_WATCHDOG,
    290								&msb, &lsb);
    291
    292	if ((retval == 0) || (lsb != 0)) {
    293		pr_err("Card did not acknowledge disable attempt\n");
    294		return -1;
    295	}
    296
    297	return 0;
    298}
    299
    300static int usb_pcwd_keepalive(struct usb_pcwd_private *usb_pcwd)
    301{
    302	unsigned char dummy;
    303
    304	/* Re-trigger Watchdog */
    305	usb_pcwd_send_command(usb_pcwd, CMD_TRIGGER, &dummy, &dummy);
    306
    307	return 0;
    308}
    309
    310static int usb_pcwd_set_heartbeat(struct usb_pcwd_private *usb_pcwd, int t)
    311{
    312	unsigned char msb = t / 256;
    313	unsigned char lsb = t % 256;
    314
    315	if ((t < 0x0001) || (t > 0xFFFF))
    316		return -EINVAL;
    317
    318	/* Write new heartbeat to watchdog */
    319	usb_pcwd_send_command(usb_pcwd, CMD_WRITE_WATCHDOG_TIMEOUT, &msb, &lsb);
    320
    321	heartbeat = t;
    322	return 0;
    323}
    324
    325static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd,
    326							int *temperature)
    327{
    328	unsigned char msb, lsb;
    329
    330	usb_pcwd_send_command(usb_pcwd, CMD_READ_TEMP, &msb, &lsb);
    331
    332	/*
    333	 * Convert celsius to fahrenheit, since this was
    334	 * the decided 'standard' for this return value.
    335	 */
    336	*temperature = (lsb * 9 / 5) + 32;
    337
    338	return 0;
    339}
    340
    341static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd,
    342								int *time_left)
    343{
    344	unsigned char msb, lsb;
    345
    346	/* Read the time that's left before rebooting */
    347	/* Note: if the board is not yet armed then we will read 0xFFFF */
    348	usb_pcwd_send_command(usb_pcwd, CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb);
    349
    350	*time_left = (msb << 8) + lsb;
    351
    352	return 0;
    353}
    354
    355/*
    356 *	/dev/watchdog handling
    357 */
    358
    359static ssize_t usb_pcwd_write(struct file *file, const char __user *data,
    360						size_t len, loff_t *ppos)
    361{
    362	/* See if we got the magic character 'V' and reload the timer */
    363	if (len) {
    364		if (!nowayout) {
    365			size_t i;
    366
    367			/* note: just in case someone wrote the magic character
    368			 * five months ago... */
    369			expect_release = 0;
    370
    371			/* scan to see whether or not we got the
    372			 * magic character */
    373			for (i = 0; i != len; i++) {
    374				char c;
    375				if (get_user(c, data + i))
    376					return -EFAULT;
    377				if (c == 'V')
    378					expect_release = 42;
    379			}
    380		}
    381
    382		/* someone wrote to us, we should reload the timer */
    383		usb_pcwd_keepalive(usb_pcwd_device);
    384	}
    385	return len;
    386}
    387
    388static long usb_pcwd_ioctl(struct file *file, unsigned int cmd,
    389						unsigned long arg)
    390{
    391	void __user *argp = (void __user *)arg;
    392	int __user *p = argp;
    393	static const struct watchdog_info ident = {
    394		.options =		WDIOF_KEEPALIVEPING |
    395					WDIOF_SETTIMEOUT |
    396					WDIOF_MAGICCLOSE,
    397		.firmware_version =	1,
    398		.identity =		DRIVER_NAME,
    399	};
    400
    401	switch (cmd) {
    402	case WDIOC_GETSUPPORT:
    403		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
    404
    405	case WDIOC_GETSTATUS:
    406	case WDIOC_GETBOOTSTATUS:
    407		return put_user(0, p);
    408
    409	case WDIOC_GETTEMP:
    410	{
    411		int temperature;
    412
    413		if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
    414			return -EFAULT;
    415
    416		return put_user(temperature, p);
    417	}
    418
    419	case WDIOC_SETOPTIONS:
    420	{
    421		int new_options, retval = -EINVAL;
    422
    423		if (get_user(new_options, p))
    424			return -EFAULT;
    425
    426		if (new_options & WDIOS_DISABLECARD) {
    427			usb_pcwd_stop(usb_pcwd_device);
    428			retval = 0;
    429		}
    430
    431		if (new_options & WDIOS_ENABLECARD) {
    432			usb_pcwd_start(usb_pcwd_device);
    433			retval = 0;
    434		}
    435
    436		return retval;
    437	}
    438
    439	case WDIOC_KEEPALIVE:
    440		usb_pcwd_keepalive(usb_pcwd_device);
    441		return 0;
    442
    443	case WDIOC_SETTIMEOUT:
    444	{
    445		int new_heartbeat;
    446
    447		if (get_user(new_heartbeat, p))
    448			return -EFAULT;
    449
    450		if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat))
    451			return -EINVAL;
    452
    453		usb_pcwd_keepalive(usb_pcwd_device);
    454	}
    455		fallthrough;
    456
    457	case WDIOC_GETTIMEOUT:
    458		return put_user(heartbeat, p);
    459
    460	case WDIOC_GETTIMELEFT:
    461	{
    462		int time_left;
    463
    464		if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left))
    465			return -EFAULT;
    466
    467		return put_user(time_left, p);
    468	}
    469
    470	default:
    471		return -ENOTTY;
    472	}
    473}
    474
    475static int usb_pcwd_open(struct inode *inode, struct file *file)
    476{
    477	/* /dev/watchdog can only be opened once */
    478	if (test_and_set_bit(0, &is_active))
    479		return -EBUSY;
    480
    481	/* Activate */
    482	usb_pcwd_start(usb_pcwd_device);
    483	usb_pcwd_keepalive(usb_pcwd_device);
    484	return stream_open(inode, file);
    485}
    486
    487static int usb_pcwd_release(struct inode *inode, struct file *file)
    488{
    489	/*
    490	 *      Shut off the timer.
    491	 */
    492	if (expect_release == 42) {
    493		usb_pcwd_stop(usb_pcwd_device);
    494	} else {
    495		pr_crit("Unexpected close, not stopping watchdog!\n");
    496		usb_pcwd_keepalive(usb_pcwd_device);
    497	}
    498	expect_release = 0;
    499	clear_bit(0, &is_active);
    500	return 0;
    501}
    502
    503/*
    504 *	/dev/temperature handling
    505 */
    506
    507static ssize_t usb_pcwd_temperature_read(struct file *file, char __user *data,
    508				size_t len, loff_t *ppos)
    509{
    510	int temperature;
    511
    512	if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
    513		return -EFAULT;
    514
    515	if (copy_to_user(data, &temperature, 1))
    516		return -EFAULT;
    517
    518	return 1;
    519}
    520
    521static int usb_pcwd_temperature_open(struct inode *inode, struct file *file)
    522{
    523	return stream_open(inode, file);
    524}
    525
    526static int usb_pcwd_temperature_release(struct inode *inode, struct file *file)
    527{
    528	return 0;
    529}
    530
    531/*
    532 *	Notify system
    533 */
    534
    535static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code,
    536								void *unused)
    537{
    538	if (code == SYS_DOWN || code == SYS_HALT)
    539		usb_pcwd_stop(usb_pcwd_device);	/* Turn the WDT off */
    540
    541	return NOTIFY_DONE;
    542}
    543
    544/*
    545 *	Kernel Interfaces
    546 */
    547
    548static const struct file_operations usb_pcwd_fops = {
    549	.owner =	THIS_MODULE,
    550	.llseek =	no_llseek,
    551	.write =	usb_pcwd_write,
    552	.unlocked_ioctl = usb_pcwd_ioctl,
    553	.compat_ioctl = compat_ptr_ioctl,
    554	.open =		usb_pcwd_open,
    555	.release =	usb_pcwd_release,
    556};
    557
    558static struct miscdevice usb_pcwd_miscdev = {
    559	.minor =	WATCHDOG_MINOR,
    560	.name =		"watchdog",
    561	.fops =		&usb_pcwd_fops,
    562};
    563
    564static const struct file_operations usb_pcwd_temperature_fops = {
    565	.owner =	THIS_MODULE,
    566	.llseek =	no_llseek,
    567	.read =		usb_pcwd_temperature_read,
    568	.open =		usb_pcwd_temperature_open,
    569	.release =	usb_pcwd_temperature_release,
    570};
    571
    572static struct miscdevice usb_pcwd_temperature_miscdev = {
    573	.minor =	TEMP_MINOR,
    574	.name =		"temperature",
    575	.fops =		&usb_pcwd_temperature_fops,
    576};
    577
    578static struct notifier_block usb_pcwd_notifier = {
    579	.notifier_call =	usb_pcwd_notify_sys,
    580};
    581
    582/**
    583 *	usb_pcwd_delete
    584 */
    585static inline void usb_pcwd_delete(struct usb_pcwd_private *usb_pcwd)
    586{
    587	usb_free_urb(usb_pcwd->intr_urb);
    588	usb_free_coherent(usb_pcwd->udev, usb_pcwd->intr_size,
    589			  usb_pcwd->intr_buffer, usb_pcwd->intr_dma);
    590	kfree(usb_pcwd);
    591}
    592
    593/**
    594 *	usb_pcwd_probe
    595 *
    596 *	Called by the usb core when a new device is connected that it thinks
    597 *	this driver might be interested in.
    598 */
    599static int usb_pcwd_probe(struct usb_interface *interface,
    600						const struct usb_device_id *id)
    601{
    602	struct usb_device *udev = interface_to_usbdev(interface);
    603	struct usb_host_interface *iface_desc;
    604	struct usb_endpoint_descriptor *endpoint;
    605	struct usb_pcwd_private *usb_pcwd = NULL;
    606	int pipe;
    607	int retval = -ENOMEM;
    608	int got_fw_rev;
    609	unsigned char fw_rev_major, fw_rev_minor;
    610	char fw_ver_str[20];
    611	unsigned char option_switches, dummy;
    612
    613	cards_found++;
    614	if (cards_found > 1) {
    615		pr_err("This driver only supports 1 device\n");
    616		return -ENODEV;
    617	}
    618
    619	/* get the active interface descriptor */
    620	iface_desc = interface->cur_altsetting;
    621
    622	/* check out that we have a HID device */
    623	if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) {
    624		pr_err("The device isn't a Human Interface Device\n");
    625		return -ENODEV;
    626	}
    627
    628	if (iface_desc->desc.bNumEndpoints < 1)
    629		return -ENODEV;
    630
    631	/* check out the endpoint: it has to be Interrupt & IN */
    632	endpoint = &iface_desc->endpoint[0].desc;
    633
    634	if (!usb_endpoint_is_int_in(endpoint)) {
    635		/* we didn't find a Interrupt endpoint with direction IN */
    636		pr_err("Couldn't find an INTR & IN endpoint\n");
    637		return -ENODEV;
    638	}
    639
    640	/* get a handle to the interrupt data pipe */
    641	pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
    642
    643	/* allocate memory for our device and initialize it */
    644	usb_pcwd = kzalloc(sizeof(struct usb_pcwd_private), GFP_KERNEL);
    645	if (usb_pcwd == NULL)
    646		goto error;
    647
    648	usb_pcwd_device = usb_pcwd;
    649
    650	mutex_init(&usb_pcwd->mtx);
    651	usb_pcwd->udev = udev;
    652	usb_pcwd->interface = interface;
    653	usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber;
    654	usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ?
    655				le16_to_cpu(endpoint->wMaxPacketSize) : 8);
    656
    657	/* set up the memory buffer's */
    658	usb_pcwd->intr_buffer = usb_alloc_coherent(udev, usb_pcwd->intr_size,
    659					GFP_KERNEL, &usb_pcwd->intr_dma);
    660	if (!usb_pcwd->intr_buffer) {
    661		pr_err("Out of memory\n");
    662		goto error;
    663	}
    664
    665	/* allocate the urb's */
    666	usb_pcwd->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
    667	if (!usb_pcwd->intr_urb)
    668		goto error;
    669
    670	/* initialise the intr urb's */
    671	usb_fill_int_urb(usb_pcwd->intr_urb, udev, pipe,
    672			usb_pcwd->intr_buffer, usb_pcwd->intr_size,
    673			usb_pcwd_intr_done, usb_pcwd, endpoint->bInterval);
    674	usb_pcwd->intr_urb->transfer_dma = usb_pcwd->intr_dma;
    675	usb_pcwd->intr_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
    676
    677	/* register our interrupt URB with the USB system */
    678	if (usb_submit_urb(usb_pcwd->intr_urb, GFP_KERNEL)) {
    679		pr_err("Problem registering interrupt URB\n");
    680		retval = -EIO; /* failure */
    681		goto error;
    682	}
    683
    684	/* The device exists and can be communicated with */
    685	usb_pcwd->exists = 1;
    686
    687	/* disable card */
    688	usb_pcwd_stop(usb_pcwd);
    689
    690	/* Get the Firmware Version */
    691	got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION,
    692						&fw_rev_major, &fw_rev_minor);
    693	if (got_fw_rev)
    694		sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
    695	else
    696		sprintf(fw_ver_str, "<card no answer>");
    697
    698	pr_info("Found card (Firmware: %s) with temp option\n", fw_ver_str);
    699
    700	/* Get switch settings */
    701	usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy,
    702							&option_switches);
    703
    704	pr_info("Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
    705		option_switches,
    706		((option_switches & 0x10) ? "ON" : "OFF"),
    707		((option_switches & 0x08) ? "ON" : "OFF"));
    708
    709	/* If heartbeat = 0 then we use the heartbeat from the dip-switches */
    710	if (heartbeat == 0)
    711		heartbeat = heartbeat_tbl[(option_switches & 0x07)];
    712
    713	/* Check that the heartbeat value is within it's range ;
    714	 * if not reset to the default */
    715	if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) {
    716		usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT);
    717		pr_info("heartbeat value must be 0<heartbeat<65536, using %d\n",
    718			WATCHDOG_HEARTBEAT);
    719	}
    720
    721	retval = register_reboot_notifier(&usb_pcwd_notifier);
    722	if (retval != 0) {
    723		pr_err("cannot register reboot notifier (err=%d)\n", retval);
    724		goto error;
    725	}
    726
    727	retval = misc_register(&usb_pcwd_temperature_miscdev);
    728	if (retval != 0) {
    729		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
    730		       TEMP_MINOR, retval);
    731		goto err_out_unregister_reboot;
    732	}
    733
    734	retval = misc_register(&usb_pcwd_miscdev);
    735	if (retval != 0) {
    736		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
    737		       WATCHDOG_MINOR, retval);
    738		goto err_out_misc_deregister;
    739	}
    740
    741	/* we can register the device now, as it is ready */
    742	usb_set_intfdata(interface, usb_pcwd);
    743
    744	pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
    745		heartbeat, nowayout);
    746
    747	return 0;
    748
    749err_out_misc_deregister:
    750	misc_deregister(&usb_pcwd_temperature_miscdev);
    751err_out_unregister_reboot:
    752	unregister_reboot_notifier(&usb_pcwd_notifier);
    753error:
    754	if (usb_pcwd)
    755		usb_pcwd_delete(usb_pcwd);
    756	usb_pcwd_device = NULL;
    757	return retval;
    758}
    759
    760
    761/**
    762 *	usb_pcwd_disconnect
    763 *
    764 *	Called by the usb core when the device is removed from the system.
    765 *
    766 *	This routine guarantees that the driver will not submit any more urbs
    767 *	by clearing dev->udev.
    768 */
    769static void usb_pcwd_disconnect(struct usb_interface *interface)
    770{
    771	struct usb_pcwd_private *usb_pcwd;
    772
    773	/* prevent races with open() */
    774	mutex_lock(&disconnect_mutex);
    775
    776	usb_pcwd = usb_get_intfdata(interface);
    777	usb_set_intfdata(interface, NULL);
    778
    779	mutex_lock(&usb_pcwd->mtx);
    780
    781	/* Stop the timer before we leave */
    782	if (!nowayout)
    783		usb_pcwd_stop(usb_pcwd);
    784
    785	/* We should now stop communicating with the USB PCWD device */
    786	usb_pcwd->exists = 0;
    787
    788	/* Deregister */
    789	misc_deregister(&usb_pcwd_miscdev);
    790	misc_deregister(&usb_pcwd_temperature_miscdev);
    791	unregister_reboot_notifier(&usb_pcwd_notifier);
    792
    793	mutex_unlock(&usb_pcwd->mtx);
    794
    795	/* Delete the USB PCWD device */
    796	usb_pcwd_delete(usb_pcwd);
    797
    798	cards_found--;
    799
    800	mutex_unlock(&disconnect_mutex);
    801
    802	pr_info("USB PC Watchdog disconnected\n");
    803}
    804
    805module_usb_driver(usb_pcwd_driver);