aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2009-09-11 12:46:35 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-15 15:02:35 -0400
commit0b33559a1adb3b9953503c9b55a61c37db34ffc0 (patch)
treee907a14dbb57329f20927dfd91a40e607e9545e6 /drivers/staging
parent1c6592f3b78640902494650efb88d8c2520c5c92 (diff)
Staging: remove heci driver
Intel has officially abandoned this project and does not want to maintian it or have it included in the main kernel tree, as no one should use the code, it's not needed anymore. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/heci/Kconfig7
-rw-r--r--drivers/staging/heci/Makefile9
-rw-r--r--drivers/staging/heci/TODO6
-rw-r--r--drivers/staging/heci/heci.h175
-rw-r--r--drivers/staging/heci/heci_data_structures.h529
-rw-r--r--drivers/staging/heci/heci_init.c1083
-rw-r--r--drivers/staging/heci/heci_interface.c498
-rw-r--r--drivers/staging/heci/heci_interface.h170
-rw-r--r--drivers/staging/heci/heci_main.c1576
-rw-r--r--drivers/staging/heci/heci_version.h54
-rw-r--r--drivers/staging/heci/interrupt.c1555
-rw-r--r--drivers/staging/heci/io_heci.c872
14 files changed, 0 insertions, 6537 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 66188a5bf44..e86a6716156 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -103,8 +103,6 @@ source "drivers/staging/phison/Kconfig"
103 103
104source "drivers/staging/p9auth/Kconfig" 104source "drivers/staging/p9auth/Kconfig"
105 105
106source "drivers/staging/heci/Kconfig"
107
108source "drivers/staging/line6/Kconfig" 106source "drivers/staging/line6/Kconfig"
109 107
110source "drivers/gpu/drm/radeon/Kconfig" 108source "drivers/gpu/drm/radeon/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 3c64d5fad65..fa5361664ba 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -34,7 +34,6 @@ obj-$(CONFIG_STLC45XX) += stlc45xx/
34obj-$(CONFIG_B3DFG) += b3dfg/ 34obj-$(CONFIG_B3DFG) += b3dfg/
35obj-$(CONFIG_IDE_PHISON) += phison/ 35obj-$(CONFIG_IDE_PHISON) += phison/
36obj-$(CONFIG_PLAN9AUTH) += p9auth/ 36obj-$(CONFIG_PLAN9AUTH) += p9auth/
37obj-$(CONFIG_HECI) += heci/
38obj-$(CONFIG_LINE6_USB) += line6/ 37obj-$(CONFIG_LINE6_USB) += line6/
39obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/ 38obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/
40obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/ 39obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/
diff --git a/drivers/staging/heci/Kconfig b/drivers/staging/heci/Kconfig
deleted file mode 100644
index c7206f8bcd9..00000000000
--- a/drivers/staging/heci/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
1config HECI
2 tristate "Intel Management Engine Interface (MEI) Support"
3 depends on PCI
4 ---help---
5 The Intel Management Engine Interface (Intel MEI) driver allows
6 applications to access the Active Management Technology
7 firmware and other Management Engine sub-systems.
diff --git a/drivers/staging/heci/Makefile b/drivers/staging/heci/Makefile
deleted file mode 100644
index 0524856fa3a..00000000000
--- a/drivers/staging/heci/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
1obj-$(CONFIG_HECI) += heci.o
2
3heci-objs := \
4 heci_init.o \
5 interrupt.o \
6 heci_interface.o \
7 io_heci.o \
8 heci_main.o
9
diff --git a/drivers/staging/heci/TODO b/drivers/staging/heci/TODO
deleted file mode 100644
index f86715d631c..00000000000
--- a/drivers/staging/heci/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
1TODO:
2 - fix user/kernel pointer mess in the ioctl handlers as pointed
3 out by sparse.
4 - resolve the ioctls and see if most of them can just be simple
5 sysfs files
6 - fix locking issues that sparse points out at the least.
diff --git a/drivers/staging/heci/heci.h b/drivers/staging/heci/heci.h
deleted file mode 100644
index 48f120dc3b2..00000000000
--- a/drivers/staging/heci/heci.h
+++ /dev/null
@@ -1,175 +0,0 @@
1/*
2 * Part of Intel(R) Manageability Engine Interface Linux driver
3 *
4 * Copyright (c) 2003 - 2008 Intel Corp.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * substantially similar to the "NO WARRANTY" disclaimer below
15 * ("Disclaimer") and any redistribution must be conditioned upon
16 * including a substantially similar Disclaimer requirement for further
17 * binary redistribution.
18 * 3. Neither the names of the above-listed copyright holders nor the names
19 * of any contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * Alternatively, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2 as published by the Free
24 * Software Foundation.
25 *
26 * NO WARRANTY
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGES.
38 *
39 */
40
41#ifndef _HECI_H_
42#define _HECI_H_
43
44#include <linux/spinlock.h>
45#include <linux/list.h>
46#include <linux/pci.h>
47#include <linux/timer.h>
48#include <linux/interrupt.h>
49#include <linux/workqueue.h>
50#include <linux/module.h>
51#include <linux/aio.h>
52#include <linux/types.h>
53#include "heci_data_structures.h"
54
55extern const struct guid heci_pthi_guid;
56extern const struct guid heci_wd_guid;
57extern const __u8 heci_start_wd_params[];
58extern const __u8 heci_stop_wd_params[];
59extern const __u8 heci_wd_state_independence_msg[3][4];
60
61/*
62 * heci device ID
63 */
64#define HECI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */
65#define HECI_DEV_ID_82G35 0x2984 /* 82G35 Express */
66#define HECI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */
67#define HECI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */
68
69#define HECI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */
70#define HECI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */
71
72#define HECI_DEV_ID_ICH9_82Q35 0x29B4 /* 82Q35 Express */
73#define HECI_DEV_ID_ICH9_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */
74#define HECI_DEV_ID_ICH9_82Q33 0x29D4 /* 82Q33 Express */
75#define HECI_DEV_ID_ICH9_82X38 0x29E4 /* 82X38/X48 Express */
76#define HECI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */
77
78#define HECI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */
79#define HECI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */
80#define HECI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */
81#define HECI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */
82#define HECI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */
83
84#define HECI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */
85#define HECI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */
86#define HECI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */
87#define HECI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */
88
89#define HECI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */
90#define HECI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */
91#define HECI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */
92#define HECI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */
93
94/*
95 * heci init function prototypes
96 */
97struct iamt_heci_device *init_heci_device(struct pci_dev *pdev);
98void heci_reset(struct iamt_heci_device *dev, int interrupts);
99int heci_hw_init(struct iamt_heci_device *dev);
100int heci_task_initialize_clients(void *data);
101int heci_initialize_clients(struct iamt_heci_device *dev);
102struct heci_file_private *heci_alloc_file_private(struct file *file);
103int heci_disconnect_host_client(struct iamt_heci_device *dev,
104 struct heci_file_private *file_ext);
105void heci_initialize_list(struct io_heci_list *list,
106 struct iamt_heci_device *dev);
107void heci_flush_list(struct io_heci_list *list,
108 struct heci_file_private *file_ext);
109void heci_flush_queues(struct iamt_heci_device *dev,
110 struct heci_file_private *file_ext);
111
112void heci_remove_client_from_file_list(struct iamt_heci_device *dev,
113 __u8 host_client_id);
114
115/*
116 * interrupt function prototype
117 */
118irqreturn_t heci_isr_interrupt(int irq, void *dev_id);
119
120void heci_wd_timer(unsigned long data);
121
122/*
123 * input output function prototype
124 */
125int heci_ioctl_get_version(struct iamt_heci_device *dev, int if_num,
126 struct heci_message_data __user *u_msg,
127 struct heci_message_data k_msg,
128 struct heci_file_private *file_ext);
129
130int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num,
131 struct heci_message_data __user *u_msg,
132 struct heci_message_data k_msg,
133 struct file *file);
134
135int heci_ioctl_wd(struct iamt_heci_device *dev, int if_num,
136 struct heci_message_data k_msg,
137 struct heci_file_private *file_ext);
138
139int heci_ioctl_bypass_wd(struct iamt_heci_device *dev, int if_num,
140 struct heci_message_data k_msg,
141 struct heci_file_private *file_ext);
142
143int heci_start_read(struct iamt_heci_device *dev, int if_num,
144 struct heci_file_private *file_ext);
145
146int pthi_write(struct iamt_heci_device *dev,
147 struct heci_cb_private *priv_cb);
148
149int pthi_read(struct iamt_heci_device *dev, int if_num, struct file *file,
150 char __user *ubuf, size_t length, loff_t *offset);
151
152struct heci_cb_private *find_pthi_read_list_entry(
153 struct iamt_heci_device *dev,
154 struct file *file);
155
156void run_next_iamthif_cmd(struct iamt_heci_device *dev);
157
158void heci_free_cb_private(struct heci_cb_private *priv_cb);
159
160/**
161 * heci_fe_same_id - tell if file private data have same id
162 *
163 * @fe1: private data of 1. file object
164 * @fe2: private data of 2. file object
165 *
166 * returns !=0 - if ids are the same, 0 - if differ.
167 */
168static inline int heci_fe_same_id(const struct heci_file_private *fe1,
169 const struct heci_file_private *fe2)
170{
171 return ((fe1->host_client_id == fe2->host_client_id)
172 && (fe1->me_client_id == fe2->me_client_id));
173}
174
175#endif /* _HECI_H_ */
diff --git a/drivers/staging/heci/heci_data_structures.h b/drivers/staging/heci/heci_data_structures.h
deleted file mode 100644
index ff30386d097..00000000000
--- a/drivers/staging/heci/heci_data_structures.h
+++ /dev/null
@@ -1,529 +0,0 @@
1/*
2 * Part of Intel(R) Manageability Engine Interface Linux driver
3 *
4 * Copyright (c) 2003 - 2008 Intel Corp.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * substantially similar to the "NO WARRANTY" disclaimer below
15 * ("Disclaimer") and any redistribution must be conditioned upon
16 * including a substantially similar Disclaimer requirement for further
17 * binary redistribution.
18 * 3. Neither the names of the above-listed copyright holders nor the names
19 * of any contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * Alternatively, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2 as published by the Free
24 * Software Foundation.
25 *
26 * NO WARRANTY
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGES.
38 *
39 */
40
41#ifndef _HECI_DATA_STRUCTURES_H_
42#define _HECI_DATA_STRUCTURES_H_
43
44#include <linux/spinlock.h>
45#include <linux/list.h>
46#include <linux/pci.h>
47#include <linux/timer.h>
48#include <linux/interrupt.h>
49#include <linux/workqueue.h>
50#include <linux/module.h>
51#include <linux/aio.h>
52#include <linux/types.h>
53
54/*
55 * error code definition
56 */
57#define ESLOTS_OVERFLOW 1
58#define ECORRUPTED_MESSAGE_HEADER 1000
59#define ECOMPLETE_MESSAGE 1001
60
61#define HECI_FC_MESSAGE_RESERVED_LENGTH 5
62
63/*
64 * Number of queue lists used by this driver
65 */
66#define HECI_IO_LISTS_NUMBER 7
67
68/*
69 * Maximum transmission unit (MTU) of heci messages
70 */
71#define IAMTHIF_MTU 4160
72
73
74/*
75 * HECI HW Section
76 */
77
78/* HECI registers */
79/* H_CB_WW - Host Circular Buffer (CB) Write Window register */
80#define H_CB_WW 0
81/* H_CSR - Host Control Status register */
82#define H_CSR 4
83/* ME_CB_RW - ME Circular Buffer Read Window register (read only) */
84#define ME_CB_RW 8
85/* ME_CSR_HA - ME Control Status Host Access register (read only) */
86#define ME_CSR_HA 0xC
87
88
89/* register bits of H_CSR (Host Control Status register) */
90/* Host Circular Buffer Depth - maximum number of 32-bit entries in CB */
91#define H_CBD 0xFF000000
92/* Host Circular Buffer Write Pointer */
93#define H_CBWP 0x00FF0000
94/* Host Circular Buffer Read Pointer */
95#define H_CBRP 0x0000FF00
96/* Host Reset */
97#define H_RST 0x00000010
98/* Host Ready */
99#define H_RDY 0x00000008
100/* Host Interrupt Generate */
101#define H_IG 0x00000004
102/* Host Interrupt Status */
103#define H_IS 0x00000002
104/* Host Interrupt Enable */
105#define H_IE 0x00000001
106
107
108/* register bits of ME_CSR_HA (ME Control Status Host Access register) */
109/* ME CB (Circular Buffer) Depth HRA (Host Read Access)
110 * - host read only access to ME_CBD */
111#define ME_CBD_HRA 0xFF000000
112/* ME CB Write Pointer HRA - host read only access to ME_CBWP */
113#define ME_CBWP_HRA 0x00FF0000
114/* ME CB Read Pointer HRA - host read only access to ME_CBRP */
115#define ME_CBRP_HRA 0x0000FF00
116/* ME Reset HRA - host read only access to ME_RST */
117#define ME_RST_HRA 0x00000010
118/* ME Ready HRA - host read only access to ME_RDY */
119#define ME_RDY_HRA 0x00000008
120/* ME Interrupt Generate HRA - host read only access to ME_IG */
121#define ME_IG_HRA 0x00000004
122/* ME Interrupt Status HRA - host read only access to ME_IS */
123#define ME_IS_HRA 0x00000002
124/* ME Interrupt Enable HRA - host read only access to ME_IE */
125#define ME_IE_HRA 0x00000001
126
127#define HECI_MINORS_BASE 1
128#define HECI_MINORS_COUNT 1
129
130#define HECI_MINOR_NUMBER 1
131#define HECI_MAX_OPEN_HANDLE_COUNT 253
132
133/*
134 * debug kernel print macro define
135 */
136extern int heci_debug;
137
138#define DBG(format, arg...) do { \
139 if (heci_debug) \
140 printk(KERN_INFO "heci: %s: " format, __func__, ## arg); \
141} while (0)
142
143
144/*
145 * time to wait HECI become ready after init
146 */
147#define HECI_INTEROP_TIMEOUT (HZ * 7)
148
149/*
150 * watch dog definition
151 */
152#define HECI_WATCHDOG_DATA_SIZE 16
153#define HECI_START_WD_DATA_SIZE 20
154#define HECI_WD_PARAMS_SIZE 4
155#define HECI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0)
156
157#define HECI_WD_HOST_CLIENT_ID 1
158#define HECI_IAMTHIF_HOST_CLIENT_ID 2
159
160struct guid {
161 __u32 data1;
162 __u16 data2;
163 __u16 data3;
164 __u8 data4[8];
165};
166
167/* File state */
168enum file_state {
169 HECI_FILE_INITIALIZING = 0,
170 HECI_FILE_CONNECTING,
171 HECI_FILE_CONNECTED,
172 HECI_FILE_DISCONNECTING,
173 HECI_FILE_DISCONNECTED
174};
175
176/* HECI device states */
177enum heci_states {
178 HECI_INITIALIZING = 0,
179 HECI_ENABLED,
180 HECI_RESETING,
181 HECI_DISABLED,
182 HECI_RECOVERING_FROM_RESET,
183 HECI_POWER_DOWN,
184 HECI_POWER_UP
185};
186
187enum iamthif_states {
188 HECI_IAMTHIF_IDLE,
189 HECI_IAMTHIF_WRITING,
190 HECI_IAMTHIF_FLOW_CONTROL,
191 HECI_IAMTHIF_READING,
192 HECI_IAMTHIF_READ_COMPLETE
193};
194
195enum heci_file_transaction_states {
196 HECI_IDLE,
197 HECI_WRITING,
198 HECI_WRITE_COMPLETE,
199 HECI_FLOW_CONTROL,
200 HECI_READING,
201 HECI_READ_COMPLETE
202};
203
204/* HECI CB */
205enum heci_cb_major_types {
206 HECI_READ = 0,
207 HECI_WRITE,
208 HECI_IOCTL,
209 HECI_OPEN,
210 HECI_CLOSE
211};
212
213/* HECI user data struct */
214struct heci_message_data {
215 __u32 size;
216 char *data;
217} __attribute__((packed));
218
219#define HECI_CONNECT_TIMEOUT 3 /* at least 2 seconds */
220
221#define IAMTHIF_STALL_TIMER 12 /* seconds */
222#define IAMTHIF_READ_TIMER 15 /* seconds */
223
224struct heci_cb_private {
225 struct list_head cb_list;
226 enum heci_cb_major_types major_file_operations;
227 void *file_private;
228 struct heci_message_data request_buffer;
229 struct heci_message_data response_buffer;
230 unsigned long information;
231 unsigned long read_time;
232 struct file *file_object;
233};
234
235/* Private file struct */
236struct heci_file_private {
237 struct list_head link;
238 struct file *file;
239 enum file_state state;
240 wait_queue_head_t tx_wait;
241 wait_queue_head_t rx_wait;
242 wait_queue_head_t wait;
243 spinlock_t file_lock; /* file lock */
244 spinlock_t read_io_lock; /* read lock */
245 spinlock_t write_io_lock; /* write lock */
246 int read_pending;
247 int status;
248 /* ID of client connected */
249 __u8 host_client_id;
250 __u8 me_client_id;
251 __u8 flow_ctrl_creds;
252 __u8 timer_count;
253 enum heci_file_transaction_states reading_state;
254 enum heci_file_transaction_states writing_state;
255 int sm_state;
256 struct heci_cb_private *read_cb;
257};
258
259struct io_heci_list {
260 struct heci_cb_private heci_cb;
261 int status;
262 struct iamt_heci_device *device_extension;
263};
264
265struct heci_driver_version {
266 __u8 major;
267 __u8 minor;
268 __u8 hotfix;
269 __u16 build;
270} __attribute__((packed));
271
272
273struct heci_client {
274 __u32 max_msg_length;
275 __u8 protocol_version;
276} __attribute__((packed));
277
278/*
279 * HECI BUS Interface Section
280 */
281struct heci_msg_hdr {
282 __u32 me_addr:8;
283 __u32 host_addr:8;
284 __u32 length:9;
285 __u32 reserved:6;
286 __u32 msg_complete:1;
287} __attribute__((packed));
288
289
290struct hbm_cmd {
291 __u8 cmd:7;
292 __u8 is_response:1;
293} __attribute__((packed));
294
295
296struct heci_bus_message {
297 struct hbm_cmd cmd;
298 __u8 command_specific_data[];
299} __attribute__((packed));
300
301struct hbm_version {
302 __u8 minor_version;
303 __u8 major_version;
304} __attribute__((packed));
305
306struct hbm_host_version_request {
307 struct hbm_cmd cmd;
308 __u8 reserved;
309 struct hbm_version host_version;
310} __attribute__((packed));
311
312struct hbm_host_version_response {
313 struct hbm_cmd cmd;
314 int host_version_supported;
315 struct hbm_version me_max_version;
316} __attribute__((packed));
317
318struct hbm_host_stop_request {
319 struct hbm_cmd cmd;
320 __u8 reason;
321 __u8 reserved[2];
322} __attribute__((packed));
323
324struct hbm_host_stop_response {
325 struct hbm_cmd cmd;
326 __u8 reserved[3];
327} __attribute__((packed));
328
329struct hbm_me_stop_request {
330 struct hbm_cmd cmd;
331 __u8 reason;
332 __u8 reserved[2];
333} __attribute__((packed));
334
335struct hbm_host_enum_request {
336 struct hbm_cmd cmd;
337 __u8 reserved[3];
338} __attribute__((packed));
339
340struct hbm_host_enum_response {
341 struct hbm_cmd cmd;
342 __u8 reserved[3];
343 __u8 valid_addresses[32];
344} __attribute__((packed));
345
346struct heci_client_properties {
347 struct guid protocol_name;
348 __u8 protocol_version;
349 __u8 max_number_of_connections;
350 __u8 fixed_address;
351 __u8 single_recv_buf;
352 __u32 max_msg_length;
353} __attribute__((packed));
354
355struct hbm_props_request {
356 struct hbm_cmd cmd;
357 __u8 address;
358 __u8 reserved[2];
359} __attribute__((packed));
360
361
362struct hbm_props_response {
363 struct hbm_cmd cmd;
364 __u8 address;
365 __u8 status;
366 __u8 reserved[1];
367 struct heci_client_properties client_properties;
368} __attribute__((packed));
369
370struct hbm_client_connect_request {
371 struct hbm_cmd cmd;
372 __u8 me_addr;
373 __u8 host_addr;
374 __u8 reserved;
375} __attribute__((packed));
376
377struct hbm_client_connect_response {
378 struct hbm_cmd cmd;
379 __u8 me_addr;
380 __u8 host_addr;
381 __u8 status;
382} __attribute__((packed));
383
384struct hbm_client_disconnect_request {
385 struct hbm_cmd cmd;
386 __u8 me_addr;
387 __u8 host_addr;
388 __u8 reserved[1];
389} __attribute__((packed));
390
391struct hbm_flow_control {
392 struct hbm_cmd cmd;
393 __u8 me_addr;
394 __u8 host_addr;
395 __u8 reserved[HECI_FC_MESSAGE_RESERVED_LENGTH];
396} __attribute__((packed));
397
398struct heci_me_client {
399 struct heci_client_properties props;
400 __u8 client_id;
401 __u8 flow_ctrl_creds;
402} __attribute__((packed));
403
404/* private device struct */
405struct iamt_heci_device {
406 struct pci_dev *pdev; /* pointer to pci device struct */
407 /*
408 * lists of queues
409 */
410 /* array of pointers to aio lists */
411 struct io_heci_list *io_list_array[HECI_IO_LISTS_NUMBER];
412 struct io_heci_list read_list; /* driver read queue */
413 struct io_heci_list write_list; /* driver write queue */
414 struct io_heci_list write_waiting_list; /* write waiting queue */
415 struct io_heci_list ctrl_wr_list; /* managed write IOCTL list */
416 struct io_heci_list ctrl_rd_list; /* managed read IOCTL list */
417 struct io_heci_list pthi_cmd_list; /* PTHI list for cmd waiting */
418
419 /* driver managed PTHI list for reading completed pthi cmd data */
420 struct io_heci_list pthi_read_complete_list;
421 /*
422 * list of files
423 */
424 struct list_head file_list;
425 /*
426 * memory of device
427 */
428 unsigned int mem_base;
429 unsigned int mem_length;
430 void __iomem *mem_addr;
431 /*
432 * lock for the device
433 */
434 spinlock_t device_lock; /* device lock*/
435 struct work_struct work;
436 int recvd_msg;
437
438 struct task_struct *reinit_tsk;
439
440 struct timer_list wd_timer;
441 /*
442 * hw states of host and fw(ME)
443 */
444 __u32 host_hw_state;
445 __u32 me_hw_state;
446 /*
447 * waiting queue for receive message from FW
448 */
449 wait_queue_head_t wait_recvd_msg;
450 wait_queue_head_t wait_stop_wd;
451 /*
452 * heci device states
453 */
454 enum heci_states heci_state;
455 int stop;
456
457 __u32 extra_write_index;
458 __u32 rd_msg_buf[128]; /* used for control messages */
459 __u32 wr_msg_buf[128]; /* used for control messages */
460 __u32 ext_msg_buf[8]; /* for control responses */
461 __u32 rd_msg_hdr;
462
463 struct hbm_version version;
464
465 int host_buffer_is_empty;
466 struct heci_file_private wd_file_ext;
467 struct heci_me_client *me_clients; /* Note: memory has to be allocated*/
468 __u8 heci_me_clients[32]; /* list of existing clients */
469 __u8 num_heci_me_clients;
470 __u8 heci_host_clients[32]; /* list of existing clients */
471 __u8 current_host_client_id;
472
473 int wd_pending;
474 int wd_stoped;
475 __u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */
476 unsigned char wd_data[HECI_START_WD_DATA_SIZE];
477
478
479 __u16 wd_due_counter;
480 int asf_mode;
481 int wd_bypass; /* if 1, don't refresh watchdog ME client */
482
483 struct file *iamthif_file_object;
484 struct heci_file_private iamthif_file_ext;
485 int iamthif_ioctl;
486 int iamthif_canceled;
487 __u32 iamthif_timer;
488 __u32 iamthif_stall_timer;
489 unsigned char iamthif_msg_buf[IAMTHIF_MTU];
490 __u32 iamthif_msg_buf_size;
491 __u32 iamthif_msg_buf_index;
492 int iamthif_flow_control_pending;
493 enum iamthif_states iamthif_state;
494
495 struct heci_cb_private *iamthif_current_cb;
496 __u8 write_hang;
497 int need_reset;
498 long open_handle_count;
499
500};
501
502/**
503 * read_heci_register - Read a byte from the heci device
504 *
505 * @dev: the device structure
506 * @offset: offset from which to read the data
507 *
508 * returns the byte read.
509 */
510static inline __u32 read_heci_register(struct iamt_heci_device *dev,
511 unsigned long offset)
512{
513 return readl(dev->mem_addr + offset);
514}
515
516/**
517 * write_heci_register - Write 4 bytes to the heci device
518 *
519 * @dev: the device structure
520 * @offset: offset from which to write the data
521 * @value: the byte to write
522 */
523static inline void write_heci_register(struct iamt_heci_device *dev,
524 unsigned long offset, __u32 value)
525{
526 writel(value, dev->mem_addr + offset);
527}
528
529#endif /* _HECI_DATA_STRUCTURES_H_ */
diff --git a/drivers/staging/heci/heci_init.c b/drivers/staging/heci/heci_init.c
deleted file mode 100644
index 31fd891c099..00000000000
--- a/drivers/staging/heci/heci_init.c
+++ /dev/null
@@ -1,1083 +0,0 @@
1/*
2 * Part of Intel(R) Manageability Engine Interface Linux driver
3 *
4 * Copyright (c) 2003 - 2008 Intel Corp.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * substantially similar to the "NO WARRANTY" disclaimer below
15 * ("Disclaimer") and any redistribution must be conditioned upon
16 * including a substantially similar Disclaimer requirement for further
17 * binary redistribution.
18 * 3. Neither the names of the above-listed copyright holders nor the names
19 * of any contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * Alternatively, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2 as published by the Free
24 * Software Foundation.
25 *
26 * NO WARRANTY
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGES.
38 *
39 */
40
41#include <linux/module.h>
42#include <linux/pci.h>
43#include <linux/reboot.h>
44#include <linux/poll.h>
45#include <linux/init.h>
46#include <linux/kdev_t.h>
47#include <linux/moduleparam.h>
48#include <linux/wait.h>
49#include <linux/delay.h>
50#include <linux/kthread.h>
51
52#include "heci_data_structures.h"
53#include "heci_interface.h"
54#include "heci.h"
55
56
57const __u8 heci_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
58const __u8 heci_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
59
60const __u8 heci_wd_state_independence_msg[3][4] = {
61 {0x05, 0x02, 0x51, 0x10},
62 {0x05, 0x02, 0x52, 0x10},
63 {0x07, 0x02, 0x01, 0x10}
64};
65
66static const struct guid heci_asf_guid = {
67 0x75B30CD6, 0xA29E, 0x4AF7,
68 {0xA7, 0x12, 0xE6, 0x17, 0x43, 0x93, 0xC8, 0xA6}
69};
70const struct guid heci_wd_guid = {
71 0x05B79A6F, 0x4628, 0x4D7F,
72 {0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB}
73};
74const struct guid heci_pthi_guid = {
75 0x12f80028, 0xb4b7, 0x4b2d,
76 {0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c}
77};
78
79
80/*
81 * heci init function prototypes
82 */
83static void heci_check_asf_mode(struct iamt_heci_device *dev);
84static int host_start_message(struct iamt_heci_device *dev);
85static int host_enum_clients_message(struct iamt_heci_device *dev);
86static int allocate_me_clients_storage(struct iamt_heci_device *dev);
87static void host_init_wd(struct iamt_heci_device *dev);
88static void host_init_iamthif(struct iamt_heci_device *dev);
89static int heci_wait_event_int_timeout(struct iamt_heci_device *dev,
90 long timeout);
91
92
93/**
94 * heci_initialize_list - Sets up a queue list.
95 *
96 * @list: An instance of our list structure
97 * @dev: Device object for our driver
98 */
99void heci_initialize_list(struct io_heci_list *list,
100 struct iamt_heci_device *dev)
101{
102 /* initialize our queue list */
103 INIT_LIST_HEAD(&list->heci_cb.cb_list);
104 list->status = 0;
105 list->device_extension = dev;
106}
107
108/**
109 * heci_flush_queues - flush our queues list belong to file_ext.
110 *
111 * @dev: Device object for our driver
112 * @file_ext: private data of the file object
113 */
114void heci_flush_queues(struct iamt_heci_device *dev,
115 struct heci_file_private *file_ext)
116{
117 int i;
118
119 if (!dev || !file_ext)
120 return;
121
122 /* flush our queue list belong to file_ext */
123 for (i = 0; i < HECI_IO_LISTS_NUMBER; i++) {
124 DBG("remove list entry belong to file_ext\n");
125 heci_flush_list(dev->io_list_array[i], file_ext);
126 }
127}
128
129
130/**
131 * heci_flush_list - remove list entry belong to file_ext.
132 *
133 * @list: An instance of our list structure
134 * @file_ext: private data of the file object
135 */
136void heci_flush_list(struct io_heci_list *list,
137 struct heci_file_private *file_ext)
138{
139 struct heci_file_private *file_ext_tmp;
140 struct heci_cb_private *priv_cb_pos = NULL;
141 struct heci_cb_private *priv_cb_next = NULL;
142
143 if (!list || !file_ext)
144 return;
145
146 if (list->status != 0)
147 return;
148
149 if (list_empty(&list->heci_cb.cb_list))
150 return;
151
152 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
153 &list->heci_cb.cb_list, cb_list) {
154 if (priv_cb_pos) {
155 file_ext_tmp = (struct heci_file_private *)
156 priv_cb_pos->file_private;
157 if (file_ext_tmp) {
158 if (heci_fe_same_id(file_ext, file_ext_tmp))
159 list_del(&priv_cb_pos->cb_list);
160 }
161 }
162 }
163}
164
165/**
166 * heci_reset_iamthif_params - initializes heci device iamthif
167 *
168 * @dev: The heci device structure
169 */
170static void heci_reset_iamthif_params(struct iamt_heci_device *dev)
171{
172 /* reset iamthif parameters. */
173 dev->iamthif_current_cb = NULL;
174 dev->iamthif_msg_buf_size = 0;
175 dev->iamthif_msg_buf_index = 0;
176 dev->iamthif_canceled = 0;
177 dev->iamthif_file_ext.file = NULL;
178 dev->iamthif_ioctl = 0;
179 dev->iamthif_state = HECI_IAMTHIF_IDLE;
180 dev->iamthif_timer = 0;
181}
182
183/**
184 * init_heci_device - allocates and initializes the heci device structure
185 *
186 * @pdev: The pci device structure
187 *
188 * returns The heci_device_device pointer on success, NULL on failure.
189 */
190struct iamt_heci_device *init_heci_device(struct pci_dev *pdev)
191{
192 int i;
193 struct iamt_heci_device *dev;
194
195 dev = kzalloc(sizeof(struct iamt_heci_device), GFP_KERNEL);
196 if (!dev)
197 return NULL;
198
199 /* setup our list array */
200 dev->io_list_array[0] = &dev->read_list;
201 dev->io_list_array[1] = &dev->write_list;
202 dev->io_list_array[2] = &dev->write_waiting_list;
203 dev->io_list_array[3] = &dev->ctrl_wr_list;
204 dev->io_list_array[4] = &dev->ctrl_rd_list;
205 dev->io_list_array[5] = &dev->pthi_cmd_list;
206 dev->io_list_array[6] = &dev->pthi_read_complete_list;
207 INIT_LIST_HEAD(&dev->file_list);
208 INIT_LIST_HEAD(&dev->wd_file_ext.link);
209 INIT_LIST_HEAD(&dev->iamthif_file_ext.link);
210 spin_lock_init(&dev->device_lock);
211 init_waitqueue_head(&dev->wait_recvd_msg);
212 init_waitqueue_head(&dev->wait_stop_wd);
213 dev->heci_state = HECI_INITIALIZING;
214 dev->iamthif_state = HECI_IAMTHIF_IDLE;
215
216 /* init work for schedule work */
217 INIT_WORK(&dev->work, NULL);
218 for (i = 0; i < HECI_IO_LISTS_NUMBER; i++)
219 heci_initialize_list(dev->io_list_array[i], dev);
220 dev->pdev = pdev;
221 return dev;
222}
223
224
225
226
227static int heci_wait_event_int_timeout(struct iamt_heci_device *dev,
228 long timeout)
229{
230 return wait_event_interruptible_timeout(dev->wait_recvd_msg,
231 (dev->recvd_msg), timeout);
232}
233
234/**
235 * heci_hw_init - init host and fw to start work.
236 *
237 * @dev: Device object for our driver
238 *
239 * returns 0 on success, <0 on failure.
240 */
241int heci_hw_init(struct iamt_heci_device *dev)
242{
243 int err = 0;
244
245 dev->host_hw_state = read_heci_register(dev, H_CSR);
246 dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
247 DBG("host_hw_state = 0x%08x, mestate = 0x%08x.\n",
248 dev->host_hw_state, dev->me_hw_state);
249
250 if ((dev->host_hw_state & H_IS) == H_IS) {
251 /* acknowledge interrupt and stop interupts */
252 heci_csr_clear_his(dev);
253 }
254 dev->recvd_msg = 0;
255 DBG("reset in start the heci device.\n");
256
257 heci_reset(dev, 1);
258
259 DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
260 dev->host_hw_state, dev->me_hw_state);
261
262 /* wait for ME to turn on ME_RDY */
263 if (!dev->recvd_msg)
264 err = heci_wait_event_int_timeout(dev, HECI_INTEROP_TIMEOUT);
265
266 if (!err && !dev->recvd_msg) {
267 dev->heci_state = HECI_DISABLED;
268 DBG("wait_event_interruptible_timeout failed"
269 "on wait for ME to turn on ME_RDY.\n");
270 return -ENODEV;
271 } else {
272 if (!(((dev->host_hw_state & H_RDY) == H_RDY)
273 && ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) {
274 dev->heci_state = HECI_DISABLED;
275 DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
276 dev->host_hw_state,
277 dev->me_hw_state);
278
279 if (!(dev->host_hw_state & H_RDY) != H_RDY)
280 DBG("host turn off H_RDY.\n");
281
282 if (!(dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
283 DBG("ME turn off ME_RDY.\n");
284
285 printk(KERN_ERR
286 "heci: link layer initialization failed.\n");
287 return -ENODEV;
288 }
289 }
290 dev->recvd_msg = 0;
291 DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
292 dev->host_hw_state, dev->me_hw_state);
293 DBG("ME turn on ME_RDY and host turn on H_RDY.\n");
294 printk(KERN_INFO "heci: link layer has been established.\n");
295 return 0;
296}
297
298/**
299 * heci_hw_reset - reset fw via heci csr register.
300 *
301 * @dev: Device object for our driver
302 * @interrupts: if interrupt should be enable after reset.
303 */
304static void heci_hw_reset(struct iamt_heci_device *dev, int interrupts)
305{
306 dev->host_hw_state |= (H_RST | H_IG);
307
308 if (interrupts)
309 heci_csr_enable_interrupts(dev);
310 else
311 heci_csr_disable_interrupts(dev);
312
313 BUG_ON((dev->host_hw_state & H_RST) != H_RST);
314 BUG_ON((dev->host_hw_state & H_RDY) != 0);
315}
316
317/**
318 * heci_reset - reset host and fw.
319 *
320 * @dev: Device object for our driver
321 * @interrupts: if interrupt should be enable after reset.
322 */
323void heci_reset(struct iamt_heci_device *dev, int interrupts)
324{
325 struct heci_file_private *file_pos = NULL;
326 struct heci_file_private *file_next = NULL;
327 struct heci_cb_private *priv_cb_pos = NULL;
328 struct heci_cb_private *priv_cb_next = NULL;
329 int unexpected = 0;
330
331 if (dev->heci_state == HECI_RECOVERING_FROM_RESET) {
332 dev->need_reset = 1;
333 return;
334 }
335
336 if (dev->heci_state != HECI_INITIALIZING &&
337 dev->heci_state != HECI_DISABLED &&
338 dev->heci_state != HECI_POWER_DOWN &&
339 dev->heci_state != HECI_POWER_UP)
340 unexpected = 1;
341
342 if (dev->reinit_tsk != NULL) {
343 kthread_stop(dev->reinit_tsk);
344 dev->reinit_tsk = NULL;
345 }
346
347 dev->host_hw_state = read_heci_register(dev, H_CSR);
348
349 DBG("before reset host_hw_state = 0x%08x.\n",
350 dev->host_hw_state);
351
352 heci_hw_reset(dev, interrupts);
353
354 dev->host_hw_state &= ~H_RST;
355 dev->host_hw_state |= H_IG;
356
357 heci_set_csr_register(dev);
358
359 DBG("currently saved host_hw_state = 0x%08x.\n",
360 dev->host_hw_state);
361
362 dev->need_reset = 0;
363
364 if (dev->heci_state != HECI_INITIALIZING) {
365 if ((dev->heci_state != HECI_DISABLED) &&
366 (dev->heci_state != HECI_POWER_DOWN))
367 dev->heci_state = HECI_RESETING;
368
369 list_for_each_entry_safe(file_pos,
370 file_next, &dev->file_list, link) {
371 file_pos->state = HECI_FILE_DISCONNECTED;
372 file_pos->flow_ctrl_creds = 0;
373 file_pos->read_cb = NULL;
374 file_pos->timer_count = 0;
375 }
376 /* remove entry if already in list */
377 DBG("list del iamthif and wd file list.\n");
378 heci_remove_client_from_file_list(dev,
379 dev->wd_file_ext.host_client_id);
380
381 heci_remove_client_from_file_list(dev,
382 dev->iamthif_file_ext.host_client_id);
383
384 heci_reset_iamthif_params(dev);
385 dev->wd_due_counter = 0;
386 dev->extra_write_index = 0;
387 }
388
389 dev->num_heci_me_clients = 0;
390 dev->rd_msg_hdr = 0;
391 dev->stop = 0;
392 dev->wd_pending = 0;
393
394 /* update the state of the registers after reset */
395 dev->host_hw_state = read_heci_register(dev, H_CSR);
396 dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
397
398 DBG("after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
399 dev->host_hw_state, dev->me_hw_state);
400
401 if (unexpected)
402 printk(KERN_WARNING "heci: unexpected reset.\n");
403
404 /* Wake up all readings so they can be interrupted */
405 list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link) {
406 if (&file_pos->rx_wait &&
407 waitqueue_active(&file_pos->rx_wait)) {
408 printk(KERN_INFO "heci: Waking up client!\n");
409 wake_up_interruptible(&file_pos->rx_wait);
410 }
411 }
412 /* remove all waiting requests */
413 if (dev->write_list.status == 0 &&
414 !list_empty(&dev->write_list.heci_cb.cb_list)) {
415 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
416 &dev->write_list.heci_cb.cb_list, cb_list) {
417 if (priv_cb_pos) {
418 list_del(&priv_cb_pos->cb_list);
419 heci_free_cb_private(priv_cb_pos);
420 }
421 }
422 }
423}
424
425/**
426 * heci_initialize_clients - heci communication initialization.
427 *
428 * @dev: Device object for our driver
429 */
430int heci_initialize_clients(struct iamt_heci_device *dev)
431{
432 int status;
433
434 msleep(100); /* FW needs time to be ready to talk with us */
435 DBG("link is established start sending messages.\n");
436 /* link is established start sending messages. */
437 status = host_start_message(dev);
438 if (status != 0) {
439 spin_lock_bh(&dev->device_lock);
440 dev->heci_state = HECI_DISABLED;
441 spin_unlock_bh(&dev->device_lock);
442 DBG("start sending messages failed.\n");
443 return status;
444 }
445
446 /* enumerate clients */
447 status = host_enum_clients_message(dev);
448 if (status != 0) {
449 spin_lock_bh(&dev->device_lock);
450 dev->heci_state = HECI_DISABLED;
451 spin_unlock_bh(&dev->device_lock);
452 DBG("enum clients failed.\n");
453 return status;
454 }
455 /* allocate storage for ME clients representation */
456 status = allocate_me_clients_storage(dev);
457 if (status != 0) {
458 spin_lock_bh(&dev->device_lock);
459 dev->num_heci_me_clients = 0;
460 dev->heci_state = HECI_DISABLED;
461 spin_unlock_bh(&dev->device_lock);
462 DBG("allocate clients failed.\n");
463 return status;
464 }
465
466 heci_check_asf_mode(dev);
467 /*heci initialization wd */
468 host_init_wd(dev);
469 /*heci initialization iamthif client */
470 host_init_iamthif(dev);
471
472 spin_lock_bh(&dev->device_lock);
473 if (dev->need_reset) {
474 dev->need_reset = 0;
475 dev->heci_state = HECI_DISABLED;
476 spin_unlock_bh(&dev->device_lock);
477 return -ENODEV;
478 }
479
480 memset(dev->heci_host_clients, 0, sizeof(dev->heci_host_clients));
481 dev->open_handle_count = 0;
482 dev->heci_host_clients[0] |= 7;
483 dev->current_host_client_id = 3;
484 dev->heci_state = HECI_ENABLED;
485 spin_unlock_bh(&dev->device_lock);
486 DBG("initialization heci clients successful.\n");
487 return 0;
488}
489
490/**
491 * heci_task_initialize_clients - heci reinitialization task
492 *
493 * @data: Device object for our driver
494 */
495int heci_task_initialize_clients(void *data)
496{
497 int ret;
498 struct iamt_heci_device *dev = (struct iamt_heci_device *) data;
499
500 spin_lock_bh(&dev->device_lock);
501 if (dev->reinit_tsk != NULL) {
502 spin_unlock_bh(&dev->device_lock);
503 DBG("reinit task already started.\n");
504 return 0;
505 }
506 dev->reinit_tsk = current;
507 current->flags |= PF_NOFREEZE;
508 spin_unlock_bh(&dev->device_lock);
509
510 ret = heci_initialize_clients(dev);
511
512 spin_lock_bh(&dev->device_lock);
513 dev->reinit_tsk = NULL;
514 spin_unlock_bh(&dev->device_lock);
515
516 return ret;
517}
518
519/**
520 * host_start_message - heci host send start message.
521 *
522 * @dev: Device object for our driver
523 *
524 * returns 0 on success, <0 on failure.
525 */
526static int host_start_message(struct iamt_heci_device *dev)
527{
528 long timeout = 60; /* 60 second */
529
530 struct heci_msg_hdr *heci_hdr;
531 struct hbm_host_version_request *host_start_req;
532 struct hbm_host_stop_request *host_stop_req;
533 int err = 0;
534
535 /* host start message */
536 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
537 heci_hdr->host_addr = 0;
538 heci_hdr->me_addr = 0;
539 heci_hdr->length = sizeof(struct hbm_host_version_request);
540 heci_hdr->msg_complete = 1;
541 heci_hdr->reserved = 0;
542
543 host_start_req =
544 (struct hbm_host_version_request *) &dev->wr_msg_buf[1];
545 memset(host_start_req, 0, sizeof(struct hbm_host_version_request));
546 host_start_req->cmd.cmd = HOST_START_REQ_CMD;
547 host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
548 host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
549 dev->recvd_msg = 0;
550 if (!heci_write_message(dev, heci_hdr,
551 (unsigned char *) (host_start_req),
552 heci_hdr->length)) {
553 DBG("send version to fw fail.\n");
554 return -ENODEV;
555 }
556 DBG("call wait_event_interruptible_timeout for response message.\n");
557 /* wait for response */
558 err = heci_wait_event_int_timeout(dev, timeout * HZ);
559 if (!err && !dev->recvd_msg) {
560 DBG("wait_timeout failed on host start response message.\n");
561 return -ENODEV;
562 }
563 dev->recvd_msg = 0;
564 DBG("wait_timeout successful on host start response message.\n");
565 if ((dev->version.major_version != HBM_MAJOR_VERSION) ||
566 (dev->version.minor_version != HBM_MINOR_VERSION)) {
567 /* send stop message */
568 heci_hdr->host_addr = 0;
569 heci_hdr->me_addr = 0;
570 heci_hdr->length = sizeof(struct hbm_host_stop_request);
571 heci_hdr->msg_complete = 1;
572 heci_hdr->reserved = 0;
573
574 host_stop_req =
575 (struct hbm_host_stop_request *) &dev->wr_msg_buf[1];
576
577 memset(host_stop_req, 0, sizeof(struct hbm_host_stop_request));
578 host_stop_req->cmd.cmd = HOST_STOP_REQ_CMD;
579 host_stop_req->reason = DRIVER_STOP_REQUEST;
580 heci_write_message(dev, heci_hdr,
581 (unsigned char *) (host_stop_req),
582 heci_hdr->length);
583 DBG("version mismatch.\n");
584 return -ENODEV;
585 }
586
587 return 0;
588}
589
590/**
591 * host_enum_clients_message - host send enumeration client request message.
592 *
593 * @dev: Device object for our driver
594 *
595 * returns 0 on success, <0 on failure.
596 */
597static int host_enum_clients_message(struct iamt_heci_device *dev)
598{
599 long timeout = 5; /*5 second */
600 struct heci_msg_hdr *heci_hdr;
601 struct hbm_host_enum_request *host_enum_req;
602 int err = 0;
603 int i, j;
604
605 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
606 /* enumerate clients */
607 heci_hdr->host_addr = 0;
608 heci_hdr->me_addr = 0;
609 heci_hdr->length = sizeof(struct hbm_host_enum_request);
610 heci_hdr->msg_complete = 1;
611 heci_hdr->reserved = 0;
612
613 host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
614 memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request));
615 host_enum_req->cmd.cmd = HOST_ENUM_REQ_CMD;
616 if (!heci_write_message(dev, heci_hdr,
617 (unsigned char *) (host_enum_req),
618 heci_hdr->length)) {
619 DBG("send enumeration request failed.\n");
620 return -ENODEV;
621 }
622 /* wait for response */
623 dev->recvd_msg = 0;
624 err = heci_wait_event_int_timeout(dev, timeout * HZ);
625 if (!err && !dev->recvd_msg) {
626 DBG("wait_event_interruptible_timeout failed "
627 "on enumeration clients response message.\n");
628 return -ENODEV;
629 }
630 dev->recvd_msg = 0;
631
632 spin_lock_bh(&dev->device_lock);
633 /* count how many ME clients we have */
634 for (i = 0; i < sizeof(dev->heci_me_clients); i++) {
635 for (j = 0; j < 8; j++) {
636 if ((dev->heci_me_clients[i] & (1 << j)) != 0)
637 dev->num_heci_me_clients++;
638
639 }
640 }
641 spin_unlock_bh(&dev->device_lock);
642
643 return 0;
644}
645
646/**
647 * host_client_properties - reads properties for client
648 *
649 * @dev: Device object for our driver
650 * @idx: client index in me client array
651 * @client_id: id of the client
652 *
653 * returns 0 on success, <0 on failure.
654 */
655static int host_client_properties(struct iamt_heci_device *dev,
656 struct heci_me_client *client)
657{
658 struct heci_msg_hdr *heci_hdr;
659 struct hbm_props_request *host_cli_req;
660 int err;
661
662 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
663 heci_hdr->host_addr = 0;
664 heci_hdr->me_addr = 0;
665 heci_hdr->length = sizeof(struct hbm_props_request);
666 heci_hdr->msg_complete = 1;
667 heci_hdr->reserved = 0;
668
669 host_cli_req = (struct hbm_props_request *) &dev->wr_msg_buf[1];
670 memset(host_cli_req, 0, sizeof(struct hbm_props_request));
671 host_cli_req->cmd.cmd = HOST_CLIENT_PROPERTEIS_REQ_CMD;
672 host_cli_req->address = client->client_id;
673 if (!heci_write_message(dev, heci_hdr,
674 (unsigned char *) (host_cli_req),
675 heci_hdr->length)) {
676 DBG("send props request failed.\n");
677 return -ENODEV;
678 }
679 /* wait for response */
680 dev->recvd_msg = 0;
681 err = heci_wait_event_int_timeout(dev, 10 * HZ);
682 if (!err && !dev->recvd_msg) {
683 DBG("wait failed on props resp msg.\n");
684 return -ENODEV;
685 }
686 dev->recvd_msg = 0;
687 return 0;
688}
689
690/**
691 * allocate_me_clients_storage - allocate storage for me clients
692 *
693 * @dev: Device object for our driver
694 *
695 * returns 0 on success, <0 on failure.
696 */
697static int allocate_me_clients_storage(struct iamt_heci_device *dev)
698{
699 struct heci_me_client *clients;
700 struct heci_me_client *client;
701 __u8 num, i, j;
702 int err;
703
704 if (dev->num_heci_me_clients <= 0)
705 return 0;
706
707 spin_lock_bh(&dev->device_lock);
708 kfree(dev->me_clients);
709 dev->me_clients = NULL;
710 spin_unlock_bh(&dev->device_lock);
711
712 /* allocate storage for ME clients representation */
713 clients = kcalloc(dev->num_heci_me_clients,
714 sizeof(struct heci_me_client), GFP_KERNEL);
715 if (!clients) {
716 DBG("memory allocation for ME clients failed.\n");
717 return -ENOMEM;
718 }
719
720 spin_lock_bh(&dev->device_lock);
721 dev->me_clients = clients;
722 spin_unlock_bh(&dev->device_lock);
723
724 num = 0;
725 for (i = 0; i < sizeof(dev->heci_me_clients); i++) {
726 for (j = 0; j < 8; j++) {
727 if ((dev->heci_me_clients[i] & (1 << j)) != 0) {
728 client = &dev->me_clients[num];
729 client->client_id = (i * 8) + j;
730 client->flow_ctrl_creds = 0;
731 err = host_client_properties(dev, client);
732 if (err != 0) {
733 spin_lock_bh(&dev->device_lock);
734 kfree(dev->me_clients);
735 dev->me_clients = NULL;
736 spin_unlock_bh(&dev->device_lock);
737 return err;
738 }
739 num++;
740 }
741 }
742 }
743
744 return 0;
745}
746
747/**
748 * heci_init_file_private - initializes private file structure.
749 *
750 * @priv: private file structure to be initialized
751 * @file: the file structure
752 */
753static void heci_init_file_private(struct heci_file_private *priv,
754 struct file *file)
755{
756 memset(priv, 0, sizeof(struct heci_file_private));
757 spin_lock_init(&priv->file_lock);
758 spin_lock_init(&priv->read_io_lock);
759 spin_lock_init(&priv->write_io_lock);
760 init_waitqueue_head(&priv->wait);
761 init_waitqueue_head(&priv->rx_wait);
762 DBG("priv->rx_wait =%p\n", &priv->rx_wait);
763 init_waitqueue_head(&priv->tx_wait);
764 INIT_LIST_HEAD(&priv->link);
765 priv->reading_state = HECI_IDLE;
766 priv->writing_state = HECI_IDLE;
767}
768
769/**
770 * heci_find_me_client - search for ME client guid
771 * sets client_id in heci_file_private if found
772 * @dev: Device object for our driver
773 * @priv: private file structure to set client_id in
774 * @cguid: searched guid of ME client
775 * @client_id: id of host client to be set in file private structure
776 *
777 * returns ME client index
778 */
779static __u8 heci_find_me_client(struct iamt_heci_device *dev,
780 struct heci_file_private *priv,
781 const struct guid *cguid, __u8 client_id)
782{
783 __u8 i;
784
785 if ((dev == NULL) || (priv == NULL) || (cguid == NULL))
786 return 0;
787
788 for (i = 0; i < dev->num_heci_me_clients; i++) {
789 if (memcmp(cguid,
790 &dev->me_clients[i].props.protocol_name,
791 sizeof(struct guid)) == 0) {
792 priv->me_client_id = dev->me_clients[i].client_id;
793 priv->state = HECI_FILE_CONNECTING;
794 priv->host_client_id = client_id;
795
796 list_add_tail(&priv->link, &dev->file_list);
797 return i;
798 }
799 }
800 return 0;
801}
802
803/**
804 * heci_check_asf_mode - check for ASF client
805 *
806 * @dev: Device object for our driver
807 */
808static void heci_check_asf_mode(struct iamt_heci_device *dev)
809{
810 __u8 i;
811
812 spin_lock_bh(&dev->device_lock);
813 dev->asf_mode = 0;
814 /* find ME ASF client - otherwise assume AMT mode */
815 DBG("find ME ASF client - otherwise assume AMT mode.\n");
816 for (i = 0; i < dev->num_heci_me_clients; i++) {
817 if (memcmp(&heci_asf_guid,
818 &dev->me_clients[i].props.protocol_name,
819 sizeof(struct guid)) == 0) {
820 dev->asf_mode = 1;
821 spin_unlock_bh(&dev->device_lock);
822 DBG("found ME ASF client.\n");
823 return;
824 }
825 }
826 spin_unlock_bh(&dev->device_lock);
827 DBG("assume AMT mode.\n");
828}
829
830/**
831 * heci_connect_me_client - connect ME client
832 * @dev: Device object for our driver
833 * @priv: private file structure
834 * @timeout: connect timeout in seconds
835 *
836 * returns 1 - if connected, 0 - if not
837 */
838static __u8 heci_connect_me_client(struct iamt_heci_device *dev,
839 struct heci_file_private *priv,
840 long timeout)
841{
842 int err = 0;
843
844 if ((dev == NULL) || (priv == NULL))
845 return 0;
846
847 if (!heci_connect(dev, priv)) {
848 DBG("failed to call heci_connect for client_id=%d.\n",
849 priv->host_client_id);
850 spin_lock_bh(&dev->device_lock);
851 heci_remove_client_from_file_list(dev, priv->host_client_id);
852 priv->state = HECI_FILE_DISCONNECTED;
853 spin_unlock_bh(&dev->device_lock);
854 return 0;
855 }
856
857 err = wait_event_timeout(dev->wait_recvd_msg,
858 (HECI_FILE_CONNECTED == priv->state ||
859 HECI_FILE_DISCONNECTED == priv->state),
860 timeout * HZ);
861 if (HECI_FILE_CONNECTED != priv->state) {
862 spin_lock_bh(&dev->device_lock);
863 heci_remove_client_from_file_list(dev, priv->host_client_id);
864 DBG("failed to connect client_id=%d state=%d.\n",
865 priv->host_client_id, priv->state);
866 if (err)
867 DBG("failed connect err=%08x\n", err);
868 priv->state = HECI_FILE_DISCONNECTED;
869 spin_unlock_bh(&dev->device_lock);
870 return 0;
871 }
872 DBG("successfully connected client_id=%d.\n",
873 priv->host_client_id);
874 return 1;
875}
876
877/**
878 * host_init_wd - heci initialization wd.
879 *
880 * @dev: Device object for our driver
881 */
882static void host_init_wd(struct iamt_heci_device *dev)
883{
884 spin_lock_bh(&dev->device_lock);
885
886 heci_init_file_private(&dev->wd_file_ext, NULL);
887
888 /* look for WD client and connect to it */
889 dev->wd_file_ext.state = HECI_FILE_DISCONNECTED;
890 dev->wd_timeout = 0;
891
892 if (dev->asf_mode) {
893 memcpy(dev->wd_data, heci_stop_wd_params, HECI_WD_PARAMS_SIZE);
894 } else {
895 /* AMT mode */
896 dev->wd_timeout = AMT_WD_VALUE;
897 DBG("dev->wd_timeout=%d.\n", dev->wd_timeout);
898 memcpy(dev->wd_data, heci_start_wd_params, HECI_WD_PARAMS_SIZE);
899 memcpy(dev->wd_data + HECI_WD_PARAMS_SIZE,
900 &dev->wd_timeout, sizeof(__u16));
901 }
902
903 /* find ME WD client */
904 heci_find_me_client(dev, &dev->wd_file_ext,
905 &heci_wd_guid, HECI_WD_HOST_CLIENT_ID);
906 spin_unlock_bh(&dev->device_lock);
907
908 DBG("check wd_file_ext\n");
909 if (HECI_FILE_CONNECTING == dev->wd_file_ext.state) {
910 if (heci_connect_me_client(dev, &dev->wd_file_ext, 15) == 1) {
911 DBG("dev->wd_timeout=%d.\n", dev->wd_timeout);
912 if (dev->wd_timeout != 0)
913 dev->wd_due_counter = 1;
914 else
915 dev->wd_due_counter = 0;
916 DBG("successfully connected to WD client.\n");
917 }
918 } else
919 DBG("failed to find WD client.\n");
920
921
922 spin_lock_bh(&dev->device_lock);
923 dev->wd_timer.function = &heci_wd_timer;
924 dev->wd_timer.data = (unsigned long) dev;
925 spin_unlock_bh(&dev->device_lock);
926}
927
928
929/**
930 * host_init_iamthif - heci initialization iamthif client.
931 *
932 * @dev: Device object for our driver
933 *
934 */
935static void host_init_iamthif(struct iamt_heci_device *dev)
936{
937 __u8 i;
938
939 spin_lock_bh(&dev->device_lock);
940
941 heci_init_file_private(&dev->iamthif_file_ext, NULL);
942 dev->iamthif_file_ext.state = HECI_FILE_DISCONNECTED;
943
944 /* find ME PTHI client */
945 i = heci_find_me_client(dev, &dev->iamthif_file_ext,
946 &heci_pthi_guid, HECI_IAMTHIF_HOST_CLIENT_ID);
947 if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTING) {
948 DBG("failed to find iamthif client.\n");
949 spin_unlock_bh(&dev->device_lock);
950 return;
951 }
952
953 BUG_ON(dev->me_clients[i].props.max_msg_length != IAMTHIF_MTU);
954
955 spin_unlock_bh(&dev->device_lock);
956 if (heci_connect_me_client(dev, &dev->iamthif_file_ext, 15) == 1) {
957 DBG("connected to iamthif client.\n");
958 dev->iamthif_state = HECI_IAMTHIF_IDLE;
959 }
960}
961
962/**
963 * heci_alloc_file_private - allocates a private file structure and set it up.
964 * @file: the file structure
965 *
966 * returns The allocated file or NULL on failure
967 */
968struct heci_file_private *heci_alloc_file_private(struct file *file)
969{
970 struct heci_file_private *priv;
971
972 priv = kmalloc(sizeof(struct heci_file_private), GFP_KERNEL);
973 if (!priv)
974 return NULL;
975
976 heci_init_file_private(priv, file);
977
978 return priv;
979}
980
981
982
983/**
984 * heci_disconnect_host_client - send disconnect message to fw from host client.
985 *
986 * @dev: Device object for our driver
987 * @file_ext: private data of the file object
988 *
989 * returns 0 on success, <0 on failure.
990 */
991int heci_disconnect_host_client(struct iamt_heci_device *dev,
992 struct heci_file_private *file_ext)
993{
994 int rets, err;
995 long timeout = 15; /* 15 seconds */
996 struct heci_cb_private *priv_cb;
997
998 if ((!dev) || (!file_ext))
999 return -ENODEV;
1000
1001 spin_lock_bh(&dev->device_lock);
1002 if (file_ext->state != HECI_FILE_DISCONNECTING) {
1003 spin_unlock_bh(&dev->device_lock);
1004 return 0;
1005 }
1006 spin_unlock_bh(&dev->device_lock);
1007
1008 priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
1009 if (!priv_cb)
1010 return -ENOMEM;
1011
1012 INIT_LIST_HEAD(&priv_cb->cb_list);
1013 priv_cb->file_private = file_ext;
1014 priv_cb->major_file_operations = HECI_CLOSE;
1015 spin_lock_bh(&dev->device_lock);
1016 if (dev->host_buffer_is_empty) {
1017 dev->host_buffer_is_empty = 0;
1018 if (heci_disconnect(dev, file_ext)) {
1019 mdelay(10); /* Wait for hardware disconnection ready */
1020 list_add_tail(&priv_cb->cb_list,
1021 &dev->ctrl_rd_list.heci_cb.cb_list);
1022 } else {
1023 spin_unlock_bh(&dev->device_lock);
1024 rets = -ENODEV;
1025 DBG("failed to call heci_disconnect.\n");
1026 goto free;
1027 }
1028 } else {
1029 DBG("add disconnect cb to control write list\n");
1030 list_add_tail(&priv_cb->cb_list,
1031 &dev->ctrl_wr_list.heci_cb.cb_list);
1032 }
1033 spin_unlock_bh(&dev->device_lock);
1034
1035 err = wait_event_timeout(dev->wait_recvd_msg,
1036 (HECI_FILE_DISCONNECTED == file_ext->state),
1037 timeout * HZ);
1038
1039 spin_lock_bh(&dev->device_lock);
1040 if (HECI_FILE_DISCONNECTED == file_ext->state) {
1041 rets = 0;
1042 DBG("successfully disconnected from fw client.\n");
1043 } else {
1044 rets = -ENODEV;
1045 if (HECI_FILE_DISCONNECTED != file_ext->state)
1046 DBG("wrong status client disconnect.\n");
1047
1048 if (err)
1049 DBG("wait failed disconnect err=%08x\n", err);
1050
1051 DBG("failed to disconnect from fw client.\n");
1052 }
1053
1054 heci_flush_list(&dev->ctrl_rd_list, file_ext);
1055 heci_flush_list(&dev->ctrl_wr_list, file_ext);
1056 spin_unlock_bh(&dev->device_lock);
1057free:
1058 heci_free_cb_private(priv_cb);
1059 return rets;
1060}
1061
1062/**
1063 * heci_remove_client_from_file_list -
1064 * remove file private data from device file list
1065 *
1066 * @dev: Device object for our driver
1067 * @host_client_id: host client id to be removed
1068 */
1069void heci_remove_client_from_file_list(struct iamt_heci_device *dev,
1070 __u8 host_client_id)
1071{
1072 struct heci_file_private *file_pos = NULL;
1073 struct heci_file_private *file_next = NULL;
1074 list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link) {
1075 if (host_client_id == file_pos->host_client_id) {
1076 DBG("remove host client = %d, ME client = %d\n",
1077 file_pos->host_client_id,
1078 file_pos->me_client_id);
1079 list_del_init(&file_pos->link);
1080 break;
1081 }
1082 }
1083}
diff --git a/drivers/staging/heci/heci_interface.c b/drivers/staging/heci/heci_interface.c
deleted file mode 100644
index 03e1df1a88a..00000000000
--- a/drivers/staging/heci/heci_interface.c
+++ /dev/null
@@ -1,498 +0,0 @@
1/*
2 * Part of Intel(R) Manageability Engine Interface Linux driver
3 *
4 * Copyright (c) 2003 - 2008 Intel Corp.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * substantially similar to the "NO WARRANTY" disclaimer below
15 * ("Disclaimer") and any redistribution must be conditioned upon
16 * including a substantially similar Disclaimer requirement for further
17 * binary redistribution.
18 * 3. Neither the names of the above-listed copyright holders nor the names
19 * of any contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * Alternatively, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2 as published by the Free
24 * Software Foundation.
25 *
26 * NO WARRANTY
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGES.
38 *
39 */
40
41
42#include "heci.h"
43#include "heci_interface.h"
44
45
46/**
47 * heci_set_csr_register - write H_CSR register to the heci device,
48 * and ignore the H_IS bit for it is write-one-to-zero.
49 *
50 * @dev: device object for our driver
51 */
52void heci_set_csr_register(struct iamt_heci_device *dev)
53{
54 if ((dev->host_hw_state & H_IS) == H_IS)
55 dev->host_hw_state &= ~H_IS;
56 write_heci_register(dev, H_CSR, dev->host_hw_state);
57 dev->host_hw_state = read_heci_register(dev, H_CSR);
58}
59
60/**
61 * heci_csr_enable_interrupts - enable heci device interrupts
62 *
63 * @dev: device object for our driver
64 */
65void heci_csr_enable_interrupts(struct iamt_heci_device *dev)
66{
67 dev->host_hw_state |= H_IE;
68 heci_set_csr_register(dev);
69}
70
71/**
72 * heci_csr_disable_interrupts - disable heci device interrupts
73 *
74 * @dev: device object for our driver
75 */
76void heci_csr_disable_interrupts(struct iamt_heci_device *dev)
77{
78 dev->host_hw_state &= ~H_IE;
79 heci_set_csr_register(dev);
80}
81
82/**
83 * heci_csr_clear_his - clear H_IS bit in H_CSR
84 *
85 * @dev: device object for our driver
86 */
87void heci_csr_clear_his(struct iamt_heci_device *dev)
88{
89 write_heci_register(dev, H_CSR, dev->host_hw_state);
90 dev->host_hw_state = read_heci_register(dev, H_CSR);
91}
92
93/**
94 * _host_get_filled_slots - get number of device filled buffer slots
95 *
96 * @device: the device structure
97 *
98 * returns numer of filled slots
99 */
100static unsigned char _host_get_filled_slots(const struct iamt_heci_device *dev)
101{
102 char read_ptr, write_ptr;
103
104 read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8);
105 write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16);
106
107 return (unsigned char) (write_ptr - read_ptr);
108}
109
110/**
111 * host_buffer_is_empty - check if host buffer is empty.
112 *
113 * @dev: device object for our driver
114 *
115 * returns 1 if empty, 0 - otherwise.
116 */
117int host_buffer_is_empty(struct iamt_heci_device *dev)
118{
119 unsigned char filled_slots;
120
121 dev->host_hw_state = read_heci_register(dev, H_CSR);
122 filled_slots = _host_get_filled_slots(dev);
123
124 if (filled_slots > 0)
125 return 0;
126
127 return 1;
128}
129
130/**
131 * count_empty_write_slots - count write empty slots.
132 *
133 * @dev: device object for our driver
134 *
135 * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count
136 */
137__s32 count_empty_write_slots(const struct iamt_heci_device *dev)
138{
139 unsigned char buffer_depth, filled_slots, empty_slots;
140
141 buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24);
142 filled_slots = _host_get_filled_slots(dev);
143 empty_slots = buffer_depth - filled_slots;
144
145 if (filled_slots > buffer_depth) {
146 /* overflow */
147 return -ESLOTS_OVERFLOW;
148 }
149
150 return (__s32) empty_slots;
151}
152
153/**
154 * heci_write_message - write a message to heci device.
155 *
156 * @dev: device object for our driver
157 * @heci_hdr: header of message
158 * @write_buffer: message buffer will be write
159 * @write_length: message size will be write
160 *
161 * returns 1 if success, 0 - otherwise.
162 */
163int heci_write_message(struct iamt_heci_device *dev,
164 struct heci_msg_hdr *header,
165 unsigned char *write_buffer,
166 unsigned long write_length)
167{
168 __u32 temp_msg = 0;
169 unsigned long bytes_written = 0;
170 unsigned char buffer_depth, filled_slots, empty_slots;
171 unsigned long dw_to_write;
172
173 dev->host_hw_state = read_heci_register(dev, H_CSR);
174 DBG("host_hw_state = 0x%08x.\n", dev->host_hw_state);
175 DBG("heci_write_message header=%08x.\n", *((__u32 *) header));
176 buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24);
177 filled_slots = _host_get_filled_slots(dev);
178 empty_slots = buffer_depth - filled_slots;
179 DBG("filled = %hu, empty = %hu.\n", filled_slots, empty_slots);
180
181 dw_to_write = ((write_length + 3) / 4);
182
183 if (dw_to_write > empty_slots)
184 return 0;
185
186 write_heci_register(dev, H_CB_WW, *((__u32 *) header));
187
188 while (write_length >= 4) {
189 write_heci_register(dev, H_CB_WW,
190 *(__u32 *) (write_buffer + bytes_written));
191 bytes_written += 4;
192 write_length -= 4;
193 }
194
195 if (write_length > 0) {
196 memcpy(&temp_msg, &write_buffer[bytes_written], write_length);
197 write_heci_register(dev, H_CB_WW, temp_msg);
198 }
199
200 dev->host_hw_state |= H_IG;
201 heci_set_csr_register(dev);
202 dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
203 if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
204 return 0;
205
206 dev->write_hang = 0;
207 return 1;
208}
209
210/**
211 * count_full_read_slots - count read full slots.
212 *
213 * @dev: device object for our driver
214 *
215 * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count
216 */
217__s32 count_full_read_slots(struct iamt_heci_device *dev)
218{
219 char read_ptr, write_ptr;
220 unsigned char buffer_depth, filled_slots;
221
222 dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
223 buffer_depth = (unsigned char)((dev->me_hw_state & ME_CBD_HRA) >> 24);
224 read_ptr = (char) ((dev->me_hw_state & ME_CBRP_HRA) >> 8);
225 write_ptr = (char) ((dev->me_hw_state & ME_CBWP_HRA) >> 16);
226 filled_slots = (unsigned char) (write_ptr - read_ptr);
227
228 if (filled_slots > buffer_depth) {
229 /* overflow */
230 return -ESLOTS_OVERFLOW;
231 }
232
233 DBG("filled_slots =%08x \n", filled_slots);
234 return (__s32) filled_slots;
235}
236
237/**
238 * heci_read_slots - read a message from heci device.
239 *
240 * @dev: device object for our driver
241 * @buffer: message buffer will be write
242 * @buffer_length: message size will be read
243 */
244void heci_read_slots(struct iamt_heci_device *dev,
245 unsigned char *buffer, unsigned long buffer_length)
246{
247 __u32 i = 0;
248 unsigned char temp_buf[sizeof(__u32)];
249
250 while (buffer_length >= sizeof(__u32)) {
251 ((__u32 *) buffer)[i] = read_heci_register(dev, ME_CB_RW);
252 DBG("buffer[%d]= %d\n", i, ((__u32 *) buffer)[i]);
253 i++;
254 buffer_length -= sizeof(__u32);
255 }
256
257 if (buffer_length > 0) {
258 *((__u32 *) &temp_buf) = read_heci_register(dev, ME_CB_RW);
259 memcpy(&buffer[i * 4], temp_buf, buffer_length);
260 }
261
262 dev->host_hw_state |= H_IG;
263 heci_set_csr_register(dev);
264}
265
266/**
267 * flow_ctrl_creds - check flow_control credentials.
268 *
269 * @dev: device object for our driver
270 * @file_ext: private data of the file object
271 *
272 * returns 1 if flow_ctrl_creds >0, 0 - otherwise.
273 */
274int flow_ctrl_creds(struct iamt_heci_device *dev,
275 struct heci_file_private *file_ext)
276{
277 __u8 i;
278
279 if (!dev->num_heci_me_clients)
280 return 0;
281
282 if (file_ext == NULL)
283 return 0;
284
285 if (file_ext->flow_ctrl_creds > 0)
286 return 1;
287
288 for (i = 0; i < dev->num_heci_me_clients; i++) {
289 if (dev->me_clients[i].client_id == file_ext->me_client_id) {
290 if (dev->me_clients[i].flow_ctrl_creds > 0) {
291 BUG_ON(dev->me_clients[i].props.single_recv_buf
292 == 0);
293 return 1;
294 }
295 return 0;
296 }
297 }
298 BUG();
299 return 0;
300}
301
302/**
303 * flow_ctrl_reduce - reduce flow_control.
304 *
305 * @dev: device object for our driver
306 * @file_ext: private data of the file object
307 */
308void flow_ctrl_reduce(struct iamt_heci_device *dev,
309 struct heci_file_private *file_ext)
310{
311 __u8 i;
312
313 if (!dev->num_heci_me_clients)
314 return;
315
316 for (i = 0; i < dev->num_heci_me_clients; i++) {
317 if (dev->me_clients[i].client_id == file_ext->me_client_id) {
318 if (dev->me_clients[i].props.single_recv_buf != 0) {
319 BUG_ON(dev->me_clients[i].flow_ctrl_creds <= 0);
320 dev->me_clients[i].flow_ctrl_creds--;
321 } else {
322 BUG_ON(file_ext->flow_ctrl_creds <= 0);
323 file_ext->flow_ctrl_creds--;
324 }
325 return;
326 }
327 }
328 BUG();
329}
330
331/**
332 * heci_send_flow_control - send flow control to fw.
333 *
334 * @dev: device object for our driver
335 * @file_ext: private data of the file object
336 *
337 * returns 1 if success, 0 - otherwise.
338 */
339int heci_send_flow_control(struct iamt_heci_device *dev,
340 struct heci_file_private *file_ext)
341{
342 struct heci_msg_hdr *heci_hdr;
343 struct hbm_flow_control *heci_flow_control;
344
345 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
346 heci_hdr->host_addr = 0;
347 heci_hdr->me_addr = 0;
348 heci_hdr->length = sizeof(struct hbm_flow_control);
349 heci_hdr->msg_complete = 1;
350 heci_hdr->reserved = 0;
351
352 heci_flow_control = (struct hbm_flow_control *) &dev->wr_msg_buf[1];
353 memset(heci_flow_control, 0, sizeof(heci_flow_control));
354 heci_flow_control->host_addr = file_ext->host_client_id;
355 heci_flow_control->me_addr = file_ext->me_client_id;
356 heci_flow_control->cmd.cmd = HECI_FLOW_CONTROL_CMD;
357 memset(heci_flow_control->reserved, 0,
358 sizeof(heci_flow_control->reserved));
359 DBG("sending flow control host client = %d, me client = %d\n",
360 file_ext->host_client_id, file_ext->me_client_id);
361 if (!heci_write_message(dev, heci_hdr,
362 (unsigned char *) heci_flow_control,
363 sizeof(struct hbm_flow_control)))
364 return 0;
365
366 return 1;
367
368}
369
370/**
371 * other_client_is_connecting - check if other
372 * client with the same client id is connected.
373 *
374 * @dev: device object for our driver
375 * @file_ext: private data of the file object
376 *
377 * returns 1 if other client is connected, 0 - otherwise.
378 */
379int other_client_is_connecting(struct iamt_heci_device *dev,
380 struct heci_file_private *file_ext)
381{
382 struct heci_file_private *file_pos = NULL;
383 struct heci_file_private *file_next = NULL;
384
385 list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link) {
386 if ((file_pos->state == HECI_FILE_CONNECTING)
387 && (file_pos != file_ext)
388 && file_ext->me_client_id == file_pos->me_client_id)
389 return 1;
390
391 }
392 return 0;
393}
394
395/**
396 * heci_send_wd - send watch dog message to fw.
397 *
398 * @dev: device object for our driver
399 *
400 * returns 1 if success, 0 - otherwise.
401 */
402int heci_send_wd(struct iamt_heci_device *dev)
403{
404 struct heci_msg_hdr *heci_hdr;
405
406 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
407 heci_hdr->host_addr = dev->wd_file_ext.host_client_id;
408 heci_hdr->me_addr = dev->wd_file_ext.me_client_id;
409 heci_hdr->msg_complete = 1;
410 heci_hdr->reserved = 0;
411
412 if (!memcmp(dev->wd_data, heci_start_wd_params,
413 HECI_WD_PARAMS_SIZE)) {
414 heci_hdr->length = HECI_START_WD_DATA_SIZE;
415 } else {
416 BUG_ON(memcmp(dev->wd_data, heci_stop_wd_params,
417 HECI_WD_PARAMS_SIZE));
418 heci_hdr->length = HECI_WD_PARAMS_SIZE;
419 }
420
421 if (!heci_write_message(dev, heci_hdr, dev->wd_data, heci_hdr->length))
422 return 0;
423
424 return 1;
425}
426
427/**
428 * heci_disconnect - send disconnect message to fw.
429 *
430 * @dev: device object for our driver
431 * @file_ext: private data of the file object
432 *
433 * returns 1 if success, 0 - otherwise.
434 */
435int heci_disconnect(struct iamt_heci_device *dev,
436 struct heci_file_private *file_ext)
437{
438 struct heci_msg_hdr *heci_hdr;
439 struct hbm_client_disconnect_request *heci_cli_disconnect;
440
441 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
442 heci_hdr->host_addr = 0;
443 heci_hdr->me_addr = 0;
444 heci_hdr->length = sizeof(struct hbm_client_disconnect_request);
445 heci_hdr->msg_complete = 1;
446 heci_hdr->reserved = 0;
447
448 heci_cli_disconnect =
449 (struct hbm_client_disconnect_request *) &dev->wr_msg_buf[1];
450 memset(heci_cli_disconnect, 0, sizeof(heci_cli_disconnect));
451 heci_cli_disconnect->host_addr = file_ext->host_client_id;
452 heci_cli_disconnect->me_addr = file_ext->me_client_id;
453 heci_cli_disconnect->cmd.cmd = CLIENT_DISCONNECT_REQ_CMD;
454 heci_cli_disconnect->reserved[0] = 0;
455
456 if (!heci_write_message(dev, heci_hdr,
457 (unsigned char *) heci_cli_disconnect,
458 sizeof(struct hbm_client_disconnect_request)))
459 return 0;
460
461 return 1;
462}
463
464/**
465 * heci_connect - send connect message to fw.
466 *
467 * @dev: device object for our driver
468 * @file_ext: private data of the file object
469 *
470 * returns 1 if success, 0 - otherwise.
471 */
472int heci_connect(struct iamt_heci_device *dev,
473 struct heci_file_private *file_ext)
474{
475 struct heci_msg_hdr *heci_hdr;
476 struct hbm_client_connect_request *heci_cli_connect;
477
478 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
479 heci_hdr->host_addr = 0;
480 heci_hdr->me_addr = 0;
481 heci_hdr->length = sizeof(struct hbm_client_connect_request);
482 heci_hdr->msg_complete = 1;
483 heci_hdr->reserved = 0;
484
485 heci_cli_connect =
486 (struct hbm_client_connect_request *) &dev->wr_msg_buf[1];
487 heci_cli_connect->host_addr = file_ext->host_client_id;
488 heci_cli_connect->me_addr = file_ext->me_client_id;
489 heci_cli_connect->cmd.cmd = CLIENT_CONNECT_REQ_CMD;
490 heci_cli_connect->reserved = 0;
491
492 if (!heci_write_message(dev, heci_hdr,
493 (unsigned char *) heci_cli_connect,
494 sizeof(struct hbm_client_connect_request)))
495 return 0;
496
497 return 1;
498}
diff --git a/drivers/staging/heci/heci_interface.h b/drivers/staging/heci/heci_interface.h
deleted file mode 100644
index 34db7e52b8e..00000000000
--- a/drivers/staging/heci/heci_interface.h
+++ /dev/null
@@ -1,170 +0,0 @@
1/*
2 * Part of Intel(R) Manageability Engine Interface Linux driver
3 *
4 * Copyright (c) 2003 - 2008 Intel Corp.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * substantially similar to the "NO WARRANTY" disclaimer below
15 * ("Disclaimer") and any redistribution must be conditioned upon
16 * including a substantially similar Disclaimer requirement for further
17 * binary redistribution.
18 * 3. Neither the names of the above-listed copyright holders nor the names
19 * of any contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * Alternatively, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2 as published by the Free
24 * Software Foundation.
25 *
26 * NO WARRANTY
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGES.
38 *
39 */
40
41
42#ifndef _HECI_INTERFACE_H_
43#define _HECI_INTERFACE_H_
44
45#include <linux/spinlock.h>
46#include <linux/list.h>
47#include <linux/pci.h>
48#include <linux/timer.h>
49#include <linux/interrupt.h>
50#include <linux/workqueue.h>
51#include <linux/module.h>
52#include <linux/aio.h>
53#include <linux/types.h>
54#include "heci_data_structures.h"
55
56
57#define HBM_MINOR_VERSION 0
58#define HBM_MAJOR_VERSION 1
59#define HBM_TIMEOUT 1 /* 1 second */
60
61
62#define HOST_START_REQ_CMD 0x01
63#define HOST_START_RES_CMD 0x81
64
65#define HOST_STOP_REQ_CMD 0x02
66#define HOST_STOP_RES_CMD 0x82
67
68#define ME_STOP_REQ_CMD 0x03
69
70#define HOST_ENUM_REQ_CMD 0x04
71#define HOST_ENUM_RES_CMD 0x84
72
73#define HOST_CLIENT_PROPERTEIS_REQ_CMD 0x05
74#define HOST_CLIENT_PROPERTEIS_RES_CMD 0x85
75
76#define CLIENT_CONNECT_REQ_CMD 0x06
77#define CLIENT_CONNECT_RES_CMD 0x86
78
79#define CLIENT_DISCONNECT_REQ_CMD 0x07
80#define CLIENT_DISCONNECT_RES_CMD 0x87
81
82#define HECI_FLOW_CONTROL_CMD 0x08
83
84
85#define AMT_WD_VALUE 120 /* seconds */
86
87#define HECI_WATCHDOG_DATA_SIZE 16
88#define HECI_START_WD_DATA_SIZE 20
89#define HECI_WD_PARAMS_SIZE 4
90
91/* IOCTL commands */
92#define IOCTL_HECI_GET_VERSION \
93 _IOWR('H' , 0x0, struct heci_message_data)
94#define IOCTL_HECI_CONNECT_CLIENT \
95 _IOWR('H' , 0x01, struct heci_message_data)
96#define IOCTL_HECI_WD \
97 _IOWR('H' , 0x02, struct heci_message_data)
98#define IOCTL_HECI_BYPASS_WD \
99 _IOWR('H' , 0x10, struct heci_message_data)
100
101enum heci_stop_reason_types{
102 DRIVER_STOP_REQUEST = 0x00,
103 DEVICE_D1_ENTRY = 0x01,
104 DEVICE_D2_ENTRY = 0x02,
105 DEVICE_D3_ENTRY = 0x03,
106 SYSTEM_S1_ENTRY = 0x04,
107 SYSTEM_S2_ENTRY = 0x05,
108 SYSTEM_S3_ENTRY = 0x06,
109 SYSTEM_S4_ENTRY = 0x07,
110 SYSTEM_S5_ENTRY = 0x08
111};
112
113enum me_stop_reason_types{
114 FW_UPDATE = 0x00
115};
116
117enum client_connect_status_types{
118 CCS_SUCCESS = 0x00,
119 CCS_NOT_FOUND = 0x01,
120 CCS_ALREADY_STARTED = 0x02,
121 CCS_OUT_OF_RESOURCES = 0x03,
122 CCS_MESSAGE_SMALL = 0x04
123};
124
125enum client_disconnect_status_types{
126 CDS_SUCCESS = 0x00
127};
128
129
130/*
131 * heci interface function prototypes
132 */
133void heci_set_csr_register(struct iamt_heci_device *dev);
134void heci_csr_enable_interrupts(struct iamt_heci_device *dev);
135void heci_csr_disable_interrupts(struct iamt_heci_device *dev);
136void heci_csr_clear_his(struct iamt_heci_device *dev);
137
138void heci_read_slots(struct iamt_heci_device *dev,
139 unsigned char *buffer, unsigned long buffer_length);
140
141int heci_write_message(struct iamt_heci_device *dev,
142 struct heci_msg_hdr *header,
143 unsigned char *write_buffer,
144 unsigned long write_length);
145
146int host_buffer_is_empty(struct iamt_heci_device *dev);
147
148__s32 count_full_read_slots(struct iamt_heci_device *dev);
149
150__s32 count_empty_write_slots(const struct iamt_heci_device *dev);
151
152int flow_ctrl_creds(struct iamt_heci_device *dev,
153 struct heci_file_private *file_ext);
154
155int heci_send_wd(struct iamt_heci_device *dev);
156
157void flow_ctrl_reduce(struct iamt_heci_device *dev,
158 struct heci_file_private *file_ext);
159
160int heci_send_flow_control(struct iamt_heci_device *dev,
161 struct heci_file_private *file_ext);
162
163int heci_disconnect(struct iamt_heci_device *dev,
164 struct heci_file_private *file_ext);
165int other_client_is_connecting(struct iamt_heci_device *dev,
166 struct heci_file_private *file_ext);
167int heci_connect(struct iamt_heci_device *dev,
168 struct heci_file_private *file_ext);
169
170#endif /* _HECI_INTERFACE_H_ */
diff --git a/drivers/staging/heci/heci_main.c b/drivers/staging/heci/heci_main.c
deleted file mode 100644
index ddf48227e35..00000000000
--- a/drivers/staging/heci/heci_main.c
+++ /dev/null
@@ -1,1576 +0,0 @@
1/*
2 * Part of Intel(R) Manageability Engine Interface Linux driver
3 *
4 * Copyright (c) 2003 - 2008 Intel Corp.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * substantially similar to the "NO WARRANTY" disclaimer below
15 * ("Disclaimer") and any redistribution must be conditioned upon
16 * including a substantially similar Disclaimer requirement for further
17 * binary redistribution.
18 * 3. Neither the names of the above-listed copyright holders nor the names
19 * of any contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * Alternatively, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2 as published by the Free
24 * Software Foundation.
25 *
26 * NO WARRANTY
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGES.
38 *
39 */
40
41
42#include <linux/module.h>
43#include <linux/moduleparam.h>
44#include <linux/kernel.h>
45#include <linux/slab.h>
46#include <linux/fs.h>
47#include <linux/errno.h>
48#include <linux/types.h>
49#include <linux/fcntl.h>
50#include <linux/aio.h>
51#include <linux/pci.h>
52#include <linux/reboot.h>
53#include <linux/poll.h>
54#include <linux/init.h>
55#include <linux/kdev_t.h>
56#include <linux/ioctl.h>
57#include <linux/cdev.h>
58#include <linux/device.h>
59#include <linux/unistd.h>
60#include <linux/kthread.h>
61
62#include "heci.h"
63#include "heci_interface.h"
64#include "heci_version.h"
65
66
67#define HECI_READ_TIMEOUT 45
68
69#define HECI_DRIVER_NAME "heci"
70
71/*
72 * heci driver strings
73 */
74static char heci_driver_name[] = HECI_DRIVER_NAME;
75static char heci_driver_string[] = "Intel(R) Management Engine Interface";
76static char heci_driver_version[] = HECI_DRIVER_VERSION;
77static char heci_copyright[] = "Copyright (c) 2003 - 2008 Intel Corporation.";
78
79
80#ifdef HECI_DEBUG
81int heci_debug = 1;
82#else
83int heci_debug;
84#endif
85MODULE_PARM_DESC(heci_debug, "Debug enabled or not");
86module_param(heci_debug, int, 0644);
87
88
89#define HECI_DEV_NAME "heci"
90
91/* heci char device for registration */
92static struct cdev heci_cdev;
93
94/* major number for device */
95static int heci_major;
96/* The device pointer */
97static struct pci_dev *heci_device;
98
99static struct class *heci_class;
100
101
102/* heci_pci_tbl - PCI Device ID Table */
103static struct pci_device_id heci_pci_tbl[] = {
104 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82946GZ)},
105 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82G35)},
106 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82Q965)},
107 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82G965)},
108 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82GM965)},
109 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82GME965)},
110 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82Q35)},
111 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82G33)},
112 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82Q33)},
113 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82X38)},
114 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_3200)},
115 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_6)},
116 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_7)},
117 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_8)},
118 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_9)},
119 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_10)},
120 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_1)},
121 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_2)},
122 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_3)},
123 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_4)},
124 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_1)},
125 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_2)},
126 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_3)},
127 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_4)},
128 /* required last entry */
129 {0, }
130};
131
132MODULE_DEVICE_TABLE(pci, heci_pci_tbl);
133
134/*
135 * Local Function Prototypes
136 */
137static int __init heci_init_module(void);
138static void __exit heci_exit_module(void);
139static int __devinit heci_probe(struct pci_dev *pdev,
140 const struct pci_device_id *ent);
141static void __devexit heci_remove(struct pci_dev *pdev);
142static int heci_open(struct inode *inode, struct file *file);
143static int heci_release(struct inode *inode, struct file *file);
144static ssize_t heci_read(struct file *file, char __user *ubuf,
145 size_t length, loff_t *offset);
146static int heci_ioctl(struct inode *inode, struct file *file,
147 unsigned int cmd, unsigned long data);
148static ssize_t heci_write(struct file *file, const char __user *ubuf,
149 size_t length, loff_t *offset);
150static unsigned int heci_poll(struct file *file, poll_table *wait);
151static struct heci_cb_private *find_read_list_entry(
152 struct iamt_heci_device *dev,
153 struct heci_file_private *file_ext);
154#ifdef CONFIG_PM
155static int heci_suspend(struct pci_dev *pdev, pm_message_t state);
156static int heci_resume(struct pci_dev *pdev);
157static __u16 g_sus_wd_timeout;
158#else
159#define heci_suspend NULL
160#define heci_resume NULL
161#endif
162/*
163 * PCI driver structure
164 */
165static struct pci_driver heci_driver = {
166 .name = heci_driver_name,
167 .id_table = heci_pci_tbl,
168 .probe = heci_probe,
169 .remove = __devexit_p(heci_remove),
170 .shutdown = __devexit_p(heci_remove),
171 .suspend = heci_suspend,
172 .resume = heci_resume
173};
174
175/*
176 * file operations structure will be use heci char device.
177 */
178static const struct file_operations heci_fops = {
179 .owner = THIS_MODULE,
180 .read = heci_read,
181 .ioctl = heci_ioctl,
182 .open = heci_open,
183 .release = heci_release,
184 .write = heci_write,
185 .poll = heci_poll,
186};
187
188/**
189 * heci_registration_cdev - set up the cdev structure for heci device.
190 *
191 * @dev: char device struct
192 * @hminor: minor number for registration char device
193 * @fops: file operations structure
194 *
195 * returns 0 on success, <0 on failure.
196 */
197static int heci_registration_cdev(struct cdev *dev, int hminor,
198 const struct file_operations *fops)
199{
200 int ret, devno = MKDEV(heci_major, hminor);
201
202 cdev_init(dev, fops);
203 dev->owner = THIS_MODULE;
204 ret = cdev_add(dev, devno, 1);
205 /* Fail gracefully if need be */
206 if (ret) {
207 printk(KERN_ERR "heci: Error %d registering heci device %d\n",
208 ret, hminor);
209 }
210 return ret;
211}
212
213/* Display the version of heci driver. */
214static ssize_t version_show(struct class *dev, char *buf)
215{
216 return sprintf(buf, "%s %s.\n",
217 heci_driver_string, heci_driver_version);
218}
219
220static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
221
222/**
223 * heci_register_cdev - registers heci char device
224 *
225 * returns 0 on success, <0 on failure.
226 */
227static int heci_register_cdev(void)
228{
229 int ret;
230 dev_t dev;
231
232 /* registration of char devices */
233 ret = alloc_chrdev_region(&dev, HECI_MINORS_BASE, HECI_MINORS_COUNT,
234 HECI_DRIVER_NAME);
235 if (ret) {
236 printk(KERN_ERR "heci: Error allocating char device region.\n");
237 return ret;
238 }
239
240 heci_major = MAJOR(dev);
241
242 ret = heci_registration_cdev(&heci_cdev, HECI_MINOR_NUMBER,
243 &heci_fops);
244 if (ret)
245 unregister_chrdev_region(MKDEV(heci_major, HECI_MINORS_BASE),
246 HECI_MINORS_COUNT);
247
248 return ret;
249}
250
251/**
252 * heci_unregister_cdev - unregisters heci char device
253 */
254static void heci_unregister_cdev(void)
255{
256 cdev_del(&heci_cdev);
257 unregister_chrdev_region(MKDEV(heci_major, HECI_MINORS_BASE),
258 HECI_MINORS_COUNT);
259}
260
261#ifndef HECI_DEVICE_CREATE
262#define HECI_DEVICE_CREATE device_create
263#endif
264/**
265 * heci_sysfs_device_create - adds device entry to sysfs
266 *
267 * returns 0 on success, <0 on failure.
268 */
269static int heci_sysfs_device_create(void)
270{
271 struct class *class;
272 void *tmphdev;
273 int err = 0;
274
275 class = class_create(THIS_MODULE, HECI_DRIVER_NAME);
276 if (IS_ERR(class)) {
277 err = PTR_ERR(class);
278 printk(KERN_ERR "heci: Error creating heci class.\n");
279 goto err_out;
280 }
281
282 err = class_create_file(class, &class_attr_version);
283 if (err) {
284 class_destroy(class);
285 printk(KERN_ERR "heci: Error creating heci class file.\n");
286 goto err_out;
287 }
288
289 tmphdev = HECI_DEVICE_CREATE(class, NULL, heci_cdev.dev, NULL,
290 HECI_DEV_NAME);
291 if (IS_ERR(tmphdev)) {
292 err = PTR_ERR(tmphdev);
293 class_remove_file(class, &class_attr_version);
294 class_destroy(class);
295 goto err_out;
296 }
297
298 heci_class = class;
299err_out:
300 return err;
301}
302
303/**
304 * heci_sysfs_device_remove - unregisters the device entry on sysfs
305 */
306static void heci_sysfs_device_remove(void)
307{
308 if ((heci_class == NULL) || (IS_ERR(heci_class)))
309 return;
310
311 device_destroy(heci_class, heci_cdev.dev);
312 class_remove_file(heci_class, &class_attr_version);
313 class_destroy(heci_class);
314}
315
316/**
317 * heci_init_module - Driver Registration Routine
318 *
319 * heci_init_module is the first routine called when the driver is
320 * loaded. All it does is register with the PCI subsystem.
321 *
322 * returns 0 on success, <0 on failure.
323 */
324static int __init heci_init_module(void)
325{
326 int ret = 0;
327
328 printk(KERN_INFO "heci: %s - version %s\n", heci_driver_string,
329 heci_driver_version);
330 printk(KERN_INFO "heci: %s\n", heci_copyright);
331
332 /* init pci module */
333 ret = pci_register_driver(&heci_driver);
334 if (ret < 0) {
335 printk(KERN_ERR "heci: Error registering driver.\n");
336 goto end;
337 }
338
339 ret = heci_register_cdev();
340 if (ret)
341 goto unregister_pci;
342
343 ret = heci_sysfs_device_create();
344 if (ret)
345 goto unregister_cdev;
346
347 return ret;
348
349unregister_cdev:
350 heci_unregister_cdev();
351unregister_pci:
352 pci_unregister_driver(&heci_driver);
353end:
354 return ret;
355}
356
357module_init(heci_init_module);
358
359
360/**
361 * heci_exit_module - Driver Exit Cleanup Routine
362 *
363 * heci_exit_module is called just before the driver is removed
364 * from memory.
365 */
366static void __exit heci_exit_module(void)
367{
368 pci_unregister_driver(&heci_driver);
369 heci_sysfs_device_remove();
370 heci_unregister_cdev();
371}
372
373module_exit(heci_exit_module);
374
375
376/**
377 * heci_probe - Device Initialization Routine
378 *
379 * @pdev: PCI device information struct
380 * @ent: entry in kcs_pci_tbl
381 *
382 * returns 0 on success, <0 on failure.
383 */
384static int __devinit heci_probe(struct pci_dev *pdev,
385 const struct pci_device_id *ent)
386{
387 struct iamt_heci_device *dev = NULL;
388 int i, err = 0;
389
390 if (heci_device) {
391 err = -EEXIST;
392 goto end;
393 }
394 /* enable pci dev */
395 err = pci_enable_device(pdev);
396 if (err) {
397 printk(KERN_ERR "heci: Failed to enable pci device.\n");
398 goto end;
399 }
400 /* set PCI host mastering */
401 pci_set_master(pdev);
402 /* pci request regions for heci driver */
403 err = pci_request_regions(pdev, heci_driver_name);
404 if (err) {
405 printk(KERN_ERR "heci: Failed to get pci regions.\n");
406 goto disable_device;
407 }
408 /* allocates and initializes the heci dev structure */
409 dev = init_heci_device(pdev);
410 if (!dev) {
411 err = -ENOMEM;
412 goto release_regions;
413 }
414 /* mapping IO device memory */
415 for (i = 0; i <= 5; i++) {
416 if (pci_resource_len(pdev, i) == 0)
417 continue;
418 if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
419 printk(KERN_ERR "heci: heci has IO ports.\n");
420 goto free_device;
421 } else if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
422 if (dev->mem_base) {
423 printk(KERN_ERR
424 "heci: Too many mem addresses.\n");
425 goto free_device;
426 }
427 dev->mem_base = pci_resource_start(pdev, i);
428 dev->mem_length = pci_resource_len(pdev, i);
429 }
430 }
431 if (!dev->mem_base) {
432 printk(KERN_ERR "heci: No address to use.\n");
433 err = -ENODEV;
434 goto free_device;
435 }
436 dev->mem_addr = ioremap_nocache(dev->mem_base,
437 dev->mem_length);
438 if (!dev->mem_addr) {
439 printk(KERN_ERR "heci: Remap IO device memory failure.\n");
440 err = -ENOMEM;
441 goto free_device;
442 }
443 /* request and enable interrupt */
444 err = request_irq(pdev->irq, heci_isr_interrupt, IRQF_SHARED,
445 heci_driver_name, dev);
446 if (err) {
447 printk(KERN_ERR "heci: Request_irq failure. irq = %d \n",
448 pdev->irq);
449 goto unmap_memory;
450 }
451
452 if (heci_hw_init(dev)) {
453 printk(KERN_ERR "heci: Init hw failure.\n");
454 err = -ENODEV;
455 goto release_irq;
456 }
457 init_timer(&dev->wd_timer);
458
459 heci_initialize_clients(dev);
460 if (dev->heci_state != HECI_ENABLED) {
461 err = -ENODEV;
462 goto release_hw;
463 }
464
465 spin_lock_bh(&dev->device_lock);
466 heci_device = pdev;
467 pci_set_drvdata(pdev, dev);
468 spin_unlock_bh(&dev->device_lock);
469
470 if (dev->wd_timeout)
471 mod_timer(&dev->wd_timer, jiffies);
472
473#ifdef CONFIG_PM
474 g_sus_wd_timeout = 0;
475#endif
476 printk(KERN_INFO "heci driver initialization successful.\n");
477 return 0;
478
479release_hw:
480 /* disable interrupts */
481 dev->host_hw_state = read_heci_register(dev, H_CSR);
482 heci_csr_disable_interrupts(dev);
483
484 del_timer_sync(&dev->wd_timer);
485
486 flush_scheduled_work();
487
488release_irq:
489 free_irq(pdev->irq, dev);
490unmap_memory:
491 if (dev->mem_addr)
492 iounmap(dev->mem_addr);
493free_device:
494 kfree(dev);
495release_regions:
496 pci_release_regions(pdev);
497disable_device:
498 pci_disable_device(pdev);
499end:
500 printk(KERN_ERR "heci driver initialization failed.\n");
501 return err;
502}
503
504/**
505 * heci_remove - Device Removal Routine
506 *
507 * @pdev: PCI device information struct
508 *
509 * heci_remove is called by the PCI subsystem to alert the driver
510 * that it should release a PCI device.
511 */
512static void __devexit heci_remove(struct pci_dev *pdev)
513{
514 struct iamt_heci_device *dev = pci_get_drvdata(pdev);
515
516 if (heci_device != pdev)
517 return;
518
519 if (dev == NULL)
520 return;
521
522 spin_lock_bh(&dev->device_lock);
523 if (heci_device != pdev) {
524 spin_unlock_bh(&dev->device_lock);
525 return;
526 }
527
528 if (dev->reinit_tsk != NULL) {
529 kthread_stop(dev->reinit_tsk);
530 dev->reinit_tsk = NULL;
531 }
532
533 del_timer_sync(&dev->wd_timer);
534 if (dev->wd_file_ext.state == HECI_FILE_CONNECTED
535 && dev->wd_timeout) {
536 dev->wd_timeout = 0;
537 dev->wd_due_counter = 0;
538 memcpy(dev->wd_data, heci_stop_wd_params, HECI_WD_PARAMS_SIZE);
539 dev->stop = 1;
540 if (dev->host_buffer_is_empty &&
541 flow_ctrl_creds(dev, &dev->wd_file_ext)) {
542 dev->host_buffer_is_empty = 0;
543
544 if (!heci_send_wd(dev))
545 DBG("send stop WD failed\n");
546 else
547 flow_ctrl_reduce(dev, &dev->wd_file_ext);
548
549 dev->wd_pending = 0;
550 } else {
551 dev->wd_pending = 1;
552 }
553 dev->wd_stoped = 0;
554 spin_unlock_bh(&dev->device_lock);
555
556 wait_event_interruptible_timeout(dev->wait_stop_wd,
557 (dev->wd_stoped), 10 * HZ);
558 spin_lock_bh(&dev->device_lock);
559 if (!dev->wd_stoped)
560 DBG("stop wd failed to complete.\n");
561 else
562 DBG("stop wd complete.\n");
563
564 }
565
566 heci_device = NULL;
567 spin_unlock_bh(&dev->device_lock);
568
569 if (dev->iamthif_file_ext.state == HECI_FILE_CONNECTED) {
570 dev->iamthif_file_ext.state = HECI_FILE_DISCONNECTING;
571 heci_disconnect_host_client(dev,
572 &dev->iamthif_file_ext);
573 }
574 if (dev->wd_file_ext.state == HECI_FILE_CONNECTED) {
575 dev->wd_file_ext.state = HECI_FILE_DISCONNECTING;
576 heci_disconnect_host_client(dev,
577 &dev->wd_file_ext);
578 }
579
580 spin_lock_bh(&dev->device_lock);
581
582 /* remove entry if already in list */
583 DBG("list del iamthif and wd file list.\n");
584 heci_remove_client_from_file_list(dev, dev->wd_file_ext.
585 host_client_id);
586 heci_remove_client_from_file_list(dev,
587 dev->iamthif_file_ext.host_client_id);
588
589 dev->iamthif_current_cb = NULL;
590 dev->iamthif_file_ext.file = NULL;
591 dev->num_heci_me_clients = 0;
592
593 spin_unlock_bh(&dev->device_lock);
594
595 flush_scheduled_work();
596
597 /* disable interrupts */
598 heci_csr_disable_interrupts(dev);
599
600 free_irq(pdev->irq, dev);
601 pci_set_drvdata(pdev, NULL);
602
603 if (dev->mem_addr)
604 iounmap(dev->mem_addr);
605
606 kfree(dev);
607
608 pci_release_regions(pdev);
609 pci_disable_device(pdev);
610}
611
612/**
613 * heci_clear_list - remove all callbacks associated with file
614 * from heci_cb_list
615 *
616 * @file: file information struct
617 * @heci_cb_list: callbacks list
618 *
619 * heci_clear_list is called to clear resources associated with file
620 * when application calls close function or Ctrl-C was pressed
621 *
622 * returns 1 if callback removed from the list, 0 otherwise
623 */
624static int heci_clear_list(struct iamt_heci_device *dev,
625 struct file *file, struct list_head *heci_cb_list)
626{
627 struct heci_cb_private *priv_cb_pos = NULL;
628 struct heci_cb_private *priv_cb_next = NULL;
629 struct file *file_temp;
630 int rets = 0;
631
632 /* list all list member */
633 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
634 heci_cb_list, cb_list) {
635 file_temp = (struct file *)priv_cb_pos->file_object;
636 /* check if list member associated with a file */
637 if (file_temp == file) {
638 /* remove member from the list */
639 list_del(&priv_cb_pos->cb_list);
640 /* check if cb equal to current iamthif cb */
641 if (dev->iamthif_current_cb == priv_cb_pos) {
642 dev->iamthif_current_cb = NULL;
643 /* send flow control to iamthif client */
644 heci_send_flow_control(dev,
645 &dev->iamthif_file_ext);
646 }
647 /* free all allocated buffers */
648 heci_free_cb_private(priv_cb_pos);
649 rets = 1;
650 }
651 }
652 return rets;
653}
654
655/**
656 * heci_clear_lists - remove all callbacks associated with file
657 *
658 * @dev: device information struct
659 * @file: file information struct
660 *
661 * heci_clear_lists is called to clear resources associated with file
662 * when application calls close function or Ctrl-C was pressed
663 *
664 * returns 1 if callback removed from the list, 0 otherwise
665 */
666static int heci_clear_lists(struct iamt_heci_device *dev, struct file *file)
667{
668 int rets = 0;
669
670 /* remove callbacks associated with a file */
671 heci_clear_list(dev, file, &dev->pthi_cmd_list.heci_cb.cb_list);
672 if (heci_clear_list(dev, file,
673 &dev->pthi_read_complete_list.heci_cb.cb_list))
674 rets = 1;
675
676 heci_clear_list(dev, file, &dev->ctrl_rd_list.heci_cb.cb_list);
677
678 if (heci_clear_list(dev, file, &dev->ctrl_wr_list.heci_cb.cb_list))
679 rets = 1;
680
681 if (heci_clear_list(dev, file,
682 &dev->write_waiting_list.heci_cb.cb_list))
683 rets = 1;
684
685 if (heci_clear_list(dev, file, &dev->write_list.heci_cb.cb_list))
686 rets = 1;
687
688 /* check if iamthif_current_cb not NULL */
689 if (dev->iamthif_current_cb && (!rets)) {
690 /* check file and iamthif current cb association */
691 if (dev->iamthif_current_cb->file_object == file) {
692 /* remove cb */
693 heci_free_cb_private(dev->iamthif_current_cb);
694 dev->iamthif_current_cb = NULL;
695 rets = 1;
696 }
697 }
698 return rets;
699}
700
701/**
702 * heci_open - the open function
703 *
704 * @inode: pointer to inode structure
705 * @file: pointer to file structure
706 *
707 * returns 0 on success, <0 on error
708 */
709static int heci_open(struct inode *inode, struct file *file)
710{
711 struct heci_file_private *file_ext;
712 int if_num = iminor(inode);
713 struct iamt_heci_device *dev;
714
715 if (!heci_device)
716 return -ENODEV;
717
718 dev = pci_get_drvdata(heci_device);
719 if ((if_num != HECI_MINOR_NUMBER) || (!dev))
720 return -ENODEV;
721
722 file_ext = heci_alloc_file_private(file);
723 if (file_ext == NULL)
724 return -ENOMEM;
725
726 spin_lock_bh(&dev->device_lock);
727 if (dev->heci_state != HECI_ENABLED) {
728 spin_unlock_bh(&dev->device_lock);
729 kfree(file_ext);
730 return -ENODEV;
731 }
732 if (dev->open_handle_count >= HECI_MAX_OPEN_HANDLE_COUNT) {
733 spin_unlock_bh(&dev->device_lock);
734 kfree(file_ext);
735 return -ENFILE;
736 };
737 dev->open_handle_count++;
738 list_add_tail(&file_ext->link, &dev->file_list);
739 while ((dev->heci_host_clients[dev->current_host_client_id / 8]
740 & (1 << (dev->current_host_client_id % 8))) != 0) {
741
742 dev->current_host_client_id++; /* allow overflow */
743 DBG("current_host_client_id = %d\n",
744 dev->current_host_client_id);
745 DBG("dev->open_handle_count = %lu\n",
746 dev->open_handle_count);
747 }
748 DBG("current_host_client_id = %d\n", dev->current_host_client_id);
749 file_ext->host_client_id = dev->current_host_client_id;
750 dev->heci_host_clients[file_ext->host_client_id / 8] |=
751 (1 << (file_ext->host_client_id % 8));
752 spin_unlock_bh(&dev->device_lock);
753 spin_lock(&file_ext->file_lock);
754 spin_lock_bh(&dev->device_lock);
755 file_ext->state = HECI_FILE_INITIALIZING;
756 spin_unlock_bh(&dev->device_lock);
757 file_ext->sm_state = 0;
758
759 file->private_data = file_ext;
760 spin_unlock(&file_ext->file_lock);
761
762 return 0;
763}
764
765/**
766 * heci_release - the release function
767 *
768 * @inode: pointer to inode structure
769 * @file: pointer to file structure
770 *
771 * returns 0 on success, <0 on error
772 */
773static int heci_release(struct inode *inode, struct file *file)
774{
775 int rets = 0;
776 int if_num = iminor(inode);
777 struct heci_file_private *file_ext = file->private_data;
778 struct heci_cb_private *priv_cb = NULL;
779 struct iamt_heci_device *dev;
780
781 if (!heci_device)
782 return -ENODEV;
783
784 dev = pci_get_drvdata(heci_device);
785 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
786 return -ENODEV;
787
788 if (file_ext != &dev->iamthif_file_ext) {
789 spin_lock(&file_ext->file_lock);
790 spin_lock_bh(&dev->device_lock);
791 if (file_ext->state == HECI_FILE_CONNECTED) {
792 file_ext->state = HECI_FILE_DISCONNECTING;
793 spin_unlock_bh(&dev->device_lock);
794 spin_unlock(&file_ext->file_lock);
795 DBG("disconnecting client host client = %d, "
796 "ME client = %d\n",
797 file_ext->host_client_id,
798 file_ext->me_client_id);
799 rets = heci_disconnect_host_client(dev, file_ext);
800 spin_lock(&file_ext->file_lock);
801 spin_lock_bh(&dev->device_lock);
802 }
803 heci_flush_queues(dev, file_ext);
804 DBG("remove client host client = %d, ME client = %d\n",
805 file_ext->host_client_id,
806 file_ext->me_client_id);
807
808 if (dev->open_handle_count > 0) {
809 dev->heci_host_clients[file_ext->host_client_id / 8] &=
810 ~(1 << (file_ext->host_client_id % 8));
811 dev->open_handle_count--;
812 }
813 heci_remove_client_from_file_list(dev,
814 file_ext->host_client_id);
815
816 /* free read cb */
817 if (file_ext->read_cb != NULL) {
818 priv_cb = find_read_list_entry(dev, file_ext);
819 /* Remove entry from read list */
820 if (priv_cb != NULL)
821 list_del(&priv_cb->cb_list);
822
823 priv_cb = file_ext->read_cb;
824 file_ext->read_cb = NULL;
825 }
826
827 spin_unlock_bh(&dev->device_lock);
828 file->private_data = NULL;
829 spin_unlock(&file_ext->file_lock);
830
831 if (priv_cb != NULL)
832 heci_free_cb_private(priv_cb);
833
834 kfree(file_ext);
835 } else {
836 spin_lock_bh(&dev->device_lock);
837
838 if (dev->open_handle_count > 0)
839 dev->open_handle_count--;
840
841 if (dev->iamthif_file_object == file
842 && dev->iamthif_state != HECI_IAMTHIF_IDLE) {
843 DBG("pthi canceled iamthif state %d\n",
844 dev->iamthif_state);
845 dev->iamthif_canceled = 1;
846 if (dev->iamthif_state == HECI_IAMTHIF_READ_COMPLETE) {
847 DBG("run next pthi iamthif cb\n");
848 run_next_iamthif_cmd(dev);
849 }
850 }
851
852 if (heci_clear_lists(dev, file))
853 dev->iamthif_state = HECI_IAMTHIF_IDLE;
854
855 spin_unlock_bh(&dev->device_lock);
856 }
857 return rets;
858}
859
860static struct heci_cb_private *find_read_list_entry(
861 struct iamt_heci_device *dev,
862 struct heci_file_private *file_ext)
863{
864 struct heci_cb_private *priv_cb_pos = NULL;
865 struct heci_cb_private *priv_cb_next = NULL;
866 struct heci_file_private *file_ext_list_temp;
867
868 if (dev->read_list.status == 0
869 && !list_empty(&dev->read_list.heci_cb.cb_list)) {
870 DBG("remove read_list CB \n");
871 list_for_each_entry_safe(priv_cb_pos,
872 priv_cb_next,
873 &dev->read_list.heci_cb.cb_list, cb_list) {
874
875 file_ext_list_temp = (struct heci_file_private *)
876 priv_cb_pos->file_private;
877
878 if ((file_ext_list_temp != NULL) &&
879 heci_fe_same_id(file_ext, file_ext_list_temp))
880 return priv_cb_pos;
881
882 }
883 }
884 return NULL;
885}
886
887/**
888 * heci_read - the read client message function.
889 *
890 * @file: pointer to file structure
891 * @ubuf: pointer to user buffer
892 * @length: buffer length
893 * @offset: data offset in buffer
894 *
895 * returns >=0 data length on success , <0 on error
896 */
897static ssize_t heci_read(struct file *file, char __user *ubuf,
898 size_t length, loff_t *offset)
899{
900 int i;
901 int rets = 0, err = 0;
902 int if_num = iminor(file->f_dentry->d_inode);
903 struct heci_file_private *file_ext = file->private_data;
904 struct heci_cb_private *priv_cb_pos = NULL;
905 struct heci_cb_private *priv_cb = NULL;
906 struct iamt_heci_device *dev;
907
908 if (!heci_device)
909 return -ENODEV;
910
911 dev = pci_get_drvdata(heci_device);
912 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
913 return -ENODEV;
914
915 spin_lock_bh(&dev->device_lock);
916 if (dev->heci_state != HECI_ENABLED) {
917 spin_unlock_bh(&dev->device_lock);
918 return -ENODEV;
919 }
920 spin_unlock_bh(&dev->device_lock);
921
922 spin_lock(&file_ext->file_lock);
923 if ((file_ext->sm_state & HECI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
924 spin_unlock(&file_ext->file_lock);
925 /* Do not allow to read watchdog client */
926 for (i = 0; i < dev->num_heci_me_clients; i++) {
927 if (memcmp(&heci_wd_guid,
928 &dev->me_clients[i].props.protocol_name,
929 sizeof(struct guid)) == 0) {
930 if (file_ext->me_client_id ==
931 dev->me_clients[i].client_id)
932 return -EBADF;
933 }
934 }
935 } else {
936 file_ext->sm_state &= ~HECI_WD_STATE_INDEPENDENCE_MSG_SENT;
937 spin_unlock(&file_ext->file_lock);
938 }
939
940 if (file_ext == &dev->iamthif_file_ext) {
941 rets = pthi_read(dev, if_num, file, ubuf, length, offset);
942 goto out;
943 }
944
945 if (file_ext->read_cb && file_ext->read_cb->information > *offset) {
946 priv_cb = file_ext->read_cb;
947 goto copy_buffer;
948 } else if (file_ext->read_cb && file_ext->read_cb->information > 0 &&
949 file_ext->read_cb->information <= *offset) {
950 priv_cb = file_ext->read_cb;
951 rets = 0;
952 goto free;
953 } else if ((!file_ext->read_cb || file_ext->read_cb->information == 0)
954 && *offset > 0) {
955 /*Offset needs to be cleaned for contingous reads*/
956 *offset = 0;
957 rets = 0;
958 goto out;
959 }
960
961 err = heci_start_read(dev, if_num, file_ext);
962 spin_lock_bh(&file_ext->read_io_lock);
963 if (err != 0 && err != -EBUSY) {
964 DBG("heci start read failure with status = %d\n", err);
965 spin_unlock_bh(&file_ext->read_io_lock);
966 rets = err;
967 goto out;
968 }
969 if (HECI_READ_COMPLETE != file_ext->reading_state
970 && !waitqueue_active(&file_ext->rx_wait)) {
971 if (file->f_flags & O_NONBLOCK) {
972 rets = -EAGAIN;
973 spin_unlock_bh(&file_ext->read_io_lock);
974 goto out;
975 }
976 spin_unlock_bh(&file_ext->read_io_lock);
977
978 if (wait_event_interruptible(file_ext->rx_wait,
979 (HECI_READ_COMPLETE == file_ext->reading_state
980 || HECI_FILE_INITIALIZING == file_ext->state
981 || HECI_FILE_DISCONNECTED == file_ext->state
982 || HECI_FILE_DISCONNECTING == file_ext->state))) {
983 if (signal_pending(current)) {
984 rets = -EINTR;
985 goto out;
986 }
987 return -ERESTARTSYS;
988 }
989
990 spin_lock_bh(&dev->device_lock);
991 if (HECI_FILE_INITIALIZING == file_ext->state ||
992 HECI_FILE_DISCONNECTED == file_ext->state ||
993 HECI_FILE_DISCONNECTING == file_ext->state) {
994 spin_unlock_bh(&dev->device_lock);
995 rets = -EBUSY;
996 goto out;
997 }
998 spin_unlock_bh(&dev->device_lock);
999 spin_lock_bh(&file_ext->read_io_lock);
1000 }
1001
1002 priv_cb = file_ext->read_cb;
1003
1004 if (!priv_cb) {
1005 spin_unlock_bh(&file_ext->read_io_lock);
1006 return -ENODEV;
1007 }
1008 if (file_ext->reading_state != HECI_READ_COMPLETE) {
1009 spin_unlock_bh(&file_ext->read_io_lock);
1010 return 0;
1011 }
1012 spin_unlock_bh(&file_ext->read_io_lock);
1013 /* now copy the data to user space */
1014copy_buffer:
1015 DBG("priv_cb->response_buffer size - %d\n",
1016 priv_cb->response_buffer.size);
1017 DBG("priv_cb->information - %lu\n",
1018 priv_cb->information);
1019 if (length == 0 || ubuf == NULL ||
1020 *offset > priv_cb->information) {
1021 rets = -EMSGSIZE;
1022 goto free;
1023 }
1024
1025 /* length is being turncated to PAGE_SIZE, however, */
1026 /* information size may be longer */
1027 length = (length < (priv_cb->information - *offset) ?
1028 length : (priv_cb->information - *offset));
1029
1030 if (copy_to_user(ubuf,
1031 priv_cb->response_buffer.data + *offset,
1032 length)) {
1033 rets = -EFAULT;
1034 goto free;
1035 }
1036
1037 rets = length;
1038 *offset += length;
1039 if ((unsigned long)*offset < priv_cb->information)
1040 goto out;
1041
1042free:
1043 spin_lock_bh(&dev->device_lock);
1044 priv_cb_pos = find_read_list_entry(dev, file_ext);
1045 /* Remove entry from read list */
1046 if (priv_cb_pos != NULL)
1047 list_del(&priv_cb_pos->cb_list);
1048 spin_unlock_bh(&dev->device_lock);
1049 heci_free_cb_private(priv_cb);
1050 spin_lock_bh(&file_ext->read_io_lock);
1051 file_ext->reading_state = HECI_IDLE;
1052 file_ext->read_cb = NULL;
1053 file_ext->read_pending = 0;
1054 spin_unlock_bh(&file_ext->read_io_lock);
1055out: DBG("end heci read rets= %d\n", rets);
1056 return rets;
1057}
1058
1059/**
1060 * heci_write - the write function.
1061 *
1062 * @file: pointer to file structure
1063 * @ubuf: pointer to user buffer
1064 * @length: buffer length
1065 * @offset: data offset in buffer
1066 *
1067 * returns >=0 data length on success , <0 on error
1068 */
1069static ssize_t heci_write(struct file *file, const char __user *ubuf,
1070 size_t length, loff_t *offset)
1071{
1072 int rets = 0;
1073 __u8 i;
1074 int if_num = iminor(file->f_dentry->d_inode);
1075 struct heci_file_private *file_ext = file->private_data;
1076 struct heci_cb_private *priv_write_cb = NULL;
1077 struct heci_msg_hdr heci_hdr;
1078 struct iamt_heci_device *dev;
1079 unsigned long currtime = get_seconds();
1080
1081 if (!heci_device)
1082 return -ENODEV;
1083
1084 dev = pci_get_drvdata(heci_device);
1085
1086 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
1087 return -ENODEV;
1088
1089 spin_lock_bh(&dev->device_lock);
1090
1091 if (dev->heci_state != HECI_ENABLED) {
1092 spin_unlock_bh(&dev->device_lock);
1093 return -ENODEV;
1094 }
1095 if (file_ext == &dev->iamthif_file_ext) {
1096 priv_write_cb = find_pthi_read_list_entry(dev, file);
1097 if ((priv_write_cb != NULL) &&
1098 (((currtime - priv_write_cb->read_time) >=
1099 IAMTHIF_READ_TIMER) ||
1100 (file_ext->reading_state == HECI_READ_COMPLETE))) {
1101 (*offset) = 0;
1102 list_del(&priv_write_cb->cb_list);
1103 heci_free_cb_private(priv_write_cb);
1104 priv_write_cb = NULL;
1105 }
1106 }
1107
1108 /* free entry used in read */
1109 if (file_ext->reading_state == HECI_READ_COMPLETE) {
1110 *offset = 0;
1111 priv_write_cb = find_read_list_entry(dev, file_ext);
1112 if (priv_write_cb != NULL) {
1113 list_del(&priv_write_cb->cb_list);
1114 heci_free_cb_private(priv_write_cb);
1115 priv_write_cb = NULL;
1116 spin_lock_bh(&file_ext->read_io_lock);
1117 file_ext->reading_state = HECI_IDLE;
1118 file_ext->read_cb = NULL;
1119 file_ext->read_pending = 0;
1120 spin_unlock_bh(&file_ext->read_io_lock);
1121 }
1122 } else if (file_ext->reading_state == HECI_IDLE &&
1123 file_ext->read_pending == 0)
1124 (*offset) = 0;
1125
1126 spin_unlock_bh(&dev->device_lock);
1127
1128 priv_write_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
1129 if (!priv_write_cb)
1130 return -ENOMEM;
1131
1132 priv_write_cb->file_object = file;
1133 priv_write_cb->file_private = file_ext;
1134 priv_write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
1135 if (!priv_write_cb->request_buffer.data) {
1136 kfree(priv_write_cb);
1137 return -ENOMEM;
1138 }
1139 DBG("length =%d\n", (int) length);
1140
1141 if (copy_from_user(priv_write_cb->request_buffer.data,
1142 ubuf, length)) {
1143 rets = -EFAULT;
1144 goto fail;
1145 }
1146
1147 spin_lock(&file_ext->file_lock);
1148 file_ext->sm_state = 0;
1149 if ((length == 4) &&
1150 ((memcmp(heci_wd_state_independence_msg[0],
1151 priv_write_cb->request_buffer.data, 4) == 0) ||
1152 (memcmp(heci_wd_state_independence_msg[1],
1153 priv_write_cb->request_buffer.data, 4) == 0) ||
1154 (memcmp(heci_wd_state_independence_msg[2],
1155 priv_write_cb->request_buffer.data, 4) == 0)))
1156 file_ext->sm_state |= HECI_WD_STATE_INDEPENDENCE_MSG_SENT;
1157 spin_unlock(&file_ext->file_lock);
1158
1159 INIT_LIST_HEAD(&priv_write_cb->cb_list);
1160 if (file_ext == &dev->iamthif_file_ext) {
1161 priv_write_cb->response_buffer.data =
1162 kmalloc(IAMTHIF_MTU, GFP_KERNEL);
1163 if (!priv_write_cb->response_buffer.data) {
1164 rets = -ENOMEM;
1165 goto fail;
1166 }
1167 spin_lock_bh(&dev->device_lock);
1168 if (dev->heci_state != HECI_ENABLED) {
1169 spin_unlock_bh(&dev->device_lock);
1170 rets = -ENODEV;
1171 goto fail;
1172 }
1173 for (i = 0; i < dev->num_heci_me_clients; i++) {
1174 if (dev->me_clients[i].client_id ==
1175 dev->iamthif_file_ext.me_client_id)
1176 break;
1177 }
1178
1179 BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
1180 if ((i == dev->num_heci_me_clients) ||
1181 (dev->me_clients[i].client_id !=
1182 dev->iamthif_file_ext.me_client_id)) {
1183
1184 spin_unlock_bh(&dev->device_lock);
1185 rets = -ENODEV;
1186 goto fail;
1187 } else if ((length > dev->me_clients[i].props.max_msg_length)
1188 || (length <= 0)) {
1189 spin_unlock_bh(&dev->device_lock);
1190 rets = -EMSGSIZE;
1191 goto fail;
1192 }
1193
1194
1195 priv_write_cb->response_buffer.size = IAMTHIF_MTU;
1196 priv_write_cb->major_file_operations = HECI_IOCTL;
1197 priv_write_cb->information = 0;
1198 priv_write_cb->request_buffer.size = length;
1199 if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTED) {
1200 spin_unlock_bh(&dev->device_lock);
1201 rets = -ENODEV;
1202 goto fail;
1203 }
1204
1205 if (!list_empty(&dev->pthi_cmd_list.heci_cb.cb_list)
1206 || dev->iamthif_state != HECI_IAMTHIF_IDLE) {
1207 DBG("pthi_state = %d\n", (int) dev->iamthif_state);
1208 DBG("add PTHI cb to pthi cmd waiting list\n");
1209 list_add_tail(&priv_write_cb->cb_list,
1210 &dev->pthi_cmd_list.heci_cb.cb_list);
1211 rets = length;
1212 } else {
1213 DBG("call pthi write\n");
1214 rets = pthi_write(dev, priv_write_cb);
1215
1216 if (rets != 0) {
1217 DBG("pthi write failed with status = %d\n",
1218 rets);
1219 spin_unlock_bh(&dev->device_lock);
1220 goto fail;
1221 }
1222 rets = length;
1223 }
1224 spin_unlock_bh(&dev->device_lock);
1225 return rets;
1226 }
1227
1228 priv_write_cb->major_file_operations = HECI_WRITE;
1229 /* make sure information is zero before we start */
1230
1231 priv_write_cb->information = 0;
1232 priv_write_cb->request_buffer.size = length;
1233
1234 spin_lock(&file_ext->write_io_lock);
1235 spin_lock_bh(&dev->device_lock);
1236 DBG("host client = %d, ME client = %d\n",
1237 file_ext->host_client_id, file_ext->me_client_id);
1238 if (file_ext->state != HECI_FILE_CONNECTED) {
1239 rets = -ENODEV;
1240 DBG("host client = %d, is not connected to ME client = %d",
1241 file_ext->host_client_id,
1242 file_ext->me_client_id);
1243 spin_unlock_bh(&dev->device_lock);
1244 goto unlock;
1245 }
1246 for (i = 0; i < dev->num_heci_me_clients; i++) {
1247 if (dev->me_clients[i].client_id ==
1248 file_ext->me_client_id)
1249 break;
1250 }
1251 BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
1252 if (i == dev->num_heci_me_clients) {
1253 rets = -ENODEV;
1254 spin_unlock_bh(&dev->device_lock);
1255 goto unlock;
1256 }
1257 if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
1258 rets = -EINVAL;
1259 spin_unlock_bh(&dev->device_lock);
1260 goto unlock;
1261 }
1262 priv_write_cb->file_private = file_ext;
1263
1264 if (flow_ctrl_creds(dev, file_ext) &&
1265 dev->host_buffer_is_empty) {
1266 spin_unlock_bh(&dev->device_lock);
1267 dev->host_buffer_is_empty = 0;
1268 if (length > ((((dev->host_hw_state & H_CBD) >> 24) *
1269 sizeof(__u32)) - sizeof(struct heci_msg_hdr))) {
1270
1271 heci_hdr.length =
1272 (((dev->host_hw_state & H_CBD) >> 24) *
1273 sizeof(__u32)) -
1274 sizeof(struct heci_msg_hdr);
1275 heci_hdr.msg_complete = 0;
1276 } else {
1277 heci_hdr.length = length;
1278 heci_hdr.msg_complete = 1;
1279 }
1280 heci_hdr.host_addr = file_ext->host_client_id;
1281 heci_hdr.me_addr = file_ext->me_client_id;
1282 heci_hdr.reserved = 0;
1283 DBG("call heci_write_message header=%08x.\n",
1284 *((__u32 *) &heci_hdr));
1285 spin_unlock(&file_ext->write_io_lock);
1286 /* protect heci low level write */
1287 spin_lock_bh(&dev->device_lock);
1288 if (!heci_write_message(dev, &heci_hdr,
1289 (unsigned char *) (priv_write_cb->request_buffer.data),
1290 heci_hdr.length)) {
1291
1292 spin_unlock_bh(&dev->device_lock);
1293 heci_free_cb_private(priv_write_cb);
1294 rets = -ENODEV;
1295 priv_write_cb->information = 0;
1296 return rets;
1297 }
1298 file_ext->writing_state = HECI_WRITING;
1299 priv_write_cb->information = heci_hdr.length;
1300 if (heci_hdr.msg_complete) {
1301 flow_ctrl_reduce(dev, file_ext);
1302 list_add_tail(&priv_write_cb->cb_list,
1303 &dev->write_waiting_list.heci_cb.cb_list);
1304 } else {
1305 list_add_tail(&priv_write_cb->cb_list,
1306 &dev->write_list.heci_cb.cb_list);
1307 }
1308 spin_unlock_bh(&dev->device_lock);
1309
1310 } else {
1311
1312 spin_unlock_bh(&dev->device_lock);
1313 priv_write_cb->information = 0;
1314 file_ext->writing_state = HECI_WRITING;
1315 spin_unlock(&file_ext->write_io_lock);
1316 list_add_tail(&priv_write_cb->cb_list,
1317 &dev->write_list.heci_cb.cb_list);
1318 }
1319 return length;
1320
1321unlock:
1322 spin_unlock(&file_ext->write_io_lock);
1323fail:
1324 heci_free_cb_private(priv_write_cb);
1325 return rets;
1326
1327}
1328
1329/**
1330 * heci_ioctl - the IOCTL function
1331 *
1332 * @inode: pointer to inode structure
1333 * @file: pointer to file structure
1334 * @cmd: ioctl command
1335 * @data: pointer to heci message structure
1336 *
1337 * returns 0 on success , <0 on error
1338 */
1339static int heci_ioctl(struct inode *inode, struct file *file,
1340 unsigned int cmd, unsigned long data)
1341{
1342 int rets = 0;
1343 int if_num = iminor(inode);
1344 struct heci_file_private *file_ext = file->private_data;
1345 /* in user space */
1346 struct heci_message_data __user *u_msg;
1347 struct heci_message_data k_msg; /* all in kernel on the stack */
1348 struct iamt_heci_device *dev;
1349
1350 if (!capable(CAP_SYS_ADMIN))
1351 return -EPERM;
1352
1353 if (!heci_device)
1354 return -ENODEV;
1355
1356 dev = pci_get_drvdata(heci_device);
1357 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
1358 return -ENODEV;
1359
1360 spin_lock_bh(&dev->device_lock);
1361 if (dev->heci_state != HECI_ENABLED) {
1362 spin_unlock_bh(&dev->device_lock);
1363 return -ENODEV;
1364 }
1365 spin_unlock_bh(&dev->device_lock);
1366
1367 /* first copy from user all data needed */
1368 u_msg = (struct heci_message_data __user *)data;
1369 if (copy_from_user(&k_msg, u_msg, sizeof(k_msg))) {
1370 DBG("first copy from user all data needed filled\n");
1371 return -EFAULT;
1372 }
1373 DBG("user message size is %d\n", k_msg.size);
1374
1375 switch (cmd) {
1376 case IOCTL_HECI_GET_VERSION:
1377 DBG(": IOCTL_HECI_GET_VERSION\n");
1378 rets = heci_ioctl_get_version(dev, if_num, u_msg, k_msg,
1379 file_ext);
1380 break;
1381
1382 case IOCTL_HECI_CONNECT_CLIENT:
1383 DBG(": IOCTL_HECI_CONNECT_CLIENT.\n");
1384 rets = heci_ioctl_connect_client(dev, if_num, u_msg, k_msg,
1385 file);
1386 break;
1387
1388 case IOCTL_HECI_WD:
1389 DBG(": IOCTL_HECI_WD.\n");
1390 rets = heci_ioctl_wd(dev, if_num, k_msg, file_ext);
1391 break;
1392
1393 case IOCTL_HECI_BYPASS_WD:
1394 DBG(": IOCTL_HECI_BYPASS_WD.\n");
1395 rets = heci_ioctl_bypass_wd(dev, if_num, k_msg, file_ext);
1396 break;
1397
1398 default:
1399 rets = -EINVAL;
1400 break;
1401 }
1402 return rets;
1403}
1404
1405/**
1406 * heci_poll - the poll function
1407 *
1408 * @file: pointer to file structure
1409 * @wait: pointer to poll_table structure
1410 *
1411 * returns poll mask
1412 */
1413static unsigned int heci_poll(struct file *file, poll_table *wait)
1414{
1415 int if_num = iminor(file->f_dentry->d_inode);
1416 unsigned int mask = 0;
1417 struct heci_file_private *file_ext = file->private_data;
1418 struct iamt_heci_device *dev;
1419
1420 if (!heci_device)
1421 return mask;
1422
1423 dev = pci_get_drvdata(heci_device);
1424
1425 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
1426 return mask;
1427
1428 spin_lock_bh(&dev->device_lock);
1429 if (dev->heci_state != HECI_ENABLED) {
1430 spin_unlock_bh(&dev->device_lock);
1431 return mask;
1432 }
1433 spin_unlock_bh(&dev->device_lock);
1434
1435 if (file_ext == &dev->iamthif_file_ext) {
1436 poll_wait(file, &dev->iamthif_file_ext.wait, wait);
1437 spin_lock(&dev->iamthif_file_ext.file_lock);
1438 if (dev->iamthif_state == HECI_IAMTHIF_READ_COMPLETE
1439 && dev->iamthif_file_object == file) {
1440 mask |= (POLLIN | POLLRDNORM);
1441 spin_lock_bh(&dev->device_lock);
1442 DBG("run next pthi cb\n");
1443 run_next_iamthif_cmd(dev);
1444 spin_unlock_bh(&dev->device_lock);
1445 }
1446 spin_unlock(&dev->iamthif_file_ext.file_lock);
1447
1448 } else{
1449 poll_wait(file, &file_ext->tx_wait, wait);
1450 spin_lock(&file_ext->write_io_lock);
1451 if (HECI_WRITE_COMPLETE == file_ext->writing_state)
1452 mask |= (POLLIN | POLLRDNORM);
1453
1454 spin_unlock(&file_ext->write_io_lock);
1455 }
1456
1457 return mask;
1458}
1459
1460#ifdef CONFIG_PM
1461static int heci_suspend(struct pci_dev *pdev, pm_message_t state)
1462{
1463 struct iamt_heci_device *dev = pci_get_drvdata(pdev);
1464 int err = 0;
1465
1466 spin_lock_bh(&dev->device_lock);
1467 if (dev->reinit_tsk != NULL) {
1468 kthread_stop(dev->reinit_tsk);
1469 dev->reinit_tsk = NULL;
1470 }
1471 spin_unlock_bh(&dev->device_lock);
1472
1473 /* Stop watchdog if exists */
1474 del_timer_sync(&dev->wd_timer);
1475 if (dev->wd_file_ext.state == HECI_FILE_CONNECTED
1476 && dev->wd_timeout) {
1477 spin_lock_bh(&dev->device_lock);
1478 g_sus_wd_timeout = dev->wd_timeout;
1479 dev->wd_timeout = 0;
1480 dev->wd_due_counter = 0;
1481 memcpy(dev->wd_data, heci_stop_wd_params,
1482 HECI_WD_PARAMS_SIZE);
1483 dev->stop = 1;
1484 if (dev->host_buffer_is_empty &&
1485 flow_ctrl_creds(dev, &dev->wd_file_ext)) {
1486 dev->host_buffer_is_empty = 0;
1487 if (!heci_send_wd(dev))
1488 DBG("send stop WD failed\n");
1489 else
1490 flow_ctrl_reduce(dev, &dev->wd_file_ext);
1491
1492 dev->wd_pending = 0;
1493 } else {
1494 dev->wd_pending = 1;
1495 }
1496 spin_unlock_bh(&dev->device_lock);
1497 dev->wd_stoped = 0;
1498
1499 err = wait_event_interruptible_timeout(dev->wait_stop_wd,
1500 (dev->wd_stoped),
1501 10 * HZ);
1502 if (!dev->wd_stoped)
1503 DBG("stop wd failed to complete.\n");
1504 else {
1505 DBG("stop wd complete %d.\n", err);
1506 err = 0;
1507 }
1508 }
1509 /* Set new heci state */
1510 spin_lock_bh(&dev->device_lock);
1511 if (dev->heci_state == HECI_ENABLED ||
1512 dev->heci_state == HECI_RECOVERING_FROM_RESET) {
1513 dev->heci_state = HECI_POWER_DOWN;
1514 heci_reset(dev, 0);
1515 }
1516 spin_unlock_bh(&dev->device_lock);
1517
1518 pci_save_state(pdev);
1519
1520 pci_disable_device(pdev);
1521 free_irq(pdev->irq, dev);
1522
1523 pci_set_power_state(pdev, PCI_D3hot);
1524
1525 return err;
1526}
1527
1528static int heci_resume(struct pci_dev *pdev)
1529{
1530 struct iamt_heci_device *dev;
1531 int err = 0;
1532
1533 pci_set_power_state(pdev, PCI_D0);
1534 pci_restore_state(pdev);
1535
1536 dev = pci_get_drvdata(pdev);
1537 if (!dev)
1538 return -ENODEV;
1539
1540 /* request and enable interrupt */
1541 err = request_irq(pdev->irq, heci_isr_interrupt, IRQF_SHARED,
1542 heci_driver_name, dev);
1543 if (err) {
1544 printk(KERN_ERR "heci: Request_irq failure. irq = %d \n",
1545 pdev->irq);
1546 return err;
1547 }
1548
1549 spin_lock_bh(&dev->device_lock);
1550 dev->heci_state = HECI_POWER_UP;
1551 heci_reset(dev, 1);
1552 spin_unlock_bh(&dev->device_lock);
1553
1554 /* Start watchdog if stopped in suspend */
1555 if (g_sus_wd_timeout != 0) {
1556 dev->wd_timeout = g_sus_wd_timeout;
1557
1558 memcpy(dev->wd_data, heci_start_wd_params,
1559 HECI_WD_PARAMS_SIZE);
1560 memcpy(dev->wd_data + HECI_WD_PARAMS_SIZE,
1561 &dev->wd_timeout, sizeof(__u16));
1562 dev->wd_due_counter = 1;
1563
1564 if (dev->wd_timeout)
1565 mod_timer(&dev->wd_timer, jiffies);
1566
1567 g_sus_wd_timeout = 0;
1568 }
1569 return err;
1570}
1571#endif
1572
1573MODULE_AUTHOR("Intel Corporation");
1574MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
1575MODULE_LICENSE("Dual BSD/GPL");
1576MODULE_VERSION(HECI_DRIVER_VERSION);
diff --git a/drivers/staging/heci/heci_version.h b/drivers/staging/heci/heci_version.h
deleted file mode 100644
index 3007aa6e17d..00000000000
--- a/drivers/staging/heci/heci_version.h
+++ /dev/null
@@ -1,54 +0,0 @@
1/*
2 * Part of Intel(R) Manageability Engine Interface Linux driver
3 *
4 * Copyright (c) 2003 - 2008 Intel Corp.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * substantially similar to the "NO WARRANTY" disclaimer below
15 * ("Disclaimer") and any redistribution must be conditioned upon
16 * including a substantially similar Disclaimer requirement for further
17 * binary redistribution.
18 * 3. Neither the names of the above-listed copyright holders nor the names
19 * of any contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * Alternatively, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2 as published by the Free
24 * Software Foundation.
25 *
26 * NO WARRANTY
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGES.
38 *
39 */
40
41#ifndef HECI_VERSION_H
42#define HECI_VERSION_H
43
44#define MAJOR_VERSION 5
45#define MINOR_VERSION 0
46#define QUICK_FIX_NUMBER 0
47#define VER_BUILD 31
48
49#define HECI_DRV_VER1 __stringify(MAJOR_VERSION) "." __stringify(MINOR_VERSION)
50#define HECI_DRV_VER2 __stringify(QUICK_FIX_NUMBER) "." __stringify(VER_BUILD)
51
52#define HECI_DRIVER_VERSION HECI_DRV_VER1 "." HECI_DRV_VER2
53
54#endif
diff --git a/drivers/staging/heci/interrupt.c b/drivers/staging/heci/interrupt.c
deleted file mode 100644
index 2a3a01a62bb..00000000000
--- a/drivers/staging/heci/interrupt.c
+++ /dev/null
@@ -1,1555 +0,0 @@
1/*
2 * Part of Intel(R) Manageability Engine Interface Linux driver
3 *
4 * Copyright (c) 2003 - 2008 Intel Corp.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * substantially similar to the "NO WARRANTY" disclaimer below
15 * ("Disclaimer") and any redistribution must be conditioned upon
16 * including a substantially similar Disclaimer requirement for further
17 * binary redistribution.
18 * 3. Neither the names of the above-listed copyright holders nor the names
19 * of any contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * Alternatively, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2 as published by the Free
24 * Software Foundation.
25 *
26 * NO WARRANTY
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGES.
38 *
39 */
40
41#include <linux/kthread.h>
42
43#include "heci.h"
44#include "heci_interface.h"
45
46/*
47 * interrupt function prototypes
48 */
49static void heci_bh_handler(struct work_struct *work);
50static int heci_bh_read_handler(struct io_heci_list *complete_list,
51 struct iamt_heci_device *dev,
52 __s32 *slots);
53static int heci_bh_write_handler(struct io_heci_list *complete_list,
54 struct iamt_heci_device *dev,
55 __s32 *slots);
56static void heci_bh_read_bus_message(struct iamt_heci_device *dev,
57 struct heci_msg_hdr *heci_hdr);
58static int heci_bh_read_pthi_message(struct io_heci_list *complete_list,
59 struct iamt_heci_device *dev,
60 struct heci_msg_hdr *heci_hdr);
61static int heci_bh_read_client_message(struct io_heci_list *complete_list,
62 struct iamt_heci_device *dev,
63 struct heci_msg_hdr *heci_hdr);
64static void heci_client_connect_response(struct iamt_heci_device *dev,
65 struct hbm_client_connect_response *connect_res);
66static void heci_client_disconnect_response(struct iamt_heci_device *dev,
67 struct hbm_client_connect_response *disconnect_res);
68static void heci_client_flow_control_response(struct iamt_heci_device *dev,
69 struct hbm_flow_control *flow_control);
70static void heci_client_disconnect_request(struct iamt_heci_device *dev,
71 struct hbm_client_disconnect_request *disconnect_req);
72
73
74/**
75 * heci_isr_interrupt - The ISR of the HECI device
76 *
77 * @irq: The irq number
78 * @dev_id: pointer to the device structure
79 *
80 * returns irqreturn_t
81 */
82irqreturn_t heci_isr_interrupt(int irq, void *dev_id)
83{
84 int err;
85 struct iamt_heci_device *dev = (struct iamt_heci_device *) dev_id;
86
87 dev->host_hw_state = read_heci_register(dev, H_CSR);
88
89 if ((dev->host_hw_state & H_IS) != H_IS)
90 return IRQ_NONE;
91
92 /* disable interrupts */
93 heci_csr_disable_interrupts(dev);
94
95 /* clear H_IS bit in H_CSR */
96 heci_csr_clear_his(dev);
97
98 /*
99 * Our device interrupted, schedule work the heci_bh_handler
100 * to handle the interrupt processing. This needs to be a
101 * workqueue item since the handler can sleep.
102 */
103 PREPARE_WORK(&dev->work, heci_bh_handler);
104 DBG("schedule work the heci_bh_handler.\n");
105 err = schedule_work(&dev->work);
106 if (!err)
107 DBG("heci_bh_handler was already on the workqueue.\n");
108 return IRQ_HANDLED;
109}
110
111/**
112 * _heci_cmpl - process completed operation.
113 *
114 * @file_ext: private data of the file object.
115 * @priv_cb_pos: callback block.
116 */
117static void _heci_cmpl(struct heci_file_private *file_ext,
118 struct heci_cb_private *priv_cb_pos)
119{
120 if (priv_cb_pos->major_file_operations == HECI_WRITE) {
121 heci_free_cb_private(priv_cb_pos);
122 DBG("completing write call back.\n");
123 file_ext->writing_state = HECI_WRITE_COMPLETE;
124 if ((&file_ext->tx_wait) &&
125 waitqueue_active(&file_ext->tx_wait))
126 wake_up_interruptible(&file_ext->tx_wait);
127
128 } else if (priv_cb_pos->major_file_operations == HECI_READ
129 && HECI_READING == file_ext->reading_state) {
130 DBG("completing read call back information= %lu\n",
131 priv_cb_pos->information);
132 file_ext->reading_state = HECI_READ_COMPLETE;
133 if ((&file_ext->rx_wait) &&
134 waitqueue_active(&file_ext->rx_wait))
135 wake_up_interruptible(&file_ext->rx_wait);
136
137 }
138}
139
140/**
141 * _heci_cmpl_iamthif - process completed iamthif operation.
142 *
143 * @dev: Device object for our driver.
144 * @priv_cb_pos: callback block.
145 */
146static void _heci_cmpl_iamthif(struct iamt_heci_device *dev,
147 struct heci_cb_private *priv_cb_pos)
148{
149 if (dev->iamthif_canceled != 1) {
150 dev->iamthif_state = HECI_IAMTHIF_READ_COMPLETE;
151 dev->iamthif_stall_timer = 0;
152 memcpy(priv_cb_pos->response_buffer.data,
153 dev->iamthif_msg_buf,
154 dev->iamthif_msg_buf_index);
155 list_add_tail(&priv_cb_pos->cb_list,
156 &dev->pthi_read_complete_list.heci_cb.cb_list);
157 DBG("pthi read completed.\n");
158 } else {
159 run_next_iamthif_cmd(dev);
160 }
161 if (&dev->iamthif_file_ext.wait) {
162 DBG("completing pthi call back.\n");
163 wake_up_interruptible(&dev->iamthif_file_ext.wait);
164 }
165}
166/**
167 * heci_bh_handler - function called after ISR to handle the interrupt
168 * processing.
169 *
170 * @work: pointer to the work structure
171 *
172 * NOTE: This function is called by schedule work
173 */
174static void heci_bh_handler(struct work_struct *work)
175{
176 struct iamt_heci_device *dev =
177 container_of(work, struct iamt_heci_device, work);
178 struct io_heci_list complete_list;
179 __s32 slots;
180 int rets;
181 struct heci_cb_private *cb_pos = NULL, *cb_next = NULL;
182 struct heci_file_private *file_ext;
183 int bus_message_received = 0;
184 struct task_struct *tsk;
185
186 DBG("function called after ISR to handle the interrupt processing.\n");
187 /* initialize our complete list */
188 spin_lock_bh(&dev->device_lock);
189 heci_initialize_list(&complete_list, dev);
190 dev->host_hw_state = read_heci_register(dev, H_CSR);
191 dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
192
193 /* check if ME wants a reset */
194 if (((dev->me_hw_state & ME_RDY_HRA) == 0)
195 && (dev->heci_state != HECI_RESETING)
196 && (dev->heci_state != HECI_INITIALIZING)) {
197 DBG("FW not ready.\n");
198 heci_reset(dev, 1);
199 spin_unlock_bh(&dev->device_lock);
200 return;
201 }
202
203 /* check if we need to start the dev */
204 if ((dev->host_hw_state & H_RDY) == 0) {
205 if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) {
206 DBG("we need to start the dev.\n");
207 dev->host_hw_state |= (H_IE | H_IG | H_RDY);
208 heci_set_csr_register(dev);
209 if (dev->heci_state == HECI_INITIALIZING) {
210 dev->recvd_msg = 1;
211 spin_unlock_bh(&dev->device_lock);
212 wake_up_interruptible(&dev->wait_recvd_msg);
213 return;
214
215 } else {
216 spin_unlock_bh(&dev->device_lock);
217 tsk = kthread_run(heci_task_initialize_clients,
218 dev, "heci_reinit");
219 if (IS_ERR(tsk)) {
220 int rc = PTR_ERR(tsk);
221 printk(KERN_WARNING "heci: Unable to"
222 "start the heci thread: %d\n", rc);
223 }
224 return;
225 }
226 } else {
227 DBG("enable interrupt FW not ready.\n");
228 heci_csr_enable_interrupts(dev);
229 spin_unlock_bh(&dev->device_lock);
230 return;
231 }
232 }
233 /* check slots avalable for reading */
234 slots = count_full_read_slots(dev);
235 DBG("slots =%08x extra_write_index =%08x.\n",
236 slots, dev->extra_write_index);
237 while ((slots > 0) && (!dev->extra_write_index)) {
238 DBG("slots =%08x extra_write_index =%08x.\n", slots,
239 dev->extra_write_index);
240 DBG("call heci_bh_read_handler.\n");
241 rets = heci_bh_read_handler(&complete_list, dev, &slots);
242 if (rets != 0)
243 goto end;
244 }
245 rets = heci_bh_write_handler(&complete_list, dev, &slots);
246end:
247 DBG("end of bottom half function.\n");
248 dev->host_hw_state = read_heci_register(dev, H_CSR);
249 dev->host_buffer_is_empty = host_buffer_is_empty(dev);
250
251 if ((dev->host_hw_state & H_IS) == H_IS) {
252 /* acknowledge interrupt and disable interrupts */
253 heci_csr_disable_interrupts(dev);
254
255 /* clear H_IS bit in H_CSR */
256 heci_csr_clear_his(dev);
257
258 PREPARE_WORK(&dev->work, heci_bh_handler);
259 DBG("schedule work the heci_bh_handler.\n");
260 rets = schedule_work(&dev->work);
261 if (!rets)
262 DBG("heci_bh_handler was already queued.\n");
263 } else {
264 heci_csr_enable_interrupts(dev);
265 }
266
267 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
268 DBG("received waiting bus message\n");
269 bus_message_received = 1;
270 }
271 spin_unlock_bh(&dev->device_lock);
272 if (bus_message_received) {
273 DBG("wake up dev->wait_recvd_msg\n");
274 wake_up_interruptible(&dev->wait_recvd_msg);
275 bus_message_received = 0;
276 }
277 if ((complete_list.status != 0)
278 || list_empty(&complete_list.heci_cb.cb_list))
279 return;
280
281
282 list_for_each_entry_safe(cb_pos, cb_next,
283 &complete_list.heci_cb.cb_list, cb_list) {
284 file_ext = (struct heci_file_private *)cb_pos->file_private;
285 list_del(&cb_pos->cb_list);
286 if (file_ext != NULL) {
287 if (file_ext != &dev->iamthif_file_ext) {
288 DBG("completing call back.\n");
289 _heci_cmpl(file_ext, cb_pos);
290 cb_pos = NULL;
291 } else if (file_ext == &dev->iamthif_file_ext) {
292 _heci_cmpl_iamthif(dev, cb_pos);
293 }
294 }
295 }
296}
297
298
299/**
300 * heci_bh_read_handler - bottom half read routine after ISR to
301 * handle the read processing.
302 *
303 * @cmpl_list: An instance of our list structure
304 * @dev: Device object for our driver
305 * @slots: slots to read.
306 *
307 * returns 0 on success, <0 on failure.
308 */
309static int heci_bh_read_handler(struct io_heci_list *cmpl_list,
310 struct iamt_heci_device *dev,
311 __s32 *slots)
312{
313 struct heci_msg_hdr *heci_hdr;
314 int ret = 0;
315 struct heci_file_private *file_pos = NULL;
316 struct heci_file_private *file_next = NULL;
317
318 if (!dev->rd_msg_hdr) {
319 dev->rd_msg_hdr = read_heci_register(dev, ME_CB_RW);
320 DBG("slots=%08x.\n", *slots);
321 (*slots)--;
322 DBG("slots=%08x.\n", *slots);
323 }
324 heci_hdr = (struct heci_msg_hdr *) &dev->rd_msg_hdr;
325 DBG("heci_hdr->length =%d\n", heci_hdr->length);
326
327 if ((heci_hdr->reserved) || !(dev->rd_msg_hdr)) {
328 DBG("corrupted message header.\n");
329 ret = -ECORRUPTED_MESSAGE_HEADER;
330 goto end;
331 }
332
333 if ((heci_hdr->host_addr) || (heci_hdr->me_addr)) {
334 list_for_each_entry_safe(file_pos, file_next,
335 &dev->file_list, link) {
336 DBG("list_for_each_entry_safe read host"
337 " client = %d, ME client = %d\n",
338 file_pos->host_client_id,
339 file_pos->me_client_id);
340 if ((file_pos->host_client_id == heci_hdr->host_addr)
341 && (file_pos->me_client_id == heci_hdr->me_addr))
342 break;
343 }
344
345 if (&file_pos->link == &dev->file_list) {
346 DBG("corrupted message header\n");
347 ret = -ECORRUPTED_MESSAGE_HEADER;
348 goto end;
349 }
350 }
351 if (((*slots) * sizeof(__u32)) < heci_hdr->length) {
352 DBG("we can't read the message slots=%08x.\n", *slots);
353 /* we can't read the message */
354 ret = -ERANGE;
355 goto end;
356 }
357
358 /* decide where to read the message too */
359 if (!heci_hdr->host_addr) {
360 DBG("call heci_bh_read_bus_message.\n");
361 heci_bh_read_bus_message(dev, heci_hdr);
362 DBG("end heci_bh_read_bus_message.\n");
363 } else if ((heci_hdr->host_addr == dev->iamthif_file_ext.host_client_id)
364 && (HECI_FILE_CONNECTED == dev->iamthif_file_ext.state)
365 && (dev->iamthif_state == HECI_IAMTHIF_READING)) {
366 DBG("call heci_bh_read_iamthif_message.\n");
367 DBG("heci_hdr->length =%d\n", heci_hdr->length);
368 ret = heci_bh_read_pthi_message(cmpl_list, dev, heci_hdr);
369 if (ret != 0)
370 goto end;
371
372 } else {
373 DBG("call heci_bh_read_client_message.\n");
374 ret = heci_bh_read_client_message(cmpl_list, dev, heci_hdr);
375 if (ret != 0)
376 goto end;
377
378 }
379
380 /* reset the number of slots and header */
381 *slots = count_full_read_slots(dev);
382 dev->rd_msg_hdr = 0;
383
384 if (*slots == -ESLOTS_OVERFLOW) {
385 /* overflow - reset */
386 DBG("reseting due to slots overflow.\n");
387 /* set the event since message has been read */
388 ret = -ERANGE;
389 goto end;
390 }
391end:
392 return ret;
393}
394
395
396/**
397 * heci_bh_read_bus_message - bottom half read routine after ISR to
398 * handle the read bus message cmd processing.
399 *
400 * @dev: Device object for our driver
401 * @heci_hdr: header of bus message
402 */
403static void heci_bh_read_bus_message(struct iamt_heci_device *dev,
404 struct heci_msg_hdr *heci_hdr)
405{
406 struct heci_bus_message *heci_msg;
407 struct hbm_host_version_response *version_res;
408 struct hbm_client_connect_response *connect_res;
409 struct hbm_client_connect_response *disconnect_res;
410 struct hbm_flow_control *flow_control;
411 struct hbm_props_response *props_res;
412 struct hbm_host_enum_response *enum_res;
413 struct hbm_client_disconnect_request *disconnect_req;
414 struct hbm_host_stop_request *h_stop_req;
415 int i;
416 unsigned char *buffer;
417
418 /* read the message to our buffer */
419 buffer = (unsigned char *) dev->rd_msg_buf;
420 BUG_ON(heci_hdr->length >= sizeof(dev->rd_msg_buf));
421 heci_read_slots(dev, buffer, heci_hdr->length);
422 heci_msg = (struct heci_bus_message *) buffer;
423
424 switch (*(__u8 *) heci_msg) {
425 case HOST_START_RES_CMD:
426 version_res = (struct hbm_host_version_response *) heci_msg;
427 if (version_res->host_version_supported) {
428 dev->version.major_version = HBM_MAJOR_VERSION;
429 dev->version.minor_version = HBM_MINOR_VERSION;
430 } else {
431 dev->version = version_res->me_max_version;
432 }
433 dev->recvd_msg = 1;
434 DBG("host start response message received.\n");
435 break;
436
437 case CLIENT_CONNECT_RES_CMD:
438 connect_res =
439 (struct hbm_client_connect_response *) heci_msg;
440 heci_client_connect_response(dev, connect_res);
441 DBG("client connect response message received.\n");
442 wake_up(&dev->wait_recvd_msg);
443 break;
444
445 case CLIENT_DISCONNECT_RES_CMD:
446 disconnect_res =
447 (struct hbm_client_connect_response *) heci_msg;
448 heci_client_disconnect_response(dev, disconnect_res);
449 DBG("client disconnect response message received.\n");
450 wake_up(&dev->wait_recvd_msg);
451 break;
452
453 case HECI_FLOW_CONTROL_CMD:
454 flow_control = (struct hbm_flow_control *) heci_msg;
455 heci_client_flow_control_response(dev, flow_control);
456 DBG("client flow control response message received.\n");
457 break;
458
459 case HOST_CLIENT_PROPERTEIS_RES_CMD:
460 props_res = (struct hbm_props_response *) heci_msg;
461 if (props_res->status != 0) {
462 BUG();
463 break;
464 }
465 for (i = 0; i < dev->num_heci_me_clients; i++) {
466 if (dev->me_clients[i].client_id ==
467 props_res->address) {
468 dev->me_clients[i].props =
469 props_res->client_properties;
470 break;
471 }
472
473 }
474 dev->recvd_msg = 1;
475 break;
476
477 case HOST_ENUM_RES_CMD:
478 enum_res = (struct hbm_host_enum_response *) heci_msg;
479 memcpy(dev->heci_me_clients, enum_res->valid_addresses, 32);
480 dev->recvd_msg = 1;
481 break;
482
483 case HOST_STOP_RES_CMD:
484 dev->heci_state = HECI_DISABLED;
485 DBG("reseting because of FW stop response.\n");
486 heci_reset(dev, 1);
487 break;
488
489 case CLIENT_DISCONNECT_REQ_CMD:
490 /* search for client */
491 disconnect_req =
492 (struct hbm_client_disconnect_request *) heci_msg;
493 heci_client_disconnect_request(dev, disconnect_req);
494 break;
495
496 case ME_STOP_REQ_CMD:
497 /* prepare stop request */
498 heci_hdr = (struct heci_msg_hdr *) &dev->ext_msg_buf[0];
499 heci_hdr->host_addr = 0;
500 heci_hdr->me_addr = 0;
501 heci_hdr->length = sizeof(struct hbm_host_stop_request);
502 heci_hdr->msg_complete = 1;
503 heci_hdr->reserved = 0;
504 h_stop_req =
505 (struct hbm_host_stop_request *) &dev->ext_msg_buf[1];
506 memset(h_stop_req, 0, sizeof(struct hbm_host_stop_request));
507 h_stop_req->cmd.cmd = HOST_STOP_REQ_CMD;
508 h_stop_req->reason = DRIVER_STOP_REQUEST;
509 h_stop_req->reserved[0] = 0;
510 h_stop_req->reserved[1] = 0;
511 dev->extra_write_index = 2;
512 break;
513
514 default:
515 BUG();
516 break;
517
518 }
519}
520
521/**
522 * heci_bh_read_pthi_message - bottom half read routine after ISR to
523 * handle the read pthi message data processing.
524 *
525 * @complete_list: An instance of our list structure
526 * @dev: Device object for our driver
527 * @heci_hdr: header of pthi message
528 *
529 * returns 0 on success, <0 on failure.
530 */
531static int heci_bh_read_pthi_message(struct io_heci_list *complete_list,
532 struct iamt_heci_device *dev,
533 struct heci_msg_hdr *heci_hdr)
534{
535 struct heci_file_private *file_ext;
536 struct heci_cb_private *priv_cb;
537 unsigned char *buffer;
538
539 BUG_ON(heci_hdr->me_addr != dev->iamthif_file_ext.me_client_id);
540 BUG_ON(dev->iamthif_state != HECI_IAMTHIF_READING);
541
542 buffer = (unsigned char *) (dev->iamthif_msg_buf +
543 dev->iamthif_msg_buf_index);
544 BUG_ON(sizeof(dev->iamthif_msg_buf) <
545 (dev->iamthif_msg_buf_index + heci_hdr->length));
546
547 heci_read_slots(dev, buffer, heci_hdr->length);
548
549 dev->iamthif_msg_buf_index += heci_hdr->length;
550
551 if (!(heci_hdr->msg_complete))
552 return 0;
553
554 DBG("pthi_message_buffer_index=%d\n", heci_hdr->length);
555 DBG("completed pthi read.\n ");
556 if (!dev->iamthif_current_cb)
557 return -ENODEV;
558
559 priv_cb = dev->iamthif_current_cb;
560 dev->iamthif_current_cb = NULL;
561
562 file_ext = (struct heci_file_private *)priv_cb->file_private;
563 if (!file_ext)
564 return -ENODEV;
565
566 dev->iamthif_stall_timer = 0;
567 priv_cb->information = dev->iamthif_msg_buf_index;
568 priv_cb->read_time = get_seconds();
569 if ((dev->iamthif_ioctl) && (file_ext == &dev->iamthif_file_ext)) {
570 /* found the iamthif cb */
571 DBG("complete the pthi read cb.\n ");
572 if (&dev->iamthif_file_ext) {
573 DBG("add the pthi read cb to complete.\n ");
574 list_add_tail(&priv_cb->cb_list,
575 &complete_list->heci_cb.cb_list);
576 }
577 }
578 return 0;
579}
580
581/**
582 * _heci_bh_state_ok - check if heci header matches file private data
583 *
584 * @file_ext: private data of the file object
585 * @heci_hdr: header of heci client message
586 *
587 * returns !=0 if matches, 0 if no match.
588 */
589static int _heci_bh_state_ok(struct heci_file_private *file_ext,
590 struct heci_msg_hdr *heci_hdr)
591{
592 return ((file_ext->host_client_id == heci_hdr->host_addr)
593 && (file_ext->me_client_id == heci_hdr->me_addr)
594 && (file_ext->state == HECI_FILE_CONNECTED)
595 && (HECI_READ_COMPLETE != file_ext->reading_state));
596}
597
598/**
599 * heci_bh_read_client_message - bottom half read routine after ISR to
600 * handle the read heci client message data processing.
601 *
602 * @complete_list: An instance of our list structure
603 * @dev: Device object for our driver
604 * @heci_hdr: header of heci client message
605 *
606 * returns 0 on success, <0 on failure.
607 */
608static int heci_bh_read_client_message(struct io_heci_list *complete_list,
609 struct iamt_heci_device *dev,
610 struct heci_msg_hdr *heci_hdr)
611{
612 struct heci_file_private *file_ext;
613 struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL;
614 unsigned char *buffer = NULL;
615
616 DBG("start client msg\n");
617 if (!((dev->read_list.status == 0) &&
618 !list_empty(&dev->read_list.heci_cb.cb_list)))
619 goto quit;
620
621 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
622 &dev->read_list.heci_cb.cb_list, cb_list) {
623 file_ext = (struct heci_file_private *)
624 priv_cb_pos->file_private;
625 if ((file_ext != NULL) &&
626 (_heci_bh_state_ok(file_ext, heci_hdr))) {
627 spin_lock_bh(&file_ext->read_io_lock);
628 file_ext->reading_state = HECI_READING;
629 buffer = (unsigned char *)
630 (priv_cb_pos->response_buffer.data +
631 priv_cb_pos->information);
632 BUG_ON(priv_cb_pos->response_buffer.size <
633 heci_hdr->length +
634 priv_cb_pos->information);
635
636 if (priv_cb_pos->response_buffer.size <
637 heci_hdr->length +
638 priv_cb_pos->information) {
639 DBG("message overflow.\n");
640 list_del(&priv_cb_pos->cb_list);
641 spin_unlock_bh(&file_ext->read_io_lock);
642 return -ENOMEM;
643 }
644 if (buffer) {
645 heci_read_slots(dev, buffer,
646 heci_hdr->length);
647 }
648 priv_cb_pos->information += heci_hdr->length;
649 if (heci_hdr->msg_complete) {
650 file_ext->status = 0;
651 list_del(&priv_cb_pos->cb_list);
652 spin_unlock_bh(&file_ext->read_io_lock);
653 DBG("completed read host client = %d,"
654 "ME client = %d, "
655 "data length = %lu\n",
656 file_ext->host_client_id,
657 file_ext->me_client_id,
658 priv_cb_pos->information);
659
660 *(priv_cb_pos->response_buffer.data +
661 priv_cb_pos->information) = '\0';
662 DBG("priv_cb_pos->res_buffer - %s\n",
663 priv_cb_pos->response_buffer.data);
664 list_add_tail(&priv_cb_pos->cb_list,
665 &complete_list->heci_cb.cb_list);
666 } else {
667 spin_unlock_bh(&file_ext->read_io_lock);
668 }
669
670 break;
671 }
672
673 }
674
675quit:
676 DBG("message read\n");
677 if (!buffer) {
678 heci_read_slots(dev, (unsigned char *) dev->rd_msg_buf,
679 heci_hdr->length);
680 DBG("discarding message, header=%08x.\n",
681 *(__u32 *) dev->rd_msg_buf);
682 }
683
684 return 0;
685}
686
687/**
688 * _heci_bh_iamthif_read - prepare to read iamthif data.
689 *
690 * @dev: Device object for our driver.
691 * @slots: free slots.
692 *
693 * returns 0, OK; otherwise, error.
694 */
695static int _heci_bh_iamthif_read(struct iamt_heci_device *dev, __s32 *slots)
696{
697
698 if (((*slots) * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr)
699 + sizeof(struct hbm_flow_control))) {
700 *slots -= (sizeof(struct heci_msg_hdr) +
701 sizeof(struct hbm_flow_control) + 3) / 4;
702 if (!heci_send_flow_control(dev, &dev->iamthif_file_ext)) {
703 DBG("iamthif flow control failed\n");
704 } else {
705 DBG("iamthif flow control success\n");
706 dev->iamthif_state = HECI_IAMTHIF_READING;
707 dev->iamthif_flow_control_pending = 0;
708 dev->iamthif_msg_buf_index = 0;
709 dev->iamthif_msg_buf_size = 0;
710 dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
711 dev->host_buffer_is_empty = host_buffer_is_empty(dev);
712 }
713 return 0;
714 } else {
715 return -ECOMPLETE_MESSAGE;
716 }
717}
718
719/**
720 * _heci_bh_close - process close related operation.
721 *
722 * @dev: Device object for our driver.
723 * @slots: free slots.
724 * @priv_cb_pos: callback block.
725 * @file_ext: private data of the file object.
726 * @cmpl_list: complete list.
727 *
728 * returns 0, OK; otherwise, error.
729 */
730static int _heci_bh_close(struct iamt_heci_device *dev, __s32 *slots,
731 struct heci_cb_private *priv_cb_pos,
732 struct heci_file_private *file_ext,
733 struct io_heci_list *cmpl_list)
734{
735 if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) +
736 sizeof(struct hbm_client_disconnect_request))) {
737 *slots -= (sizeof(struct heci_msg_hdr) +
738 sizeof(struct hbm_client_disconnect_request) + 3) / 4;
739
740 if (!heci_disconnect(dev, file_ext)) {
741 file_ext->status = 0;
742 priv_cb_pos->information = 0;
743 list_move_tail(&priv_cb_pos->cb_list,
744 &cmpl_list->heci_cb.cb_list);
745 return -ECOMPLETE_MESSAGE;
746 } else {
747 file_ext->state = HECI_FILE_DISCONNECTING;
748 file_ext->status = 0;
749 priv_cb_pos->information = 0;
750 list_move_tail(&priv_cb_pos->cb_list,
751 &dev->ctrl_rd_list.heci_cb.cb_list);
752 file_ext->timer_count = HECI_CONNECT_TIMEOUT;
753 }
754 } else {
755 /* return the cancel routine */
756 return -ECORRUPTED_MESSAGE_HEADER;
757 }
758
759 return 0;
760}
761
762/**
763 * _heci_hb_close - process read related operation.
764 *
765 * @dev: Device object for our driver.
766 * @slots: free slots.
767 * @priv_cb_pos: callback block.
768 * @file_ext: private data of the file object.
769 * @cmpl_list: complete list.
770 *
771 * returns 0, OK; otherwise, error.
772 */
773static int _heci_bh_read(struct iamt_heci_device *dev, __s32 *slots,
774 struct heci_cb_private *priv_cb_pos,
775 struct heci_file_private *file_ext,
776 struct io_heci_list *cmpl_list)
777{
778 if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) +
779 sizeof(struct hbm_flow_control))) {
780 *slots -= (sizeof(struct heci_msg_hdr) +
781 sizeof(struct hbm_flow_control) + 3) / 4;
782 if (!heci_send_flow_control(dev, file_ext)) {
783 file_ext->status = -ENODEV;
784 priv_cb_pos->information = 0;
785 list_move_tail(&priv_cb_pos->cb_list,
786 &cmpl_list->heci_cb.cb_list);
787 return -ENODEV;
788 } else {
789 list_move_tail(&priv_cb_pos->cb_list,
790 &dev->read_list.heci_cb.cb_list);
791 }
792 } else {
793 /* return the cancel routine */
794 list_del(&priv_cb_pos->cb_list);
795 return -ECORRUPTED_MESSAGE_HEADER;
796 }
797
798 return 0;
799}
800
801
802/**
803 * _heci_bh_ioctl - process ioctl related operation.
804 *
805 * @dev: Device object for our driver.
806 * @slots: free slots.
807 * @priv_cb_pos: callback block.
808 * @file_ext: private data of the file object.
809 * @cmpl_list: complete list.
810 *
811 * returns 0, OK; otherwise, error.
812 */
813static int _heci_bh_ioctl(struct iamt_heci_device *dev, __s32 *slots,
814 struct heci_cb_private *priv_cb_pos,
815 struct heci_file_private *file_ext,
816 struct io_heci_list *cmpl_list)
817{
818 if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) +
819 sizeof(struct hbm_client_connect_request))) {
820 file_ext->state = HECI_FILE_CONNECTING;
821 *slots -= (sizeof(struct heci_msg_hdr) +
822 sizeof(struct hbm_client_connect_request) + 3) / 4;
823 if (!heci_connect(dev, file_ext)) {
824 file_ext->status = -ENODEV;
825 priv_cb_pos->information = 0;
826 list_del(&priv_cb_pos->cb_list);
827 return -ENODEV;
828 } else {
829 list_move_tail(&priv_cb_pos->cb_list,
830 &dev->ctrl_rd_list.heci_cb.cb_list);
831 file_ext->timer_count = HECI_CONNECT_TIMEOUT;
832 }
833 } else {
834 /* return the cancel routine */
835 list_del(&priv_cb_pos->cb_list);
836 return -ECORRUPTED_MESSAGE_HEADER;
837 }
838
839 return 0;
840}
841
842/**
843 * _heci_bh_cmpl - process completed and no-iamthif operation.
844 *
845 * @dev: Device object for our driver.
846 * @slots: free slots.
847 * @priv_cb_pos: callback block.
848 * @file_ext: private data of the file object.
849 * @cmpl_list: complete list.
850 *
851 * returns 0, OK; otherwise, error.
852 */
853static int _heci_bh_cmpl(struct iamt_heci_device *dev, __s32 *slots,
854 struct heci_cb_private *priv_cb_pos,
855 struct heci_file_private *file_ext,
856 struct io_heci_list *cmpl_list)
857{
858 struct heci_msg_hdr *heci_hdr;
859
860 if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) +
861 (priv_cb_pos->request_buffer.size -
862 priv_cb_pos->information))) {
863 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
864 heci_hdr->host_addr = file_ext->host_client_id;
865 heci_hdr->me_addr = file_ext->me_client_id;
866 heci_hdr->length = ((priv_cb_pos->request_buffer.size) -
867 (priv_cb_pos->information));
868 heci_hdr->msg_complete = 1;
869 heci_hdr->reserved = 0;
870 DBG("priv_cb_pos->request_buffer.size =%d"
871 "heci_hdr->msg_complete= %d\n",
872 priv_cb_pos->request_buffer.size,
873 heci_hdr->msg_complete);
874 DBG("priv_cb_pos->information =%lu\n",
875 priv_cb_pos->information);
876 DBG("heci_hdr->length =%d\n",
877 heci_hdr->length);
878 *slots -= (sizeof(struct heci_msg_hdr) +
879 heci_hdr->length + 3) / 4;
880 if (!heci_write_message(dev, heci_hdr,
881 (unsigned char *)
882 (priv_cb_pos->request_buffer.data +
883 priv_cb_pos->information),
884 heci_hdr->length)) {
885 file_ext->status = -ENODEV;
886 list_move_tail(&priv_cb_pos->cb_list,
887 &cmpl_list->heci_cb.cb_list);
888 return -ENODEV;
889 } else {
890 flow_ctrl_reduce(dev, file_ext);
891 file_ext->status = 0;
892 priv_cb_pos->information += heci_hdr->length;
893 list_move_tail(&priv_cb_pos->cb_list,
894 &dev->write_waiting_list.heci_cb.cb_list);
895 }
896 } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
897 /* buffer is still empty */
898 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
899 heci_hdr->host_addr = file_ext->host_client_id;
900 heci_hdr->me_addr = file_ext->me_client_id;
901 heci_hdr->length =
902 (*slots * sizeof(__u32)) - sizeof(struct heci_msg_hdr);
903 heci_hdr->msg_complete = 0;
904 heci_hdr->reserved = 0;
905
906 (*slots) -= (sizeof(struct heci_msg_hdr) +
907 heci_hdr->length + 3) / 4;
908 if (!heci_write_message(dev, heci_hdr,
909 (unsigned char *)
910 (priv_cb_pos->request_buffer.data +
911 priv_cb_pos->information),
912 heci_hdr->length)) {
913 file_ext->status = -ENODEV;
914 list_move_tail(&priv_cb_pos->cb_list,
915 &cmpl_list->heci_cb.cb_list);
916 return -ENODEV;
917 } else {
918 priv_cb_pos->information += heci_hdr->length;
919 DBG("priv_cb_pos->request_buffer.size =%d"
920 " heci_hdr->msg_complete= %d\n",
921 priv_cb_pos->request_buffer.size,
922 heci_hdr->msg_complete);
923 DBG("priv_cb_pos->information =%lu\n",
924 priv_cb_pos->information);
925 DBG("heci_hdr->length =%d\n", heci_hdr->length);
926 }
927 return -ECOMPLETE_MESSAGE;
928 } else {
929 return -ECORRUPTED_MESSAGE_HEADER;
930 }
931
932 return 0;
933}
934
935/**
936 * _heci_bh_cmpl_iamthif - process completed iamthif operation.
937 *
938 * @dev: Device object for our driver.
939 * @slots: free slots.
940 * @priv_cb_pos: callback block.
941 * @file_ext: private data of the file object.
942 * @cmpl_list: complete list.
943 *
944 * returns 0, OK; otherwise, error.
945 */
946static int _heci_bh_cmpl_iamthif(struct iamt_heci_device *dev, __s32 *slots,
947 struct heci_cb_private *priv_cb_pos,
948 struct heci_file_private *file_ext,
949 struct io_heci_list *cmpl_list)
950{
951 struct heci_msg_hdr *heci_hdr;
952
953 if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) +
954 dev->iamthif_msg_buf_size -
955 dev->iamthif_msg_buf_index)) {
956 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
957 heci_hdr->host_addr = file_ext->host_client_id;
958 heci_hdr->me_addr = file_ext->me_client_id;
959 heci_hdr->length = dev->iamthif_msg_buf_size -
960 dev->iamthif_msg_buf_index;
961 heci_hdr->msg_complete = 1;
962 heci_hdr->reserved = 0;
963
964 *slots -= (sizeof(struct heci_msg_hdr) +
965 heci_hdr->length + 3) / 4;
966
967 if (!heci_write_message(dev, heci_hdr,
968 (dev->iamthif_msg_buf +
969 dev->iamthif_msg_buf_index),
970 heci_hdr->length)) {
971 dev->iamthif_state = HECI_IAMTHIF_IDLE;
972 file_ext->status = -ENODEV;
973 list_del(&priv_cb_pos->cb_list);
974 return -ENODEV;
975 } else {
976 flow_ctrl_reduce(dev, file_ext);
977 dev->iamthif_msg_buf_index += heci_hdr->length;
978 priv_cb_pos->information = dev->iamthif_msg_buf_index;
979 file_ext->status = 0;
980 dev->iamthif_state = HECI_IAMTHIF_FLOW_CONTROL;
981 dev->iamthif_flow_control_pending = 1;
982 /* save iamthif cb sent to pthi client */
983 dev->iamthif_current_cb = priv_cb_pos;
984 list_move_tail(&priv_cb_pos->cb_list,
985 &dev->write_waiting_list.heci_cb.cb_list);
986
987 }
988 } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
989 /* buffer is still empty */
990 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
991 heci_hdr->host_addr = file_ext->host_client_id;
992 heci_hdr->me_addr = file_ext->me_client_id;
993 heci_hdr->length =
994 (*slots * sizeof(__u32)) - sizeof(struct heci_msg_hdr);
995 heci_hdr->msg_complete = 0;
996 heci_hdr->reserved = 0;
997
998 *slots -= (sizeof(struct heci_msg_hdr) +
999 heci_hdr->length + 3) / 4;
1000
1001 if (!heci_write_message(dev, heci_hdr,
1002 (dev->iamthif_msg_buf +
1003 dev->iamthif_msg_buf_index),
1004 heci_hdr->length)) {
1005 file_ext->status = -ENODEV;
1006 list_del(&priv_cb_pos->cb_list);
1007 } else {
1008 dev->iamthif_msg_buf_index += heci_hdr->length;
1009 }
1010 return -ECOMPLETE_MESSAGE;
1011 } else {
1012 return -ECORRUPTED_MESSAGE_HEADER;
1013 }
1014
1015 return 0;
1016}
1017
1018/**
1019 * heci_bh_write_handler - bottom half write routine after
1020 * ISR to handle the write processing.
1021 *
1022 * @cmpl_list: An instance of our list structure
1023 * @dev: Device object for our driver
1024 * @slots: slots to write.
1025 *
1026 * returns 0 on success, <0 on failure.
1027 */
1028static int heci_bh_write_handler(struct io_heci_list *cmpl_list,
1029 struct iamt_heci_device *dev,
1030 __s32 *slots)
1031{
1032
1033 struct heci_file_private *file_ext;
1034 struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL;
1035 struct io_heci_list *list;
1036 int ret;
1037
1038 if (!host_buffer_is_empty(dev)) {
1039 DBG("host buffer is not empty.\n");
1040 return 0;
1041 }
1042 dev->write_hang = -1;
1043 *slots = count_empty_write_slots(dev);
1044 /* complete all waiting for write CB */
1045 DBG("complete all waiting for write cb.\n");
1046
1047 list = &dev->write_waiting_list;
1048 if ((list->status == 0)
1049 && !list_empty(&list->heci_cb.cb_list)) {
1050 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
1051 &list->heci_cb.cb_list, cb_list) {
1052 file_ext = (struct heci_file_private *)
1053 priv_cb_pos->file_private;
1054 if (file_ext != NULL) {
1055 file_ext->status = 0;
1056 list_del(&priv_cb_pos->cb_list);
1057 if ((HECI_WRITING == file_ext->writing_state) &&
1058 (priv_cb_pos->major_file_operations ==
1059 HECI_WRITE) &&
1060 (file_ext != &dev->iamthif_file_ext)) {
1061 DBG("HECI WRITE COMPLETE\n");
1062 file_ext->writing_state =
1063 HECI_WRITE_COMPLETE;
1064 list_add_tail(&priv_cb_pos->cb_list,
1065 &cmpl_list->heci_cb.cb_list);
1066 }
1067 if (file_ext == &dev->iamthif_file_ext) {
1068 DBG("check iamthif flow control.\n");
1069 if (dev->iamthif_flow_control_pending) {
1070 ret = _heci_bh_iamthif_read(dev,
1071 slots);
1072 if (ret != 0)
1073 return ret;
1074 }
1075 }
1076 }
1077
1078 }
1079 }
1080
1081 if ((dev->stop) && (!dev->wd_pending)) {
1082 dev->wd_stoped = 1;
1083 wake_up_interruptible(&dev->wait_stop_wd);
1084 return 0;
1085 }
1086
1087 if (dev->extra_write_index != 0) {
1088 DBG("extra_write_index =%d.\n", dev->extra_write_index);
1089 heci_write_message(dev,
1090 (struct heci_msg_hdr *) &dev->ext_msg_buf[0],
1091 (unsigned char *) &dev->ext_msg_buf[1],
1092 (dev->extra_write_index - 1) * sizeof(__u32));
1093 *slots -= dev->extra_write_index;
1094 dev->extra_write_index = 0;
1095 }
1096 if (dev->heci_state == HECI_ENABLED) {
1097 if ((dev->wd_pending)
1098 && flow_ctrl_creds(dev, &dev->wd_file_ext)) {
1099 if (!heci_send_wd(dev))
1100 DBG("wd send failed.\n");
1101 else
1102 flow_ctrl_reduce(dev, &dev->wd_file_ext);
1103
1104 dev->wd_pending = 0;
1105
1106 if (dev->wd_timeout != 0) {
1107 *slots -= (sizeof(struct heci_msg_hdr) +
1108 HECI_START_WD_DATA_SIZE + 3) / 4;
1109 dev->wd_due_counter = 2;
1110 } else {
1111 *slots -= (sizeof(struct heci_msg_hdr) +
1112 HECI_WD_PARAMS_SIZE + 3) / 4;
1113 dev->wd_due_counter = 0;
1114 }
1115
1116 }
1117 }
1118 if (dev->stop)
1119 return ~ENODEV;
1120
1121 /* complete control write list CB */
1122 if (dev->ctrl_wr_list.status == 0) {
1123 /* complete control write list CB */
1124 DBG("complete control write list cb.\n");
1125 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
1126 &dev->ctrl_wr_list.heci_cb.cb_list, cb_list) {
1127 file_ext = (struct heci_file_private *)
1128 priv_cb_pos->file_private;
1129 if (file_ext == NULL) {
1130 list_del(&priv_cb_pos->cb_list);
1131 return -ENODEV;
1132 }
1133 switch (priv_cb_pos->major_file_operations) {
1134 case HECI_CLOSE:
1135 /* send disconnect message */
1136 ret = _heci_bh_close(dev, slots,
1137 priv_cb_pos,
1138 file_ext, cmpl_list);
1139 if (ret != 0)
1140 return ret;
1141
1142 break;
1143 case HECI_READ:
1144 /* send flow control message */
1145 ret = _heci_bh_read(dev, slots,
1146 priv_cb_pos,
1147 file_ext, cmpl_list);
1148 if (ret != 0)
1149 return ret;
1150
1151 break;
1152 case HECI_IOCTL:
1153 /* connect message */
1154 if (!other_client_is_connecting(dev, file_ext))
1155 continue;
1156 ret = _heci_bh_ioctl(dev, slots,
1157 priv_cb_pos,
1158 file_ext, cmpl_list);
1159 if (ret != 0)
1160 return ret;
1161
1162 break;
1163
1164 default:
1165 BUG();
1166 }
1167
1168 }
1169 }
1170 /* complete write list CB */
1171 if ((dev->write_list.status == 0)
1172 && !list_empty(&dev->write_list.heci_cb.cb_list)) {
1173 DBG("complete write list cb.\n");
1174 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
1175 &dev->write_list.heci_cb.cb_list, cb_list) {
1176 file_ext = (struct heci_file_private *)
1177 priv_cb_pos->file_private;
1178
1179 if (file_ext != NULL) {
1180 if (file_ext != &dev->iamthif_file_ext) {
1181 if (!flow_ctrl_creds(dev, file_ext)) {
1182 DBG("No flow control"
1183 " credentials for client"
1184 " %d, not sending.\n",
1185 file_ext->host_client_id);
1186 continue;
1187 }
1188 ret = _heci_bh_cmpl(dev, slots,
1189 priv_cb_pos,
1190 file_ext,
1191 cmpl_list);
1192 if (ret != 0)
1193 return ret;
1194
1195 } else if (file_ext == &dev->iamthif_file_ext) {
1196 /* IAMTHIF IOCTL */
1197 DBG("complete pthi write cb.\n");
1198 if (!flow_ctrl_creds(dev, file_ext)) {
1199 DBG("No flow control"
1200 " credentials for pthi"
1201 " client %d.\n",
1202 file_ext->host_client_id);
1203 continue;
1204 }
1205 ret = _heci_bh_cmpl_iamthif(dev, slots,
1206 priv_cb_pos,
1207 file_ext,
1208 cmpl_list);
1209 if (ret != 0)
1210 return ret;
1211
1212 }
1213 }
1214
1215 }
1216 }
1217 return 0;
1218}
1219
1220
1221/**
1222 * is_treat_specially_client - check if the message belong
1223 * to the file private data.
1224 *
1225 * @file_ext: private data of the file object
1226 * @rs: connect response bus message
1227 * @dev: Device object for our driver
1228 *
1229 * returns 0 on success, <0 on failure.
1230 */
1231static int is_treat_specially_client(struct heci_file_private *file_ext,
1232 struct hbm_client_connect_response *rs)
1233{
1234 int ret = 0;
1235
1236 if ((file_ext->host_client_id == rs->host_addr) &&
1237 (file_ext->me_client_id == rs->me_addr)) {
1238 if (rs->status == 0) {
1239 DBG("client connect status = 0x%08x.\n", rs->status);
1240 file_ext->state = HECI_FILE_CONNECTED;
1241 file_ext->status = 0;
1242 } else {
1243 DBG("client connect status = 0x%08x.\n", rs->status);
1244 file_ext->state = HECI_FILE_DISCONNECTED;
1245 file_ext->status = -ENODEV;
1246 }
1247 ret = 1;
1248 }
1249 DBG("client state = %d.\n", file_ext->state);
1250 return ret;
1251}
1252
1253/**
1254 * heci_client_connect_response - connect response bh routine
1255 *
1256 * @dev: Device object for our driver
1257 * @rs: connect response bus message
1258 */
1259static void heci_client_connect_response(struct iamt_heci_device *dev,
1260 struct hbm_client_connect_response *rs)
1261{
1262
1263 struct heci_file_private *file_ext;
1264 struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL;
1265
1266 /* if WD or iamthif client treat specially */
1267
1268 if ((is_treat_specially_client(&(dev->wd_file_ext), rs)) ||
1269 (is_treat_specially_client(&(dev->iamthif_file_ext), rs)))
1270 return;
1271
1272 if (dev->ctrl_rd_list.status == 0
1273 && !list_empty(&dev->ctrl_rd_list.heci_cb.cb_list)) {
1274 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
1275 &dev->ctrl_rd_list.heci_cb.cb_list, cb_list) {
1276 file_ext = (struct heci_file_private *)
1277 priv_cb_pos->file_private;
1278 if (file_ext == NULL) {
1279 list_del(&priv_cb_pos->cb_list);
1280 return;
1281 }
1282 if (HECI_IOCTL == priv_cb_pos->major_file_operations) {
1283 if (is_treat_specially_client(file_ext, rs)) {
1284 list_del(&priv_cb_pos->cb_list);
1285 file_ext->status = 0;
1286 file_ext->timer_count = 0;
1287 break;
1288 }
1289 }
1290 }
1291 }
1292}
1293
1294/**
1295 * heci_client_disconnect_response - disconnect response bh routine
1296 *
1297 * @dev: Device object for our driver
1298 * @rs: disconnect response bus message
1299 */
1300static void heci_client_disconnect_response(struct iamt_heci_device *dev,
1301 struct hbm_client_connect_response *rs)
1302{
1303 struct heci_file_private *file_ext;
1304 struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL;
1305
1306 if (dev->ctrl_rd_list.status == 0
1307 && !list_empty(&dev->ctrl_rd_list.heci_cb.cb_list)) {
1308 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
1309 &dev->ctrl_rd_list.heci_cb.cb_list, cb_list) {
1310 file_ext = (struct heci_file_private *)
1311 priv_cb_pos->file_private;
1312
1313 if (file_ext == NULL) {
1314 list_del(&priv_cb_pos->cb_list);
1315 return;
1316 }
1317
1318 DBG("list_for_each_entry_safe in ctrl_rd_list.\n");
1319 if ((file_ext->host_client_id == rs->host_addr) &&
1320 (file_ext->me_client_id == rs->me_addr)) {
1321
1322 list_del(&priv_cb_pos->cb_list);
1323 if (rs->status == 0) {
1324 file_ext->state =
1325 HECI_FILE_DISCONNECTED;
1326 }
1327
1328 file_ext->status = 0;
1329 file_ext->timer_count = 0;
1330 break;
1331 }
1332 }
1333 }
1334}
1335
1336/**
1337 * same_flow_addr - tell they have same address.
1338 *
1339 * @file: private data of the file object.
1340 * @flow: flow control.
1341 *
1342 * returns !=0, same; 0,not.
1343 */
1344static int same_flow_addr(struct heci_file_private *file,
1345 struct hbm_flow_control *flow)
1346{
1347 return ((file->host_client_id == flow->host_addr)
1348 && (file->me_client_id == flow->me_addr));
1349}
1350
1351/**
1352 * add_single_flow_creds - add single buffer credentials.
1353 *
1354 * @file: private data ot the file object.
1355 * @flow: flow control.
1356 */
1357static void add_single_flow_creds(struct iamt_heci_device *dev,
1358 struct hbm_flow_control *flow)
1359{
1360 struct heci_me_client *client;
1361 int i;
1362
1363 for (i = 0; i < dev->num_heci_me_clients; i++) {
1364 client = &dev->me_clients[i];
1365 if ((client != NULL) &&
1366 (flow->me_addr == client->client_id)) {
1367 if (client->props.single_recv_buf != 0) {
1368 client->flow_ctrl_creds++;
1369 DBG("recv flow ctrl msg ME %d (single).\n",
1370 flow->me_addr);
1371 DBG("flow control credentials=%d.\n",
1372 client->flow_ctrl_creds);
1373 } else {
1374 BUG(); /* error in flow control */
1375 }
1376 }
1377 }
1378}
1379
1380/**
1381 * heci_client_flow_control_response - flow control response bh routine
1382 *
1383 * @dev: Device object for our driver
1384 * @flow_control: flow control response bus message
1385 */
1386static void heci_client_flow_control_response(struct iamt_heci_device *dev,
1387 struct hbm_flow_control *flow_control)
1388{
1389 struct heci_file_private *file_pos = NULL;
1390 struct heci_file_private *file_next = NULL;
1391
1392 if (flow_control->host_addr == 0) {
1393 /* single receive buffer */
1394 add_single_flow_creds(dev, flow_control);
1395 } else {
1396 /* normal connection */
1397 list_for_each_entry_safe(file_pos, file_next,
1398 &dev->file_list, link) {
1399 DBG("list_for_each_entry_safe in file_list\n");
1400
1401 DBG("file_ext of host client %d ME client %d.\n",
1402 file_pos->host_client_id,
1403 file_pos->me_client_id);
1404 DBG("flow ctrl msg for host %d ME %d.\n",
1405 flow_control->host_addr,
1406 flow_control->me_addr);
1407 if (same_flow_addr(file_pos, flow_control)) {
1408 DBG("recv ctrl msg for host %d ME %d.\n",
1409 flow_control->host_addr,
1410 flow_control->me_addr);
1411 file_pos->flow_ctrl_creds++;
1412 DBG("flow control credentials=%d.\n",
1413 file_pos->flow_ctrl_creds);
1414 break;
1415 }
1416 }
1417 }
1418}
1419
1420/**
1421 * same_disconn_addr - tell they have same address
1422 *
1423 * @file: private data of the file object.
1424 * @disconn: disconnection request.
1425 *
1426 * returns !=0, same; 0,not.
1427 */
1428static int same_disconn_addr(struct heci_file_private *file,
1429 struct hbm_client_disconnect_request *disconn)
1430{
1431 return ((file->host_client_id == disconn->host_addr)
1432 && (file->me_client_id == disconn->me_addr));
1433}
1434
1435/**
1436 * heci_client_disconnect_request - disconnect request bh routine
1437 *
1438 * @dev: Device object for our driver.
1439 * @disconnect_req: disconnect request bus message.
1440 */
1441static void heci_client_disconnect_request(struct iamt_heci_device *dev,
1442 struct hbm_client_disconnect_request *disconnect_req)
1443{
1444 struct heci_msg_hdr *heci_hdr;
1445 struct hbm_client_connect_response *disconnect_res;
1446 struct heci_file_private *file_pos = NULL;
1447 struct heci_file_private *file_next = NULL;
1448
1449 list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link) {
1450 if (same_disconn_addr(file_pos, disconnect_req)) {
1451 DBG("disconnect request host client %d ME client %d.\n",
1452 disconnect_req->host_addr,
1453 disconnect_req->me_addr);
1454 file_pos->state = HECI_FILE_DISCONNECTED;
1455 file_pos->timer_count = 0;
1456 if (file_pos == &dev->wd_file_ext) {
1457 dev->wd_due_counter = 0;
1458 dev->wd_pending = 0;
1459 } else if (file_pos == &dev->iamthif_file_ext)
1460 dev->iamthif_timer = 0;
1461
1462 /* prepare disconnect response */
1463 heci_hdr =
1464 (struct heci_msg_hdr *) &dev->ext_msg_buf[0];
1465 heci_hdr->host_addr = 0;
1466 heci_hdr->me_addr = 0;
1467 heci_hdr->length =
1468 sizeof(struct hbm_client_connect_response);
1469 heci_hdr->msg_complete = 1;
1470 heci_hdr->reserved = 0;
1471
1472 disconnect_res =
1473 (struct hbm_client_connect_response *)
1474 &dev->ext_msg_buf[1];
1475 disconnect_res->host_addr = file_pos->host_client_id;
1476 disconnect_res->me_addr = file_pos->me_client_id;
1477 *(__u8 *) (&disconnect_res->cmd) =
1478 CLIENT_DISCONNECT_RES_CMD;
1479 disconnect_res->status = 0;
1480 dev->extra_write_index = 2;
1481 break;
1482 }
1483 }
1484}
1485
1486/**
1487 * heci_timer - timer function.
1488 *
1489 * @data: pointer to the device structure
1490 *
1491 * NOTE: This function is called by timer interrupt work
1492 */
1493void heci_wd_timer(unsigned long data)
1494{
1495 struct iamt_heci_device *dev = (struct iamt_heci_device *) data;
1496
1497 DBG("send watchdog.\n");
1498 spin_lock_bh(&dev->device_lock);
1499 if (dev->heci_state != HECI_ENABLED) {
1500 mod_timer(&dev->wd_timer, round_jiffies(jiffies + 2 * HZ));
1501 spin_unlock_bh(&dev->device_lock);
1502 return;
1503 }
1504 if (dev->wd_file_ext.state != HECI_FILE_CONNECTED) {
1505 mod_timer(&dev->wd_timer, round_jiffies(jiffies + 2 * HZ));
1506 spin_unlock_bh(&dev->device_lock);
1507 return;
1508 }
1509 /* Watchdog */
1510 if ((dev->wd_due_counter != 0) && (dev->wd_bypass == 0)) {
1511 if (--dev->wd_due_counter == 0) {
1512 if (dev->host_buffer_is_empty &&
1513 flow_ctrl_creds(dev, &dev->wd_file_ext)) {
1514 dev->host_buffer_is_empty = 0;
1515 if (!heci_send_wd(dev)) {
1516 DBG("wd send failed.\n");
1517 } else {
1518 flow_ctrl_reduce(dev,
1519 &dev->wd_file_ext);
1520 }
1521
1522 if (dev->wd_timeout != 0)
1523 dev->wd_due_counter = 2;
1524 else
1525 dev->wd_due_counter = 0;
1526
1527 } else
1528 dev->wd_pending = 1;
1529
1530 }
1531 }
1532 if (dev->iamthif_stall_timer != 0) {
1533 if (--dev->iamthif_stall_timer == 0) {
1534 DBG("reseting because of hang to PTHI.\n");
1535 heci_reset(dev, 1);
1536 dev->iamthif_msg_buf_size = 0;
1537 dev->iamthif_msg_buf_index = 0;
1538 dev->iamthif_canceled = 0;
1539 dev->iamthif_ioctl = 1;
1540 dev->iamthif_state = HECI_IAMTHIF_IDLE;
1541 dev->iamthif_timer = 0;
1542 spin_unlock_bh(&dev->device_lock);
1543
1544 if (dev->iamthif_current_cb)
1545 heci_free_cb_private(dev->iamthif_current_cb);
1546
1547 spin_lock_bh(&dev->device_lock);
1548 dev->iamthif_file_object = NULL;
1549 dev->iamthif_current_cb = NULL;
1550 run_next_iamthif_cmd(dev);
1551 }
1552 }
1553 mod_timer(&dev->wd_timer, round_jiffies(jiffies + 2 * HZ));
1554 spin_unlock_bh(&dev->device_lock);
1555}
diff --git a/drivers/staging/heci/io_heci.c b/drivers/staging/heci/io_heci.c
deleted file mode 100644
index 1a6faf88e16..00000000000
--- a/drivers/staging/heci/io_heci.c
+++ /dev/null
@@ -1,872 +0,0 @@
1/*
2 * Part of Intel(R) Manageability Engine Interface Linux driver
3 *
4 * Copyright (c) 2003 - 2008 Intel Corp.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * substantially similar to the "NO WARRANTY" disclaimer below
15 * ("Disclaimer") and any redistribution must be conditioned upon
16 * including a substantially similar Disclaimer requirement for further
17 * binary redistribution.
18 * 3. Neither the names of the above-listed copyright holders nor the names
19 * of any contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * Alternatively, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2 as published by the Free
24 * Software Foundation.
25 *
26 * NO WARRANTY
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGES.
38 *
39 */
40
41#include <linux/module.h>
42#include <linux/moduleparam.h>
43#include <linux/kernel.h>
44#include <linux/slab.h>
45#include <linux/fs.h>
46#include <linux/errno.h>
47#include <linux/types.h>
48#include <linux/fcntl.h>
49#include <linux/aio.h>
50#include <linux/pci.h>
51#include <linux/reboot.h>
52#include <linux/poll.h>
53#include <linux/init.h>
54#include <linux/kdev_t.h>
55#include <linux/ioctl.h>
56#include <linux/cdev.h>
57#include <linux/list.h>
58#include <linux/unistd.h>
59#include <linux/delay.h>
60
61#include "heci_data_structures.h"
62#include "heci.h"
63#include "heci_interface.h"
64#include "heci_version.h"
65
66
67/**
68 * heci_ioctl_get_version - the get driver version IOCTL function
69 *
70 * @dev: Device object for our driver
71 * @if_num: minor number
72 * @*u_msg: pointer to user data struct in user space
73 * @k_msg: data in kernel on the stack
74 * @file_ext: private data of the file object
75 *
76 * returns 0 on success, <0 on failure.
77 */
78int heci_ioctl_get_version(struct iamt_heci_device *dev, int if_num,
79 struct heci_message_data __user *u_msg,
80 struct heci_message_data k_msg,
81 struct heci_file_private *file_ext)
82{
83 int rets = 0;
84 struct heci_driver_version *version;
85 struct heci_message_data res_msg;
86
87 if ((if_num != HECI_MINOR_NUMBER) || (!dev)
88 || (!file_ext))
89 return -ENODEV;
90
91 if (k_msg.size < (sizeof(struct heci_driver_version) - 2)) {
92 DBG("user buffer less than heci_driver_version.\n");
93 return -EMSGSIZE;
94 }
95
96 res_msg.data = kmalloc(sizeof(struct heci_driver_version), GFP_KERNEL);
97 if (!res_msg.data) {
98 DBG("failed allocation response buffer size = %d.\n",
99 (int) sizeof(struct heci_driver_version));
100 return -ENOMEM;
101 }
102
103 version = (struct heci_driver_version *) res_msg.data;
104 version->major = MAJOR_VERSION;
105 version->minor = MINOR_VERSION;
106 version->hotfix = QUICK_FIX_NUMBER;
107 version->build = VER_BUILD;
108 res_msg.size = sizeof(struct heci_driver_version);
109 if (k_msg.size < sizeof(struct heci_driver_version))
110 res_msg.size -= 2;
111
112 rets = file_ext->status;
113 /* now copy the data to user space */
114 if (copy_to_user((void __user *)k_msg.data, res_msg.data, res_msg.size)) {
115 rets = -EFAULT;
116 goto end;
117 }
118 if (put_user(res_msg.size, &u_msg->size)) {
119 rets = -EFAULT;
120 goto end;
121 }
122end:
123 kfree(res_msg.data);
124 return rets;
125}
126
127/**
128 * heci_ioctl_connect_client - the connect to fw client IOCTL function
129 *
130 * @dev: Device object for our driver
131 * @if_num: minor number
132 * @*u_msg: pointer to user data struct in user space
133 * @k_msg: data in kernel on the stack
134 * @file_ext: private data of the file object
135 *
136 * returns 0 on success, <0 on failure.
137 */
138int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num,
139 struct heci_message_data __user *u_msg,
140 struct heci_message_data k_msg,
141 struct file *file)
142{
143 int rets = 0;
144 struct heci_message_data req_msg, res_msg;
145 struct heci_cb_private *priv_cb = NULL;
146 struct heci_client *client;
147 struct heci_file_private *file_ext;
148 struct heci_file_private *file_pos = NULL;
149 struct heci_file_private *file_next = NULL;
150 long timeout = 15; /*15 second */
151 __u8 i;
152 int err = 0;
153
154 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file))
155 return -ENODEV;
156
157 file_ext = file->private_data;
158 if (!file_ext)
159 return -ENODEV;
160
161 if (k_msg.size != sizeof(struct guid)) {
162 DBG("user buffer size is not equal to size of struct "
163 "guid(16).\n");
164 return -EMSGSIZE;
165 }
166
167 if (!k_msg.data)
168 return -EIO;
169
170 req_msg.data = kmalloc(sizeof(struct guid), GFP_KERNEL);
171 res_msg.data = kmalloc(sizeof(struct heci_client), GFP_KERNEL);
172
173 if (!res_msg.data) {
174 DBG("failed allocation response buffer size = %d.\n",
175 (int) sizeof(struct heci_client));
176 kfree(req_msg.data);
177 return -ENOMEM;
178 }
179 if (!req_msg.data) {
180 DBG("failed allocation request buffer size = %d.\n",
181 (int) sizeof(struct guid));
182 kfree(res_msg.data);
183 return -ENOMEM;
184 }
185 req_msg.size = sizeof(struct guid);
186 res_msg.size = sizeof(struct heci_client);
187
188 /* copy the message to kernel space -
189 * use a pointer already copied into kernel space
190 */
191 if (copy_from_user(req_msg.data, (void __user *)k_msg.data, k_msg.size)) {
192 rets = -EFAULT;
193 goto end;
194 }
195 /* buffered ioctl cb */
196 priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
197 if (!priv_cb) {
198 rets = -ENOMEM;
199 goto end;
200 }
201 INIT_LIST_HEAD(&priv_cb->cb_list);
202 priv_cb->response_buffer.data = res_msg.data;
203 priv_cb->response_buffer.size = res_msg.size;
204 priv_cb->request_buffer.data = req_msg.data;
205 priv_cb->request_buffer.size = req_msg.size;
206 priv_cb->major_file_operations = HECI_IOCTL;
207 spin_lock_bh(&dev->device_lock);
208 if (dev->heci_state != HECI_ENABLED) {
209 rets = -ENODEV;
210 spin_unlock_bh(&dev->device_lock);
211 goto end;
212 }
213 if ((file_ext->state != HECI_FILE_INITIALIZING) &&
214 (file_ext->state != HECI_FILE_DISCONNECTED)) {
215 rets = -EBUSY;
216 spin_unlock_bh(&dev->device_lock);
217 goto end;
218 }
219
220 /* find ME client we're trying to connect to */
221 for (i = 0; i < dev->num_heci_me_clients; i++) {
222 if (memcmp((struct guid *)req_msg.data,
223 &dev->me_clients[i].props.protocol_name,
224 sizeof(struct guid)) == 0) {
225 if (dev->me_clients[i].props.fixed_address == 0) {
226 file_ext->me_client_id =
227 dev->me_clients[i].client_id;
228 file_ext->state = HECI_FILE_CONNECTING;
229 }
230 break;
231 }
232 }
233 /* if we're connecting to PTHI client so we will use the exist
234 * connection
235 */
236 if (memcmp((struct guid *)req_msg.data, &heci_pthi_guid,
237 sizeof(struct guid)) == 0) {
238 if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTED) {
239 rets = -ENODEV;
240 spin_unlock_bh(&dev->device_lock);
241 goto end;
242 }
243 dev->heci_host_clients[file_ext->host_client_id / 8] &=
244 ~(1 << (file_ext->host_client_id % 8));
245 list_for_each_entry_safe(file_pos,
246 file_next, &dev->file_list, link) {
247 if (heci_fe_same_id(file_ext, file_pos)) {
248 DBG("remove file private data node host"
249 " client = %d, ME client = %d.\n",
250 file_pos->host_client_id,
251 file_pos->me_client_id);
252 list_del(&file_pos->link);
253 }
254
255 }
256 DBG("free file private data memory.\n");
257 kfree(file_ext);
258 file_ext = NULL;
259 file->private_data = &dev->iamthif_file_ext;
260 client = (struct heci_client *) res_msg.data;
261 client->max_msg_length =
262 dev->me_clients[i].props.max_msg_length;
263 client->protocol_version =
264 dev->me_clients[i].props.protocol_version;
265 rets = dev->iamthif_file_ext.status;
266 spin_unlock_bh(&dev->device_lock);
267
268 /* now copy the data to user space */
269 if (copy_to_user((void __user *)k_msg.data,
270 res_msg.data, res_msg.size)) {
271 rets = -EFAULT;
272 goto end;
273 }
274 if (put_user(res_msg.size, &u_msg->size)) {
275 rets = -EFAULT;
276 goto end;
277 }
278 goto end;
279 }
280 spin_unlock_bh(&dev->device_lock);
281
282 spin_lock(&file_ext->file_lock);
283 spin_lock_bh(&dev->device_lock);
284 if (file_ext->state != HECI_FILE_CONNECTING) {
285 rets = -ENODEV;
286 spin_unlock_bh(&dev->device_lock);
287 spin_unlock(&file_ext->file_lock);
288 goto end;
289 }
290 /* prepare the output buffer */
291 client = (struct heci_client *) res_msg.data;
292 client->max_msg_length = dev->me_clients[i].props.max_msg_length;
293 client->protocol_version = dev->me_clients[i].props.protocol_version;
294 if (dev->host_buffer_is_empty
295 && !other_client_is_connecting(dev, file_ext)) {
296 dev->host_buffer_is_empty = 0;
297 if (!heci_connect(dev, file_ext)) {
298 rets = -ENODEV;
299 spin_unlock_bh(&dev->device_lock);
300 spin_unlock(&file_ext->file_lock);
301 goto end;
302 } else {
303 file_ext->timer_count = HECI_CONNECT_TIMEOUT;
304 priv_cb->file_private = file_ext;
305 list_add_tail(&priv_cb->cb_list,
306 &dev->ctrl_rd_list.heci_cb.
307 cb_list);
308 }
309
310
311 } else {
312 priv_cb->file_private = file_ext;
313 DBG("add connect cb to control write list.\n");
314 list_add_tail(&priv_cb->cb_list,
315 &dev->ctrl_wr_list.heci_cb.cb_list);
316 }
317 spin_unlock_bh(&dev->device_lock);
318 spin_unlock(&file_ext->file_lock);
319 err = wait_event_timeout(dev->wait_recvd_msg,
320 (HECI_FILE_CONNECTED == file_ext->state
321 || HECI_FILE_DISCONNECTED == file_ext->state),
322 timeout * HZ);
323
324 spin_lock_bh(&dev->device_lock);
325 if (HECI_FILE_CONNECTED == file_ext->state) {
326 spin_unlock_bh(&dev->device_lock);
327 DBG("successfully connected to FW client.\n");
328 rets = file_ext->status;
329 /* now copy the data to user space */
330 if (copy_to_user((void __user *)k_msg.data,
331 res_msg.data, res_msg.size)) {
332 rets = -EFAULT;
333 goto end;
334 }
335 if (put_user(res_msg.size, &u_msg->size)) {
336 rets = -EFAULT;
337 goto end;
338 }
339 goto end;
340 } else {
341 DBG("failed to connect to FW client.file_ext->state = %d.\n",
342 file_ext->state);
343 spin_unlock_bh(&dev->device_lock);
344 if (!err) {
345 DBG("wait_event_interruptible_timeout failed on client"
346 " connect message fw response message.\n");
347 }
348 rets = -EFAULT;
349 goto remove_list;
350 }
351
352remove_list:
353 if (priv_cb) {
354 spin_lock_bh(&dev->device_lock);
355 heci_flush_list(&dev->ctrl_rd_list, file_ext);
356 heci_flush_list(&dev->ctrl_wr_list, file_ext);
357 spin_unlock_bh(&dev->device_lock);
358 }
359end:
360 DBG("free connect cb memory.");
361 kfree(req_msg.data);
362 kfree(res_msg.data);
363 kfree(priv_cb);
364 return rets;
365}
366
367/**
368 * heci_ioctl_wd - the wd IOCTL function
369 *
370 * @dev: Device object for our driver
371 * @if_num: minor number
372 * @k_msg: data in kernel on the stack
373 * @file_ext: private data of the file object
374 *
375 * returns 0 on success, <0 on failure.
376 */
377int heci_ioctl_wd(struct iamt_heci_device *dev, int if_num,
378 struct heci_message_data k_msg,
379 struct heci_file_private *file_ext)
380{
381 int rets = 0;
382 struct heci_message_data req_msg; /*in kernel on the stack */
383
384 if (if_num != HECI_MINOR_NUMBER)
385 return -ENODEV;
386
387 spin_lock(&file_ext->file_lock);
388 if (k_msg.size != HECI_WATCHDOG_DATA_SIZE) {
389 DBG("user buffer has invalid size.\n");
390 spin_unlock(&file_ext->file_lock);
391 return -EMSGSIZE;
392 }
393 spin_unlock(&file_ext->file_lock);
394
395 req_msg.data = kmalloc(HECI_WATCHDOG_DATA_SIZE, GFP_KERNEL);
396 if (!req_msg.data) {
397 DBG("failed allocation request buffer size = %d.\n",
398 HECI_WATCHDOG_DATA_SIZE);
399 return -ENOMEM;
400 }
401 req_msg.size = HECI_WATCHDOG_DATA_SIZE;
402
403 /* copy the message to kernel space - use a pointer already
404 * copied into kernel space
405 */
406 if (copy_from_user(req_msg.data,
407 (void __user *)k_msg.data, req_msg.size)) {
408 rets = -EFAULT;
409 goto end;
410 }
411 spin_lock_bh(&dev->device_lock);
412 if (dev->heci_state != HECI_ENABLED) {
413 rets = -ENODEV;
414 spin_unlock_bh(&dev->device_lock);
415 goto end;
416 }
417
418 if (dev->wd_file_ext.state != HECI_FILE_CONNECTED) {
419 rets = -ENODEV;
420 spin_unlock_bh(&dev->device_lock);
421 goto end;
422 }
423 if (!dev->asf_mode) {
424 rets = -EIO;
425 spin_unlock_bh(&dev->device_lock);
426 goto end;
427 }
428
429 memcpy(&dev->wd_data[HECI_WD_PARAMS_SIZE], req_msg.data,
430 HECI_WATCHDOG_DATA_SIZE);
431
432 dev->wd_timeout = (req_msg.data[1] << 8) + req_msg.data[0];
433 dev->wd_pending = 0;
434 dev->wd_due_counter = 1; /* next timer */
435 if (dev->wd_timeout == 0) {
436 memcpy(dev->wd_data, heci_stop_wd_params,
437 HECI_WD_PARAMS_SIZE);
438 } else {
439 memcpy(dev->wd_data, heci_start_wd_params,
440 HECI_WD_PARAMS_SIZE);
441 mod_timer(&dev->wd_timer, jiffies);
442 }
443 spin_unlock_bh(&dev->device_lock);
444end:
445 kfree(req_msg.data);
446 return rets;
447}
448
449
450/**
451 * heci_ioctl_bypass_wd - the bypass_wd IOCTL function
452 *
453 * @dev: Device object for our driver
454 * @if_num: minor number
455 * @k_msg: data in kernel on the stack
456 * @file_ext: private data of the file object
457 *
458 * returns 0 on success, <0 on failure.
459 */
460int heci_ioctl_bypass_wd(struct iamt_heci_device *dev, int if_num,
461 struct heci_message_data k_msg,
462 struct heci_file_private *file_ext)
463{
464 __u8 flag = 0;
465 int rets = 0;
466
467 if (if_num != HECI_MINOR_NUMBER)
468 return -ENODEV;
469
470 spin_lock(&file_ext->file_lock);
471 if (k_msg.size < 1) {
472 DBG("user buffer less than HECI_WATCHDOG_DATA_SIZE.\n");
473 spin_unlock(&file_ext->file_lock);
474 return -EMSGSIZE;
475 }
476 spin_unlock(&file_ext->file_lock);
477 if (copy_from_user(&flag, (void __user *)k_msg.data, 1)) {
478 rets = -EFAULT;
479 goto end;
480 }
481
482 spin_lock_bh(&dev->device_lock);
483 flag = flag ? (1) : (0);
484 dev->wd_bypass = flag;
485 spin_unlock_bh(&dev->device_lock);
486end:
487 return rets;
488}
489
490/**
491 * find_pthi_read_list_entry - finds a PTHIlist entry for current file
492 *
493 * @dev: Device object for our driver
494 * @file: pointer to file object
495 *
496 * returns returned a list entry on success, NULL on failure.
497 */
498struct heci_cb_private *find_pthi_read_list_entry(
499 struct iamt_heci_device *dev,
500 struct file *file)
501{
502 struct heci_file_private *file_ext_temp;
503 struct heci_cb_private *priv_cb_pos = NULL;
504 struct heci_cb_private *priv_cb_next = NULL;
505
506 if ((dev->pthi_read_complete_list.status == 0) &&
507 !list_empty(&dev->pthi_read_complete_list.heci_cb.cb_list)) {
508 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
509 &dev->pthi_read_complete_list.heci_cb.cb_list, cb_list) {
510 file_ext_temp = (struct heci_file_private *)
511 priv_cb_pos->file_private;
512 if ((file_ext_temp != NULL) &&
513 (file_ext_temp == &dev->iamthif_file_ext) &&
514 (priv_cb_pos->file_object == file))
515 return priv_cb_pos;
516 }
517 }
518 return NULL;
519}
520
521/**
522 * pthi_read - read data from pthi client
523 *
524 * @dev: Device object for our driver
525 * @if_num: minor number
526 * @file: pointer to file object
527 * @*ubuf: pointer to user data in user space
528 * @length: data length to read
529 * @offset: data read offset
530 *
531 * returns
532 * returned data length on success,
533 * zero if no data to read,
534 * negative on failure.
535 */
536int pthi_read(struct iamt_heci_device *dev, int if_num, struct file *file,
537 char __user *ubuf, size_t length, loff_t *offset)
538{
539 int rets = 0;
540 struct heci_cb_private *priv_cb = NULL;
541 struct heci_file_private *file_ext = file->private_data;
542 __u8 i;
543 unsigned long currtime = get_seconds();
544
545 if ((if_num != HECI_MINOR_NUMBER) || (!dev))
546 return -ENODEV;
547
548 if ((file_ext == NULL) || (file_ext != &dev->iamthif_file_ext))
549 return -ENODEV;
550
551 spin_lock_bh(&dev->device_lock);
552 for (i = 0; i < dev->num_heci_me_clients; i++) {
553 if (dev->me_clients[i].client_id ==
554 dev->iamthif_file_ext.me_client_id)
555 break;
556 }
557 BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
558 if ((i == dev->num_heci_me_clients)
559 || (dev->me_clients[i].client_id !=
560 dev->iamthif_file_ext.me_client_id)) {
561 DBG("PTHI client not found.\n");
562 spin_unlock_bh(&dev->device_lock);
563 return -ENODEV;
564 }
565 priv_cb = find_pthi_read_list_entry(dev, file);
566 if (!priv_cb) {
567 spin_unlock_bh(&dev->device_lock);
568 return 0; /* No more data to read */
569 } else {
570 if (priv_cb &&
571 (currtime - priv_cb->read_time > IAMTHIF_READ_TIMER)) {
572 /* 15 sec for the message has expired */
573 list_del(&priv_cb->cb_list);
574 spin_unlock_bh(&dev->device_lock);
575 rets = -ETIMEDOUT;
576 goto free;
577 }
578 /* if the whole message will fit remove it from the list */
579 if ((priv_cb->information >= *offset) &&
580 (length >= (priv_cb->information - *offset)))
581 list_del(&priv_cb->cb_list);
582 else if ((priv_cb->information > 0) &&
583 (priv_cb->information <= *offset)) {
584 /* end of the message has been reached */
585 list_del(&priv_cb->cb_list);
586 rets = 0;
587 spin_unlock_bh(&dev->device_lock);
588 goto free;
589 }
590 /* else means that not full buffer will be read and do not
591 * remove message from deletion list
592 */
593 }
594 DBG("pthi priv_cb->response_buffer size - %d\n",
595 priv_cb->response_buffer.size);
596 DBG("pthi priv_cb->information - %lu\n",
597 priv_cb->information);
598 spin_unlock_bh(&dev->device_lock);
599
600 /* length is being turncated to PAGE_SIZE, however,
601 * the information may be longer */
602 length = length < (priv_cb->information - *offset) ?
603 length : (priv_cb->information - *offset);
604
605 if (copy_to_user(ubuf,
606 priv_cb->response_buffer.data + *offset,
607 length))
608 rets = -EFAULT;
609 else {
610 rets = length;
611 if ((*offset + length) < priv_cb->information) {
612 *offset += length;
613 goto out;
614 }
615 }
616free:
617 DBG("free pthi cb memory.\n");
618 *offset = 0;
619 heci_free_cb_private(priv_cb);
620out:
621 return rets;
622}
623
624/**
625 * heci_start_read - the start read client message function.
626 *
627 * @dev: Device object for our driver
628 * @if_num: minor number
629 * @file_ext: private data of the file object
630 *
631 * returns 0 on success, <0 on failure.
632 */
633int heci_start_read(struct iamt_heci_device *dev, int if_num,
634 struct heci_file_private *file_ext)
635{
636 int rets = 0;
637 __u8 i;
638 struct heci_cb_private *priv_cb = NULL;
639
640 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext)) {
641 DBG("received wrong function input param.\n");
642 return -ENODEV;
643 }
644
645 spin_lock_bh(&dev->device_lock);
646 if (file_ext->state != HECI_FILE_CONNECTED) {
647 spin_unlock_bh(&dev->device_lock);
648 return -ENODEV;
649 }
650
651 if (dev->heci_state != HECI_ENABLED) {
652 spin_unlock_bh(&dev->device_lock);
653 return -ENODEV;
654 }
655 spin_unlock_bh(&dev->device_lock);
656 DBG("check if read is pending.\n");
657 spin_lock_bh(&file_ext->read_io_lock);
658 if ((file_ext->read_pending) || (file_ext->read_cb != NULL)) {
659 DBG("read is pending.\n");
660 spin_unlock_bh(&file_ext->read_io_lock);
661 return -EBUSY;
662 }
663 spin_unlock_bh(&file_ext->read_io_lock);
664
665 priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
666 if (!priv_cb)
667 return -ENOMEM;
668
669 spin_lock_bh(&file_ext->read_io_lock);
670 DBG("allocation call back success\n"
671 "host client = %d, ME client = %d\n",
672 file_ext->host_client_id, file_ext->me_client_id);
673 spin_unlock_bh(&file_ext->read_io_lock);
674
675 spin_lock_bh(&dev->device_lock);
676 spin_lock_bh(&file_ext->read_io_lock);
677 for (i = 0; i < dev->num_heci_me_clients; i++) {
678 if (dev->me_clients[i].client_id == file_ext->me_client_id)
679 break;
680
681 }
682
683 BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
684 spin_unlock_bh(&file_ext->read_io_lock);
685 if (i == dev->num_heci_me_clients) {
686 rets = -ENODEV;
687 goto unlock;
688 }
689
690 priv_cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
691 spin_unlock_bh(&dev->device_lock);
692 priv_cb->response_buffer.data =
693 kmalloc(priv_cb->response_buffer.size, GFP_KERNEL);
694 if (!priv_cb->response_buffer.data) {
695 rets = -ENOMEM;
696 goto fail;
697 }
698 DBG("allocation call back data success.\n");
699 priv_cb->major_file_operations = HECI_READ;
700 /* make sure information is zero before we start */
701 priv_cb->information = 0;
702 priv_cb->file_private = (void *) file_ext;
703 spin_lock_bh(&dev->device_lock);
704 spin_lock_bh(&file_ext->read_io_lock);
705 file_ext->read_cb = priv_cb;
706 if (dev->host_buffer_is_empty) {
707 dev->host_buffer_is_empty = 0;
708 if (!heci_send_flow_control(dev, file_ext)) {
709 rets = -ENODEV;
710 spin_unlock_bh(&file_ext->read_io_lock);
711 goto unlock;
712 } else {
713 list_add_tail(&priv_cb->cb_list,
714 &dev->read_list.heci_cb.cb_list);
715 }
716 } else {
717 list_add_tail(&priv_cb->cb_list,
718 &dev->ctrl_wr_list.heci_cb.cb_list);
719 }
720 spin_unlock_bh(&file_ext->read_io_lock);
721 spin_unlock_bh(&dev->device_lock);
722 return rets;
723unlock:
724 spin_unlock_bh(&dev->device_lock);
725fail:
726 heci_free_cb_private(priv_cb);
727 return rets;
728}
729
730/**
731 * pthi_write - write iamthif data to pthi client
732 *
733 * @dev: Device object for our driver
734 * @priv_cb: heci call back struct
735 *
736 * returns 0 on success, <0 on failure.
737 */
738int pthi_write(struct iamt_heci_device *dev,
739 struct heci_cb_private *priv_cb)
740{
741 int rets = 0;
742 struct heci_msg_hdr heci_hdr;
743
744 if ((!dev) || (!priv_cb))
745 return -ENODEV;
746
747 DBG("write data to pthi client.\n");
748
749 dev->iamthif_state = HECI_IAMTHIF_WRITING;
750 dev->iamthif_current_cb = priv_cb;
751 dev->iamthif_file_object = priv_cb->file_object;
752 dev->iamthif_canceled = 0;
753 dev->iamthif_ioctl = 1;
754 dev->iamthif_msg_buf_size = priv_cb->request_buffer.size;
755 memcpy(dev->iamthif_msg_buf, priv_cb->request_buffer.data,
756 priv_cb->request_buffer.size);
757
758 if (flow_ctrl_creds(dev, &dev->iamthif_file_ext) &&
759 dev->host_buffer_is_empty) {
760 dev->host_buffer_is_empty = 0;
761 if (priv_cb->request_buffer.size >
762 (((dev->host_hw_state & H_CBD) >> 24) *
763 sizeof(__u32)) - sizeof(struct heci_msg_hdr)) {
764 heci_hdr.length =
765 (((dev->host_hw_state & H_CBD) >> 24) *
766 sizeof(__u32)) - sizeof(struct heci_msg_hdr);
767 heci_hdr.msg_complete = 0;
768 } else {
769 heci_hdr.length = priv_cb->request_buffer.size;
770 heci_hdr.msg_complete = 1;
771 }
772
773 heci_hdr.host_addr = dev->iamthif_file_ext.host_client_id;
774 heci_hdr.me_addr = dev->iamthif_file_ext.me_client_id;
775 heci_hdr.reserved = 0;
776 dev->iamthif_msg_buf_index += heci_hdr.length;
777 if (!heci_write_message(dev, &heci_hdr,
778 (unsigned char *)(dev->iamthif_msg_buf),
779 heci_hdr.length))
780 return -ENODEV;
781
782 if (heci_hdr.msg_complete) {
783 flow_ctrl_reduce(dev, &dev->iamthif_file_ext);
784 dev->iamthif_flow_control_pending = 1;
785 dev->iamthif_state = HECI_IAMTHIF_FLOW_CONTROL;
786 DBG("add pthi cb to write waiting list\n");
787 dev->iamthif_current_cb = priv_cb;
788 dev->iamthif_file_object = priv_cb->file_object;
789 list_add_tail(&priv_cb->cb_list,
790 &dev->write_waiting_list.heci_cb.cb_list);
791 } else {
792 DBG("message does not complete, "
793 "so add pthi cb to write list.\n");
794 list_add_tail(&priv_cb->cb_list,
795 &dev->write_list.heci_cb.cb_list);
796 }
797 } else {
798 if (!(dev->host_buffer_is_empty))
799 DBG("host buffer is not empty");
800
801 DBG("No flow control credentials, "
802 "so add iamthif cb to write list.\n");
803 list_add_tail(&priv_cb->cb_list,
804 &dev->write_list.heci_cb.cb_list);
805 }
806 return rets;
807}
808
809/**
810 * iamthif_ioctl_send_msg - send cmd data to pthi client
811 *
812 * @dev: Device object for our driver
813 *
814 * returns 0 on success, <0 on failure.
815 */
816void run_next_iamthif_cmd(struct iamt_heci_device *dev)
817{
818 struct heci_file_private *file_ext_tmp;
819 struct heci_cb_private *priv_cb_pos = NULL;
820 struct heci_cb_private *priv_cb_next = NULL;
821 int status = 0;
822
823 if (!dev)
824 return;
825
826 dev->iamthif_msg_buf_size = 0;
827 dev->iamthif_msg_buf_index = 0;
828 dev->iamthif_canceled = 0;
829 dev->iamthif_ioctl = 1;
830 dev->iamthif_state = HECI_IAMTHIF_IDLE;
831 dev->iamthif_timer = 0;
832 dev->iamthif_file_object = NULL;
833
834 if (dev->pthi_cmd_list.status == 0 &&
835 !list_empty(&dev->pthi_cmd_list.heci_cb.cb_list)) {
836 DBG("complete pthi cmd_list cb.\n");
837
838 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
839 &dev->pthi_cmd_list.heci_cb.cb_list, cb_list) {
840 list_del(&priv_cb_pos->cb_list);
841 file_ext_tmp = (struct heci_file_private *)
842 priv_cb_pos->file_private;
843
844 if ((file_ext_tmp != NULL) &&
845 (file_ext_tmp == &dev->iamthif_file_ext)) {
846 status = pthi_write(dev, priv_cb_pos);
847 if (status != 0) {
848 DBG("pthi write failed status = %d\n",
849 status);
850 return;
851 }
852 break;
853 }
854 }
855 }
856}
857
858/**
859 * heci_free_cb_private - free heci_cb_private related memory
860 *
861 * @priv_cb: heci callback struct
862 */
863void heci_free_cb_private(struct heci_cb_private *priv_cb)
864{
865 if (priv_cb == NULL)
866 return;
867
868 kfree(priv_cb->request_buffer.data);
869 kfree(priv_cb->response_buffer.data);
870 kfree(priv_cb);
871}
872