]> Pileus Git - ~andy/linux/blob - drivers/misc/mei/client.c
Merge tag 'sound-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
[~andy/linux] / drivers / misc / mei / client.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/pci.h>
18 #include <linux/sched.h>
19 #include <linux/wait.h>
20 #include <linux/delay.h>
21
22 #include <linux/mei.h>
23
24 #include "mei_dev.h"
25 #include "hbm.h"
26 #include "client.h"
27
28 /**
29  * mei_me_cl_by_uuid - locate index of me client
30  *
31  * @dev: mei device
32  * returns me client index or -ENOENT if not found
33  */
34 int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *uuid)
35 {
36         int i, res = -ENOENT;
37
38         for (i = 0; i < dev->me_clients_num; ++i)
39                 if (uuid_le_cmp(*uuid,
40                                 dev->me_clients[i].props.protocol_name) == 0) {
41                         res = i;
42                         break;
43                 }
44
45         return res;
46 }
47
48
49 /**
50  * mei_me_cl_by_id return index to me_clients for client_id
51  *
52  * @dev: the device structure
53  * @client_id: me client id
54  *
55  * Locking: called under "dev->device_lock" lock
56  *
57  * returns index on success, -ENOENT on failure.
58  */
59
60 int mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
61 {
62         int i;
63         for (i = 0; i < dev->me_clients_num; i++)
64                 if (dev->me_clients[i].client_id == client_id)
65                         break;
66         if (WARN_ON(dev->me_clients[i].client_id != client_id))
67                 return -ENOENT;
68
69         if (i == dev->me_clients_num)
70                 return -ENOENT;
71
72         return i;
73 }
74
75
76 /**
77  * mei_io_list_flush - removes list entry belonging to cl.
78  *
79  * @list:  An instance of our list structure
80  * @cl: host client
81  */
82 void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
83 {
84         struct mei_cl_cb *cb;
85         struct mei_cl_cb *next;
86
87         list_for_each_entry_safe(cb, next, &list->list, list) {
88                 if (cb->cl && mei_cl_cmp_id(cl, cb->cl))
89                         list_del(&cb->list);
90         }
91 }
92
93 /**
94  * mei_io_cb_free - free mei_cb_private related memory
95  *
96  * @cb: mei callback struct
97  */
98 void mei_io_cb_free(struct mei_cl_cb *cb)
99 {
100         if (cb == NULL)
101                 return;
102
103         kfree(cb->request_buffer.data);
104         kfree(cb->response_buffer.data);
105         kfree(cb);
106 }
107
108 /**
109  * mei_io_cb_init - allocate and initialize io callback
110  *
111  * @cl - mei client
112  * @file: pointer to file structure
113  *
114  * returns mei_cl_cb pointer or NULL;
115  */
116 struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
117 {
118         struct mei_cl_cb *cb;
119
120         cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
121         if (!cb)
122                 return NULL;
123
124         mei_io_list_init(cb);
125
126         cb->file_object = fp;
127         cb->cl = cl;
128         cb->buf_idx = 0;
129         return cb;
130 }
131
132 /**
133  * mei_io_cb_alloc_req_buf - allocate request buffer
134  *
135  * @cb -  io callback structure
136  * @size: size of the buffer
137  *
138  * returns 0 on success
139  *         -EINVAL if cb is NULL
140  *         -ENOMEM if allocation failed
141  */
142 int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
143 {
144         if (!cb)
145                 return -EINVAL;
146
147         if (length == 0)
148                 return 0;
149
150         cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
151         if (!cb->request_buffer.data)
152                 return -ENOMEM;
153         cb->request_buffer.size = length;
154         return 0;
155 }
156 /**
157  * mei_io_cb_alloc_req_buf - allocate respose buffer
158  *
159  * @cb -  io callback structure
160  * @size: size of the buffer
161  *
162  * returns 0 on success
163  *         -EINVAL if cb is NULL
164  *         -ENOMEM if allocation failed
165  */
166 int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
167 {
168         if (!cb)
169                 return -EINVAL;
170
171         if (length == 0)
172                 return 0;
173
174         cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
175         if (!cb->response_buffer.data)
176                 return -ENOMEM;
177         cb->response_buffer.size = length;
178         return 0;
179 }
180
181
182
183 /**
184  * mei_cl_flush_queues - flushes queue lists belonging to cl.
185  *
186  * @dev: the device structure
187  * @cl: host client
188  */
189 int mei_cl_flush_queues(struct mei_cl *cl)
190 {
191         if (WARN_ON(!cl || !cl->dev))
192                 return -EINVAL;
193
194         dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
195         mei_io_list_flush(&cl->dev->read_list, cl);
196         mei_io_list_flush(&cl->dev->write_list, cl);
197         mei_io_list_flush(&cl->dev->write_waiting_list, cl);
198         mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
199         mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
200         mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
201         mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
202         return 0;
203 }
204
205
206 /**
207  * mei_cl_init - initializes intialize cl.
208  *
209  * @cl: host client to be initialized
210  * @dev: mei device
211  */
212 void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
213 {
214         memset(cl, 0, sizeof(struct mei_cl));
215         init_waitqueue_head(&cl->wait);
216         init_waitqueue_head(&cl->rx_wait);
217         init_waitqueue_head(&cl->tx_wait);
218         INIT_LIST_HEAD(&cl->link);
219         cl->reading_state = MEI_IDLE;
220         cl->writing_state = MEI_IDLE;
221         cl->dev = dev;
222 }
223
224 /**
225  * mei_cl_allocate - allocates cl  structure and sets it up.
226  *
227  * @dev: mei device
228  * returns  The allocated file or NULL on failure
229  */
230 struct mei_cl *mei_cl_allocate(struct mei_device *dev)
231 {
232         struct mei_cl *cl;
233
234         cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
235         if (!cl)
236                 return NULL;
237
238         mei_cl_init(cl, dev);
239
240         return cl;
241 }
242
243 /**
244  * mei_cl_find_read_cb - find this cl's callback in the read list
245  *
246  * @dev: device structure
247  * returns cb on success, NULL on error
248  */
249 struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
250 {
251         struct mei_device *dev = cl->dev;
252         struct mei_cl_cb *cb = NULL;
253         struct mei_cl_cb *next = NULL;
254
255         list_for_each_entry_safe(cb, next, &dev->read_list.list, list)
256                 if (mei_cl_cmp_id(cl, cb->cl))
257                         return cb;
258         return NULL;
259 }
260
261 /** mei_cl_link: allocte host id in the host map
262  *
263  * @cl - host client
264  * @id - fixed host id or -1 for genereting one
265  * returns 0 on success
266  *      -EINVAL on incorrect values
267  *      -ENONET if client not found
268  */
269 int mei_cl_link(struct mei_cl *cl, int id)
270 {
271         struct mei_device *dev;
272
273         if (WARN_ON(!cl || !cl->dev))
274                 return -EINVAL;
275
276         dev = cl->dev;
277
278         /* If Id is not asigned get one*/
279         if (id == MEI_HOST_CLIENT_ID_ANY)
280                 id = find_first_zero_bit(dev->host_clients_map,
281                                         MEI_CLIENTS_MAX);
282
283         if (id >= MEI_CLIENTS_MAX) {
284                 dev_err(&dev->pdev->dev, "id exceded %d", MEI_CLIENTS_MAX) ;
285                 return -ENOENT;
286         }
287
288         dev->open_handle_count++;
289
290         cl->host_client_id = id;
291         list_add_tail(&cl->link, &dev->file_list);
292
293         set_bit(id, dev->host_clients_map);
294
295         cl->state = MEI_FILE_INITIALIZING;
296
297         dev_dbg(&dev->pdev->dev, "link cl host id = %d\n", cl->host_client_id);
298         return 0;
299 }
300
301 /**
302  * mei_cl_unlink - remove me_cl from the list
303  *
304  * @dev: the device structure
305  */
306 int mei_cl_unlink(struct mei_cl *cl)
307 {
308         struct mei_device *dev;
309         struct mei_cl *pos, *next;
310
311         /* don't shout on error exit path */
312         if (!cl)
313                 return 0;
314
315         /* wd and amthif might not be initialized */
316         if (!cl->dev)
317                 return 0;
318
319         dev = cl->dev;
320
321         list_for_each_entry_safe(pos, next, &dev->file_list, link) {
322                 if (cl->host_client_id == pos->host_client_id) {
323                         dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
324                                 pos->host_client_id, pos->me_client_id);
325                         list_del_init(&pos->link);
326                         break;
327                 }
328         }
329         return 0;
330 }
331
332
333 void mei_host_client_init(struct work_struct *work)
334 {
335         struct mei_device *dev = container_of(work,
336                                               struct mei_device, init_work);
337         struct mei_client_properties *client_props;
338         int i;
339
340         mutex_lock(&dev->device_lock);
341
342         bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
343         dev->open_handle_count = 0;
344
345         /*
346          * Reserving the first three client IDs
347          * 0: Reserved for MEI Bus Message communications
348          * 1: Reserved for Watchdog
349          * 2: Reserved for AMTHI
350          */
351         bitmap_set(dev->host_clients_map, 0, 3);
352
353         for (i = 0; i < dev->me_clients_num; i++) {
354                 client_props = &dev->me_clients[i].props;
355
356                 if (!uuid_le_cmp(client_props->protocol_name, mei_amthif_guid))
357                         mei_amthif_host_init(dev);
358                 else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
359                         mei_wd_host_init(dev);
360         }
361
362         dev->dev_state = MEI_DEV_ENABLED;
363
364         mutex_unlock(&dev->device_lock);
365 }
366
367
368 /**
369  * mei_cl_disconnect - disconnect host clinet form the me one
370  *
371  * @cl: host client
372  *
373  * Locking: called under "dev->device_lock" lock
374  *
375  * returns 0 on success, <0 on failure.
376  */
377 int mei_cl_disconnect(struct mei_cl *cl)
378 {
379         struct mei_device *dev;
380         struct mei_cl_cb *cb;
381         int rets, err;
382
383         if (WARN_ON(!cl || !cl->dev))
384                 return -ENODEV;
385
386         dev = cl->dev;
387
388         if (cl->state != MEI_FILE_DISCONNECTING)
389                 return 0;
390
391         cb = mei_io_cb_init(cl, NULL);
392         if (!cb)
393                 return -ENOMEM;
394
395         cb->fop_type = MEI_FOP_CLOSE;
396         if (dev->hbuf_is_ready) {
397                 dev->hbuf_is_ready = false;
398                 if (mei_hbm_cl_disconnect_req(dev, cl)) {
399                         rets = -ENODEV;
400                         dev_err(&dev->pdev->dev, "failed to disconnect.\n");
401                         goto free;
402                 }
403                 mdelay(10); /* Wait for hardware disconnection ready */
404                 list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
405         } else {
406                 dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
407                 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
408
409         }
410         mutex_unlock(&dev->device_lock);
411
412         err = wait_event_timeout(dev->wait_recvd_msg,
413                         MEI_FILE_DISCONNECTED == cl->state,
414                         mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
415
416         mutex_lock(&dev->device_lock);
417         if (MEI_FILE_DISCONNECTED == cl->state) {
418                 rets = 0;
419                 dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n");
420         } else {
421                 rets = -ENODEV;
422                 if (MEI_FILE_DISCONNECTED != cl->state)
423                         dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n");
424
425                 if (err)
426                         dev_dbg(&dev->pdev->dev,
427                                         "wait failed disconnect err=%08x\n",
428                                         err);
429
430                 dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
431         }
432
433         mei_io_list_flush(&dev->ctrl_rd_list, cl);
434         mei_io_list_flush(&dev->ctrl_wr_list, cl);
435 free:
436         mei_io_cb_free(cb);
437         return rets;
438 }
439
440
441 /**
442  * mei_cl_is_other_connecting - checks if other
443  *    client with the same me client id is connecting
444  *
445  * @cl: private data of the file object
446  *
447  * returns ture if other client is connected, 0 - otherwise.
448  */
449 bool mei_cl_is_other_connecting(struct mei_cl *cl)
450 {
451         struct mei_device *dev;
452         struct mei_cl *pos;
453         struct mei_cl *next;
454
455         if (WARN_ON(!cl || !cl->dev))
456                 return false;
457
458         dev = cl->dev;
459
460         list_for_each_entry_safe(pos, next, &dev->file_list, link) {
461                 if ((pos->state == MEI_FILE_CONNECTING) &&
462                     (pos != cl) && cl->me_client_id == pos->me_client_id)
463                         return true;
464
465         }
466
467         return false;
468 }
469
470 /**
471  * mei_cl_connect - connect host clinet to the me one
472  *
473  * @cl: host client
474  *
475  * Locking: called under "dev->device_lock" lock
476  *
477  * returns 0 on success, <0 on failure.
478  */
479 int mei_cl_connect(struct mei_cl *cl, struct file *file)
480 {
481         struct mei_device *dev;
482         struct mei_cl_cb *cb;
483         long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT);
484         int rets;
485
486         if (WARN_ON(!cl || !cl->dev))
487                 return -ENODEV;
488
489         dev = cl->dev;
490
491         cb = mei_io_cb_init(cl, file);
492         if (!cb) {
493                 rets = -ENOMEM;
494                 goto out;
495         }
496
497         cb->fop_type = MEI_FOP_IOCTL;
498
499         if (dev->hbuf_is_ready && !mei_cl_is_other_connecting(cl)) {
500                 dev->hbuf_is_ready = false;
501
502                 if (mei_hbm_cl_connect_req(dev, cl)) {
503                         rets = -ENODEV;
504                         goto out;
505                 }
506                 cl->timer_count = MEI_CONNECT_TIMEOUT;
507                 list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
508         } else {
509                 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
510         }
511
512         mutex_unlock(&dev->device_lock);
513         rets = wait_event_timeout(dev->wait_recvd_msg,
514                                  (cl->state == MEI_FILE_CONNECTED ||
515                                   cl->state == MEI_FILE_DISCONNECTED),
516                                  timeout * HZ);
517         mutex_lock(&dev->device_lock);
518
519         if (cl->state != MEI_FILE_CONNECTED) {
520                 rets = -EFAULT;
521
522                 mei_io_list_flush(&dev->ctrl_rd_list, cl);
523                 mei_io_list_flush(&dev->ctrl_wr_list, cl);
524                 goto out;
525         }
526
527         rets = cl->status;
528
529 out:
530         mei_io_cb_free(cb);
531         return rets;
532 }
533
534 /**
535  * mei_cl_flow_ctrl_creds - checks flow_control credits for cl.
536  *
537  * @dev: the device structure
538  * @cl: private data of the file object
539  *
540  * returns 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
541  *      -ENOENT if mei_cl is not present
542  *      -EINVAL if single_recv_buf == 0
543  */
544 int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
545 {
546         struct mei_device *dev;
547         int i;
548
549         if (WARN_ON(!cl || !cl->dev))
550                 return -EINVAL;
551
552         dev = cl->dev;
553
554         if (!dev->me_clients_num)
555                 return 0;
556
557         if (cl->mei_flow_ctrl_creds > 0)
558                 return 1;
559
560         for (i = 0; i < dev->me_clients_num; i++) {
561                 struct mei_me_client  *me_cl = &dev->me_clients[i];
562                 if (me_cl->client_id == cl->me_client_id) {
563                         if (me_cl->mei_flow_ctrl_creds) {
564                                 if (WARN_ON(me_cl->props.single_recv_buf == 0))
565                                         return -EINVAL;
566                                 return 1;
567                         } else {
568                                 return 0;
569                         }
570                 }
571         }
572         return -ENOENT;
573 }
574
575 /**
576  * mei_cl_flow_ctrl_reduce - reduces flow_control.
577  *
578  * @dev: the device structure
579  * @cl: private data of the file object
580  * @returns
581  *      0 on success
582  *      -ENOENT when me client is not found
583  *      -EINVAL when ctrl credits are <= 0
584  */
585 int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
586 {
587         struct mei_device *dev;
588         int i;
589
590         if (WARN_ON(!cl || !cl->dev))
591                 return -EINVAL;
592
593         dev = cl->dev;
594
595         if (!dev->me_clients_num)
596                 return -ENOENT;
597
598         for (i = 0; i < dev->me_clients_num; i++) {
599                 struct mei_me_client  *me_cl = &dev->me_clients[i];
600                 if (me_cl->client_id == cl->me_client_id) {
601                         if (me_cl->props.single_recv_buf != 0) {
602                                 if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0))
603                                         return -EINVAL;
604                                 dev->me_clients[i].mei_flow_ctrl_creds--;
605                         } else {
606                                 if (WARN_ON(cl->mei_flow_ctrl_creds <= 0))
607                                         return -EINVAL;
608                                 cl->mei_flow_ctrl_creds--;
609                         }
610                         return 0;
611                 }
612         }
613         return -ENOENT;
614 }
615
616 /**
617  * mei_cl_start_read - the start read client message function.
618  *
619  * @cl: host client
620  *
621  * returns 0 on success, <0 on failure.
622  */
623 int mei_cl_read_start(struct mei_cl *cl)
624 {
625         struct mei_device *dev;
626         struct mei_cl_cb *cb;
627         int rets;
628         int i;
629
630         if (WARN_ON(!cl || !cl->dev))
631                 return -ENODEV;
632
633         dev = cl->dev;
634
635         if (cl->state != MEI_FILE_CONNECTED)
636                 return -ENODEV;
637
638         if (dev->dev_state != MEI_DEV_ENABLED)
639                 return -ENODEV;
640
641         if (cl->read_cb) {
642                 dev_dbg(&dev->pdev->dev, "read is pending.\n");
643                 return -EBUSY;
644         }
645         i = mei_me_cl_by_id(dev, cl->me_client_id);
646         if (i < 0) {
647                 dev_err(&dev->pdev->dev, "no such me client %d\n",
648                         cl->me_client_id);
649                 return  -ENODEV;
650         }
651
652         cb = mei_io_cb_init(cl, NULL);
653         if (!cb)
654                 return -ENOMEM;
655
656         rets = mei_io_cb_alloc_resp_buf(cb,
657                         dev->me_clients[i].props.max_msg_length);
658         if (rets)
659                 goto err;
660
661         cb->fop_type = MEI_FOP_READ;
662         cl->read_cb = cb;
663         if (dev->hbuf_is_ready) {
664                 dev->hbuf_is_ready = false;
665                 if (mei_hbm_cl_flow_control_req(dev, cl)) {
666                         rets = -ENODEV;
667                         goto err;
668                 }
669                 list_add_tail(&cb->list, &dev->read_list.list);
670         } else {
671                 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
672         }
673         return rets;
674 err:
675         mei_io_cb_free(cb);
676         return rets;
677 }
678
679 /**
680  * mei_cl_all_disconnect - disconnect forcefully all connected clients
681  *
682  * @dev - mei device
683  */
684
685 void mei_cl_all_disconnect(struct mei_device *dev)
686 {
687         struct mei_cl *cl, *next;
688
689         list_for_each_entry_safe(cl, next, &dev->file_list, link) {
690                 cl->state = MEI_FILE_DISCONNECTED;
691                 cl->mei_flow_ctrl_creds = 0;
692                 cl->read_cb = NULL;
693                 cl->timer_count = 0;
694         }
695 }
696
697
698 /**
699  * mei_cl_all_read_wakeup  - wake up all readings so they can be interrupted
700  *
701  * @dev  - mei device
702  */
703 void mei_cl_all_read_wakeup(struct mei_device *dev)
704 {
705         struct mei_cl *cl, *next;
706         list_for_each_entry_safe(cl, next, &dev->file_list, link) {
707                 if (waitqueue_active(&cl->rx_wait)) {
708                         dev_dbg(&dev->pdev->dev, "Waking up client!\n");
709                         wake_up_interruptible(&cl->rx_wait);
710                 }
711         }
712 }
713
714 /**
715  * mei_cl_all_write_clear - clear all pending writes
716
717  * @dev - mei device
718  */
719 void mei_cl_all_write_clear(struct mei_device *dev)
720 {
721         struct mei_cl_cb *cb, *next;
722
723         list_for_each_entry_safe(cb, next, &dev->write_list.list, list) {
724                 list_del(&cb->list);
725                 mei_io_cb_free(cb);
726         }
727 }
728
729