lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 21 May 2008 00:27:18 +0200
From:	Jiri Slaby <jirislaby@...il.com>
To:	Anas Nashif <nashif@...ux.intel.com>
CC:	Andrew Morton <akpm@...ux-foundation.org>,
	linux-kernel@...r.kernel.org
Subject: Re: [PATCH] Intel Management Engine Interface

On 05/20/2008 02:11 AM, Anas Nashif wrote:
> We have addressed more issues raised on lkml after initial submission,
> especially the legacy device support issue which was removed in this
> patch.
> 
> The Intel Management Engine Interface (aka HECI: Host Embedded
> Controller Interface ) enables communication between the host OS and
> the Management Engine firmware. MEI is bi-directional, and either the
> host or Intel AMT firmware can initiate transactions.
[...]
> diff --git a/drivers/char/Makefile b/drivers/char/Makefile
> index 5407b76..26c81a0 100644
> --- a/drivers/char/Makefile
> +++ b/drivers/char/Makefile
> @@ -106,6 +106,7 @@ obj-$(CONFIG_IPMI_HANDLER)	+= ipmi/
> 
>  obj-$(CONFIG_HANGCHECK_TIMER)	+= hangcheck-timer.o
>  obj-$(CONFIG_TCG_TPM)		+= tpm/
> +obj-$(CONFIG_HECI)              += heci/

Who sets this config up?

> 
>  obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
> 
[...]
> diff --git a/drivers/char/heci/heci_init.c b/drivers/char/heci/heci_init.c
> new file mode 100644
> index 0000000..ffd4f7f
> --- /dev/null
> +++ b/drivers/char/heci/heci_init.c
> @@ -0,0 +1,1104 @@
[...]
> +static int heci_wait_event_int_timeout(struct iamt_heci_device *dev,
> +		long timeout)
> +{
> +	int err = 0;
> +
> +	err = wait_event_interruptible_timeout(dev->wait_recvd_msg,
> +			(dev->recvd_msg), timeout);
> +	return err;
> +}

return wait_event_interruptible_timeout();

