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 (!mei_cl_is_connected(cl)) {
 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_cl_alloc_cb(cl, length, MEI_FOP_WRITE, NULL);
 259        if (!cb) {
 260                rets = -ENOMEM;
 261                goto out;
 262        }
 263
 264        memcpy(cb->buf.data, buf, length);
 265
 266        rets = mei_cl_write(cl, cb, blocking);
 267
 268out:
 269        mei_me_cl_put(me_cl);
 270        mutex_unlock(&dev->device_lock);
 271        if (rets < 0)
 272                mei_io_cb_free(cb);
 273
 274        return rets;
 275}
 276
 277ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 278{
 279        struct mei_device *dev;
 280        struct mei_cl_cb *cb;
 281        size_t r_length;
 282        ssize_t rets;
 283
 284        if (WARN_ON(!cl || !cl->dev))
 285                return -ENODEV;
 286
 287        dev = cl->dev;
 288
 289        mutex_lock(&dev->device_lock);
 290
 291        cb = mei_cl_read_cb(cl, NULL);
 292        if (cb)
 293                goto copy;
 294
 295        rets = mei_cl_read_start(cl, length, NULL);
 296        if (rets && rets != -EBUSY)
 297                goto out;
 298
 299        if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
 300
 301                mutex_unlock(&dev->device_lock);
 302
 303                if (wait_event_interruptible(cl->rx_wait,
 304                                (!list_empty(&cl->rd_completed)) ||
 305                                (!mei_cl_is_connected(cl)))) {
 306
 307                        if (signal_pending(current))
 308                                return -EINTR;
 309                        return -ERESTARTSYS;
 310                }
 311
 312                mutex_lock(&dev->device_lock);
 313
 314                if (!mei_cl_is_connected(cl)) {
 315                        rets = -EBUSY;
 316                        goto out;
 317                }
 318        }
 319
 320        cb = mei_cl_read_cb(cl, NULL);
 321        if (!cb) {
 322                rets = 0;
 323                goto out;
 324        }
 325
 326copy:
 327        if (cb->status) {
 328                rets = cb->status;
 329                goto free;
 330        }
 331
 332        r_length = min_t(size_t, length, cb->buf_idx);
 333        memcpy(buf, cb->buf.data, r_length);
 334        rets = r_length;
 335
 336free:
 337        mei_io_cb_free(cb);
 338out:
 339        mutex_unlock(&dev->device_lock);
 340
 341        return rets;
 342}
 343
 344inline ssize_t __mei_cl_async_send(struct mei_cl *cl, u8 *buf, size_t length)
 345{
 346        return ___mei_cl_send(cl, buf, length, 0);
 347}
 348
 349inline ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length)
 350{
 351        return ___mei_cl_send(cl, buf, length, 1);
 352}
 353
 354ssize_t mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length)
 355{
 356        struct mei_cl *cl = device->cl;
 357
 358        if (cl == NULL)
 359                return -ENODEV;
 360
 361        if (device->ops && device->ops->send)
 362                return device->ops->send(device, buf, length);
 363
 364        return __mei_cl_send(cl, buf, length);
 365}
 366EXPORT_SYMBOL_GPL(mei_cl_send);
 367
 368ssize_t mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length)
 369{
 370        struct mei_cl *cl =  device->cl;
 371
 372        if (cl == NULL)
 373                return -ENODEV;
 374
 375        if (device->ops && device->ops->recv)
 376                return device->ops->recv(device, buf, length);
 377
 378        return __mei_cl_recv(cl, buf, length);
 379}
 380EXPORT_SYMBOL_GPL(mei_cl_recv);
 381
 382static void mei_bus_event_work(struct work_struct *work)
 383{
 384        struct mei_cl_device *device;
 385
 386        device = container_of(work, struct mei_cl_device, event_work);
 387
 388        if (device->event_cb)
 389                device->event_cb(device, device->events, device->event_context);
 390
 391        device->events = 0;
 392
 393        /* Prepare for the next read */
 394        mei_cl_read_start(device->cl, 0, NULL);
 395}
 396
 397int mei_cl_register_event_cb(struct mei_cl_device *device,
 398                          mei_cl_event_cb_t event_cb, void *context)
 399{
 400        if (device->event_cb)
 401                return -EALREADY;
 402
 403        device->events = 0;
 404        device->event_cb = event_cb;
 405        device->event_context = context;
 406        INIT_WORK(&device->event_work, mei_bus_event_work);
 407
 408        mei_cl_read_start(device->cl, 0, NULL);
 409
 410        return 0;
 411}
 412EXPORT_SYMBOL_GPL(mei_cl_register_event_cb);
 413
 414void *mei_cl_get_drvdata(const struct mei_cl_device *device)
 415{
 416        return dev_get_drvdata(&device->dev);
 417}
 418EXPORT_SYMBOL_GPL(mei_cl_get_drvdata);
 419
 420void mei_cl_set_drvdata(struct mei_cl_device *device, void *data)
 421{
 422        dev_set_drvdata(&device->dev, data);
 423}
 424EXPORT_SYMBOL_GPL(mei_cl_set_drvdata);
 425
 426int mei_cl_enable_device(struct mei_cl_device *device)
 427{
 428        int err;
 429        struct mei_device *dev;
 430        struct mei_cl *cl = device->cl;
 431
 432        if (cl == NULL)
 433                return -ENODEV;
 434
 435        dev = cl->dev;
 436
 437        mutex_lock(&dev->device_lock);
 438
 439        err = mei_cl_connect(cl, NULL);
 440        if (err < 0) {
 441                mutex_unlock(&dev->device_lock);
 442                dev_err(dev->dev, "Could not connect to the ME client");
 443
 444                return err;
 445        }
 446
 447        mutex_unlock(&dev->device_lock);
 448
 449        if (device->event_cb)
 450                mei_cl_read_start(device->cl, 0, NULL);
 451
 452        if (!device->ops || !device->ops->enable)
 453                return 0;
 454
 455        return device->ops->enable(device);
 456}
 457EXPORT_SYMBOL_GPL(mei_cl_enable_device);
 458
 459int mei_cl_disable_device(struct mei_cl_device *device)
 460{
 461        int err;
 462        struct mei_device *dev;
 463        struct mei_cl *cl = device->cl;
 464
 465        if (cl == NULL)
 466                return -ENODEV;
 467
 468        dev = cl->dev;
 469
 470        if (device->ops && device->ops->disable)
 471                device->ops->disable(device);
 472
 473        device->event_cb = NULL;
 474
 475        mutex_lock(&dev->device_lock);
 476
 477        if (!mei_cl_is_connected(cl)) {
 478                dev_err(dev->dev, "Already disconnected");
 479                err = 0;
 480                goto out;
 481        }
 482
 483        cl->state = MEI_FILE_DISCONNECTING;
 484
 485        err = mei_cl_disconnect(cl);
 486        if (err < 0) {
 487                dev_err(dev->dev, "Could not disconnect from the ME client");
 488                goto out;
 489        }
 490
 491        /* Flush queues and remove any pending read */
 492        mei_cl_flush_queues(cl, NULL);
 493
 494out:
 495        mutex_unlock(&dev->device_lock);
 496        return err;
 497
 498}
 499EXPORT_SYMBOL_GPL(mei_cl_disable_device);
 500
 501void mei_cl_bus_rx_event(struct mei_cl *cl)
 502{
 503        struct mei_cl_device *device = cl->device;
 504
 505        if (!device || !device->event_cb)
 506                return;
 507
 508        set_bit(MEI_CL_EVENT_RX, &device->events);
 509
 510        schedule_work(&device->event_work);
 511}
 512
 513void mei_cl_bus_remove_devices(struct mei_device *dev)
 514{
 515        struct mei_cl *cl, *next;
 516
 517        mutex_lock(&dev->device_lock);
 518        list_for_each_entry_safe(cl, next, &dev->device_list, device_link) {
 519                if (cl->device)
 520                        mei_cl_remove_device(cl->device);
 521
 522                list_del(&cl->device_link);
 523                mei_cl_unlink(cl);
 524                kfree(cl);
 525        }
 526        mutex_unlock(&dev->device_lock);
 527}
 528
 529int __init mei_cl_bus_init(void)
 530{
 531        return bus_register(&mei_cl_bus_type);
 532}
 533
 534void __exit mei_cl_bus_exit(void)
 535{
 536        bus_unregister(&mei_cl_bus_type);
 537}
 538