Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
iorw.c
Go to the documentation of this file.
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 
18 #include <linux/kernel.h>
19 #include <linux/fs.h>
20 #include <linux/errno.h>
21 #include <linux/types.h>
22 #include <linux/fcntl.h>
23 #include <linux/aio.h>
24 #include <linux/pci.h>
25 #include <linux/init.h>
26 #include <linux/ioctl.h>
27 #include <linux/cdev.h>
28 #include <linux/list.h>
29 #include <linux/delay.h>
30 #include <linux/sched.h>
31 #include <linux/uuid.h>
32 #include <linux/jiffies.h>
33 #include <linux/uaccess.h>
34 
35 
36 #include "mei_dev.h"
37 #include "hw.h"
38 #include <linux/mei.h>
39 #include "interface.h"
40 
53 {
54  int i;
55  for (i = 0; i < dev->me_clients_num; i++)
56  if (dev->me_clients[i].client_id == client_id)
57  break;
58  if (WARN_ON(dev->me_clients[i].client_id != client_id))
59  return -ENOENT;
60 
61  if (i == dev->me_clients_num)
62  return -ENOENT;
63 
64  return i;
65 }
66 
80 {
81  struct mei_device *dev;
82  struct mei_cl_cb *cb;
83  struct mei_client *client;
84  struct mei_cl *cl;
85  struct mei_cl *cl_pos = NULL;
86  struct mei_cl *cl_next = NULL;
87  long timeout = CONNECT_TIMEOUT;
88  int i;
89  int err;
90  int rets;
91 
92  cl = file->private_data;
93  if (WARN_ON(!cl || !cl->dev))
94  return -ENODEV;
95 
96  dev = cl->dev;
97 
98  dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n");
99 
100 
101  /* buffered ioctl cb */
102  cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
103  if (!cb) {
104  rets = -ENOMEM;
105  goto end;
106  }
107  INIT_LIST_HEAD(&cb->cb_list);
108 
110 
111  if (dev->dev_state != MEI_DEV_ENABLED) {
112  rets = -ENODEV;
113  goto end;
114  }
115  if (cl->state != MEI_FILE_INITIALIZING &&
116  cl->state != MEI_FILE_DISCONNECTED) {
117  rets = -EBUSY;
118  goto end;
119  }
120 
121  /* find ME client we're trying to connect to */
122  i = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
123  if (i >= 0 && !dev->me_clients[i].props.fixed_address) {
124  cl->me_client_id = dev->me_clients[i].client_id;
126  }
127 
128  dev_dbg(&dev->pdev->dev, "Connect to FW Client ID = %d\n",
129  cl->me_client_id);
130  dev_dbg(&dev->pdev->dev, "FW Client - Protocol Version = %d\n",
131  dev->me_clients[i].props.protocol_version);
132  dev_dbg(&dev->pdev->dev, "FW Client - Max Msg Len = %d\n",
133  dev->me_clients[i].props.max_msg_length);
134 
135  /* if we're connecting to amthi client then we will use the
136  * existing connection
137  */
138  if (uuid_le_cmp(data->in_client_uuid, mei_amthi_guid) == 0) {
139  dev_dbg(&dev->pdev->dev, "FW Client is amthi\n");
140  if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
141  rets = -ENODEV;
142  goto end;
143  }
144  clear_bit(cl->host_client_id, dev->host_clients_map);
145  list_for_each_entry_safe(cl_pos, cl_next,
146  &dev->file_list, link) {
147  if (mei_cl_cmp_id(cl, cl_pos)) {
148  dev_dbg(&dev->pdev->dev,
149  "remove file private data node host"
150  " client = %d, ME client = %d.\n",
151  cl_pos->host_client_id,
152  cl_pos->me_client_id);
153  list_del(&cl_pos->link);
154  }
155 
156  }
157  dev_dbg(&dev->pdev->dev, "free file private data memory.\n");
158  kfree(cl);
159 
160  cl = NULL;
161  file->private_data = &dev->iamthif_cl;
162 
163  client = &data->out_client_properties;
164  client->max_msg_length =
165  dev->me_clients[i].props.max_msg_length;
166  client->protocol_version =
167  dev->me_clients[i].props.protocol_version;
168  rets = dev->iamthif_cl.status;
169 
170  goto end;
171  }
172 
173  if (cl->state != MEI_FILE_CONNECTING) {
174  rets = -ENODEV;
175  goto end;
176  }
177 
178 
179  /* prepare the output buffer */
180  client = &data->out_client_properties;
181  client->max_msg_length = dev->me_clients[i].props.max_msg_length;
182  client->protocol_version = dev->me_clients[i].props.protocol_version;
183  dev_dbg(&dev->pdev->dev, "Can connect?\n");
184  if (dev->mei_host_buffer_is_empty
185  && !mei_other_client_is_connecting(dev, cl)) {
186  dev_dbg(&dev->pdev->dev, "Sending Connect Message\n");
187  dev->mei_host_buffer_is_empty = false;
188  if (mei_connect(dev, cl)) {
189  dev_dbg(&dev->pdev->dev, "Sending connect message - failed\n");
190  rets = -ENODEV;
191  goto end;
192  } else {
193  dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n");
195  cb->file_private = cl;
196  list_add_tail(&cb->cb_list,
197  &dev->ctrl_rd_list.mei_cb.
198  cb_list);
199  }
200 
201 
202  } else {
203  dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n");
204  cb->file_private = cl;
205  dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n");
206  list_add_tail(&cb->cb_list,
207  &dev->ctrl_wr_list.mei_cb.cb_list);
208  }
209  mutex_unlock(&dev->device_lock);
211  (MEI_FILE_CONNECTED == cl->state ||
213  timeout * HZ);
214 
215  mutex_lock(&dev->device_lock);
216  if (MEI_FILE_CONNECTED == cl->state) {
217  dev_dbg(&dev->pdev->dev, "successfully connected to FW client.\n");
218  rets = cl->status;
219  goto end;
220  } else {
221  dev_dbg(&dev->pdev->dev, "failed to connect to FW client.cl->state = %d.\n",
222  cl->state);
223  if (!err) {
224  dev_dbg(&dev->pdev->dev,
225  "wait_event_interruptible_timeout failed on client"
226  " connect message fw response message.\n");
227  }
228  rets = -EFAULT;
229 
230  mei_io_list_flush(&dev->ctrl_rd_list, cl);
231  mei_io_list_flush(&dev->ctrl_wr_list, cl);
232  goto end;
233  }
234  rets = 0;
235 end:
236  dev_dbg(&dev->pdev->dev, "free connect cb memory.");
237  kfree(cb);
238  return rets;
239 }
240 
250  struct mei_device *dev,
251  struct file *file)
252 {
253  struct mei_cl *cl_temp;
254  struct mei_cl_cb *pos = NULL;
255  struct mei_cl_cb *next = NULL;
256 
257  list_for_each_entry_safe(pos, next,
258  &dev->amthi_read_complete_list.mei_cb.cb_list, cb_list) {
259  cl_temp = (struct mei_cl *)pos->file_private;
260  if (cl_temp && cl_temp == &dev->iamthif_cl &&
261  pos->file_object == file)
262  return pos;
263  }
264  return NULL;
265 }
266 
284 int amthi_read(struct mei_device *dev, struct file *file,
285  char __user *ubuf, size_t length, loff_t *offset)
286 {
287  int rets;
288  int wait_ret;
289  struct mei_cl_cb *cb = NULL;
290  struct mei_cl *cl = file->private_data;
291  unsigned long timeout;
292  int i;
293 
294  /* Only Posible if we are in timeout */
295  if (!cl || cl != &dev->iamthif_cl) {
296  dev_dbg(&dev->pdev->dev, "bad file ext.\n");
297  return -ETIMEDOUT;
298  }
299 
300  i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
301 
302  if (i < 0) {
303  dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
304  return -ENODEV;
305  }
306  dev_dbg(&dev->pdev->dev, "checking amthi data\n");
307  cb = find_amthi_read_list_entry(dev, file);
308 
309  /* Check for if we can block or not*/
310  if (cb == NULL && file->f_flags & O_NONBLOCK)
311  return -EAGAIN;
312 
313 
314  dev_dbg(&dev->pdev->dev, "waiting for amthi data\n");
315  while (cb == NULL) {
316  /* unlock the Mutex */
317  mutex_unlock(&dev->device_lock);
318 
319  wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
320  (cb = find_amthi_read_list_entry(dev, file)));
321 
322  if (wait_ret)
323  return -ERESTARTSYS;
324 
325  dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
326 
327  /* Locking again the Mutex */
328  mutex_lock(&dev->device_lock);
329  }
330 
331 
332  dev_dbg(&dev->pdev->dev, "Got amthi data\n");
333  dev->iamthif_timer = 0;
334 
335  if (cb) {
337  dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
338  timeout);
339 
340  if (time_after(jiffies, timeout)) {
341  dev_dbg(&dev->pdev->dev, "amthi Time out\n");
342  /* 15 sec for the message has expired */
343  list_del(&cb->cb_list);
344  rets = -ETIMEDOUT;
345  goto free;
346  }
347  }
348  /* if the whole message will fit remove it from the list */
349  if (cb->information >= *offset && length >= (cb->information - *offset))
350  list_del(&cb->cb_list);
351  else if (cb->information > 0 && cb->information <= *offset) {
352  /* end of the message has been reached */
353  list_del(&cb->cb_list);
354  rets = 0;
355  goto free;
356  }
357  /* else means that not full buffer will be read and do not
358  * remove message from deletion list
359  */
360 
361  dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
362  cb->response_buffer.size);
363  dev_dbg(&dev->pdev->dev, "amthi cb->information - %lu\n",
364  cb->information);
365 
366  /* length is being turncated to PAGE_SIZE, however,
367  * the information may be longer */
368  length = min_t(size_t, length, (cb->information - *offset));
369 
370  if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
371  rets = -EFAULT;
372  else {
373  rets = length;
374  if ((*offset + length) < cb->information) {
375  *offset += length;
376  goto out;
377  }
378  }
379 free:
380  dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
381  *offset = 0;
383 out:
384  return rets;
385 }
386 
396 int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
397 {
398  struct mei_cl_cb *cb;
399  int rets = 0;
400  int i;
401 
402  if (cl->state != MEI_FILE_CONNECTED)
403  return -ENODEV;
404 
405  if (dev->dev_state != MEI_DEV_ENABLED)
406  return -ENODEV;
407 
408  dev_dbg(&dev->pdev->dev, "check if read is pending.\n");
409  if (cl->read_pending || cl->read_cb) {
410  dev_dbg(&dev->pdev->dev, "read is pending.\n");
411  return -EBUSY;
412  }
413 
414  cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
415  if (!cb)
416  return -ENOMEM;
417 
418  dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
419  cl->host_client_id, cl->me_client_id);
420  i = mei_me_cl_by_id(dev, cl->me_client_id);
421  if (i < 0) {
422  rets = -ENODEV;
423  goto unlock;
424  }
425 
426  cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
427  cb->response_buffer.data =
429  if (!cb->response_buffer.data) {
430  rets = -ENOMEM;
431  goto unlock;
432  }
433  dev_dbg(&dev->pdev->dev, "allocation call back data success.\n");
435  /* make sure information is zero before we start */
436  cb->information = 0;
437  cb->file_private = (void *) cl;
438  cl->read_cb = cb;
439  if (dev->mei_host_buffer_is_empty) {
440  dev->mei_host_buffer_is_empty = false;
441  if (mei_send_flow_control(dev, cl)) {
442  rets = -ENODEV;
443  goto unlock;
444  }
445  list_add_tail(&cb->cb_list, &dev->read_list.mei_cb.cb_list);
446  } else {
447  list_add_tail(&cb->cb_list, &dev->ctrl_wr_list.mei_cb.cb_list);
448  }
449  return rets;
450 unlock:
452  return rets;
453 }
454 
463 int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
464 {
465  struct mei_msg_hdr mei_hdr;
466  int ret;
467 
468  if (!dev || !cb)
469  return -ENODEV;
470 
471  dev_dbg(&dev->pdev->dev, "write data to amthi client.\n");
472 
474  dev->iamthif_current_cb = cb;
475  dev->iamthif_file_object = cb->file_object;
476  dev->iamthif_canceled = false;
477  dev->iamthif_ioctl = true;
478  dev->iamthif_msg_buf_size = cb->request_buffer.size;
479  memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
480  cb->request_buffer.size);
481 
482  ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
483  if (ret < 0)
484  return ret;
485 
486  if (ret && dev->mei_host_buffer_is_empty) {
487  ret = 0;
488  dev->mei_host_buffer_is_empty = false;
489  if (cb->request_buffer.size > mei_hbuf_max_data(dev)) {
490  mei_hdr.length = mei_hbuf_max_data(dev);
491  mei_hdr.msg_complete = 0;
492  } else {
493  mei_hdr.length = cb->request_buffer.size;
494  mei_hdr.msg_complete = 1;
495  }
496 
497  mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
498  mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
499  mei_hdr.reserved = 0;
500  dev->iamthif_msg_buf_index += mei_hdr.length;
501  if (mei_write_message(dev, &mei_hdr,
502  (unsigned char *)(dev->iamthif_msg_buf),
503  mei_hdr.length))
504  return -ENODEV;
505 
506  if (mei_hdr.msg_complete) {
507  if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
508  return -ENODEV;
509  dev->iamthif_flow_control_pending = true;
511  dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
512  dev->iamthif_current_cb = cb;
513  dev->iamthif_file_object = cb->file_object;
514  list_add_tail(&cb->cb_list,
515  &dev->write_waiting_list.mei_cb.cb_list);
516  } else {
517  dev_dbg(&dev->pdev->dev, "message does not complete, "
518  "so add amthi cb to write list.\n");
519  list_add_tail(&cb->cb_list,
520  &dev->write_list.mei_cb.cb_list);
521  }
522  } else {
523  if (!(dev->mei_host_buffer_is_empty))
524  dev_dbg(&dev->pdev->dev, "host buffer is not empty");
525 
526  dev_dbg(&dev->pdev->dev, "No flow control credentials, "
527  "so add iamthif cb to write list.\n");
528  list_add_tail(&cb->cb_list, &dev->write_list.mei_cb.cb_list);
529  }
530  return 0;
531 }
532 
541 {
542  struct mei_cl *cl_tmp;
543  struct mei_cl_cb *pos = NULL;
544  struct mei_cl_cb *next = NULL;
545  int status;
546 
547  if (!dev)
548  return;
549 
550  dev->iamthif_msg_buf_size = 0;
551  dev->iamthif_msg_buf_index = 0;
552  dev->iamthif_canceled = false;
553  dev->iamthif_ioctl = true;
555  dev->iamthif_timer = 0;
556  dev->iamthif_file_object = NULL;
557 
558  dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
559 
560  list_for_each_entry_safe(pos, next,
561  &dev->amthi_cmd_list.mei_cb.cb_list, cb_list) {
562  list_del(&pos->cb_list);
563  cl_tmp = (struct mei_cl *)pos->file_private;
564 
565  if (cl_tmp && cl_tmp == &dev->iamthif_cl) {
566  status = amthi_write(dev, pos);
567  if (status) {
568  dev_dbg(&dev->pdev->dev,
569  "amthi write failed status = %d\n",
570  status);
571  return;
572  }
573  break;
574  }
575  }
576 }
577 
584 {
585  if (cb == NULL)
586  return;
587 
588  kfree(cb->request_buffer.data);
589  kfree(cb->response_buffer.data);
590  kfree(cb);
591 }