[...]
> +static int host_start_message(struct iamt_heci_device *dev)
> +{
> +	long timeout = 60;	/* 60 second */
> +
> +	struct heci_msg_hdr *heci_hdr;
> +	struct hbm_host_version_request *host_start_req;
> +	struct hbm_host_stop_request *host_stop_req;
> +	int err = 0;
> +
> +	/* host start message */
> +	heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
> +	heci_hdr->host_addr = 0;
> +	heci_hdr->me_addr = 0;
> +	heci_hdr->length = sizeof(struct hbm_host_version_request);
> +	heci_hdr->msg_complete = 1;
> +	heci_hdr->reserved = 0;
> +
> +	host_start_req =
> +	    (struct hbm_host_version_request *) &dev->wr_msg_buf[1];
> +	memset(host_start_req, 0, sizeof(host_start_req));

wrong memset

> +	host_start_req->cmd.cmd = HOST_START_REQ_CMD;
> +	host_start_req->reserved = 0;
> +	host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
> +	host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
> +	dev->recvd_msg = 0;
> +	if (!heci_write_message(dev, heci_hdr,
> +				       (unsigned char *) (host_start_req),
> +				       heci_hdr->length)) {
> +		DBG("send version to fw fail.\n");
> +		return -ENODEV;
> +	}
> +	DBG("call wait_event_interruptible_timeout for response message.\n");
> +	/* wait for response */
> +	err = heci_wait_event_int_timeout(dev, timeout * HZ);
> +	if (!err && !dev->recvd_msg) {
> +		DBG("wait_timeout failed on host start response message.\n");
> +		return -ENODEV;
> +	}
> +	dev->recvd_msg = 0;
> +	DBG("wait_timeout successful on host start response message.\n");
> +	if ((dev->version.major_version != HBM_MAJOR_VERSION) ||
> +	    (dev->version.minor_version != HBM_MINOR_VERSION)) {
> +		/* send stop message */
> +		heci_hdr->host_addr = 0;
> +		heci_hdr->me_addr = 0;
> +		heci_hdr->length = sizeof(struct hbm_host_stop_request);
> +		heci_hdr->msg_complete = 1;
> +		heci_hdr->reserved = 0;
> +
> +		host_stop_req =
> +		    (struct hbm_host_stop_request *) &dev->wr_msg_buf[1];
> +
> +		memset(host_stop_req, 0, sizeof(host_stop_req));

same here

> +		host_stop_req->cmd.cmd = HOST_STOP_REQ_CMD;
> +		host_stop_req->reason = DRIVER_STOP_REQUEST;
> +		memset(host_stop_req->reserved, 0,
> +		       sizeof(host_stop_req->reserved));
> +		heci_write_message(dev, heci_hdr,
> +				   (unsigned char *) (host_stop_req),
> +				   heci_hdr->length);
> +		DBG("version mismatch.\n");
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
[...]
> +static void host_init_wd(struct iamt_heci_device *dev)
> +{
> +
> +	spin_lock_bh(&dev->device_lock);
> +
> +	heci_init_file_private(&dev->wd_file_ext, NULL);
> +
> +	/* look for WD client and connect to it */
> +	dev->wd_file_ext.state = HECI_FILE_DISCONNECTED;
> +	dev->wd_timeout = 0;
> +
> +	heci_check_asf_mode(dev);
> +	if (dev->asf_mode) {
> +		memcpy(dev->wd_data, stop_wd_params, HECI_WD_PARAMS_SIZE);
> +	} else {
> +		/* AMT mode */
> +		dev->wd_timeout = AMT_WD_VALUE;
> +		DBG("dev->wd_timeout=%d.\n", dev->wd_timeout);
> +		memcpy(dev->wd_data, start_wd_params, HECI_WD_PARAMS_SIZE);
> +		memcpy(dev->wd_data + HECI_WD_PARAMS_SIZE,
> +		       &dev->wd_timeout, sizeof(__u16));
> +	}
> +
> +	/* find ME WD client */
> +	heci_find_me_client(dev, &dev->wd_file_ext,
> +			    &heci_wd_guid, HECI_WD_HOST_CLIENT_ID);
> +	spin_unlock_bh(&dev->device_lock);
> +
> +	DBG("check wd_file_ext\n");
> +	if (HECI_FILE_CONNECTING == dev->wd_file_ext.state) {
> +		if (heci_connect_me_client(dev, &dev->wd_file_ext, 15) == 1) {
> +			DBG("dev->wd_timeout=%d.\n", dev->wd_timeout);
> +			if (dev->wd_timeout != 0)
> +				dev->wd_due_counter = 1;
> +			else
> +				dev->wd_due_counter = 0;
> +			DBG("successfully connected to WD client.\n");
> +		}
> +	} else
> +		DBG("failed to find WD client.\n");
> +
> +
> +	spin_lock_bh(&dev->device_lock);
> +	dev->wd_timer.function = &heci_wd_timer;
> +	dev->wd_timer.data = (unsigned long) dev;

setup_timer?

> +	spin_unlock_bh(&dev->device_lock);
> +}
[...]
> +struct heci_file_private *alloc_priv(struct file *file)

not a good name.

> +{
[...]
> +int heci_disconnect_host_client(struct iamt_heci_device *dev,
> +		struct heci_file_private *file_ext)
> +{
> +	int rets = 0, err = 0;

no need to init them

> +	long timeout = 15;	/*15 second */
> +	struct heci_cb_private *priv_cb = NULL;
[...]
> diff --git a/drivers/char/heci/heci_interface.c b/drivers/char/heci/heci_interface.c
> new file mode 100644
> index 0000000..6369dd0
> --- /dev/null
> +++ b/drivers/char/heci/heci_interface.c
> @@ -0,0 +1,497 @@
[...]
> +int flow_ctrl_creds(struct iamt_heci_device *dev,
> +				   struct heci_file_private *file_ext)
> +{
> +	__u8 i;
> +
> +	if (!dev->num_heci_me_clients)
> +		return 0;
> +
> +	if (file_ext == NULL)
> +		return 0;
> +
> +	if (file_ext->flow_ctrl_creds > 0)
> +		return 1;
> +
> +	for (i = 0; i < dev->num_heci_me_clients; i++) {
> +		if (dev->me_clients[i].client_id == file_ext->me_client_id) {
> +			if (dev->me_clients[i].flow_ctrl_creds > 0) {
> +				BUG_ON(dev->me_clients[i].props.single_recv_buf
> +					 == 0);
> +				return 1;
> +			}
> +			return 0;
> +		}
> +	}
> +	BUG_ON(1);

So just BUG();

> +	return 0;
> +}
> +
> +/**
> + * flow_ctrl_reduce  - reduce flow_control .
> + *
> + * @dev -Device object for our driver
> + * @file_ext -extension of the file object
> + */
> +void flow_ctrl_reduce(struct iamt_heci_device *dev,
> +			 struct heci_file_private *file_ext)
> +{
> +	__u8 i;
> +
> +	if (!dev->num_heci_me_clients)
> +		return;
> +
> +	for (i = 0; i < dev->num_heci_me_clients; i++) {
> +		if (dev->me_clients[i].client_id == file_ext->me_client_id) {
> +			if (dev->me_clients[i].props.single_recv_buf != 0) {
> +				BUG_ON(dev->me_clients[i].flow_ctrl_creds <= 0);
> +				dev->me_clients[i].flow_ctrl_creds--;
> +			} else {
> +				BUG_ON(file_ext->flow_ctrl_creds <= 0);
> +				file_ext->flow_ctrl_creds--;
> +			}
> +			return;
> +		}
> +	}
> +	BUG_ON(1);

ditto

> +}
> +
> +/**
> + * heci_send_flow_control  - send flow control to fw.
> + *
> + * @dev -Device object for our driver
> + * @file_ext -extension of the file object
> + *
> + * @return :
> + * 1 if success
> + * 0 - otherwise.
> + */
> +int heci_send_flow_control(struct iamt_heci_device *dev,
> +				 struct heci_file_private *file_ext)
> +{
> +	struct heci_msg_hdr *heci_hdr;
> +	struct hbm_flow_control *heci_flow_control;
> +
> +	heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
> +	heci_hdr->host_addr = 0;
> +	heci_hdr->me_addr = 0;
> +	heci_hdr->length = sizeof(struct hbm_flow_control);
> +	heci_hdr->msg_complete = 1;
> +	heci_hdr->reserved = 0;
> +
> +	heci_flow_control = (struct hbm_flow_control *) &dev->wr_msg_buf[1];
> +	memset(heci_flow_control, 0, sizeof(heci_flow_control));

again?

> +	heci_flow_control->host_addr = file_ext->host_client_id;
> +	heci_flow_control->me_addr = file_ext->me_client_id;
> +	heci_flow_control->cmd.cmd = FLOW_CONTROL_CMD;
[...]
> diff --git a/drivers/char/heci/heci_interface.h b/drivers/char/heci/heci_interface.h
> new file mode 100644
> index 0000000..4081fd3
> --- /dev/null
> +++ b/drivers/char/heci/heci_interface.h
> @@ -0,0 +1,169 @@
[...]
> +/* IOCTL commands */
> +#define HECI_IOCTL_LETTER 'H'

'H'     all     linux/hiddev.h

add

> +#define IOCTL_HECI_GET_VERSION \
> +    _IOWR(HECI_IOCTL_LETTER , 0x800, struct heci_message_data)
> +#define IOCTL_HECI_CONNECT_CLIENT \
> +    _IOWR(HECI_IOCTL_LETTER , 0x801, struct heci_message_data)
> +#define IOCTL_HECI_WD \
> +    _IOWR(HECI_IOCTL_LETTER , 0x802, struct heci_message_data)
> +#define IOCTL_HECI_BYPASS_WD \
> +    _IOWR(HECI_IOCTL_LETTER , 0x810, struct heci_message_data)

struct heci_message_data is not 32/64-bit friendly
_IOC_NRBITS is 8, 0x800 is far higher than that

[...]
> diff --git a/drivers/char/heci/heci_main.c b/drivers/char/heci/heci_main.c
> new file mode 100644
> index 0000000..608e1c7
> --- /dev/null
> +++ b/drivers/char/heci/heci_main.c
> @@ -0,0 +1,1544 @@
[...]
> +#ifdef HECI_DEBUG
> +int heci_debug = 1;
> +#else
> +int heci_debug;  /* initialized to 0 automatically.*/

we know that, comment unneeded

> +#endif
> +MODULE_PARM_DESC(heci_debug,  "Debug enabled or not");

so why not bool?

> +module_param(heci_debug, int, 0644);
> +
> +
[...]
> +/* heci_pci_tbl - PCI Device ID Table */
> +static struct pci_device_id heci_pci_tbl[] = {
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID01)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID02)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID03)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID04)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID05)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID06)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID07)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID08)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID09)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID10)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID11)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID12)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID13)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID14)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID15)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID16)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID17)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID18)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID19)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID20)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID21)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID22)},
> +	/* required last entry */
> +	{0, }

