mei: replace callback structures used as list head by list_head
[muen/linux.git] / drivers / misc / mei / amthif.c
1 /*
2  *
3  * Intel Management Engine Interface (Intel MEI) Linux driver
4  * Copyright (c) 2003-2012, Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/fs.h>
19 #include <linux/errno.h>
20 #include <linux/types.h>
21 #include <linux/fcntl.h>
22 #include <linux/ioctl.h>
23 #include <linux/cdev.h>
24 #include <linux/list.h>
25 #include <linux/delay.h>
26 #include <linux/sched.h>
27 #include <linux/uuid.h>
28 #include <linux/jiffies.h>
29 #include <linux/uaccess.h>
30 #include <linux/slab.h>
31
32 #include <linux/mei.h>
33
34 #include "mei_dev.h"
35 #include "hbm.h"
36 #include "client.h"
37
38 const uuid_le mei_amthif_guid  = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d,
39                                          0xac, 0xa8, 0x46, 0xe0,
40                                          0xff, 0x65, 0x81, 0x4c);
41
42 /**
43  * mei_amthif_reset_params - initializes mei device iamthif
44  *
45  * @dev: the device structure
46  */
47 void mei_amthif_reset_params(struct mei_device *dev)
48 {
49         /* reset iamthif parameters. */
50         dev->iamthif_canceled = false;
51         dev->iamthif_state = MEI_IAMTHIF_IDLE;
52         dev->iamthif_stall_timer = 0;
53         dev->iamthif_open_count = 0;
54 }
55
56 /**
57  * mei_amthif_host_init - mei initialization amthif client.
58  *
59  * @dev: the device structure
60  * @me_cl: me client
61  *
62  * Return: 0 on success, <0 on failure.
63  */
64 int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
65 {
66         struct mei_cl *cl = &dev->iamthif_cl;
67         int ret;
68
69         mutex_lock(&dev->device_lock);
70
71         if (mei_cl_is_connected(cl)) {
72                 ret = 0;
73                 goto out;
74         }
75
76         dev->iamthif_state = MEI_IAMTHIF_IDLE;
77
78         mei_cl_init(cl, dev);
79
80         ret = mei_cl_link(cl);
81         if (ret < 0) {
82                 dev_err(dev->dev, "amthif: failed cl_link %d\n", ret);
83                 goto out;
84         }
85
86         ret = mei_cl_connect(cl, me_cl, NULL);
87
88 out:
89         mutex_unlock(&dev->device_lock);
90         return ret;
91 }
92
93 /**
94  * mei_amthif_read_start - queue message for sending read credential
95  *
96  * @cl: host client
97  * @fp: file pointer of message recipient
98  *
99  * Return: 0 on success, <0 on failure.
100  */
101 static int mei_amthif_read_start(struct mei_cl *cl, const struct file *fp)
102 {
103         struct mei_device *dev = cl->dev;
104         struct mei_cl_cb *cb;
105
106         cb = mei_cl_enqueue_ctrl_wr_cb(cl, mei_cl_mtu(cl), MEI_FOP_READ, fp);
107         if (!cb)
108                 return -ENOMEM;
109
110         cl->rx_flow_ctrl_creds++;
111
112         dev->iamthif_state = MEI_IAMTHIF_READING;
113         cl->fp = cb->fp;
114
115         return 0;
116 }
117
118 /**
119  * mei_amthif_run_next_cmd - send next amt command from queue
120  *
121  * @dev: the device structure
122  *
123  * Return: 0 on success, <0 on failure.
124  */
125 int mei_amthif_run_next_cmd(struct mei_device *dev)
126 {
127         struct mei_cl *cl = &dev->iamthif_cl;
128         struct mei_cl_cb *cb;
129         int ret;
130
131         dev->iamthif_canceled = false;
132
133         dev_dbg(dev->dev, "complete amthif cmd_list cb.\n");
134
135         cb = list_first_entry_or_null(&dev->amthif_cmd_list, typeof(*cb), list);
136         if (!cb) {
137                 dev->iamthif_state = MEI_IAMTHIF_IDLE;
138                 cl->fp = NULL;
139                 return 0;
140         }
141
142         list_del_init(&cb->list);
143         dev->iamthif_state = MEI_IAMTHIF_WRITING;
144         cl->fp = cb->fp;
145
146         ret = mei_cl_write(cl, cb);
147         if (ret < 0)
148                 return ret;
149
150         if (cb->completed)
151                 cb->status = mei_amthif_read_start(cl, cb->fp);
152
153         return 0;
154 }
155
156 /**
157  * mei_amthif_write - write amthif data to amthif client
158  *
159  * @cl: host client
160  * @cb: mei call back struct
161  *
162  * Return: 0 on success, <0 on failure.
163  */
164 int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb)
165 {
166
167         struct mei_device *dev = cl->dev;
168
169         list_add_tail(&cb->list, &dev->amthif_cmd_list);
170
171         /*
172          * The previous request is still in processing, queue this one.
173          */
174         if (dev->iamthif_state != MEI_IAMTHIF_IDLE)
175                 return 0;
176
177         return mei_amthif_run_next_cmd(dev);
178 }
179
180 /**
181  * mei_amthif_poll - the amthif poll function
182  *
183  * @file: pointer to file structure
184  * @wait: pointer to poll_table structure
185  *
186  * Return: poll mask
187  *
188  * Locking: called under "dev->device_lock" lock
189  */
190 unsigned int mei_amthif_poll(struct file *file, poll_table *wait)
191 {
192         struct mei_cl *cl = file->private_data;
193         struct mei_cl_cb *cb = mei_cl_read_cb(cl, file);
194         unsigned int mask = 0;
195
196         poll_wait(file, &cl->rx_wait, wait);
197         if (cb)
198                 mask |= POLLIN | POLLRDNORM;
199
200         return mask;
201 }
202
203 /**
204  * mei_amthif_irq_write - write iamthif command in irq thread context.
205  *
206  * @cl: private data of the file object.
207  * @cb: callback block.
208  * @cmpl_list: complete list.
209  *
210  * Return: 0, OK; otherwise, error.
211  */
212 int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
213                          struct list_head *cmpl_list)
214 {
215         int ret;
216
217         ret = mei_cl_irq_write(cl, cb, cmpl_list);
218         if (ret)
219                 return ret;
220
221         if (cb->completed)
222                 cb->status = mei_amthif_read_start(cl, cb->fp);
223
224         return 0;
225 }
226
227 /**
228  * mei_amthif_irq_read_msg - read routine after ISR to
229  *                      handle the read amthif message
230  *
231  * @cl: mei client
232  * @mei_hdr: header of amthif message
233  * @cmpl_list: completed callbacks list
234  *
235  * Return: -ENODEV if cb is NULL 0 otherwise; error message is in cb->status
236  */
237 int mei_amthif_irq_read_msg(struct mei_cl *cl,
238                             struct mei_msg_hdr *mei_hdr,
239                             struct list_head *cmpl_list)
240 {
241         struct mei_device *dev;
242         int ret;
243
244         dev = cl->dev;
245
246         if (dev->iamthif_state != MEI_IAMTHIF_READING) {
247                 mei_irq_discard_msg(dev, mei_hdr);
248                 return 0;
249         }
250
251         ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
252         if (ret)
253                 return ret;
254
255         if (!mei_hdr->msg_complete)
256                 return 0;
257
258         dev_dbg(dev->dev, "completed amthif read.\n ");
259         dev->iamthif_stall_timer = 0;
260
261         return 0;
262 }
263
264 /**
265  * mei_amthif_complete - complete amthif callback.
266  *
267  * @cl: host client
268  * @cb: callback block.
269  */
270 void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
271 {
272         struct mei_device *dev = cl->dev;
273
274         dev_dbg(dev->dev, "completing amthif call back.\n");
275         switch (cb->fop_type) {
276         case MEI_FOP_WRITE:
277                 if (!cb->status) {
278                         dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
279                         mei_schedule_stall_timer(dev);
280                         mei_io_cb_free(cb);
281                         return;
282                 }
283                 dev->iamthif_state = MEI_IAMTHIF_IDLE;
284                 cl->fp = NULL;
285                 if (!dev->iamthif_canceled) {
286                         /*
287                          * in case of error enqueue the write cb to complete
288                          * read list so it can be propagated to the reader
289                          */
290                         list_add_tail(&cb->list, &cl->rd_completed);
291                         wake_up_interruptible(&cl->rx_wait);
292                 } else {
293                         mei_io_cb_free(cb);
294                 }
295                 break;
296         case MEI_FOP_READ:
297                 if (!dev->iamthif_canceled) {
298                         list_add_tail(&cb->list, &cl->rd_completed);
299                         dev_dbg(dev->dev, "amthif read completed\n");
300                         wake_up_interruptible(&cl->rx_wait);
301                 } else {
302                         mei_io_cb_free(cb);
303                 }
304
305                 dev->iamthif_stall_timer = 0;
306                 mei_amthif_run_next_cmd(dev);
307                 break;
308         default:
309                 WARN_ON(1);
310         }
311 }
312
313 /**
314  * mei_clear_list - removes all callbacks associated with file
315  *              from mei_cb_list
316  *
317  * @file: file structure
318  * @mei_cb_list: callbacks list
319  *
320  * mei_clear_list is called to clear resources associated with file
321  * when application calls close function or Ctrl-C was pressed
322  */
323 static void mei_clear_list(const struct file *file,
324                            struct list_head *mei_cb_list)
325 {
326         struct mei_cl_cb *cb, *next;
327
328         list_for_each_entry_safe(cb, next, mei_cb_list, list)
329                 if (file == cb->fp)
330                         mei_io_cb_free(cb);
331 }
332
333 /**
334 * mei_amthif_release - the release function
335 *
336 *  @dev: device structure
337 *  @file: pointer to file structure
338 *
339 *  Return: 0 on success, <0 on error
340 */
341 int mei_amthif_release(struct mei_device *dev, struct file *file)
342 {
343         struct mei_cl *cl = file->private_data;
344
345         if (dev->iamthif_open_count > 0)
346                 dev->iamthif_open_count--;
347
348         if (cl->fp == file && dev->iamthif_state != MEI_IAMTHIF_IDLE) {
349
350                 dev_dbg(dev->dev, "amthif canceled iamthif state %d\n",
351                     dev->iamthif_state);
352                 dev->iamthif_canceled = true;
353         }
354
355         /* Don't clean ctrl_rd_list here, the reads has to be completed */
356         mei_clear_list(file, &dev->amthif_cmd_list);
357         mei_clear_list(file, &cl->rd_completed);
358
359         return 0;
360 }