fs: move struct kiocb to fs.h
[linux-2.6-block.git] / drivers / misc / mei / main.c
CommitLineData
ab841160
OW
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
733ba91c 4 * Copyright (c) 2003-2012, Intel Corporation.
ab841160
OW
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 */
ab841160
OW
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/kernel.h>
19#include <linux/device.h>
1f180359 20#include <linux/slab.h>
ab841160
OW
21#include <linux/fs.h>
22#include <linux/errno.h>
23#include <linux/types.h>
24#include <linux/fcntl.h>
ab841160
OW
25#include <linux/poll.h>
26#include <linux/init.h>
27#include <linux/ioctl.h>
28#include <linux/cdev.h>
ab841160
OW
29#include <linux/sched.h>
30#include <linux/uuid.h>
31#include <linux/compat.h>
32#include <linux/jiffies.h>
33#include <linux/interrupt.h>
34
4f3afe1d 35#include <linux/mei.h>
47a73801
TW
36
37#include "mei_dev.h"
90e0b5f1 38#include "client.h"
ab841160 39
ab841160
OW
40/**
41 * mei_open - the open function
42 *
43 * @inode: pointer to inode structure
44 * @file: pointer to file structure
83ce0741 45 *
a8605ea2 46 * Return: 0 on success, <0 on error
ab841160
OW
47 */
48static int mei_open(struct inode *inode, struct file *file)
49{
ab841160 50 struct mei_device *dev;
f3d8e878 51 struct mei_cl *cl;
2703d4b2 52
6f37aca8 53 int err;
ab841160 54
f3d8e878 55 dev = container_of(inode->i_cdev, struct mei_device, cdev);
5b881e3c 56 if (!dev)
e036cc57 57 return -ENODEV;
ab841160
OW
58
59 mutex_lock(&dev->device_lock);
e036cc57
TW
60
61 cl = NULL;
ab841160
OW
62
63 err = -ENODEV;
b210d750 64 if (dev->dev_state != MEI_DEV_ENABLED) {
2bf94cab 65 dev_dbg(dev->dev, "dev_state != MEI_ENABLED dev_state = %s\n",
b210d750 66 mei_dev_state_str(dev->dev_state));
e036cc57 67 goto err_unlock;
1b812947 68 }
ab841160 69
e036cc57
TW
70 err = -ENOMEM;
71 cl = mei_cl_allocate(dev);
72 if (!cl)
73 goto err_unlock;
74
75 /* open_handle_count check is handled in the mei_cl_link */
781d0d89
TW
76 err = mei_cl_link(cl, MEI_HOST_CLIENT_ID_ANY);
77 if (err)
e036cc57 78 goto err_unlock;
ab841160
OW
79
80 file->private_data = cl;
e036cc57 81
ab841160
OW
82 mutex_unlock(&dev->device_lock);
83
5b881e3c 84 return nonseekable_open(inode, file);
ab841160 85
e036cc57 86err_unlock:
ab841160
OW
87 mutex_unlock(&dev->device_lock);
88 kfree(cl);
ab841160
OW
89 return err;
90}
91
92/**
93 * mei_release - the release function
94 *
95 * @inode: pointer to inode structure
96 * @file: pointer to file structure
97 *
a8605ea2 98 * Return: 0 on success, <0 on error
ab841160
OW
99 */
100static int mei_release(struct inode *inode, struct file *file)
101{
102 struct mei_cl *cl = file->private_data;
103 struct mei_cl_cb *cb;
104 struct mei_device *dev;
105 int rets = 0;
106
107 if (WARN_ON(!cl || !cl->dev))
108 return -ENODEV;
109
110 dev = cl->dev;
111
112 mutex_lock(&dev->device_lock);
a562d5c2
TW
113 if (cl == &dev->iamthif_cl) {
114 rets = mei_amthif_release(dev, file);
115 goto out;
116 }
117 if (cl->state == MEI_FILE_CONNECTED) {
118 cl->state = MEI_FILE_DISCONNECTING;
46922186 119 cl_dbg(dev, cl, "disconnecting\n");
90e0b5f1 120 rets = mei_cl_disconnect(cl);
a562d5c2
TW
121 }
122 mei_cl_flush_queues(cl);
46922186 123 cl_dbg(dev, cl, "removing\n");
a562d5c2 124
90e0b5f1 125 mei_cl_unlink(cl);
a562d5c2 126
781d0d89 127
a562d5c2
TW
128 /* free read cb */
129 cb = NULL;
130 if (cl->read_cb) {
90e0b5f1 131 cb = mei_cl_find_read_cb(cl);
a562d5c2
TW
132 /* Remove entry from read list */
133 if (cb)
134 list_del(&cb->list);
135
136 cb = cl->read_cb;
137 cl->read_cb = NULL;
138 }
ab841160 139
a562d5c2 140 file->private_data = NULL;
ab841160 141
a9c8a17a 142 mei_io_cb_free(cb);
a562d5c2
TW
143
144 kfree(cl);
145out:
ab841160
OW
146 mutex_unlock(&dev->device_lock);
147 return rets;
148}
149
150
151/**
152 * mei_read - the read function.
153 *
154 * @file: pointer to file structure
155 * @ubuf: pointer to user buffer
156 * @length: buffer length
157 * @offset: data offset in buffer
158 *
a8605ea2 159 * Return: >=0 data length on success , <0 on error
ab841160
OW
160 */
161static ssize_t mei_read(struct file *file, char __user *ubuf,
441ab50f 162 size_t length, loff_t *offset)
ab841160
OW
163{
164 struct mei_cl *cl = file->private_data;
165 struct mei_cl_cb *cb_pos = NULL;
166 struct mei_cl_cb *cb = NULL;
167 struct mei_device *dev;
ab841160
OW
168 int rets;
169 int err;
170
171
172 if (WARN_ON(!cl || !cl->dev))
173 return -ENODEV;
174
175 dev = cl->dev;
176
dd5de1f1 177
ab841160 178 mutex_lock(&dev->device_lock);
b210d750 179 if (dev->dev_state != MEI_DEV_ENABLED) {
ab841160
OW
180 rets = -ENODEV;
181 goto out;
182 }
183
dd5de1f1
TW
184 if (length == 0) {
185 rets = 0;
186 goto out;
187 }
188
ab841160 189 if (cl == &dev->iamthif_cl) {
19838fb8 190 rets = mei_amthif_read(dev, file, ubuf, length, offset);
ab841160
OW
191 goto out;
192 }
193
139aacf7 194 if (cl->read_cb) {
ab841160 195 cb = cl->read_cb;
139aacf7
TW
196 /* read what left */
197 if (cb->buf_idx > *offset)
198 goto copy_buffer;
199 /* offset is beyond buf_idx we have no more data return 0 */
200 if (cb->buf_idx > 0 && cb->buf_idx <= *offset) {
201 rets = 0;
202 goto free;
203 }
204 /* Offset needs to be cleaned for contiguous reads*/
205 if (cb->buf_idx == 0 && *offset > 0)
206 *offset = 0;
207 } else if (*offset > 0) {
ab841160 208 *offset = 0;
ab841160
OW
209 }
210
fcb136e1 211 err = mei_cl_read_start(cl, length);
ab841160 212 if (err && err != -EBUSY) {
2bf94cab 213 dev_dbg(dev->dev,
ab841160
OW
214 "mei start read failure with status = %d\n", err);
215 rets = err;
216 goto out;
217 }
218
219 if (MEI_READ_COMPLETE != cl->reading_state &&
220 !waitqueue_active(&cl->rx_wait)) {
221 if (file->f_flags & O_NONBLOCK) {
222 rets = -EAGAIN;
223 goto out;
224 }
225
226 mutex_unlock(&dev->device_lock);
227
228 if (wait_event_interruptible(cl->rx_wait,
e2b31644
TW
229 MEI_READ_COMPLETE == cl->reading_state ||
230 mei_cl_is_transitioning(cl))) {
231
ab841160
OW
232 if (signal_pending(current))
233 return -EINTR;
234 return -ERESTARTSYS;
235 }
236
237 mutex_lock(&dev->device_lock);
e2b31644 238 if (mei_cl_is_transitioning(cl)) {
ab841160
OW
239 rets = -EBUSY;
240 goto out;
241 }
242 }
243
244 cb = cl->read_cb;
245
246 if (!cb) {
247 rets = -ENODEV;
248 goto out;
249 }
250 if (cl->reading_state != MEI_READ_COMPLETE) {
251 rets = 0;
252 goto out;
253 }
254 /* now copy the data to user space */
255copy_buffer:
2bf94cab 256 dev_dbg(dev->dev, "buf.size = %d buf.idx= %ld\n",
fcb136e1 257 cb->response_buffer.size, cb->buf_idx);
ebb108ef 258 if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) {
ab841160
OW
259 rets = -EMSGSIZE;
260 goto free;
261 }
262
ebb108ef
TW
263 /* length is being truncated to PAGE_SIZE,
264 * however buf_idx may point beyond that */
265 length = min_t(size_t, length, cb->buf_idx - *offset);
ab841160 266
441ab50f 267 if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
2bf94cab 268 dev_dbg(dev->dev, "failed to copy data to userland\n");
ab841160
OW
269 rets = -EFAULT;
270 goto free;
271 }
272
273 rets = length;
274 *offset += length;
ebb108ef 275 if ((unsigned long)*offset < cb->buf_idx)
ab841160
OW
276 goto out;
277
278free:
90e0b5f1 279 cb_pos = mei_cl_find_read_cb(cl);
ab841160
OW
280 /* Remove entry from read list */
281 if (cb_pos)
fb601adb 282 list_del(&cb_pos->list);
601a1efa 283 mei_io_cb_free(cb);
ab841160
OW
284 cl->reading_state = MEI_IDLE;
285 cl->read_cb = NULL;
ab841160 286out:
2bf94cab 287 dev_dbg(dev->dev, "end mei read rets= %d\n", rets);
ab841160
OW
288 mutex_unlock(&dev->device_lock);
289 return rets;
290}
ab841160
OW
291/**
292 * mei_write - the write function.
293 *
294 * @file: pointer to file structure
295 * @ubuf: pointer to user buffer
296 * @length: buffer length
297 * @offset: data offset in buffer
298 *
a8605ea2 299 * Return: >=0 data length on success , <0 on error
ab841160
OW
300 */
301static ssize_t mei_write(struct file *file, const char __user *ubuf,
441ab50f 302 size_t length, loff_t *offset)
ab841160
OW
303{
304 struct mei_cl *cl = file->private_data;
79563db9 305 struct mei_me_client *me_cl = NULL;
ab841160 306 struct mei_cl_cb *write_cb = NULL;
ab841160
OW
307 struct mei_device *dev;
308 unsigned long timeout = 0;
309 int rets;
ab841160
OW
310
311 if (WARN_ON(!cl || !cl->dev))
312 return -ENODEV;
313
314 dev = cl->dev;
315
316 mutex_lock(&dev->device_lock);
317
b210d750 318 if (dev->dev_state != MEI_DEV_ENABLED) {
75f0ee15 319 rets = -ENODEV;
4234a6de 320 goto out;
ab841160
OW
321 }
322
d880f329 323 me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
d320832f 324 if (!me_cl) {
7ca96aa2 325 rets = -ENOTTY;
4234a6de 326 goto out;
75f0ee15 327 }
dd5de1f1
TW
328
329 if (length == 0) {
330 rets = 0;
331 goto out;
332 }
333
d320832f 334 if (length > me_cl->props.max_msg_length) {
dd5de1f1 335 rets = -EFBIG;
4234a6de 336 goto out;
75f0ee15
TW
337 }
338
339 if (cl->state != MEI_FILE_CONNECTED) {
2bf94cab 340 dev_err(dev->dev, "host client = %d, is not connected to ME client = %d",
75f0ee15 341 cl->host_client_id, cl->me_client_id);
4234a6de
TW
342 rets = -ENODEV;
343 goto out;
75f0ee15 344 }
ab841160 345 if (cl == &dev->iamthif_cl) {
19838fb8 346 write_cb = mei_amthif_find_read_list_entry(dev, file);
ab841160
OW
347
348 if (write_cb) {
349 timeout = write_cb->read_time +
3870c320 350 mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
ab841160
OW
351
352 if (time_after(jiffies, timeout) ||
75f0ee15
TW
353 cl->reading_state == MEI_READ_COMPLETE) {
354 *offset = 0;
fb601adb 355 list_del(&write_cb->list);
601a1efa 356 mei_io_cb_free(write_cb);
75f0ee15 357 write_cb = NULL;
ab841160
OW
358 }
359 }
360 }
361
362 /* free entry used in read */
363 if (cl->reading_state == MEI_READ_COMPLETE) {
364 *offset = 0;
90e0b5f1 365 write_cb = mei_cl_find_read_cb(cl);
ab841160 366 if (write_cb) {
fb601adb 367 list_del(&write_cb->list);
601a1efa 368 mei_io_cb_free(write_cb);
ab841160
OW
369 write_cb = NULL;
370 cl->reading_state = MEI_IDLE;
371 cl->read_cb = NULL;
ab841160 372 }
d91aaed3 373 } else if (cl->reading_state == MEI_IDLE)
ab841160
OW
374 *offset = 0;
375
376
33d28c92 377 write_cb = mei_io_cb_init(cl, file);
ab841160 378 if (!write_cb) {
33d28c92 379 rets = -ENOMEM;
4234a6de 380 goto out;
ab841160 381 }
33d28c92
TW
382 rets = mei_io_cb_alloc_req_buf(write_cb, length);
383 if (rets)
4234a6de 384 goto out;
ab841160 385
75f0ee15 386 rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
d8b29efa 387 if (rets) {
2bf94cab 388 dev_dbg(dev->dev, "failed to copy data from userland\n");
d8b29efa 389 rets = -EFAULT;
4234a6de 390 goto out;
d8b29efa 391 }
ab841160 392
ab841160 393 if (cl == &dev->iamthif_cl) {
ab5c4a56 394 rets = mei_amthif_write(dev, write_cb);
ab841160 395
ab5c4a56 396 if (rets) {
2bf94cab 397 dev_err(dev->dev,
1a1aca42 398 "amthif write failed with status = %d\n", rets);
4234a6de 399 goto out;
ab841160 400 }
79563db9 401 mei_me_cl_put(me_cl);
ab841160 402 mutex_unlock(&dev->device_lock);
75f0ee15 403 return length;
ab841160
OW
404 }
405
4234a6de 406 rets = mei_cl_write(cl, write_cb, false);
b0d0cf77 407out:
79563db9 408 mei_me_cl_put(me_cl);
ab841160 409 mutex_unlock(&dev->device_lock);
4234a6de
TW
410 if (rets < 0)
411 mei_io_cb_free(write_cb);
ab841160
OW
412 return rets;
413}
414
9f81abda
TW
415/**
416 * mei_ioctl_connect_client - the connect to fw client IOCTL function
417 *
9f81abda 418 * @file: private data of the file object
a8605ea2 419 * @data: IOCTL connect data, input and output parameters
9f81abda
TW
420 *
421 * Locking: called under "dev->device_lock" lock
422 *
a8605ea2 423 * Return: 0 on success, <0 on failure.
9f81abda
TW
424 */
425static int mei_ioctl_connect_client(struct file *file,
426 struct mei_connect_client_data *data)
427{
428 struct mei_device *dev;
429 struct mei_client *client;
d320832f 430 struct mei_me_client *me_cl;
9f81abda 431 struct mei_cl *cl;
9f81abda
TW
432 int rets;
433
434 cl = file->private_data;
9f81abda
TW
435 dev = cl->dev;
436
79563db9
TW
437 if (dev->dev_state != MEI_DEV_ENABLED)
438 return -ENODEV;
9f81abda
TW
439
440 if (cl->state != MEI_FILE_INITIALIZING &&
79563db9
TW
441 cl->state != MEI_FILE_DISCONNECTED)
442 return -EBUSY;
9f81abda
TW
443
444 /* find ME client we're trying to connect to */
d320832f
TW
445 me_cl = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
446 if (!me_cl || me_cl->props.fixed_address) {
2bf94cab 447 dev_dbg(dev->dev, "Cannot connect to FW Client UUID = %pUl\n",
80fe6361 448 &data->in_client_uuid);
79563db9 449 return -ENOTTY;
9f81abda
TW
450 }
451
d320832f 452 cl->me_client_id = me_cl->client_id;
d880f329 453 cl->cl_uuid = me_cl->props.protocol_name;
80fe6361 454
2bf94cab 455 dev_dbg(dev->dev, "Connect to FW Client ID = %d\n",
9f81abda 456 cl->me_client_id);
2bf94cab 457 dev_dbg(dev->dev, "FW Client - Protocol Version = %d\n",
d320832f 458 me_cl->props.protocol_version);
2bf94cab 459 dev_dbg(dev->dev, "FW Client - Max Msg Len = %d\n",
d320832f 460 me_cl->props.max_msg_length);
9f81abda 461
1a1aca42 462 /* if we're connecting to amthif client then we will use the
9f81abda
TW
463 * existing connection
464 */
1a1aca42 465 if (uuid_le_cmp(data->in_client_uuid, mei_amthif_guid) == 0) {
2bf94cab 466 dev_dbg(dev->dev, "FW Client is amthi\n");
9f81abda
TW
467 if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
468 rets = -ENODEV;
469 goto end;
470 }
9f81abda
TW
471 mei_cl_unlink(cl);
472
473 kfree(cl);
474 cl = NULL;
22f96a0e 475 dev->iamthif_open_count++;
9f81abda
TW
476 file->private_data = &dev->iamthif_cl;
477
478 client = &data->out_client_properties;
d320832f
TW
479 client->max_msg_length = me_cl->props.max_msg_length;
480 client->protocol_version = me_cl->props.protocol_version;
9f81abda
TW
481 rets = dev->iamthif_cl.status;
482
483 goto end;
484 }
485
9f81abda
TW
486 /* prepare the output buffer */
487 client = &data->out_client_properties;
d320832f
TW
488 client->max_msg_length = me_cl->props.max_msg_length;
489 client->protocol_version = me_cl->props.protocol_version;
2bf94cab 490 dev_dbg(dev->dev, "Can connect?\n");
9f81abda 491
9f81abda
TW
492 rets = mei_cl_connect(cl, file);
493
494end:
79563db9 495 mei_me_cl_put(me_cl);
9f81abda
TW
496 return rets;
497}
498
ab841160
OW
499/**
500 * mei_ioctl - the IOCTL function
501 *
502 * @file: pointer to file structure
503 * @cmd: ioctl command
504 * @data: pointer to mei message structure
505 *
a8605ea2 506 * Return: 0 on success , <0 on error
ab841160
OW
507 */
508static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
509{
510 struct mei_device *dev;
511 struct mei_cl *cl = file->private_data;
154eb18f 512 struct mei_connect_client_data connect_data;
ab841160
OW
513 int rets;
514
ab841160
OW
515
516 if (WARN_ON(!cl || !cl->dev))
517 return -ENODEV;
518
519 dev = cl->dev;
520
2bf94cab 521 dev_dbg(dev->dev, "IOCTL cmd = 0x%x", cmd);
ab841160
OW
522
523 mutex_lock(&dev->device_lock);
b210d750 524 if (dev->dev_state != MEI_DEV_ENABLED) {
ab841160
OW
525 rets = -ENODEV;
526 goto out;
527 }
528
4f046e7b
TW
529 switch (cmd) {
530 case IOCTL_MEI_CONNECT_CLIENT:
2bf94cab 531 dev_dbg(dev->dev, ": IOCTL_MEI_CONNECT_CLIENT.\n");
154eb18f 532 if (copy_from_user(&connect_data, (char __user *)data,
4f046e7b 533 sizeof(struct mei_connect_client_data))) {
2bf94cab 534 dev_dbg(dev->dev, "failed to copy data from userland\n");
4f046e7b
TW
535 rets = -EFAULT;
536 goto out;
537 }
ab841160 538
154eb18f 539 rets = mei_ioctl_connect_client(file, &connect_data);
4f046e7b
TW
540 if (rets)
541 goto out;
ab841160 542
4f046e7b 543 /* if all is ok, copying the data back to user. */
154eb18f 544 if (copy_to_user((char __user *)data, &connect_data,
ab841160 545 sizeof(struct mei_connect_client_data))) {
2bf94cab 546 dev_dbg(dev->dev, "failed to copy data to userland\n");
4f046e7b
TW
547 rets = -EFAULT;
548 goto out;
549 }
550
551 break;
154eb18f 552
4f046e7b 553 default:
2bf94cab 554 dev_err(dev->dev, ": unsupported ioctl %d.\n", cmd);
4f046e7b 555 rets = -ENOIOCTLCMD;
ab841160
OW
556 }
557
558out:
ab841160
OW
559 mutex_unlock(&dev->device_lock);
560 return rets;
561}
562
563/**
564 * mei_compat_ioctl - the compat IOCTL function
565 *
566 * @file: pointer to file structure
567 * @cmd: ioctl command
568 * @data: pointer to mei message structure
569 *
a8605ea2 570 * Return: 0 on success , <0 on error
ab841160
OW
571 */
572#ifdef CONFIG_COMPAT
573static long mei_compat_ioctl(struct file *file,
441ab50f 574 unsigned int cmd, unsigned long data)
ab841160
OW
575{
576 return mei_ioctl(file, cmd, (unsigned long)compat_ptr(data));
577}
578#endif
579
580
581/**
582 * mei_poll - the poll function
583 *
584 * @file: pointer to file structure
585 * @wait: pointer to poll_table structure
586 *
a8605ea2 587 * Return: poll mask
ab841160
OW
588 */
589static unsigned int mei_poll(struct file *file, poll_table *wait)
590{
591 struct mei_cl *cl = file->private_data;
592 struct mei_device *dev;
593 unsigned int mask = 0;
594
595 if (WARN_ON(!cl || !cl->dev))
b950ac1d 596 return POLLERR;
ab841160
OW
597
598 dev = cl->dev;
599
600 mutex_lock(&dev->device_lock);
601
b950ac1d
TW
602 if (!mei_cl_is_connected(cl)) {
603 mask = POLLERR;
ab841160
OW
604 goto out;
605 }
606
607 mutex_unlock(&dev->device_lock);
b950ac1d
TW
608
609
610 if (cl == &dev->iamthif_cl)
611 return mei_amthif_poll(dev, file, wait);
612
ab841160 613 poll_wait(file, &cl->tx_wait, wait);
b950ac1d 614
ab841160 615 mutex_lock(&dev->device_lock);
b950ac1d
TW
616
617 if (!mei_cl_is_connected(cl)) {
618 mask = POLLERR;
619 goto out;
620 }
621
34ec4366 622 mask |= (POLLIN | POLLRDNORM);
ab841160
OW
623
624out:
625 mutex_unlock(&dev->device_lock);
626 return mask;
627}
628
55c4e640
TW
629/**
630 * fw_status_show - mei device attribute show method
631 *
632 * @device: device pointer
633 * @attr: attribute pointer
634 * @buf: char out buffer
635 *
636 * Return: number of the bytes printed into buf or error
637 */
638static ssize_t fw_status_show(struct device *device,
639 struct device_attribute *attr, char *buf)
640{
641 struct mei_device *dev = dev_get_drvdata(device);
642 struct mei_fw_status fw_status;
643 int err, i;
644 ssize_t cnt = 0;
645
646 mutex_lock(&dev->device_lock);
647 err = mei_fw_status(dev, &fw_status);
648 mutex_unlock(&dev->device_lock);
649 if (err) {
650 dev_err(device, "read fw_status error = %d\n", err);
651 return err;
652 }
653
654 for (i = 0; i < fw_status.count; i++)
655 cnt += scnprintf(buf + cnt, PAGE_SIZE - cnt, "%08X\n",
656 fw_status.status[i]);
657 return cnt;
658}
659static DEVICE_ATTR_RO(fw_status);
660
661static struct attribute *mei_attrs[] = {
662 &dev_attr_fw_status.attr,
663 NULL
664};
665ATTRIBUTE_GROUPS(mei);
666
5b881e3c
OW
667/*
668 * file operations structure will be used for mei char device.
669 */
670static const struct file_operations mei_fops = {
671 .owner = THIS_MODULE,
672 .read = mei_read,
673 .unlocked_ioctl = mei_ioctl,
674#ifdef CONFIG_COMPAT
675 .compat_ioctl = mei_compat_ioctl,
676#endif
677 .open = mei_open,
678 .release = mei_release,
679 .write = mei_write,
680 .poll = mei_poll,
681 .llseek = no_llseek
682};
683
f3d8e878
AU
684static struct class *mei_class;
685static dev_t mei_devt;
686#define MEI_MAX_DEVS MINORMASK
687static DEFINE_MUTEX(mei_minor_lock);
688static DEFINE_IDR(mei_idr);
689
690/**
691 * mei_minor_get - obtain next free device minor number
692 *
693 * @dev: device pointer
694 *
a8605ea2 695 * Return: allocated minor, or -ENOSPC if no free minor left
5b881e3c 696 */
f3d8e878
AU
697static int mei_minor_get(struct mei_device *dev)
698{
699 int ret;
700
701 mutex_lock(&mei_minor_lock);
702 ret = idr_alloc(&mei_idr, dev, 0, MEI_MAX_DEVS, GFP_KERNEL);
703 if (ret >= 0)
704 dev->minor = ret;
705 else if (ret == -ENOSPC)
2bf94cab 706 dev_err(dev->dev, "too many mei devices\n");
5b881e3c 707
f3d8e878
AU
708 mutex_unlock(&mei_minor_lock);
709 return ret;
710}
30e53bb8 711
f3d8e878
AU
712/**
713 * mei_minor_free - mark device minor number as free
714 *
715 * @dev: device pointer
716 */
717static void mei_minor_free(struct mei_device *dev)
9a123f19 718{
f3d8e878
AU
719 mutex_lock(&mei_minor_lock);
720 idr_remove(&mei_idr, dev->minor);
721 mutex_unlock(&mei_minor_lock);
722}
723
724int mei_register(struct mei_device *dev, struct device *parent)
725{
726 struct device *clsdev; /* class device */
727 int ret, devno;
728
729 ret = mei_minor_get(dev);
730 if (ret < 0)
30e53bb8
TW
731 return ret;
732
f3d8e878
AU
733 /* Fill in the data structures */
734 devno = MKDEV(MAJOR(mei_devt), dev->minor);
735 cdev_init(&dev->cdev, &mei_fops);
736 dev->cdev.owner = mei_fops.owner;
737
738 /* Add the device */
739 ret = cdev_add(&dev->cdev, devno, 1);
740 if (ret) {
741 dev_err(parent, "unable to add device %d:%d\n",
742 MAJOR(mei_devt), dev->minor);
743 goto err_dev_add;
744 }
745
55c4e640
TW
746 clsdev = device_create_with_groups(mei_class, parent, devno,
747 dev, mei_groups,
748 "mei%d", dev->minor);
f3d8e878
AU
749
750 if (IS_ERR(clsdev)) {
751 dev_err(parent, "unable to create device %d:%d\n",
752 MAJOR(mei_devt), dev->minor);
753 ret = PTR_ERR(clsdev);
754 goto err_dev_create;
755 }
756
757 ret = mei_dbgfs_register(dev, dev_name(clsdev));
758 if (ret) {
759 dev_err(clsdev, "cannot register debugfs ret = %d\n", ret);
760 goto err_dev_dbgfs;
761 }
30e53bb8
TW
762
763 return 0;
f3d8e878
AU
764
765err_dev_dbgfs:
766 device_destroy(mei_class, devno);
767err_dev_create:
768 cdev_del(&dev->cdev);
769err_dev_add:
770 mei_minor_free(dev);
771 return ret;
5b881e3c 772}
40e0b67b 773EXPORT_SYMBOL_GPL(mei_register);
5b881e3c 774
30e53bb8 775void mei_deregister(struct mei_device *dev)
5b881e3c 776{
f3d8e878
AU
777 int devno;
778
779 devno = dev->cdev.dev;
780 cdev_del(&dev->cdev);
781
30e53bb8 782 mei_dbgfs_deregister(dev);
f3d8e878
AU
783
784 device_destroy(mei_class, devno);
785
786 mei_minor_free(dev);
5b881e3c 787}
40e0b67b 788EXPORT_SYMBOL_GPL(mei_deregister);
ab841160 789
cf3baefb
SO
790static int __init mei_init(void)
791{
f3d8e878
AU
792 int ret;
793
794 mei_class = class_create(THIS_MODULE, "mei");
795 if (IS_ERR(mei_class)) {
796 pr_err("couldn't create class\n");
797 ret = PTR_ERR(mei_class);
798 goto err;
799 }
800
801 ret = alloc_chrdev_region(&mei_devt, 0, MEI_MAX_DEVS, "mei");
802 if (ret < 0) {
803 pr_err("unable to allocate char dev region\n");
804 goto err_class;
805 }
806
807 ret = mei_cl_bus_init();
808 if (ret < 0) {
809 pr_err("unable to initialize bus\n");
810 goto err_chrdev;
811 }
812
813 return 0;
814
815err_chrdev:
816 unregister_chrdev_region(mei_devt, MEI_MAX_DEVS);
817err_class:
818 class_destroy(mei_class);
819err:
820 return ret;
cf3baefb
SO
821}
822
823static void __exit mei_exit(void)
824{
f3d8e878
AU
825 unregister_chrdev_region(mei_devt, MEI_MAX_DEVS);
826 class_destroy(mei_class);
cf3baefb
SO
827 mei_cl_bus_exit();
828}
829
830module_init(mei_init);
831module_exit(mei_exit);
832
40e0b67b
TW
833MODULE_AUTHOR("Intel Corporation");
834MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
827eef51 835MODULE_LICENSE("GPL v2");
ab841160 836