PCI_VDEVICE?

[...]
> +static struct pci_driver heci_driver = {
> +	.name = heci_driver_name,
> +	.id_table = heci_pci_tbl,
> +	.probe = heci_probe,
> +	.remove = heci_remove,

__devexit_p()

> +	.shutdown = heci_remove,

you'll trigger remove twice, I think.

> +#ifdef CONFIG_PM
> +	.suspend = heci_suspend,
> +	.resume = heci_resume
> +#endif

define them as null on !PM to avoid these ifdefs.

> +};
[...]
> +static int heci_registration_cdev(struct cdev *dev, int hminor,
> +				  struct file_operations *fops)
> +{
> +	int ret = 0, devno = MKDEV(heci_major, hminor);

do not init ret

> +
> +	cdev_init(dev, fops);
> +	dev->owner = THIS_MODULE;
> +	dev->ops = fops;

no need to re-set

> +	ret = cdev_add(dev, devno, 1);
> +	/* Fail gracefully if need be */
> +	if (ret) {
> +		kobject_put(&dev->kobj);

why?

> +		printk(KERN_ERR "%s: Error %d registering heci device %d\n",
> +		       THIS_MODULE->name, ret, hminor);
> +	}
> +	return ret;
> +}
> +
> +/* Display the version of heci driver. */
> +static ssize_t version_show(struct class *dev, char *buf)
> +{
> +	return sprintf(buf, "%s %s.\n",
> +		       heci_driver_string, heci_driver_version);
> +}
> +
> +static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
> +
> +/**
> + * heci_sysfs_create - creates a struct class to contain heci info
> + * @owner  - pointer to the module that is to "own" heci sysfs class
> + * @name   - pointer to a string for the name of this class

the format is:
(* @parameterx(space)*: (description of parameter x)?)*

> + *
> + * @return :
> + * valid pointer to a struct class on success
> + * false pointer on failure
> + */
> +static struct class *heci_sysfs_create(struct module *owner, char *name)
[...]
> +/**
> + * heci_sysfs_device_create - adds two devices to sysfs for chararcter devices
> + * @cs      - pointer to the struct class that the device to be registered on
> + *
> + * @return :
> + * 0 on success,
> + * negative on failure
> + */
> +static int heci_sysfs_device_create(struct class *cs)
> +{
> +	int err = 0;
> +
> +	if ((cs == NULL) || (IS_ERR(cs))) {
> +		err = -EINVAL;
> +		goto err_out;
> +	}
> +
> +	heci_class_dev = class_device_create(cs, NULL,
> +					     heci_cdev.dev,
> +					     NULL,
> +					     HECI_DEV_NAME);

device_create

> +	if (IS_ERR(heci_class_dev))
> +		err = PTR_ERR(heci_class_dev);
> +
> +err_out:
> +	return err;
> +}
[...]
> +static int __init heci_init_module(void)
> +{
> +	int ret = 0;
> +	dev_t dev;
> +
> +	printk(KERN_INFO "%s: %s - version %s\n",
> +	       THIS_MODULE->name, heci_driver_string, heci_driver_version);
> +	printk(KERN_INFO "%s: %s\n", THIS_MODULE->name, heci_copyright);
> +
> +	/* init pci module */
> +	ret = pci_register_driver(&heci_driver);
> +	if (ret < 0)
> +		goto end;
> +
> +	/* registration char devices */
> +	ret = alloc_chrdev_region(&dev, HECI_MINORS_BASE, HECI_MINORS_COUNT,
> +				  HECI_DRIVER_NAME);

just one minor? why not misc_register?

> +
> +	heci_major = MAJOR(dev);
[...]
> +static int __devinit heci_probe(struct pci_dev *pdev,
> +				const struct pci_device_id *ent)
> +{
> +	struct iamt_heci_device *dev = NULL;
> +	int i, err = 0;
> +
> +	if (heci_device) {
> +		err = -EEXIST;
> +		goto end;
> +	}
> +	/* enable pci dev */
> +	err = pci_enable_device(pdev);
> +	if (err) {
> +		printk(KERN_ERR "%s: Failed to enable pci device.\n",
> +		       THIS_MODULE->name);
> +		goto end;
> +	}
> +	/* set PCI host mastering  */
> +	pci_set_master(pdev);
> +	/* pci request regions for heci driver */
> +	err = pci_request_regions(pdev, heci_driver_name);
> +	if (err) {
> +		printk(KERN_ERR "%s: Failed to get pci regions.\n",
> +		       THIS_MODULE->name);
> +		goto disable_device;
> +	}
> +	/* allocates and initializes the heci dev structure */
> +	dev = init_heci_device(pdev);
> +	if (!dev) {
> +		err = -ENOMEM;
> +		goto release_regions;
> +	}
> +	/* mapping  IO device memory */
> +	for (i = BAR_0; i <= BAR_5; i++) {
> +		if (pci_resource_len(pdev, i) == 0)
> +			continue;
> +		if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
> +			printk(KERN_ERR "%s: heci has an IO ports.\n",
> +			       THIS_MODULE->name);
> +			goto free_device;
> +		} else if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
> +			if (dev->mem_base) {
> +				printk(KERN_ERR "%s: Too many mem addresses.\n",
> +				       THIS_MODULE->name);
> +				goto free_device;
> +			}
> +			dev->mem_base = pci_resource_start(pdev, i);
> +			dev->mem_length = pci_resource_len(pdev, i);
> +		}
> +	}
> +	if (!dev->mem_base) {
> +		printk(KERN_ERR "%s: No address to use.\n", THIS_MODULE->name);
> +		err = -ENODEV;
> +		goto free_device;
> +	}
> +	dev->mem_addr = ioremap_nocache(dev->mem_base,
> +			dev->mem_length);
> +	if (!dev->mem_addr) {
> +		printk(KERN_ERR "%s: Remap IO device memory failure.\n",
> +		       THIS_MODULE->name);
> +		err = -ENOMEM;
> +		goto free_device;
> +	}
> +	/* request and enable interrupt   */
> +	dev->irq = pdev->irq;
> +	err = request_irq(dev->irq, heci_isr_interrupt, IRQF_SHARED,
> +			heci_driver_name, dev);
> +	if (err) {
> +		printk(KERN_ERR "%s: Request_irq failure. irq = %d \n",
> +		       THIS_MODULE->name, dev->irq);
> +		goto unmap_memory;
> +	}
> +
> +	if (heci_hw_init(dev)) {
> +		printk(KERN_ERR "%s: Init hw failure.\n", THIS_MODULE->name);

This can be built tristate, right? What if THIS_MODULE is 0.

Use dev_* prints anyway.

> +		err = -ENODEV;
> +		goto release_irq;
> +	}
> +	init_timer(&dev->wd_timer);

