Intel Management Engine Interface
PATCH 1/1 Intel Management Engine Interface
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.
The core hardware architecture of Intel Active Management Technology (Intel AMT) is resident in firmware. The micro-controller within the chipset's graphics and memory controller (GMCH) hub houses the Management Engine (ME) firmware, which implements various services on behalf of management applications.
Some of the ME subsystems that can be access via MEI driver:
- Intel(R) Quiet System Technology (QST) is implemented as a firmware subsystem that runs in the ME. Programs that wish to expose the health monitoring and fan speed control capabilities of Intel(R) QST will need to use the MEI driver to communicate with the ME sub-system.
- ASF is the "Alert Standard Format" which is an DMTF manageability standard. It is implemented in the PC's hardware and firmware, and is managed from a remote console.
Most recent Intel desktop chipsets have one or more of the above ME services. The MEI driver will make it possible to support the above features on Linux and provides applications access to the ME and it's features.
---
MAINTAINERS +9 -0
@@ -2082,6 +2082,15 @@ L: [email protected] W: http://e1000.sourceforge.net/ S: Supported +INTEL MANAGEABILITY ENGINE INTERFACE (HECI) +P: Anas Nashif +M: [email protected] +P: Marcin Obara +M: [email protected] +W: http://www.openamt.org/ +L: [email protected] +S: Supported + INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT P: Zhu Yi M: [email protected]
drivers/char/Kconfig +1 -0
@@ -1048,6 +1048,7 @@ config DEVPORT default y source "drivers/s390/char/Kconfig" +source "drivers/char/heci/Kconfig" endmenu
drivers/char/Makefile +1 -0
@@ -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/ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
drivers/char/heci/Kconfig new file +12 -0
@@ -0,0 +1,12 @@ +# +# HECI device configuration +# + +config INTEL_MEI + tristate "Intel Management Engine Interface (MEI) Support" + 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. +
drivers/char/heci/Makefile new file +7 -0
@@ -0,0 +1,7 @@ +# +## Makefile for the Intel MEI driver (heci) +# + +obj-$(CONFIG_INTEL_MEI) += heci.o + +heci-objs := heci_init.o heci_interface.o heci_main.o interrupt.o io_heci.o
drivers/char/heci/heci.h new file +184 -0
184 lines not on this page · raw message
(quoted diff) +0 -0
b/drivers/char/heci/heci_data_structures.h
new file mode 100644
index 0000000..ac0f488
drivers/char/heci/heci_data_structures.h new file +507 -0
507 lines not on this page · raw message
drivers/char/heci/heci_init.c new file +1104 -0
1,104 lines not on this page · raw message
drivers/char/heci/heci_interface.c new file +497 -0
497 lines not on this page · raw message
drivers/char/heci/heci_interface.h new file +169 -0
169 lines not on this page · raw message
drivers/char/heci/heci_main.c new file +1544 -0
491 lines not on this page · raw message
drivers/char/heci/heci_version.h new file +56 -0
56 lines not on this page · raw message
drivers/char/heci/interrupt.c new file +1551 -0
1,551 lines not on this page · raw message
drivers/char/heci/io_heci.c new file +865 -0
865 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
Quoted 25 lines · On Mon, 19 May 2008 20:11:54 -0400 Anas Nashif <[email protected]> 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.
The core hardware architecture of Intel Active Management Technology (Intel AMT) is resident in firmware. The micro-controller within the chipset's graphics and memory controller (GMCH) hub houses the Management Engine (ME) firmware, which implements various services on behalf of management applications.
Some of the ME subsystems that can be access via MEI driver:
- Intel(R) Quiet System Technology (QST) is implemented as a firmware subsystem that runs in the ME. Programs that wish to expose the health monitoring and fan speed control capabilities of Intel(R) QST will need to use the MEI driver to communicate with the ME sub-system.
- ASF is the "Alert Standard Format" which is an DMTF manageability standard. It is implemented in the PC's hardware and firmware, and is managed from a remote console.
Quoted 4 lines
Most recent Intel desktop chipsets have one or more of the above ME services. The MEI driver will make it possible to support the above features on Linux and provides applications access to the ME and it's features.
What a lot of code.
It'd be nice if the changelog were to describe the proposed and all-important kernel<->userspace interface, please. From a five-second peek it looks like a miscdev with ioctls? Ah, and there's read and write too.
What is the payload for those system calls, and the meanings of their return values, etc, etc?
Does it make sense for this driver to be available on all architectures?
Quoted 40 lines · Andrew Morton
Quoted 25 lines · On Mon, 19 May 2008 20:11:54 -0400 Anas Nashif <[email protected]> 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.
The core hardware architecture of Intel Active Management Technology (Intel AMT) is resident in firmware. The micro-controller within the chipset's graphics and memory controller (GMCH) hub houses the Management Engine (ME) firmware, which implements various services on behalf of management applications.
Some of the ME subsystems that can be access via MEI driver:
- Intel(R) Quiet System Technology (QST) is implemented as a firmware subsystem that runs in the ME. Programs that wish to expose the health monitoring and fan speed control capabilities of Intel(R) QST will need to use the MEI driver to communicate with the ME sub-system.
- ASF is the "Alert Standard Format" which is an DMTF manageability standard. It is implemented in the PC's hardware and firmware, and is managed from a remote console.Quoted 4 lines
Most recent Intel desktop chipsets have one or more of the above ME services. The MEI driver will make it possible to support the above features on Linux and provides applications access to the ME and it's features.
What a lot of code.
It'd be nice if the changelog were to describe the proposed and all-important kernel<->userspace interface, please. From a five-second peek it looks like a miscdev with ioctls? Ah, and there's read and write too.
Quoted 5 lines
What is the payload for those system calls, and the meanings of their return values, etc, etc?
Does it make sense for this driver to be available on all architectures?
This patch is against what tree / kernel version ?
Won't compile on current kernels cause it still uses class_device_* so I guess it is based on 2.6.22/23 ?
Also in drivers/char/Makefile $(CONFIG_HECI) should be $(CONFIG_INTEL_MEI)
Gabriel
Hi!
Quoted 30 lines
Quoted 25 lines
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.
The core hardware architecture of Intel Active Management Technology (Intel AMT) is resident in firmware. The micro-controller within the chipset's graphics and memory controller (GMCH) hub houses the Management Engine (ME) firmware, which implements various services on behalf of management applications.
Some of the ME subsystems that can be access via MEI driver:
- Intel(R) Quiet System Technology (QST) is implemented as a firmware subsystem that runs in the ME. Programs that wish to expose the health monitoring and fan speed control capabilities of Intel(R) QST will need to use the MEI driver to communicate with the ME sub-system.
- ASF is the "Alert Standard Format" which is an DMTF manageability standard. It is implemented in the PC's hardware and firmware, and is managed from a remote console.Quoted 4 lines
Most recent Intel desktop chipsets have one or more of the above ME services. The MEI driver will make it possible to support the above features on Linux and provides applications access to the ME and it's features.
Quoted 6 lines
What a lot of code.
It'd be nice if the changelog were to describe the proposed and all-important kernel<->userspace interface, please. From a five-second peek it looks like a miscdev with ioctls? Ah, and there's read and write too.
Actuallly, we already have perfectly good interface for sensor-like stuff -- in lm_sensors. Even acpi is moving in that direction...
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Quoted 15 lines · On Tuesday, 20 May 2008 03:11:54 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.
The core hardware architecture of Intel Active Management Technology (Intel AMT) is resident in firmware. The micro-controller within the chipset's graphics and memory controller (GMCH) hub houses the Management Engine (ME) firmware, which implements various services on behalf of management applications.
Quoted 6 lines
Some of the ME subsystems that can be access via MEI driver:
- Intel(R) Quiet System Technology (QST) is implemented as a firmware subsystem that runs in the ME. Programs that wish to expose the health monitoring and fan speed control capabilities of Intel(R) QST will need to use the MEI driver to communicate with the ME sub-system.
I bought a system with intel DG965RY motherboard year ago, and still no support for its O/B sensors in linux.
Can I ask again, when you expect it to be released.
At least intel should release documents how to access the QST sensors.
I know that HECI is first step for that, but it is not enought to read those sensors.
I Really hope there are good news,
Best regards,
Maxim Levitsky
drivers/char/heci/heci_data_structures.h line 198
Quoted 8 lines
drivers/char/heci/heci_data_structures.h new file +3
-0+#define SECOND_TO_MILLI 1000 +#define SECOND_TO_MICRO SECOND_TO_MILLI * 1000 +#define SECOND_TO_100NANO SECOND_TO_MICRO * 10
These definitions are not used in any file, why don't you remove them?
Quoted 8 lines · Anas Nashif
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.
[...]
drivers/char/Makefile obj-$(CONFIG_IPMI_HANDLER) += ipmi/ · line 109
Quoted 9 lines
drivers/char/Makefile +1
-0@@ -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?
Quoted 3 lines
drivers/char/Makefile +0
-0obj-$(CONFIG_PS3_FLASH) += ps3flash.o
[...]
Quoted 6 lines
drivers/char/heci/heci_init.c new file +0
-0@@ -0,0 +1,1104 @@
[...]
drivers/char/heci/heci_init.c line 234
Quoted 9 lines
drivers/char/heci/heci_init.c new file +9
-0+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();
[...]
Quoted 10 lines
drivers/char/heci/heci_init.c new file +10
-0+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 */
drivers/char/heci/heci_init.c line 537
Quoted 10 lines
drivers/char/heci/heci_init.c new file +10
-0+ 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
Quoted 23 lines
drivers/char/heci/heci_init.c new file +23
-0+ 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 */
drivers/char/heci/heci_init.c line 570
Quoted 10 lines
drivers/char/heci/heci_init.c new file +10
-0+ 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
Quoted 13 lines
drivers/char/heci/heci_init.c new file +13
-0+ 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 ; +}
[...]
Quoted 35 lines
drivers/char/heci/heci_init.c new file +35
-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
drivers/char/heci/heci_init.c line 928
Quoted 10 lines
drivers/char/heci/heci_init.c new file +10
-0+ 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?
Quoted 2 lines
drivers/char/heci/heci_init.c new file +2
-0+spin_unlock_bh (&dev->device_lock); +}
[...]
Quoted 1 line
+struct
heci_file_private*alloc_priv(struct file *file)
not a good name.
Quoted 1 line
+{
[...]
drivers/char/heci/heci_init.c line 1020
Quoted 4 lines
drivers/char/heci/heci_init.c new file +4
-0+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
Quoted 2 lines
drivers/char/heci/heci_init.c new file +2
-0+long timeout =15 ;/*15 second */ +struct heci_cb_private *priv_cb =NULL ;
[...]
Quoted 6 lines
drivers/char/heci/heci_interface.c new file +0
-0@@ -0,0 +1,497 @@
[...]
Quoted 15 lines
drivers/char/heci/heci_interface.c new file +15
-0+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++) {
drivers/char/heci/heci_interface.c line 287
Quoted 10 lines
drivers/char/heci/heci_interface.c new file +10
-0+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();
Quoted 20 lines
drivers/char/heci/heci_interface.c new file +20
-0+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 ) {
drivers/char/heci/heci_interface.c line 317
Quoted 10 lines
drivers/char/heci/heci_interface.c new file +10
-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
Quoted 17 lines
drivers/char/heci/heci_interface.c new file +17
-0+} + +/** +* 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;
drivers/char/heci/heci_interface.c line 344
Quoted 10 lines
drivers/char/heci/heci_interface.c new file +10
-0+ + 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?
Quoted 3 lines
drivers/char/heci/heci_interface.c new file +3
-0+ 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 ;
[...]
Quoted 6 lines
drivers/char/heci/heci_interface.h new file +0
-0@@ -0,0 +1,169 @@
[...]
drivers/char/heci/heci_interface.h line 93
Quoted 2 lines
drivers/char/heci/heci_interface.h new file +2
-0+/* IOCTL commands */ +#define HECI_IOCTL_LETTER 'H'
'H' all linux/hiddev.h
add
drivers/char/heci/heci_interface.h line 103
Quoted 8 lines
drivers/char/heci/heci_interface.h new file +8
-0+#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
[...]
Quoted 6 lines
drivers/char/heci/heci_main.c new file +0
-0@@ -0,0 +1,1544 @@
[...]
drivers/char/heci/heci_main.c line 87
Quoted 4 lines
drivers/char/heci/heci_main.c new file +4
-0+#ifdef HECI_DEBUG +int heci_debug =1 ; +#else +int heci_debug;/* initialized to 0 automatically.*/
we know that, comment unneeded
drivers/char/heci/heci_main.c line 89
Quoted 2 lines
drivers/char/heci/heci_main.c new file +2
-0+#endif +MODULE_PARM_DESC (heci_debug,"Debug enabled or not" );
so why not bool?
Quoted 3 lines
drivers/char/heci/heci_main.c new file +3
-0+module_param (heci_debug, int,0644 ); + +
[...]
Quoted 16 lines
drivers/char/heci/heci_main.c new file +16
-0+/* 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 )},
drivers/char/heci/heci_main.c line 132
Quoted 10 lines
drivers/char/heci/heci_main.c new file +10
-0+ {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?
[...]
drivers/char/heci/heci_main.c line 169
Quoted 5 lines
drivers/char/heci/heci_main.c new file +5
-0+static struct pci_driver heci_driver = { + .name = heci_driver_name, + .id_table = heci_pci_tbl, + .probe = heci_probe, + .remove = heci_remove,
__devexit_p()
drivers/char/heci/heci_main.c line 170
Quoted 1 line
drivers/char/heci/heci_main.c new file +1
-0+ .shutdown = heci_remove,
you'll trigger remove twice, I think.
drivers/char/heci/heci_main.c line 174
Quoted 4 lines
drivers/char/heci/heci_main.c new file +4
-0+#ifdef CONFIG_PM + .suspend = heci_suspend, + .resume = heci_resume +#endif
define them as null on !PM to avoid these ifdefs.
Quoted 1 line
+};
[...]
drivers/char/heci/heci_main.c line 202
Quoted 4 lines
drivers/char/heci/heci_main.c new file +4
-0+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
drivers/char/heci/heci_main.c line 206
Quoted 4 lines
drivers/char/heci/heci_main.c new file +4
-0+ +cdev_init (dev, fops); + dev->owner =THIS_MODULE ; + dev->ops = fops;
no need to re-set
drivers/char/heci/heci_main.c line 210
Quoted 4 lines
drivers/char/heci/heci_main.c new file +4
-0+ ret =cdev_add (dev, devno,1 ); +/* Fail gracefully if need be */ +if (ret) { +kobject_put (&dev->kobj);
why?
Quoted 9 lines
drivers/char/heci/heci_main.c new file +9
-0+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) +{
drivers/char/heci/heci_main.c line 229
Quoted 10 lines
drivers/char/heci/heci_main.c new file +10
-0+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)?)*
Quoted 6 lines
+ *
+ * @return :
+ * valid pointer to a struct class on success
+ * false pointer on failure
+ */
+static struct class *heci_sysfs_create(struct module *owner, char *name)
[...]
Quoted 11 lines
drivers/char/heci/heci_main.c new file +11
-0+/** +* 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 ;
drivers/char/heci/heci_main.c line 292
Quoted 10 lines
drivers/char/heci/heci_main.c new file +10
-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
Quoted 6 lines
drivers/char/heci/heci_main.c new file +6
-0+if (IS_ERR (heci_class_dev)) + err =PTR_ERR (heci_class_dev); + +err_out: +return err; +}
[...]
Quoted 7 lines
drivers/char/heci/heci_main.c new file +7
-0+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);
drivers/char/heci/heci_main.c line 335
Quoted 10 lines
drivers/char/heci/heci_main.c new file +10
-0+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?
Quoted 2 lines
drivers/char/heci/heci_main.c new file +2
-0+ + heci_major =MAJOR (dev);
[...]
Quoted 65 lines
drivers/char/heci/heci_main.c new file +65
-0+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;
drivers/char/heci/heci_main.c line 480
Quoted 10 lines
drivers/char/heci/heci_main.c new file +10
-0+ 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.
drivers/char/heci/heci_main.c line 484
Quoted 4 lines
drivers/char/heci/heci_main.c new file +4
-0+ err = -ENODEV ; + goto release_irq; + } +init_timer (&dev->wd_timer);
not needed, if heci_initialize_clients called setup_timer
Quoted 6 lines
drivers/char/heci/heci_main.c new file +6
-0+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; + }
[...]
Quoted 34 lines
drivers/char/heci/heci_main.c new file +34
-0+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);
drivers/char/heci/heci_main.c line 585
Quoted 10 lines
drivers/char/heci/heci_main.c new file +10
-0+ + 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?
Quoted 29 lines
drivers/char/heci/heci_main.c new file +29
-0+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 ;
drivers/char/heci/heci_main.c line 624
Quoted 10 lines
drivers/char/heci/heci_main.c new file +10
-0+ 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?
Quoted 11 lines
drivers/char/heci/heci_main.c new file +11
-0+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); +}
[...]
drivers/char/heci/heci_main.c line 902
Quoted 6 lines
drivers/char/heci/heci_main.c new file +6
-0+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?
Quoted 120 lines
drivers/char/heci/heci_main.c new file +120
-0+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, */
drivers/char/heci/heci_main.c line 1032
Quoted 10 lines
drivers/char/heci/heci_main.c new file +10
-0+/* 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
Quoted 31 lines
drivers/char/heci/heci_main.c new file +31
-0+ 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));
...
Quoted 5 lines
drivers/char/heci/heci_main.c new file +5
-0+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 ();
[...]
drivers/char/heci/heci_main.c line 1315
Quoted 2 lines
drivers/char/heci/heci_main.c new file +2
-0+static int heci_ioctl (struct inode *inode,struct file *file, +unsigned int cmd,unsigned long data)
->unlocked_ioctl
Quoted 8 lines
drivers/char/heci/heci_main.c new file +8
-0+{ +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 ;
[...]
Quoted 51 lines
drivers/char/heci/heci_main.c new file +51
-0+#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 ||
drivers/char/heci/heci_main.c line 1489
Quoted 10 lines
drivers/char/heci/heci_main.c new file +10
-0+ 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?
Quoted 10 lines
drivers/char/heci/heci_main.c new file +10
-0+ +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 ;
drivers/char/heci/heci_main.c line 1509
Quoted 10 lines
drivers/char/heci/heci_main.c new file +10
-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?
Quoted 7 lines
drivers/char/heci/heci_main.c new file +7
-0+ 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; + }
[...]
Quoted 6 lines
drivers/char/heci/heci_version.h new file +0
-0@@ -0,0 +1,56 @@
[...]
drivers/char/heci/heci_version.h line 52
Quoted 12 lines
drivers/char/heci/heci_version.h new file +12
-0+#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()
drivers/char/heci/heci_version.h line 54
Quoted 2 lines
drivers/char/heci/heci_version.h new file +2
-0+ +#define DRIVER_VERSION DRIVER_V1 "." DRIVER_V2
not good macro names at all
Quoted 8 lines
drivers/char/heci/heci_version.h new file +2
-0+ +#endif drivers/char/heci/interrupt.c new file +0
-0@@ -0,0 +1,1551 @@
[...]
Quoted 9 lines
drivers/char/heci/interrupt.c new file +9
-0+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 ; +
drivers/char/heci/interrupt.c line 101
Quoted 10 lines
drivers/char/heci/interrupt.c new file +10
-0+/* 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?
drivers/char/heci/interrupt.c line 104
Quoted 3 lines
drivers/char/heci/interrupt.c new file +3
-0+DBG ("schedule work the heci_bh_handler.\n" ); + err =schedule_work (&device->work); +if (!err) {
some ratelimit?
Quoted 5 lines
drivers/char/heci/interrupt.c new file +5
-0+printk (KERN_ERR "%s: schedule the heci_bh_handler" +" failed error=%x\n" ,THIS_MODULE ->name, err); + } +return IRQ_HANDLED ; +}
[...]
Quoted 70 lines
drivers/char/heci/interrupt.c new file +70
-0+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 )
drivers/char/heci/interrupt.c line 253
Quoted 10 lines
drivers/char/heci/interrupt.c new file +10
-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?
Quoted 6 lines
drivers/char/heci/interrupt.c new file +6
-0+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); + }
[...]
Quoted 15 lines
drivers/char/heci/interrupt.c new file +15
-0+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 ;
drivers/char/heci/interrupt.c line 832
Quoted 10 lines
drivers/char/heci/interrupt.c new file +10
-0+ }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?
Quoted 42 lines
drivers/char/heci/interrupt.c new file +42
-0+ } + +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) +
drivers/char/heci/interrupt.c line 884
Quoted 10 lines
drivers/char/heci/interrupt.c new file +10
-0+ 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?
Quoted 8 lines
drivers/char/heci/interrupt.c new file +8
-0+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);
...
Quoted 2 lines
drivers/char/heci/interrupt.c new file +2
-0+ } + }else if (*slots == ((dev->host_hw_state &H_CBD ) >>24 )) {
[...]
drivers/char/heci/interrupt.c line 1347
Quoted 9 lines
drivers/char/heci/interrupt.c new file +9
-0+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>;
Quoted 7 lines
drivers/char/heci/interrupt.c new file +7
-0+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++) {
drivers/char/heci/interrupt.c line 1370
Quoted 10 lines
drivers/char/heci/interrupt.c new file +10
-0+ 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()
[...]
Quoted 9 lines
drivers/char/heci/interrupt.c new file +9
-0+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 ; +}
...
Hi!
Quoted 4 lines
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.
* uses homebrewn DBG(), could it use dprintk() or something.
* should probably come with Documentation/ file
* defines like H_IE are a bit too terse.
drivers/char/heci/heci.h line 60
Quoted 5 lines
drivers/char/heci/heci.h new file +5
-0+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[2 ][4 ];
Externs should go to header file.
No need to use __u8 in kernel.
Variables need good names. pthi_guid is not one of them.
drivers/char/heci/heci.h line 67
Quoted 6 lines
drivers/char/heci/heci.h new file +6
-0+/** +* memory IO BAR definition +*/ +#define BAR_0 0 +#define BAR_1 1 +#define BAR_5 5
Heh. And comments should tell us what it is.
Hmm, is this kerneldoc? Does not seem like one. So don't use /**. Fix this all over the patch.
Quoted 9 lines
+/**
+ *heci_fe_same_id- tell if file extensions have same id
+ * @fe1 -file extension
+ * @fe2 -file extension
+ *
+ * @return :
+ * 1 - if ids are the same,
+ * 0 - if differ.
+ */
File extensions?!
drivers/char/heci/heci.h line 182
Quoted 10 lines
drivers/char/heci/heci.h new file +10
-0+static inline int heci_fe_same_id (struct heci_file_private *fe1, +struct heci_file_private *fe2) +{ +if ((fe1->host_client_id == fe2->host_client_id) + && (fe1->me_client_id == fe2->me_client_id)) { +return 1 ; + }else { +return 0 ; + } +}
This can be written without the if.
Quoted 18 lines
drivers/char/heci/heci.h new file +1
-0+#endif /* _HECI_H_ */ drivers/char/heci/heci_data_structures.h new file +10
-0@@ -0,0 +1,507 @@ +/* +* Part of Intel(R) Manageability Engine Interface Linux driver +* +* Copyright (c) 2003 - 2008 Intel Corp. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright
drivers/char/heci/heci_data_structures.h line 20
Quoted 10 lines
drivers/char/heci/heci_data_structures.h new file +10
-0+* notice, this list of conditions, and the following disclaimer, +* without modification. +* 2. Redistributions in binary form must reproduce at minimum a disclaimer +* substantially similar to the "NO WARRANTY" disclaimer below +* ("Disclaimer") and any redistribution must be conditioned upon +* including a substantially similar Disclaimer requirement for further +* binary redistribution. +* 3. Neither the names of the above-listed copyright holders nor the names +* of any contributors may be used to endorse or promote products derived +* from this software without specific prior written permission.
What kind of ninja mutant license is this?
drivers/char/heci/heci_data_structures.h line 66
Quoted 4 lines
drivers/char/heci/heci_data_structures.h new file +4
-0+/** +* Number of queue lists used by this driver +*/ +#define NUMBER_OF_LISTS 7
Yes, how very useful name. Plus, it is too generic and likely to conflict with someone else.
drivers/char/heci/heci_data_structures.h line 68
Quoted 1 line
drivers/char/heci/heci_data_structures.h new file +1
-0+#define IAMTHIF_MTU 4160
And this one seems encrypted.
drivers/char/heci/heci_data_structures.h line 79
Quoted 10 lines
drivers/char/heci/heci_data_structures.h new file +10
-0+ +/** +* HECI HW Section +*/ + +/* HECI addresses and defines */ +#define H_CB_WW 0 +#define H_CSR 4 +#define ME_CB_RW 8 +#define ME_CSR_HA 0xC
As do this and registers below.
drivers/char/heci/heci_data_structures.h line 124
Quoted 4 lines
drivers/char/heci/heci_data_structures.h new file +4
-0+/** +* time to wait event +*/ +#define HECI_INTEROP_TIMEOUT (HZ * 7)
Could we get _useful_ comments?
drivers/char/heci/heci_data_structures.h line 151
Quoted 8 lines
drivers/char/heci/heci_data_structures.h new file +8
-0+/* File state */ +enum file_state { +HECI_FILE_INITIALIZING =0 , +HECI_FILE_CONNECTING , +HECI_FILE_CONNECTED , +HECI_FILE_DISCONNECTING , +HECI_FILE_DISCONNECTED +};
What kind of files is this handling? Surely this is not a filesystem?
drivers/char/heci/heci_data_structures.h line 154
Quoted 2 lines
drivers/char/heci/heci_data_structures.h new file +2
-0+/* HECI states */ +enum heci_states {
Missing space, and evil comment.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html