Re: [PATCH] Intel Management Engine Interface
From: Randy Dunlap
Date: Thu Jul 17 2008 - 20:01:23 EST
On Thu, 17 Jul 2008 20:27:10 +0200 (CEST) Marcin Obara wrote:
Please include diffstat for the entire patch. See Documentation/SubmittingPatches .
> diff --git a/drivers/char/heci/Kconfig b/drivers/char/heci/Kconfig
> new file mode 100644
> index 0000000..a4d8bf4
> --- /dev/null
> +++ b/drivers/char/heci/Kconfig
> @@ -0,0 +1,12 @@
> +#
> +# HECI device configuration
> +#
> +
> +config INTEL_MEI
> + tristate "Intel Management Engine Interface (MEI) Support"
The text prompt string usually also includes "(EXPERIMENTAL)", although
I wish that the *config tools did that for us...
> + depends on EXPERIMENTAL
> + ---help---
> + The Intel Management Engine Interface (Intel MEI) driver allows
> + applications to access the Active Management Technology
> + firmware and other Management Engine sub-systems.
> +
> diff --git a/drivers/char/heci/heci.h b/drivers/char/heci/heci.h
> new file mode 100644
> index 0000000..daafbc8
> --- /dev/null
> +++ b/drivers/char/heci/heci.h
> @@ -0,0 +1,176 @@
> +
> +#ifndef _HECI_H_
> +#define _HECI_H_
> +
> +#include <linux/version.h>
> +#include <linux/spinlock.h>
> +#include <linux/list.h>
> +#include <linux/pci.h>
> +#include <linux/timer.h>
> +#include <linux/interrupt.h>
> +#include <linux/workqueue.h>
> +#include <linux/module.h>
> +#include <linux/aio.h>
> +#include <linux/types.h>
> +#include "heci_data_structures.h"
> +
> +extern const struct guid heci_pthi_guid;
> +extern const struct guid heci_wd_guid;
> +extern const __u8 start_wd_params[];
> +extern const __u8 stop_wd_params[];
> +extern const __u8 heci_wd_state_independence_msg[3][4];
> +
> +/**
Oops. We use /** to flag the beginning of kernel-doc comments, but this (and others
here) is not a kernel-doc comment. Please just use /* here and other places that are
not kernel-doc comments. Or feel free to convert to kernel-doc. :)
> + * heci device ID
> + */
> +#define HECI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */
> +#define HECI_DEV_ID_82G35 0x2984 /* 82G35 Express */
> +#define HECI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */
> +#define HECI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */
> +
> +#define HECI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */
> +#define HECI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */
> +
> +#define HECI_DEV_ID_ICH9_82Q35 0x29B4 /* 82Q35 Express */
> +#define HECI_DEV_ID_ICH9_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */
> +#define HECI_DEV_ID_ICH9_82Q33 0x29D4 /* 82Q33 Express */
> +#define HECI_DEV_ID_ICH9_82X38 0x29E4 /* 82X38/X48 Express */
> +#define HECI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */
> +
> +#define HECI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */
> +#define HECI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */
> +#define HECI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */
> +#define HECI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */
> +#define HECI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */
> +
> +#define HECI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */
> +#define HECI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */
> +#define HECI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */
> +#define HECI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */
> +
> +#define HECI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */
> +#define HECI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */
> +#define HECI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */
> +#define HECI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */
> +
> +/**
> + * heci init function prototypes
> + */
> +struct iamt_heci_device *init_heci_device(struct pci_dev *pdev);
> +void heci_reset(struct iamt_heci_device *dev, int interrupts);
> +int heci_hw_init(struct iamt_heci_device *dev);
> +int heci_task_initialize_clients(void *data);
> +int heci_initialize_clients(struct iamt_heci_device *dev);
> +struct heci_file_private *heci_alloc_file_private(struct file *file);
> +int heci_disconnect_host_client(struct iamt_heci_device *dev,
> + struct heci_file_private *file_ext);
> +void heci_initialize_list(struct io_heci_list *list,
> + struct iamt_heci_device *dev);
> +void heci_flush_list(struct io_heci_list *list,
> + struct heci_file_private *file_ext);
> +void heci_flush_queues(struct iamt_heci_device *dev,
> + struct heci_file_private *file_ext);
> +
> +void heci_remove_client_from_file_list(struct iamt_heci_device *dev,
> + __u8 host_client_id);
> +
> +/**
> + * interrupt function prototype
> + */
> +irqreturn_t heci_isr_interrupt(int irq, void *dev_id);
> +
> +void heci_wd_timer(unsigned long data);
> +
> +/**
> + * input output function prototype
> + */
> +int heci_ioctl_get_version(struct iamt_heci_device *device, int if_num,
> + struct heci_message_data *u_msg,
> + struct heci_message_data k_msg,
> + struct heci_file_private *file_ext);
> +
> +int heci_ioctl_connect_client(struct iamt_heci_device *device, int if_num,
> + struct heci_message_data *u_msg,
> + struct heci_message_data k_msg,
> + struct file *file);
> +
> +int heci_ioctl_wd(struct iamt_heci_device *device, int if_num,
> + struct heci_message_data k_msg,
> + struct heci_file_private *file_ext);
> +
> +int heci_ioctl_bypass_wd(struct iamt_heci_device *device, int if_num,
> + struct heci_message_data k_msg,
> + struct heci_file_private *file_ext);
> +
> +int heci_start_read(struct iamt_heci_device *device, int if_num,
> + struct heci_file_private *file_ext);
> +
> +int pthi_write(struct iamt_heci_device *device,
> + struct heci_cb_private *priv_cb);
> +
> +int pthi_read(struct iamt_heci_device *device, int if_num, struct file *file,
> + char *ubuf, size_t length, loff_t *offset);
> +
> +struct heci_cb_private *find_pthi_read_list_entry(
> + struct iamt_heci_device *device,
> + struct file *file);
> +
> +void run_next_iamthif_cmd(struct iamt_heci_device *device);
> +
> +void heci_free_cb_private(struct heci_cb_private *priv_cb);
> +
> +/**
> + * heci_fe_same_id - tell if file private data have same id
> + *
> + * @fe1: private data of 1. file object
> + * @fe2: private data of 2. file object
> + *
> + * @return !=0 - if ids are the same, 0 - if differ.
> + */
> +static inline int heci_fe_same_id(struct heci_file_private *fe1,
> + struct heci_file_private *fe2)
> +{
> + return ((fe1->host_client_id == fe2->host_client_id)
> + && (fe1->me_client_id == fe2->me_client_id));
> +}
> +
> +#endif /* _HECI_H_ */
> diff --git a/drivers/char/heci/heci_data_structures.h b/drivers/char/heci/heci_data_structures.h
> new file mode 100644
> index 0000000..f75af25
> --- /dev/null
> +++ b/drivers/char/heci/heci_data_structures.h
> @@ -0,0 +1,524 @@
> +
> +#ifndef _HECI_DATA_STRUCTURES_H_
> +#define _HECI_DATA_STRUCTURES_H_
> +
> +#include <linux/version.h>
> +#include <linux/spinlock.h>
> +#include <linux/list.h>
> +#include <linux/pci.h>
> +#include <linux/timer.h>
> +#include <linux/interrupt.h>
> +#include <linux/workqueue.h>
> +#include <linux/module.h>
> +#include <linux/aio.h>
> +#include <linux/types.h>
> +
> +/**
Same kernel-doc comments.
> + * error code definition
> + */
> +#define ESLOTS_OVERFLOW 1
> +#define ECORRUPTED_MESSAGE_HEADER 1000
> +#define ECOMPLETE_MESSAGE 1001
> +
> +#define HECI_FC_MESSAGE_RESERVED_LENGTH 5
> +
> +/**
> + * Number of queue lists used by this driver
> + */
> +#define HECI_IO_LISTS_NUMBER 7
> +
> +/**
> + * Maximum transmission unit (MTU) of heci messages
> + */
> +#define IAMTHIF_MTU 4160
> +
> +
> +/**
> + * HECI HW Section
> + */
> +
> +/* HECI registers */
> +/* H_CB_WW - Host Circular Buffer (CB) Write Window register */
> +#define H_CB_WW 0
> +/* H_CSR - Host Control Status register */
> +#define H_CSR 4
> +/* ME_CB_RW - ME Circular Buffer Read Window register (read only) */
> +#define ME_CB_RW 8
> +/* ME_CSR_HA - ME Control Status Host Access register (read only) */
> +#define ME_CSR_HA 0xC
> +
> +
> +/* register bits of H_CSR (Host Control Status register) */
> +/* Host Circular Buffer Depth - maximum number of 32-bit entries in CB */
> +#define H_CBD 0xFF000000
> +/* Host Circular Buffer Write Pointer */
> +#define H_CBWP 0x00FF0000
> +/* Host Circular Buffer Read Pointer */
> +#define H_CBRP 0x0000FF00
> +/* Host Reset */
> +#define H_RST 0x00000010
> +/* Host Ready */
> +#define H_RDY 0x00000008
> +/* Host Interrupt Generate */
> +#define H_IG 0x00000004
> +/* Host Interrupt Status */
> +#define H_IS 0x00000002
> +/* Host Interrupt Enable */
> +#define H_IE 0x00000001
> +
> +
> +/* register bits of ME_CSR_HA (ME Control Status Host Access register) */
> +/* ME CB (Circular Buffer) Depth HRA (Host Read Access)
> + * - host read only access to ME_CBD */
> +#define ME_CBD_HRA 0xFF000000
> +/* ME CB Write Pointer HRA - host read only access to ME_CBWP */
> +#define ME_CBWP_HRA 0x00FF0000
> +/* ME CB Read Pointer HRA - host read only access to ME_CBRP */
> +#define ME_CBRP_HRA 0x0000FF00
> +/* ME Reset HRA - host read only access to ME_RST */
> +#define ME_RST_HRA 0x00000010
> +/* ME Ready HRA - host read only access to ME_RDY */
> +#define ME_RDY_HRA 0x00000008
> +/* ME Interrupt Generate HRA - host read only access to ME_IG */
> +#define ME_IG_HRA 0x00000004
> +/* ME Interrupt Status HRA - host read only access to ME_IS */
> +#define ME_IS_HRA 0x00000002
> +/* ME Interrupt Enable HRA - host read only access to ME_IE */
> +#define ME_IE_HRA 0x00000001
> +
> +#define HECI_MINORS_BASE 1
> +#define HECI_MINORS_COUNT 1
> +
> +#define HECI_MINOR_NUMBER 1
> +#define HECI_MAX_OPEN_HANDLE_COUNT 253
> +
> +/**
> + * debug kernel print macro define
> + */
> +extern int heci_debug;
> +
> +#define DBG(format, arg...) do { \
> + if (heci_debug) \
> + printk(KERN_ERR "%s: " format , __func__ , ## arg); \
> +} while (0)
Why KERN_ERR ?
> +
> +
> +/**
> + * time to wait HECI become ready after init
> + */
> +#define HECI_INTEROP_TIMEOUT (HZ * 7)
> +
> +/**
> + * watch dog definition
> + */
> +#define HECI_WATCHDOG_DATA_SIZE 16
> +#define HECI_START_WD_DATA_SIZE 20
> +#define HECI_WD_PARAMS_SIZE 4
> +#define HECI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0)
> +
...
> +
> +/**
> + * read_heci_register - Read a byte from the heci device
> + *
> + * @device: the device structure
> + * @offset: offset from which to read the data
> + *
> + * @return the byte read.
Drop the @, just Return...
> + */
> +__u32 read_heci_register(struct iamt_heci_device *device,
> + unsigned long offset);
> +
> +/**
> + * write_heci_register - Write 4 bytes to the heci device
> + *
> + * @device: the device structure
> + * @offset: offset from which to write the data
> + * @value: the byte to write
> + */
> +void write_heci_register(struct iamt_heci_device *device, unsigned long offset,
> + __u32 value);
> +
> +#endif /* _HECI_DATA_STRUCTURES_H_ */
> diff --git a/drivers/char/heci/heci_init.c b/drivers/char/heci/heci_init.c
> new file mode 100644
> index 0000000..8eb42a0
> --- /dev/null
> +++ b/drivers/char/heci/heci_init.c
> @@ -0,0 +1,1085 @@
> +
> +const __u8 watch_dog_data[] = {
> + 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
> +};
> +const __u8 start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
> +const __u8 stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
> +
> +const __u8 heci_wd_state_independence_msg[3][4] = {
> + {0x05, 0x02, 0x51, 0x10},
> + {0x05, 0x02, 0x52, 0x10},
> + {0x07, 0x02, 0x01, 0x10}
> +};
> +
> +const struct guid heci_asf_guid = {
> + 0x75B30CD6, 0xA29E, 0x4AF7,
> + {0xA7, 0x12, 0xE6, 0x17, 0x43, 0x93, 0xC8, 0xA6}
> +};
> +const struct guid heci_wd_guid = {
> + 0x05B79A6F, 0x4628, 0x4D7F,
> + {0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB}
> +};
> +const struct guid heci_pthi_guid = {
> + 0x12f80028, 0xb4b7, 0x4b2d,
> + {0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c}
> +};
> +
> +
> +/**
Bzzt.
> + * heci init function prototypes
> + */
> +static void heci_check_asf_mode(struct iamt_heci_device *dev);
> +static int host_start_message(struct iamt_heci_device *dev);
> +static int host_enum_clients_message(struct iamt_heci_device *dev);
> +static int allocate_me_clients_storage(struct iamt_heci_device *dev);
> +static void host_init_wd(struct iamt_heci_device *dev);
> +static void host_init_iamthif(struct iamt_heci_device *dev);
> +static int heci_wait_event_int_timeout(struct iamt_heci_device *dev,
> + long timeout);
> +
> +
> +/**
> + * heci_initialize_list - Sets up a queue list.
> + *
> + * @list: An instance of our list structure
> + * @dev: Device object for our driver
> + */
> +void heci_initialize_list(struct io_heci_list *list,
> + struct iamt_heci_device *dev)
> +{
> + /* initialize our queue list */
> + INIT_LIST_HEAD(&list->heci_cb.cb_list);
> + list->status = 0;
> + list->device_extension = dev;
> +}
> +
> +/**
> + * heci_flush_queues - flush our queues list belong to file_ext.
> + *
> + * @dev: Device object for our driver
> + * @file_ext: private data of the file object
> + *
> + */
> +void heci_flush_queues(struct iamt_heci_device *dev,
> + struct heci_file_private *file_ext)
> +{
> + int i;
> +
> + if (!dev || !file_ext)
> + return;
> +
> + /* flush our queue list belong to file_ext */
> + for (i = 0; i < HECI_IO_LISTS_NUMBER; i++) {
> + DBG("remove list entry belong to file_ext\n");
> + heci_flush_list(dev->io_list_array[i], file_ext);
> + }
> +}
> +
> +
> +/**
> + * heci_flush_list - remove list entry belong to file_ext.
> + *
> + * @list: An instance of our list structure
> + * @file_ext: private data of the file object
> + */
> +void heci_flush_list(struct io_heci_list *list,
> + struct heci_file_private *file_ext)
> +{
> + struct heci_file_private *file_ext_tmp;
> + struct heci_cb_private *priv_cb_pos = NULL;
> + struct heci_cb_private *priv_cb_next = NULL;
> +
> + if (!list || !file_ext)
> + return;
> +
> + if (list->status != 0)
> + return;
> +
> + if (list_empty(&list->heci_cb.cb_list))
> + return;
> +
> + list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
> + &list->heci_cb.cb_list, cb_list) {
> + if (priv_cb_pos) {
> + file_ext_tmp = (struct heci_file_private *)
> + priv_cb_pos->file_private;
> + if (file_ext_tmp) {
> + if (heci_fe_same_id(file_ext, file_ext_tmp))
> + list_del(&priv_cb_pos->cb_list);
> + }
> + }
> + }
> +}
> +
> +/**
> + * heci_reset_iamthif_params - initializes heci device iamthif
> + * @dev: The heci device structure
> + */
> +static void heci_reset_iamthif_params(struct iamt_heci_device *dev)
> +{
> + /* reset iamthif parameters. */
> + dev->iamthif_current_cb = NULL;
> + dev->iamthif_msg_buf_size = 0;
> + dev->iamthif_msg_buf_index = 0;
> + dev->iamthif_canceled = 0;
> + dev->iamthif_file_ext.file = NULL;
> + dev->iamthif_ioctl = 0;
> + dev->iamthif_state = HECI_IAMTHIF_IDLE;
> + dev->iamthif_timer = 0;
> +}
> +
> +/**
> + * init_heci_device - allocates and initializes the heci device structure
> + * @pdev: The pci device structure
> + *
> + * @return The heci_device_device pointer on success, NULL on failure.
Drop @, just Return or Returns ....
> + */
> +struct iamt_heci_device *init_heci_device(struct pci_dev *pdev)
> +{
> +}
> +
> +
> +
> +
> +static int heci_wait_event_int_timeout(struct iamt_heci_device *dev,
> + long timeout)
> +{
> + return wait_event_interruptible_timeout(dev->wait_recvd_msg,
> + (dev->recvd_msg), timeout);
> +}
> +
> +/**
> + * heci_hw_init - init host and fw to start work.
> + *
> + * @dev: Device object for our driver
> + *
> + * @return 0 on success, <0 on failure.
Not @return....
> + */
> +int heci_hw_init(struct iamt_heci_device *dev)
> +{
> +}
> +
> +/**
> + * heci_hw_reset - reset fw via heci csr register.
> + *
> + * @dev: Device object for our driver
> + * @interrupts: if interrupt should be enable after reset.
> + */
> +static void heci_hw_reset(struct iamt_heci_device *dev, int interrupts)
> +{
> + dev->host_hw_state |= (H_RST | H_IG);
> +
> + if (interrupts)
> + heci_csr_enable_interrupts(dev);
> + else
> + heci_csr_disable_interrupts(dev);
> +
> + BUG_ON((dev->host_hw_state & H_RST) != H_RST);
> + BUG_ON((dev->host_hw_state & H_RDY) != 0);
> +}
> +
> +/**
> + * heci_reset - reset host and fw.
> + *
> + * @dev: Device object for our driver
> + * @interrupts: if interrupt should be enable after reset.
> + */
> +void heci_reset(struct iamt_heci_device *dev, int interrupts)
> +{
> + dev->num_heci_me_clients = 0;
> + dev->rd_msg_hdr = 0;
> + dev->stop = 0;
> + dev->wd_pending = 0;
> +
> + /* update the state of the registers after reset */
> + dev->host_hw_state = read_heci_register(dev, H_CSR);
> + dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
> +
> + DBG("after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
> + dev->host_hw_state, dev->me_hw_state);
> +
> + if (unexpected)
> + printk(KERN_WARNING "unexpected heci reset.\n");
printk() strings usually benefit from some common prefix, such as
printk(KERN_WARNING "heci: unexpected reset\n");
> +
> + /* Wake up all readings so they can be interrupted */
> + list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link) {
> + if (&file_pos->rx_wait &&
> + waitqueue_active(&file_pos->rx_wait)) {
> + printk(KERN_INFO "heci: Waking up client!\n");
> + wake_up_interruptible(&file_pos->rx_wait);
> + }
> + }
> + /* remove all waiting requests */
> + if (dev->write_list.status == 0 &&
> + !list_empty(&dev->write_list.heci_cb.cb_list)) {
> + list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
> + &dev->write_list.heci_cb.cb_list, cb_list) {
> + if (priv_cb_pos) {
> + list_del(&priv_cb_pos->cb_list);
> + heci_free_cb_private(priv_cb_pos);
> + }
> + }
> + }
> +}
> +
> +/**
> + * heci_initialize_clients - routine.
What routine??
> + *
> + * @dev: Device object for our driver
> + *
> + */
> +int heci_initialize_clients(struct iamt_heci_device *dev)
> +{
> +}
> +
> +/**
> + * heci_task_initialize_clients - routine.
What routine??
> + *
> + * @data: Device object for our driver
> + *
> + */
> +int heci_task_initialize_clients(void *data)
> +{
> +}
> +
> +/**
> + * host_start_message - heci host send start message.
> + *
> + * @dev: Device object for our driver
> + *
> + * @return 0 on success, <0 on failure.
Not @return.
> + */
> +static int host_start_message(struct iamt_heci_device *dev)
> +{
> +}
> +
> +/**
> + * host_enum_clients_message - host send enumeration client request message.
> + *
> + * @dev: Device object for our driver
> + * @return 0 on success, <0 on failure.
Not @return ....
> + */
> +static int host_enum_clients_message(struct iamt_heci_device *dev)
> +{
> +}
> +
> +/**
> + * host_client_properties - reads properties for client
> + *
> + * @dev: Device object for our driver
> + * @idx: client index in me client array
> + * @client_id: id of the client
> + *
> + * @return 0 on success, <0 on failure.
Ditto.
> + */
> +static int host_client_properties(struct iamt_heci_device *dev,
> + struct heci_me_client *client)
> +{
> +}
> +
> +/**
> + * allocate_me_clients_storage - allocate storage for me clients
> + *
> + * @dev: Device object for our driver
> + *
> + * @return 0 on success, <0 on failure.
Not @return.
> + */
> +static int allocate_me_clients_storage(struct iamt_heci_device *dev)
> +{
> +}
> +
> +/**
> + * heci_init_file_private - initializes private file structure.
> + *
> + * @priv: private file structure to be initialized
> + * @file: the file structure
> + *
> + */
> +static void heci_init_file_private(struct heci_file_private *priv,
> + struct file *file)
> +{
> +}
> +
> +/**
> + * heci_find_me_client - search for ME client guid
> + * sets client_id in heci_file_private if found
> + * @dev: Device object for our driver
> + * @priv: private file structure to set client_id in
> + * @cguid: searched guid of ME client
> + * @client_id: id of host client to be set in file private structure
> + *
> + * @return ME client index
Not @return ....
> + */
> +static __u8 heci_find_me_client(struct iamt_heci_device *dev,
> + struct heci_file_private *priv,
> + const struct guid *cguid, __u8 client_id)
> +{
> +}
> +
> +/**
> + * heci_check_asf_mode - check for ASF client
> + *
> + * @dev: Device object for our driver
> + *
> + */
> +static void heci_check_asf_mode(struct iamt_heci_device *dev)
> +{
> +}
> +
> +/**
> + * heci_connect_me_client - connect ME client
> + * @dev: Device object for our driver
> + * @priv: private file structure
> + * @timeout: connect timeout in seconds
> + *
> + * @return 1 - if connected, 0 - if not
Not @return ....
> + */
> +static __u8 heci_connect_me_client(struct iamt_heci_device *dev,
> + struct heci_file_private *priv,
> + long timeout)
> +{
> +}
> +
> +/**
> + * host_init_wd - heci initialization wd.
> + *
> + * @dev: Device object for our driver
> + *
> + */
> +static void host_init_wd(struct iamt_heci_device *dev)
> +{
> +}
> +
> +
> +/**
> + * host_init_iamthif - heci initialization iamthif client.
> + *
> + * @dev: Device object for our driver
> + *
> + */
> +static void host_init_iamthif(struct iamt_heci_device *dev)
> +{
> +}
> +
> +/**
> + * heci_alloc_file_private - allocates a private file structure and set it up.
> + * @file: the file structure
> + *
> + * @return The allocated file or NULL on failure
* Returns ....
> + */
> +struct heci_file_private *heci_alloc_file_private(struct file *file)
> +{
> +}
> +
> +
> +
> +/**
> + * heci_disconnect_host_client - send disconnect message to fw from host client.
> + *
> + * @dev: Device object for our driver
> + * @file_ext: private data of the file object
> + *
> + * @return 0 on success, <0 on failure.
Argh.
> + */
> +int heci_disconnect_host_client(struct iamt_heci_device *dev,
> + struct heci_file_private *file_ext)
> +{
> +}
> +
> +/**
> + * heci_remove_client_from_file_list -
> + * remove file private data from device file list
> + *
> + * @dev: Device object for our driver
> + * @host_client_id: host client id to be removed
> + *
> + */
> +void heci_remove_client_from_file_list(struct iamt_heci_device *dev,
> + __u8 host_client_id)
> +{
> +}
> diff --git a/drivers/char/heci/heci_interface.c b/drivers/char/heci/heci_interface.c
> new file mode 100644
> index 0000000..2527bb2
> --- /dev/null
> +++ b/drivers/char/heci/heci_interface.c
> @@ -0,0 +1,517 @@
> +
> +/**
> + * read_heci_register - Read a byte from the heci device
> + *
> + * @device: the device structure
> + * @offset: offset from which to read the data
> + *
> + * @return the byte read.
* Returns the byte read.
> + */
> +__u32 read_heci_register(struct iamt_heci_device *device,
> + unsigned long offset)
> +{
> + return readl(device->mem_addr + offset);
> +}
> +
> +/**
> + * write_heci_register - Write 4 bytes to the heci device
> + *
> + * @device: the device structure
> + * @offset: offset from which to write the data
> + * @value: the byte to write
> + */
> +void write_heci_register(struct iamt_heci_device *device, unsigned long offset,
> + __u32 value)
> +{
> + writel(value, device->mem_addr + offset);
> +}
> +
> +
> +/**
> + * heci_set_csr_register - write H_CSR register to the heci device
> + *
> + * @dev: device object for our driver
> + */
> +void heci_set_csr_register(struct iamt_heci_device *dev)
> +{
> + write_heci_register(dev, H_CSR, dev->host_hw_state);
> + dev->host_hw_state = read_heci_register(dev, H_CSR);
> +}
> +
> +/**
> + * heci_csr_enable_interrupts - enable heci device interrupts
> + *
> + * @dev: device object for our driver
> + */
> +void heci_csr_enable_interrupts(struct iamt_heci_device *dev)
> +{
> + dev->host_hw_state |= H_IE;
> + heci_set_csr_register(dev);
> +}
> +
> +/**
> + * heci_csr_disable_interrupts - disable heci device interrupts
> + *
> + * @dev: device object for our driver
> + */
> +void heci_csr_disable_interrupts(struct iamt_heci_device *dev)
> +{
> + dev->host_hw_state &= ~H_IE;
> + heci_set_csr_register(dev);
> +}
> +
> +
> +/**
> + * _host_get_filled_slots - get number of device filled buffer slots
> + *
> + * @device: the device structure
> + *
> + * @return numer of filled slots
Not @return.
> + */
> +static unsigned char _host_get_filled_slots(struct iamt_heci_device *dev)
> +{
> + char read_ptr, write_ptr;
> +
> + read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8);
> + write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16);
> +
> + return (unsigned char) (write_ptr - read_ptr);
> +}
> +
> +/**
> + * host_buffer_is_empty - check if host buffer is empty.
> + *
> + * @dev: device object for our driver
> + *
> + * @return 1 if empty, 0 - otherwise.
Ditto.
> + */
> +int host_buffer_is_empty(struct iamt_heci_device *dev)
> +{
> + unsigned char filled_slots;
> +
> + dev->host_hw_state = read_heci_register(dev, H_CSR);
> + filled_slots = _host_get_filled_slots(dev);
> +
> + if (filled_slots > 0)
> + return 0;
> +
> + return 1;
> +}
> +
> +/**
> + * count_empty_write_slots - count write empty slots.
> + *
> + * @dev: device object for our driver
> + *
> + * @return -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count
Ditto.
> + */
> +__s32 count_empty_write_slots(struct iamt_heci_device *dev)
> +{
> + unsigned char buffer_depth, filled_slots, empty_slots;
> +
> + buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24);
> + filled_slots = _host_get_filled_slots(dev);
> + empty_slots = buffer_depth - filled_slots;
> +
> + if (filled_slots > buffer_depth) {
> + /* overflow */
> + return -ESLOTS_OVERFLOW;
> + }
> +
> + return (__s32) empty_slots;
> +}
> +
> +/**
> + * heci_write_message - write a message to heci device.
> + *
> + * @dev: device object for our driver
> + * @heci_hdr: header of message
> + * @write_buffer: message buffer will be write
> + * @write_length: message size will be write
> + *
> + * @return 1 if success, 0 - otherwise.
Ditto.
> + */
> +int heci_write_message(struct iamt_heci_device *dev,
> + struct heci_msg_hdr *header,
> + unsigned char *write_buffer,
> + unsigned long write_length)
> +{
> +}
> +
> +/**
> + * count_full_read_slots - count read full slots.
> + *
> + * @dev: device object for our driver
> + *
> + * @return -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count
Not @return.
> + */
> +__s32 count_full_read_slots(struct iamt_heci_device *dev)
> +{
> +}
> +
> +/**
> + * heci_read_slots - read a message from heci device.
> + *
> + * @dev: device object for our driver
> + * @buffer: message buffer will be write
> + * @buffer_length: message size will be read
> + */
> +void heci_read_slots(struct iamt_heci_device *dev,
> + unsigned char *buffer, unsigned long buffer_length)
> +{
> +}
> +
> +/**
> + * flow_ctrl_creds - check flow_control credentials.
> + *
> + * @dev: device object for our driver
> + * @file_ext: private data of the file object
> + *
> + * @return 1 if flow_ctrl_creds >0, 0 - otherwise.
Not @return. OK, I won't keep repeating this comment.
> + */
> +int flow_ctrl_creds(struct iamt_heci_device *dev,
> + struct heci_file_private *file_ext)
> +{
> +}
> +
> +/**
> + * flow_ctrl_reduce - reduce flow_control.
> + *
> + * @dev: device object for our driver
> + * @file_ext: private data of the file object
> + */
> +void flow_ctrl_reduce(struct iamt_heci_device *dev,
> + struct heci_file_private *file_ext)
> +{
> +}
> +
> +/**
> + * heci_send_flow_control - send flow control to fw.
> + *
> + * @dev: device object for our driver
> + * @file_ext: private data 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)
> +{
> +}
> +
> +/**
> + * other_client_is_connecting - check if other
> + * client with the same client id is connected.
> + *
> + * @dev: device object for our driver
> + * @file_ext: private data of the file object
> + *
> + * @return 1 if other client is connected, 0 - otherwise.
> + */
> +int other_client_is_connecting(struct iamt_heci_device *dev,
> + struct heci_file_private *file_ext)
> +{
> +}
> +
> +/**
> + * heci_send_wd - send watch dog message to fw.
> + *
> + * @dev: device object for our driver
> + *
> + * @return 1 if success, 0 - otherwise.
> + */
> +int heci_send_wd(struct iamt_heci_device *dev)
> +{
> +}
> +
> +/**
> + * heci_disconnect - send disconnect message to fw.
> + *
> + * @dev: device object for our driver
> + * @file_ext: private data of the file object
> + *
> + * @return 1 if success, 0 - otherwise.
> + */
> +int heci_disconnect(struct iamt_heci_device *dev,
> + struct heci_file_private *file_ext)
> +{
> +}
> +
> +/**
> + * heci_connect - send connect message to fw.
> + *
> + * @dev: device object for our driver
> + * @file_ext: private data of the file object
> + *
> + * @return 1 if success, 0 - otherwise.
> + */
> +int heci_connect(struct iamt_heci_device *dev,
> + struct heci_file_private *file_ext)
> +{
> +}
> diff --git a/drivers/char/heci/heci_interface.h b/drivers/char/heci/heci_interface.h
> new file mode 100644
> index 0000000..a045853
> --- /dev/null
> +++ b/drivers/char/heci/heci_interface.h
> @@ -0,0 +1,170 @@
> +
> +#ifndef _HECI_INTERFACE_H_
> +#define _HECI_INTERFACE_H_
> +
> +
> +/* IOCTL commands */
> +#define IOCTL_HECI_GET_VERSION \
> + _IOWR('H' , 0x0, struct heci_message_data)
> +#define IOCTL_HECI_CONNECT_CLIENT \
> + _IOWR('H' , 0x01, struct heci_message_data)
> +#define IOCTL_HECI_WD \
> + _IOWR('H' , 0x02, struct heci_message_data)
> +#define IOCTL_HECI_BYPASS_WD \
> + _IOWR('H' , 0x10, struct heci_message_data)
> +
Needs an update to Documentation/ioctl-number.txt .
> +
> +#endif /* _HECI_INTERFACE_H_ */
> diff --git a/drivers/char/heci/heci_main.c b/drivers/char/heci/heci_main.c
> new file mode 100644
> index 0000000..ecc6031
> --- /dev/null
> +++ b/drivers/char/heci/heci_main.c
> @@ -0,0 +1,1523 @@
> +
> +/**
> + * Set up the cdev structure for heci device.
kernel-doc format:
* heci_registration_cdev - set up the cdev structure for the heci device
> + *
> + * @dev: char device struct
> + * @hminor: minor number for registration char device
> + * @fops: file operations structure
> + *
> + * @return 0 on success, <0 on failure.
> + */
> +static int heci_registration_cdev(struct cdev *dev, int hminor,
> + struct file_operations *fops)
> +{
> + int ret, devno = MKDEV(heci_major, hminor);
> +
> + cdev_init(dev, fops);
> + dev->owner = THIS_MODULE;
> + ret = cdev_add(dev, devno, 1);
> + /* Fail gracefully if need be */
> + if (ret) {
> + printk(KERN_ERR "heci: Error %d registering heci device %d\n",
> + 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_register_cdev - registers heci char device
> + *
> + * @return 0 on success, <0 on failure.
> + */
> +static int heci_register_cdev(void)
> +{
> +}
> +
> +
> +
> +
> +/**
> + * heci_open - the open function
Missing parameter descriptions.
> + */
> +static int heci_open(struct inode *inode, struct file *file)
> +{
> +}
> +
> +/**
> + * heci_release - the release function
Ditto.
> + */
> +static int heci_release(struct inode *inode, struct file *file)
> +{
> +}
> +
> +
> +/**
> + * heci_read - the read client message function.
Ditto.
> + */
> +static ssize_t heci_read(struct file *file, char __user *ubuf,
> + size_t length, loff_t *offset)
> +{
> +}
> +
> +/**
> + * heci_write - the write function.
Ditto.
> + */
> +static ssize_t heci_write(struct file *file, const char __user *ubuf,
> + size_t length, loff_t *offset)
> +{
> +}
> +
> +/**
> + * heci_ioctl - the IOCTL function
Tritto.
> + */
> +static int heci_ioctl(struct inode *inode, struct file *file,
> + unsigned int cmd, unsigned long data)
> +{
> +}
> +
> +/**
> + * heci_poll - the poll function
Again.
> + */
> +static unsigned int heci_poll(struct file *file, poll_table *wait)
> +{
> +}
> diff --git a/drivers/char/heci/interrupt.c b/drivers/char/heci/interrupt.c
> new file mode 100644
> index 0000000..b41e8d3
> --- /dev/null
> +++ b/drivers/char/heci/interrupt.c
> @@ -0,0 +1,1552 @@
> +
> +
> +/**
> + * _heci_cmpl: process completed operation.
* _heci_cmpl - process completed operation
> + *
> + * @file_ext: private data of the file object.
> + * @priv_cb_pos: callback block.
> + */
> +static void _heci_cmpl(struct heci_file_private *file_ext,
> + struct heci_cb_private *priv_cb_pos)
> +{
> +}
> +
> +/**
> + * _heci_cmpl_iamthif: process completed iamthif operation.
s/: / - /
> + *
> + * @dev: Device object for our driver.
> + * @priv_cb_pos: callback block.
> + */
> +static void _heci_cmpl_iamthif(struct iamt_heci_device *dev,
> + struct heci_cb_private *priv_cb_pos)
> +{
> +}
> +/**
> + * _heci_bh_iamthif_read: prepare to read iamthif data.
s/: / - /
> + *
> + * @dev: Device object for our driver.
> + * @slots: free slots.
> + *
> + * @return 0, OK; otherwise, error.
> + */
> +static int _heci_bh_iamthif_read(struct iamt_heci_device *dev, __s32 *slots)
> +{
> +}
> +
> +/**
> + * _heci_bh_close: process close related operation.
s/: / - /
> + *
> + * @dev: Device object for our driver.
> + * @slots: free slots.
> + * @priv_cb_pos: callback block.
> + * @file_ext: private data of the file object.
> + * @cmpl_list: complete list.
> + *
> + * @return 0, OK; otherwise, error.
> + */
> +static int _heci_bh_close(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)
> +{
> +}
> +
> +/**
> + * _heci_hb_close: process read related operation.
s/: / - /
> + *
> + * @dev: Device object for our driver.
> + * @slots: free slots.
> + * @priv_cb_pos: callback block.
> + * @file_ext: private data of the file object.
> + * @cmpl_list: complete list.
> + *
> + * @return 0, OK; otherwise, error.
> + */
> +static int _heci_bh_read(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)
> +{
> +}
> +
> +
> +/**
> + * _heci_bh_ioctl: process ioctl related operation.
s/: / - /
> + *
> + * @dev: Device object for our driver.
> + * @slots: free slots.
> + * @priv_cb_pos: callback block.
> + * @file_ext: private data of the file object.
> + * @cmpl_list: complete list.
> + *
> + * @return 0, OK; otherwise, error.
> + */
> +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)
> +{
> +}
> +
> +/**
> + * _heci_bh_cmpl: process completed and no-iamthif operation.
s/: / - /
> + *
> + * @dev: Device object for our driver.
> + * @slots: free slots.
> + * @priv_cb_pos: callback block.
> + * @file_ext: private data of the file object.
> + * @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)
> +{
> +}
> +
> +/**
> + * _heci_bh_cmpl_iamthif: process completed iamthif operation.
s/: / - /
> + *
> + * @dev: Device object for our driver.
> + * @slots: free slots.
> + * @priv_cb_pos: callback block.
> + * @file_ext: private data of the file object.
> + * @cmpl_list: complete list.
> + *
> + * @return 0, OK; otherwise, error.
> + */
> +static int _heci_bh_cmpl_iamthif(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)
> +{
> +}
General (CodingStyle): functions should not begin with a blank line after the
opening {, nor should they have blank lines before the closing }. Yes, I saw both
of those.
---
~Randy
Linux Plumbers Conference, 17-19 September 2008, Portland, Oregon USA
http://linuxplumbersconf.org/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/