not needed, if heci_initialize_clients called setup_timer

> +	msleep(100); /* FW needs time to be ready to talk with us */
> +	heci_initialize_clients(dev);
> +	if (dev->heci_state != HECI_ENABLED) {
> +		err = -ENODEV;
> +		goto release_hw;
> +	}
[...]
> +static void __devexit heci_remove(struct pci_dev *pdev)
> +{
> +	struct iamt_heci_device *dev = pci_get_drvdata(pdev);
> +	int err = 0;
> +
> +	if (heci_device != pdev)
> +		return;
> +
> +	if (dev == NULL)
> +		return;
> +
> +	spin_lock_bh(&dev->device_lock);
> +	if (dev->reinit_tsk != NULL) {
> +		kthread_stop(dev->reinit_tsk);
> +		dev->reinit_tsk = NULL;
> +	}
> +	spin_unlock_bh(&dev->device_lock);
> +
> +	del_timer_sync(&dev->wd_timer);
> +	if (dev->wd_file_ext.state == HECI_FILE_CONNECTED
> +	    && dev->wd_timeout) {
> +		spin_lock_bh(&dev->device_lock);
> +		dev->wd_timeout = 0;
> +		dev->wd_due_counter = 0;
> +		memcpy(dev->wd_data, stop_wd_params, HECI_WD_PARAMS_SIZE);
> +		dev->stop = 1;
> +		if (dev->host_buffer_is_empty &&
> +		    flow_ctrl_creds(dev, &dev->wd_file_ext)) {
> +			dev->host_buffer_is_empty = 0;
> +
> +			if (!heci_send_wd(dev))
> +				DBG("send stop WD failed\n");
> +			else
> +				flow_ctrl_reduce(dev, &dev->wd_file_ext);
> +
> +			dev->wd_pending = 0;
> +		} else {
> +			dev->wd_pending = 1;
> +		}
> +		spin_unlock_bh(&dev->device_lock);
> +		dev->wd_stoped = 0;
> +
> +		err = wait_event_interruptible_timeout(dev->wait_stop_wd,
> +				(dev->wd_stoped), 10 * HZ);

What is the retval for?

> +		if (!dev->wd_stoped)
> +			DBG("stop wd failed to complete.\n");
> +		else
> +			DBG("stop wd complete.\n");
> +
> +	}
> +
> +	heci_device = NULL;
> +	if (dev->iamthif_file_ext.status == HECI_FILE_CONNECTED) {
> +		dev->iamthif_file_ext.status = HECI_FILE_DISCONNECTING;
> +		heci_disconnect_host_client(dev,
> +					    &dev->iamthif_file_ext);
> +	}
> +	if (dev->wd_file_ext.status == HECI_FILE_CONNECTED) {
> +		dev->wd_file_ext.status = HECI_FILE_DISCONNECTING;
> +		heci_disconnect_host_client(dev,
> +					    &dev->wd_file_ext);
> +	}
> +
> +	spin_lock_bh(&dev->device_lock);
> +
> +	/* remove entry if already in list */
> +	DBG("list del iamthif and wd file list.\n");
> +	heci_remove_client_from_file_list(dev, dev->wd_file_ext.
> +					  host_client_id);
> +	heci_remove_client_from_file_list(dev,
> +			dev->iamthif_file_ext.host_client_id);
> +
> +	dev->iamthif_current_cb = NULL;
> +	dev->iamthif_file_ext.file = NULL;
> +	dev->num_heci_me_clients = 0;
> +
> +	spin_unlock_bh(&dev->device_lock);
> +
> +	flush_scheduled_work();
> +	/* disable interrupts */
> +	dev->host_hw_state &= ~H_IE;
> +	/* acknowledge interrupt and stop interupts */
> +	write_heci_register(dev, H_CSR, dev->host_hw_state);

PCI posting?

> +	free_irq(pdev->irq, dev);
> +	pci_set_drvdata(pdev, NULL);
> +
> +	if (dev->mem_addr)
> +		iounmap(dev->mem_addr);
> +
> +	kfree(dev);
> +
> +	pci_release_regions(pdev);
> +	pci_disable_device(pdev);
> +}
[...]
> +static ssize_t heci_read(struct file *file, char __user *ubuf,
> +			 size_t length, loff_t *offset)
> +{
> +	int i;
> +	int rets = 0, err = 0;
> +	int if_num = MINOR((file->f_dentry->d_inode->i_rdev));

iminor?

> +	struct heci_file_private *file_ext = file->private_data;
> +	struct heci_cb_private *priv_cb_pos = NULL;
> +	struct heci_cb_private *priv_cb = NULL;
> +	struct iamt_heci_device *dev = NULL;
> +
> +	if (!heci_device)
> +		return -ENODEV;
> +
> +	dev = pci_get_drvdata(heci_device);
> +	if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
> +		return -ENODEV;
> +
> +	spin_lock_bh(&dev->device_lock);
> +	if (dev->heci_state != HECI_ENABLED) {
> +		spin_unlock_bh(&dev->device_lock);
> +		return -ENODEV;
> +	}
> +	spin_unlock_bh(&dev->device_lock);
> +
> +	spin_lock(&file_ext->file_lock);
> +	if ((file_ext->sm_state & HECI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
> +		spin_unlock(&file_ext->file_lock);
> +		/* Do not allow to read watchdog client */
> +		for (i = 0; i < dev->num_heci_me_clients; i++) {
> +			if (memcmp(&heci_wd_guid,
> +				   &dev->me_clients[i].props.protocol_name,
> +				   sizeof(struct guid)) == 0) {
> +				if (file_ext->me_client_id ==
> +				    dev->me_clients[i].client_id)
> +					return -EBADF;
> +			}
> +		}
> +	} else {
> +		file_ext->sm_state &= ~HECI_WD_STATE_INDEPENDENCE_MSG_SENT;
> +		spin_unlock(&file_ext->file_lock);
> +	}
> +
> +	if (file_ext == &dev->iamthif_file_ext) {
> +		rets = pthi_read(dev, if_num, file, ubuf, length, offset);
> +		goto out;
> +	}
> +
> +	if (file_ext->read_cb && file_ext->read_cb->information > *offset) {
> +		priv_cb = file_ext->read_cb;
> +		goto copy_buffer;
> +	} else if (file_ext->read_cb && file_ext->read_cb->information > 0 &&
> +		   file_ext->read_cb->information <= *offset) {
> +		priv_cb = file_ext->read_cb;
> +		rets = 0;
> +		goto free;
> +	} else if ((!file_ext->read_cb || file_ext->read_cb->information == 0)
> +		    && *offset > 0) {
> +		/*Offset needs to be cleaned for contingous reads*/
> +		*offset = 0;
> +		rets = 0;
> +		goto out;
> +	}
> +
> +	spin_lock(&file_ext->read_io_lock);
> +	err = heci_start_read(dev, if_num, file_ext);
> +	if (err != 0 && err != -EBUSY) {
> +		DBG("heci start read failure with status = %d\n", err);
> +		spin_unlock(&file_ext->read_io_lock);
> +		rets = err;
> +		goto out;
> +	}
> +	if (HECI_READ_COMPLETE != file_ext->reading_state
> +			&& !waitqueue_active(&file_ext->rx_wait)) {
> +		if (file->f_flags & O_NONBLOCK) {
> +			rets = -EAGAIN;
> +			spin_unlock(&file_ext->read_io_lock);
> +			goto out;
> +		}
> +		spin_unlock(&file_ext->read_io_lock);
> +
> +		if (wait_event_interruptible(file_ext->rx_wait,
> +			(HECI_READ_COMPLETE == file_ext->reading_state
> +			 || HECI_FILE_INITIALIZING == file_ext->state
> +			 || HECI_FILE_DISCONNECTED == file_ext->state
> +			 || HECI_FILE_DISCONNECTING == file_ext->state))) {
> +			if (signal_pending(current)) {
> +				rets = -EINTR;
> +				goto out;
> +			}
> +			return -ERESTARTSYS;
> +		}
> +
> +		if (HECI_FILE_INITIALIZING == file_ext->state ||
> +		    HECI_FILE_DISCONNECTED == file_ext->state ||
> +		    HECI_FILE_DISCONNECTING == file_ext->state) {
> +			rets = -EBUSY;
> +			goto out;
> +		}
> +		spin_lock(&file_ext->read_io_lock);
> +	}
> +
> +	priv_cb = file_ext->read_cb;
> +
> +	if (!priv_cb) {
> +		spin_unlock(&file_ext->read_io_lock);
> +		return -ENODEV;
> +	}
> +	if (file_ext->reading_state != HECI_READ_COMPLETE) {
> +		spin_unlock(&file_ext->read_io_lock);
> +		return 0;
> +	}
> +	spin_unlock(&file_ext->read_io_lock);
> +	/* now copy the data to user space */
> +copy_buffer:
> +	DBG("priv_cb->response_buffer size - %d\n",
> +	    priv_cb->response_buffer.size);
> +	DBG("priv_cb->information - %lu\n",
> +	    priv_cb->information);
> +	if (length == 0 || ubuf == NULL ||
> +	    *offset > priv_cb->information) {
> +		rets = -EMSGSIZE;
> +		goto free;
> +	}
> +
> +	/* length is being turncated to PAGE_SIZE, however, */
> +	/* information size may be longer */
> +	length = (length < (priv_cb->information - *offset) ?
> +			length : (priv_cb->information - *offset));
> +
> +	if (copy_to_user(ubuf,
> +			 priv_cb->response_buffer.data + *offset,
> +			 length)) {
> +		rets = -EFAULT;
> +		goto free;
> +	} else {

no need to 'else' here

> +		rets = length;
> +		*offset += length;
> +		if ((unsigned long)*offset < priv_cb->information)
> +			goto out;
> +	}
> +free:
> +	spin_lock_bh(&dev->device_lock);
> +	priv_cb_pos = find_read_list_entry(dev, file_ext);
> +	/* Remove entry from read list */
> +	if (priv_cb_pos != NULL)
> +		list_del(&priv_cb_pos->cb_list);
> +	spin_unlock_bh(&dev->device_lock);
> +	heci_free_cb_private(priv_cb);
> +	spin_lock(&file_ext->read_io_lock);
> +	file_ext->reading_state = HECI_IDLE;
> +	file_ext->read_cb = NULL;
> +	file_ext->read_pending = 0;
> +	spin_unlock(&file_ext->read_io_lock);
> +out:	DBG("end heci read rets= %d\n", rets);
> +	return rets;
> +}
> +
> +/**
> + * heci_write - the write function.
> + */
> +static ssize_t heci_write(struct file *file, const char __user *ubuf,
> +			  size_t length, loff_t *offset)
> +{
> +	int rets = 0;
> +	__u8 i;
> +	int if_num = MINOR((file->f_dentry->d_inode->i_rdev));

...

> +	struct heci_file_private *file_ext = file->private_data;
> +	struct heci_cb_private *priv_write_cb = NULL;
> +	struct heci_msg_hdr heci_hdr;
> +	struct iamt_heci_device *dev = NULL;
> +	unsigned long currtime = get_seconds();
[...]
> +static int heci_ioctl(struct inode *inode, struct file *file,
> +		      unsigned int cmd, unsigned long data)

->unlocked_ioctl

> +{
> +	int rets = 0;
> +	int if_num = MINOR(inode->i_rdev);
> +	struct heci_file_private *file_ext = file->private_data;
> +	/* in user space */
> +	struct heci_message_data *u_msg = (struct heci_message_data *) data;
> +	struct heci_message_data k_msg;	/* all in kernel on the stack */
> +	struct iamt_heci_device *dev = NULL;
[...]
> +#ifdef CONFIG_PM
> +static int heci_suspend(struct pci_dev *pdev, pm_message_t state)
> +{
> +	struct iamt_heci_device *device = pci_get_drvdata(pdev);
> +	int err = 0;
> +
> +	spin_lock_bh(&device->device_lock);
> +	if (device->reinit_tsk != NULL) {
> +		kthread_stop(device->reinit_tsk);
> +		device->reinit_tsk = NULL;
> +	}
> +	spin_unlock_bh(&device->device_lock);
> +
> +	/* Stop watchdog if exists */
> +	del_timer_sync(&device->wd_timer);
> +	if (device->wd_file_ext.state == HECI_FILE_CONNECTED
> +	    && device->wd_timeout) {
> +		spin_lock_bh(&device->device_lock);
> +		g_sus_wd_timeout = device->wd_timeout;
> +		device->wd_timeout = 0;
> +		device->wd_due_counter = 0;
> +		memcpy(device->wd_data, stop_wd_params, HECI_WD_PARAMS_SIZE);
> +		device->stop = 1;
> +		if (device->host_buffer_is_empty &&
> +		    flow_ctrl_creds(device, &device->wd_file_ext)) {
> +			device->host_buffer_is_empty = 0;
> +			if (!heci_send_wd(device))
> +				DBG("send stop WD failed\n");
> +			else
> +				flow_ctrl_reduce(device, &device->wd_file_ext);
> +
> +			device->wd_pending = 0;
> +		} else {
> +			device->wd_pending = 1;
> +		}
> +		spin_unlock_bh(&device->device_lock);
> +		device->wd_stoped = 0;
> +
> +		err = wait_event_interruptible_timeout(device->wait_stop_wd,
> +						       (device->wd_stoped),
> +						       10 * HZ);
> +		if (!device->wd_stoped)
> +			DBG("stop wd failed to complete.\n");
> +		else {
> +			DBG("stop wd complete %d.\n", err);
> +			err = 0;
> +		}
> +	}
> +	/* Set new heci state */
> +	spin_lock_bh(&device->device_lock);
> +	if (device->heci_state == HECI_ENABLED ||
> +	    device->heci_state == HECI_RECOVERING_FROM_RESET) {
> +		device->heci_state = HECI_POWER_DOWN;
> +		heci_reset(device, 0);
> +	}
> +	spin_unlock_bh(&device->device_lock);
> +
> +	pci_save_state(pdev);
> +
> +	pci_disable_device(pdev);
> +	free_irq(pdev->irq, device);

no device irq disabling?

> +
> +	pci_set_power_state(pdev, PCI_D3hot);
> +
> +	return err;
> +}
> +
> +static int heci_resume(struct pci_dev *pdev)
> +{
> +	struct iamt_heci_device *device = NULL;
> +	int err = 0;
> +
> +	pci_set_power_state(pdev, PCI_D0);
> +	pci_restore_state(pdev);
> +
> +	device = pci_get_drvdata(pdev);
> +	if (!device)
> +		return -ENODEV;
> +
> +	/* request and enable interrupt   */
> +	device->irq = pdev->irq;

so why do you need the copy of an irq?

> +	err = request_irq(device->irq, heci_isr_interrupt, IRQF_SHARED,
> +			heci_driver_name, device);
> +	if (err) {
> +		printk(KERN_ERR "%s: Request_irq failure. irq = %d \n",
> +		       THIS_MODULE->name, device->irq);
> +		return err;
> +	}
[...]
> diff --git a/drivers/char/heci/heci_version.h b/drivers/char/heci/heci_version.h
> new file mode 100644
> index 0000000..6cbb5e2
> --- /dev/null
> +++ b/drivers/char/heci/heci_version.h
> @@ -0,0 +1,56 @@
[...]
> +#ifndef HECI_VERSION_H
> +#define HECI_VERSION_H
> +
> +#define MAJOR_VERSION              5
> +#define MINOR_VERSION              0
> +#define QUICK_FIX_NUMBER        0
> +#define VER_BUILD               1
> +
> +#define str(s) name(s)
> +#define name(s) #s
> +#define DRIVER_V1		str(MAJOR_VERSION) "." str(MINOR_VERSION)
> +#define DRIVER_V2		str(QUICK_FIX_NUMBER) "." str(VER_BUILD)

hmm, __stringify()

> +
> +#define DRIVER_VERSION	DRIVER_V1 "." DRIVER_V2

not good macro names at all

> +
> +#endif
> diff --git a/drivers/char/heci/interrupt.c b/drivers/char/heci/interrupt.c
> new file mode 100644
> index 0000000..c2fc1d0
> --- /dev/null
> +++ b/drivers/char/heci/interrupt.c
> @@ -0,0 +1,1551 @@
[...]
> +irqreturn_t heci_isr_interrupt(int irq, void *dev_id)
> +{
> +	int err;
> +	struct iamt_heci_device *device = (struct iamt_heci_device *) dev_id;
> +	device->host_hw_state = read_heci_register(device, H_CSR);
> +
> +	if ((device->host_hw_state & H_IS) != H_IS)
> +		return IRQ_NONE;
> +
> +	/* disable interrupts */
> +	device->host_hw_state &= ~H_IE;
> +	/* acknowledge interrupt and stop interupts */
> +	write_heci_register(device, H_CSR, device->host_hw_state);
> +	/**
> +	 * Our device interrupted, schedule work the heci_bh_handler
> +	 * to handle the interrupt processing. This needs to be a
> +	 * workqueue item since the handler can sleep.
> +	 */
> +	PREPARE_WORK(&device->work, heci_bh_handler);

this is racy with bh?

> +	DBG("schedule work the heci_bh_handler.\n");
> +	err = schedule_work(&device->work);
> +	if (!err) {

some ratelimit?

> +		printk(KERN_ERR "%s: schedule the heci_bh_handler"
> +		       " failed error=%x\n", THIS_MODULE->name, err);
> +	}
> +	return IRQ_HANDLED;
> +}
[...]
> +static void heci_bh_handler(struct work_struct *work)
> +{
> +	struct iamt_heci_device *dev =
> +		container_of(work, struct iamt_heci_device, work);
> +	struct io_heci_list complete_list;
> +	__s32 slots;
> +	int rets;
> +	struct heci_cb_private *cb_pos = NULL, *cb_next = NULL;
> +	struct heci_file_private *file_ext = NULL;
> +	int bus_message_received = 0;
> +	struct task_struct *tsk;
> +
> +	DBG("function called after ISR to handle the interrupt processing.\n");
> +	/* initialize our complete list */
> +	spin_lock_bh(&dev->device_lock);
> +	heci_initialize_list(&complete_list, dev);
> +	dev->host_hw_state = read_heci_register(dev, H_CSR);
> +	dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
> +
> +	/* check if ME wants a reset */
> +	if (((dev->me_hw_state & ME_RDY_HRA) == 0)
> +	    && (dev->heci_state != HECI_RESETING)
> +	    && (dev->heci_state != HECI_INITIALIZING)) {
> +		DBG("FW not ready.\n");
> +		heci_reset(dev, 1);
> +		spin_unlock_bh(&dev->device_lock);
> +		return;
> +	}
> +
> +	/*  check if we need to start the dev */
> +	if ((dev->host_hw_state & H_RDY) == 0) {
> +		if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) {
> +			DBG("we need to start the dev.\n");
> +			dev->host_hw_state |= (H_IE | H_IG | H_RDY);
> +			write_heci_register(dev, H_CSR, dev->host_hw_state);
> +			if (dev->heci_state == HECI_INITIALIZING) {
> +				dev->recvd_msg = 1;
> +				spin_unlock_bh(&dev->device_lock);
> +				wake_up_interruptible(&dev->wait_recvd_msg);
> +				return;
> +
> +			} else {
> +				spin_unlock_bh(&dev->device_lock);
> +				tsk = kthread_run(heci_task_initialize_clients,
> +						  dev, "heci_reinit");
> +				if (IS_ERR(tsk)) {
> +					int rc = PTR_ERR(tsk);
> +					printk(KERN_WARNING "heci: Unable to"
> +					"start the heci thread: %d\n", rc);
> +				}
> +				return;
> +			}
> +		} else {
> +			DBG("enable interrupt FW not ready.\n");
> +			dev->host_hw_state |= (H_IE);
> +			write_heci_register(dev, H_CSR, dev->host_hw_state);
> +			spin_unlock_bh(&dev->device_lock);
> +			return;
> +		}
> +	}
> +	/* check slots avalable for reading */
> +	slots = count_full_read_slots(dev);
> +	DBG("slots =%08x  extra_write_index =%08x.\n",
> +		slots, dev->extra_write_index);
> +	while ((slots > 0) && (!dev->extra_write_index)) {
> +		DBG("slots =%08x  extra_write_index =%08x.\n", slots,
> +				dev->extra_write_index);
> +		DBG("call heci_bh_read_handler.\n");
> +		rets = heci_bh_read_handler(&complete_list, dev, &slots);
> +		if (rets != 0)
> +			goto end;
> +	}
> +	rets = heci_bh_write_handler(&complete_list, dev, &slots);
> +end:
> +	DBG("end of bottom half function.\n");
> +	dev->host_hw_state = read_heci_register(dev, H_CSR);
> +	dev->host_buffer_is_empty = host_buffer_is_empty(dev);
> +
> +	if ((dev->host_hw_state & H_IS) == H_IS) {
> +		PREPARE_WORK(&dev->work, heci_bh_handler);

racy with hardirq?

> +		DBG("schedule work the heci_bh_handler.\n");
> +		rets = schedule_work(&dev->work);
> +		if (!rets) {
> +			printk(KERN_ERR "%s: schedule the heci_bh_handler"
> +			       " failed error=%x\n", THIS_MODULE->name, rets);
> +		}
[...]
> +static int _heci_bh_ioctl(struct iamt_heci_device *dev,	__s32 *slots,
> +			struct heci_cb_private *priv_cb_pos,
> +			struct heci_file_private *file_ext,
> +			struct io_heci_list *cmpl_list)
> +{
> +	if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) +
> +			sizeof(struct hbm_client_connect_request))) {
> +		file_ext->state = HECI_FILE_CONNECTING;
> +		*slots -= (sizeof(struct heci_msg_hdr) +
> +			sizeof(struct hbm_client_connect_request) + 3) / 4;
> +		if (!heci_connect(dev, file_ext)) {
> +			file_ext->status = -ENODEV;
> +			priv_cb_pos->information = 0;
> +			list_del(&priv_cb_pos->cb_list);
> +			return -ENODEV;
> +		} else {
> +			list_del(&priv_cb_pos->cb_list);
> +			list_add_tail(&priv_cb_pos->cb_list,
> +			&dev->ctrl_rd_list.heci_cb.cb_list);
> +			file_ext->timer_count = CONNECT_TIMEOUT;
> +		}
> +	} else {
> +		/* return the cancel routine */
> +		list_del(&priv_cb_pos->cb_list);
> +		return -ECORRUPTED_MESSAGE_HEADER;

Sorry, what?

> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * _heci_bh_cmpl: process completed and no-iamthif operation.
> + * @dev: device object.
> + * @slots: free slotsl.
> + * @priv_cb_pos: callback block.
> + * @file_ext: file extension.
> + * @cmpl_list: complete list.
> + *
> + * @return :
> + * 0, OK; otherwise, error.
> + */
> +static int _heci_bh_cmpl(struct iamt_heci_device *dev,	__s32 *slots,
> +			struct heci_cb_private *priv_cb_pos,
> +			struct heci_file_private *file_ext,
> +			struct io_heci_list *cmpl_list)
> +{
> +	struct heci_msg_hdr *heci_hdr = NULL;
> +
> +	if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) +
> +			(priv_cb_pos->request_buffer.size -
> +			priv_cb_pos->information))) {
> +		heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
> +		heci_hdr->host_addr = file_ext->host_client_id;
> +		heci_hdr->me_addr = file_ext->me_client_id;
> +		heci_hdr->length = ((priv_cb_pos->request_buffer.size) -
> +				(priv_cb_pos->information));
> +		heci_hdr->msg_complete = 1;
> +		heci_hdr->reserved = 0;
> +		DBG("priv_cb_pos->request_buffer.size =%d"
> +			"heci_hdr->msg_complete= %d\n",
> +				priv_cb_pos->request_buffer.size,
> +				heci_hdr->msg_complete);
> +		DBG("priv_cb_pos->information  =%lu\n",
> +				priv_cb_pos->information);
> +		DBG("heci_hdr->length  =%d\n",
> +				heci_hdr->length);
> +		*slots -= (sizeof(struct heci_msg_hdr) +
> +				heci_hdr->length + 3) / 4;
> +		if (!heci_write_message(dev, heci_hdr,
> +				(unsigned char *)
> +				(priv_cb_pos->request_buffer.data +
> +				priv_cb_pos->information),
> +				heci_hdr->length)) {
> +			file_ext->status = -ENODEV;
> +			list_del(&priv_cb_pos->cb_list);
> +			list_add_tail(&priv_cb_pos->cb_list,
> +				&cmpl_list->heci_cb.cb_list);

list_move_tail?

> +			return -ENODEV;
> +		} else {
> +			flow_ctrl_reduce(dev, file_ext);
> +			file_ext->status = 0;
> +			priv_cb_pos->information += heci_hdr->length;
> +			list_del(&priv_cb_pos->cb_list);
> +			list_add_tail(&priv_cb_pos->cb_list,
> +				&dev->write_waiting_list.heci_cb.cb_list);

...

> +		}
> +	} else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
[...]
> +static int same_flow_addr(struct heci_file_private *file,
> +					struct hbm_flow_control *flow)
> +{
> +	if ((file->host_client_id == flow->host_addr)
> +	    && (file->me_client_id == flow->me_addr))
> +		return 1;
> +
> +	return 0;
> +}

just return <the_condition>;

> +static void add_single_flow_creds(struct iamt_heci_device *dev,
> +				  struct hbm_flow_control *flow)
> +{
> +	struct heci_me_client *client = NULL;
> +	int i;
> +
> +	for (i = 0; i < dev->num_heci_me_clients; i++) {
> +		client = &dev->me_clients[i];
> +		if (flow->me_addr == client->client_id) {
> +			if (client->props.single_recv_buf != 0) {
> +				client->flow_ctrl_creds++;
> +				DBG("recv flow ctrl msg ME %d (single).\n",
> +				    flow->me_addr);
> +				DBG("flow control credentials=%d.\n",
> +				    client->flow_ctrl_creds);
> +			} else {
> +				BUG_ON(1);	/* error in flow control */

BUG()

[...]
> +static int same_disconn_addr(struct heci_file_private *file,
> +			     struct hbm_client_disconnect_request *disconn)
> +{
> +	if ((file->host_client_id == disconn->host_addr)
> +	    && (file->me_client_id == disconn->me_addr))
> +		return 1;
> +
> +	return 0;
> +}

...
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