linux/drivers/misc/mei/bus.c
<<
>>
Prefs
   1/*
   2 * Intel Management Engine Interface (Intel MEI) Linux driver
   3 * Copyright (c) 2012-2013, Intel Corporation.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms and conditions of the GNU General Public License,
   7 * version 2, as published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 */
  15
  16#include <linux/module.h>
  17#include <linux/device.h>
  18#include <linux/kernel.h>
  19#include <linux/sched.h>
  20#include <linux/init.h>
  21#include <linux/errno.h>
  22#include <linux/slab.h>
  23#include <linux/mutex.h>
  24#include <linux/interrupt.h>
  25#include <linux/mei_cl_bus.h>
  26
  27#include "mei_dev.h"
  28#include "client.h"
  29
  30#define to_mei_cl_driver(d) container_of(d, struct mei_cl_driver, driver)
  31#define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)
  32
  33static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
  34{
  35        struct mei_cl_device *device = to_mei_cl_device(dev);
  36        struct mei_cl_driver *driver = to_mei_cl_driver(drv);
  37        const struct mei_cl_device_id *id;
  38
  39        if (!device)
  40                return 0;
  41
  42        if (!driver || !driver->id_table)
  43                return 0;
  44
  45        id = driver->id_table;
  46
  47        while (id->name[0]) {
  48                if (!strncmp(dev_name(dev), id->name, sizeof(id->name)))
  49                        return 1;
  50
  51                id++;
  52        }
  53
  54        return 0;
  55}
  56
  57static int mei_cl_device_probe(struct device *dev)
  58{
  59        struct mei_cl_device *device = to_mei_cl_device(dev);
  60        struct mei_cl_driver *driver;
  61        struct mei_cl_device_id id;
  62
  63        if (!device)
  64                return 0;
  65
  66        driver = to_mei_cl_driver(dev->driver);
  67        if (!driver || !driver->probe)
  68                return -ENODEV;
  69
  70        dev_dbg(dev, "Device probe\n");
  71
  72        strlcpy(id.name, dev_name(dev), sizeof(id.name));
  73
  74        return driver->probe(device, &id);
  75}
  76
  77static int mei_cl_device_remove(struct device *dev)
  78{
  79        struct mei_cl_device *device = to_mei_cl_device(dev);
  80        struct mei_cl_driver *driver;
  81
  82        if (!device || !dev->driver)
  83                return 0;
  84
  85        if (device->event_cb) {
  86                device->event_cb = NULL;
  87                cancel_work_sync(&device->event_work);
  88        }
  89
  90        driver = to_mei_cl_driver(dev->driver);
  91        if (!driver->remove) {
  92                dev->driver = NULL;
  93
  94                return 0;
  95        }
  96
  97        return driver->remove(device);
  98}
  99
 100static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
 101                             char *buf)
 102{
 103        int len;
 104
 105        len = snprintf(buf, PAGE_SIZE, "mei:%s\n", dev_name(dev));
 106
 107        return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
 108}
 109static DEVICE_ATTR_RO(modalias);
 110
 111static struct attribute *mei_cl_dev_attrs[] = {
 112        &dev_attr_modalias.attr,
 113        NULL,
 114};
 115ATTRIBUTE_GROUPS(mei_cl_dev);
 116
 117static int mei_cl_uevent(struct device *dev, struct kobj_uevent_env *env)
 118{
 119        if (add_uevent_var(env, "MODALIAS=mei:%s", dev_name(dev)))
 120                return -ENOMEM;
 121
 122        return 0;
 123}
 124
 125static struct bus_type mei_cl_bus_type = {
 126        .name           = "mei",
 127        .dev_groups     = mei_cl_dev_groups,
 128        .match          = mei_cl_device_match,
 129        .probe          = mei_cl_device_probe,
 130        .remove         = mei_cl_device_remove,
 131        .uevent         = mei_cl_uevent,
 132};
 133
 134static void mei_cl_dev_release(struct device *dev)
 135{
 136        kfree(to_mei_cl_device(dev));
 137}
 138
 139static struct device_type mei_cl_device_type = {
 140        .release        = mei_cl_dev_release,
 141};
 142
 143struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev,
 144                                                uuid_le uuid)
 145{
 146        struct mei_cl *cl;
 147
 148        list_for_each_entry(cl, &dev->device_list, device_link) {
 149                if (!uuid_le_cmp(uuid, cl->cl_uuid))
 150                        return cl;
 151        }
 152
 153        return NULL;
 154}
 155struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
 156                                        uuid_le uuid, char *name,
 157                                        struct mei_cl_ops *ops)
 158{
 159        struct mei_cl_device *device;
 160        struct mei_cl *cl;
 161        int status;
 162
 163        cl = mei_cl_bus_find_cl_by_uuid(dev, uuid);
 164        if (cl == NULL)
 165                return NULL;
 166
 167        device = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
 168        if (!device)
 169                return NULL;
 170
 171        device->cl = cl;
 172        device->ops = ops;
 173
 174        device->dev.parent = dev->dev;
 175        device->dev.bus = &mei_cl_bus_type;
 176        device->dev.type = &mei_cl_device_type;
 177
 178        dev_set_name(&device->dev, "%s", name);
 179
 180        status = device_register(&device->dev);
 181        if (status) {
 182                dev_err(dev->dev, "Failed to register MEI device\n");
 183                kfree(device);
 184                return NULL;
 185        }
 186
 187        cl->device = device;
 188
 189        dev_dbg(&device->dev, "client %s registered\n", name);
 190
 191        return device;
 192}
 193EXPORT_SYMBOL_GPL(mei_cl_add_device);
 194
 195void mei_cl_remove_device(struct mei_cl_device *device)
 196{
 197        device_unregister(&device->dev);
 198}
 199EXPORT_SYMBOL_GPL(mei_cl_remove_device);
 200
 201int __mei_cl_driver_register(struct mei_cl_driver *driver, struct module *owner)
 202{
 203        int err;
 204
 205        driver->driver.name = driver->name;
 206        driver->driver.owner = owner;
 207        driver->driver.bus = &mei_cl_bus_type;
 208
 209        err = driver_register(&driver->driver);
 210        if (err)
 211                return err;
 212
 213        pr_debug("mei: driver [%s] registered\n", driver->driver.name);
 214
 215        return 0;
 216}
 217EXPORT_SYMBOL_GPL(__mei_cl_driver_register);
 218
 219void mei_cl_driver_unregister(struct mei_cl_driver *driver)
 220{
 221        driver_unregister(&driver->driver);
 222
 223        pr_debug("mei: driver [%s] unregistered\n", driver->driver.name);
 224}
 225EXPORT_SYMBOL_GPL(mei_cl_driver_unregister);
 226
 227static ssize_t ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
 228                        bool blocking)
 229{
 230        struct mei_device *dev;
 231        struct mei_me_client *me_cl = NULL;
 232        struct mei_cl_cb *cb = NULL;
 233        ssize_t rets;
 234
 235        if (WARN_ON(!cl || !cl->dev))
 236                return -ENODEV;
 237
 238        dev = cl->dev;
 239
 240        mutex_lock(&dev->device_lock);
 241        if (cl->state != MEI_FILE_CONNECTED) {
 242                rets = -ENODEV;
 243                goto out;
 244        }
 245
 246        /* Check if we have an ME client device */
 247        me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
 248        if (!me_cl) {
 249                rets = -ENOTTY;
 250                goto out;
 251        }
 252
 253        if (length > me_cl->props.max_msg_length) {
 254                rets = -EFBIG;
 255                goto out;
 256        }
 257
 258        cb = mei_io_cb_init(cl, NULL);
 259        if (!cb) {
 260                rets = -ENOMEM;
 261                goto out;
 262        }
 263
 264        rets = mei_io_cb_alloc_req_buf(cb, length);
 265        if (rets < 0)
 266                goto out;
 267
 268        memcpy(cb->request_buffer.data, buf, length);
 269
 270        rets = mei_cl_write(cl, cb, blocking);
 271
 272out:
 273        mei_me_cl_put(me_cl);
 274        mutex_unlock(&dev->device_lock);
 275        if (rets < 0)
 276                mei_io_cb_free(cb);
 277
 278        return rets;
 279}
 280
 281ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 282{
 283        struct mei_device *dev;
 284        struct mei_cl_cb *cb;
 285        size_t r_length;
 286        ssize_t rets;
 287
 288        if (WARN_ON(!cl || !cl->dev))
 289                return -ENODEV;
 290
 291        dev = cl->dev;
 292
 293        mutex_lock(&dev->device_lock);
 294
 295        if (!cl->read_cb) {
 296                rets = mei_cl_read_start(cl, length);
 297                if (rets < 0)
 298                        goto out;
 299        }
 300
 301        if (cl->reading_state != MEI_READ_COMPLETE &&
 302            !waitqueue_active(&cl->rx_wait)) {
 303
 304                mutex_unlock(&dev->device_lock);
 305
 306                if (wait_event_interruptible(cl->rx_wait,
 307                                cl->reading_state == MEI_READ_COMPLETE  ||
 308                                mei_cl_is_transitioning(cl))) {
 309
 310                        if (signal_pending(current))
 311                                return -EINTR;
 312                        return -ERESTARTSYS;
 313                }
 314
 315                mutex_lock(&dev->device_lock);
 316        }
 317
 318        cb = cl->read_cb;
 319
 320        if (cl->reading_state != MEI_READ_COMPLETE) {
 321                rets = 0;
 322                goto out;
 323        }
 324
 325        r_length = min_t(size_t, length, cb->buf_idx);
 326        memcpy(buf, cb->response_buffer.data, r_length);
 327        rets = r_length;
 328
 329        mei_io_cb_free(cb);
 330        cl->reading_state = MEI_IDLE;
 331        cl->read_cb = NULL;
 332
 333out:
 334        mutex_unlock(&dev->device_lock);
 335
 336        return rets;
 337}
 338
 339inline ssize_t __mei_cl_async_send(struct mei_cl *cl, u8 *buf, size_t length)
 340{
 341        return ___mei_cl_send(cl, buf, length, 0);
 342}
 343
 344inline ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length)
 345{
 346        return ___mei_cl_send(cl, buf, length, 1);
 347}
 348
 349ssize_t mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length)
 350{
 351        struct mei_cl *cl = device->cl;
 352
 353        if (cl == NULL)
 354                return -ENODEV;
 355
 356        if (device->ops && device->ops->send)
 357                return device->ops->send(device, buf, length);
 358
 359        return __mei_cl_send(cl, buf, length);
 360}
 361EXPORT_SYMBOL_GPL(mei_cl_send);
 362
 363ssize_t mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length)
 364{
 365        struct mei_cl *cl =  device->cl;
 366
 367        if (cl == NULL)
 368                return -ENODEV;
 369
 370        if (device->ops && device->ops->recv)
 371                return device->ops->recv(device, buf, length);
 372
 373        return __mei_cl_recv(cl, buf, length);
 374}
 375EXPORT_SYMBOL_GPL(mei_cl_recv);
 376
 377static void mei_bus_event_work(struct work_struct *work)
 378{
 379        struct mei_cl_device *device;
 380
 381        device = container_of(work, struct mei_cl_device, event_work);
 382
 383        if (device->event_cb)
 384                device->event_cb(device, device->events, device->event_context);
 385
 386        device->events = 0;
 387
 388        /* Prepare for the next read */
 389        mei_cl_read_start(device->cl, 0);
 390}
 391
 392int mei_cl_register_event_cb(struct mei_cl_device *device,
 393                          mei_cl_event_cb_t event_cb, void *context)
 394{
 395        if (device->event_cb)
 396                return -EALREADY;
 397
 398        device->events = 0;
 399        device->event_cb = event_cb;
 400        device->event_context = context;
 401        INIT_WORK(&device->event_work, mei_bus_event_work);
 402
 403        mei_cl_read_start(device->cl, 0);
 404
 405        return 0;
 406}
 407EXPORT_SYMBOL_GPL(mei_cl_register_event_cb);
 408
 409void *mei_cl_get_drvdata(const struct mei_cl_device *device)
 410{
 411        return dev_get_drvdata(&device->dev);
 412}
 413EXPORT_SYMBOL_GPL(mei_cl_get_drvdata);
 414
 415void mei_cl_set_drvdata(struct mei_cl_device *device, void *data)
 416{
 417        dev_set_drvdata(&device->dev, data);
 418}
 419EXPORT_SYMBOL_GPL(mei_cl_set_drvdata);
 420
 421int mei_cl_enable_device(struct mei_cl_device *device)
 422{
 423        int err;
 424        struct mei_device *dev;
 425        struct mei_cl *cl = device->cl;
 426
 427        if (cl == NULL)
 428                return -ENODEV;
 429
 430        dev = cl->dev;
 431
 432        mutex_lock(&dev->device_lock);
 433
 434        err = mei_cl_connect(cl, NULL);
 435        if (err < 0) {
 436                mutex_unlock(&dev->device_lock);
 437                dev_err(dev->dev, "Could not connect to the ME client");
 438
 439                return err;
 440        }
 441
 442        mutex_unlock(&dev->device_lock);
 443
 444        if (device->event_cb && !cl->read_cb)
 445                mei_cl_read_start(device->cl, 0);
 446
 447        if (!device->ops || !device->ops->enable)
 448                return 0;
 449
 450        return device->ops->enable(device);
 451}
 452EXPORT_SYMBOL_GPL(mei_cl_enable_device);
 453
 454int mei_cl_disable_device(struct mei_cl_device *device)
 455{
 456        int err;
 457        struct mei_device *dev;
 458        struct mei_cl *cl = device->cl;
 459
 460        if (cl == NULL)
 461                return -ENODEV;
 462
 463        dev = cl->dev;
 464
 465        mutex_lock(&dev->device_lock);
 466
 467        if (cl->state != MEI_FILE_CONNECTED) {
 468                mutex_unlock(&dev->device_lock);
 469                dev_err(dev->dev, "Already disconnected");
 470
 471                return 0;
 472        }
 473
 474        cl->state = MEI_FILE_DISCONNECTING;
 475
 476        err = mei_cl_disconnect(cl);
 477        if (err < 0) {
 478                mutex_unlock(&dev->device_lock);
 479                dev_err(dev->dev,
 480                        "Could not disconnect from the ME client");
 481
 482                return err;
 483        }
 484
 485        /* Flush queues and remove any pending read */
 486        mei_cl_flush_queues(cl);
 487
 488        if (cl->read_cb) {
 489                struct mei_cl_cb *cb = NULL;
 490
 491                cb = mei_cl_find_read_cb(cl);
 492                /* Remove entry from read list */
 493                if (cb)
 494                        list_del(&cb->list);
 495
 496                cb = cl->read_cb;
 497                cl->read_cb = NULL;
 498
 499                if (cb) {
 500                        mei_io_cb_free(cb);
 501                        cb = NULL;
 502                }
 503        }
 504
 505        device->event_cb = NULL;
 506
 507        mutex_unlock(&dev->device_lock);
 508
 509        if (!device->ops || !device->ops->disable)
 510                return 0;
 511
 512        return device->ops->disable(device);
 513}
 514EXPORT_SYMBOL_GPL(mei_cl_disable_device);
 515
 516void mei_cl_bus_rx_event(struct mei_cl *cl)
 517{
 518        struct mei_cl_device *device = cl->device;
 519
 520        if (!device || !device->event_cb)
 521                return;
 522
 523        set_bit(MEI_CL_EVENT_RX, &device->events);
 524
 525        schedule_work(&device->event_work);
 526}
 527
 528void mei_cl_bus_remove_devices(struct mei_device *dev)
 529{
 530        struct mei_cl *cl, *next;
 531
 532        mutex_lock(&dev->device_lock);
 533        list_for_each_entry_safe(cl, next, &dev->device_list, device_link) {
 534                if (cl->device)
 535                        mei_cl_remove_device(cl->device);
 536
 537                list_del(&cl->device_link);
 538                mei_cl_unlink(cl);
 539                kfree(cl);
 540        }
 541        mutex_unlock(&dev->device_lock);
 542}
 543
 544int __init mei_cl_bus_init(void)
 545{
 546        return bus_register(&mei_cl_bus_type);
 547}
 548
 549void __exit mei_cl_bus_exit(void)
 550{
 551        bus_unregister(&mei_cl_bus_type);
 552}
 553