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