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