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/signal.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
  33/**
  34 * __mei_cl_send - internal client send (write)
  35 *
  36 * @cl: host client
  37 * @buf: buffer to send
  38 * @length: buffer length
  39 * @mode: sending mode
  40 *
  41 * Return: written size bytes or < 0 on error
  42 */
  43ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
  44                      unsigned int mode)
  45{
  46        struct mei_device *bus;
  47        struct mei_cl_cb *cb;
  48        ssize_t rets;
  49
  50        if (WARN_ON(!cl || !cl->dev))
  51                return -ENODEV;
  52
  53        bus = cl->dev;
  54
  55        mutex_lock(&bus->device_lock);
  56        if (bus->dev_state != MEI_DEV_ENABLED) {
  57                rets = -ENODEV;
  58                goto out;
  59        }
  60
  61        if (!mei_cl_is_connected(cl)) {
  62                rets = -ENODEV;
  63                goto out;
  64        }
  65
  66        /* Check if we have an ME client device */
  67        if (!mei_me_cl_is_active(cl->me_cl)) {
  68                rets = -ENOTTY;
  69                goto out;
  70        }
  71
  72        if (length > mei_cl_mtu(cl)) {
  73                rets = -EFBIG;
  74                goto out;
  75        }
  76
  77        cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, NULL);
  78        if (!cb) {
  79                rets = -ENOMEM;
  80                goto out;
  81        }
  82
  83        cb->internal = !!(mode & MEI_CL_IO_TX_INTERNAL);
  84        cb->blocking = !!(mode & MEI_CL_IO_TX_BLOCKING);
  85        memcpy(cb->buf.data, buf, length);
  86
  87        rets = mei_cl_write(cl, cb);
  88
  89out:
  90        mutex_unlock(&bus->device_lock);
  91
  92        return rets;
  93}
  94
  95/**
  96 * __mei_cl_recv - internal client receive (read)
  97 *
  98 * @cl: host client
  99 * @buf: buffer to receive
 100 * @length: buffer length
 101 * @mode: io mode
 102 *
 103 * Return: read size in bytes of < 0 on error
 104 */
 105ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
 106                      unsigned int mode)
 107{
 108        struct mei_device *bus;
 109        struct mei_cl_cb *cb;
 110        size_t r_length;
 111        ssize_t rets;
 112        bool nonblock = !!(mode & MEI_CL_IO_RX_NONBLOCK);
 113
 114        if (WARN_ON(!cl || !cl->dev))
 115                return -ENODEV;
 116
 117        bus = cl->dev;
 118
 119        mutex_lock(&bus->device_lock);
 120        if (bus->dev_state != MEI_DEV_ENABLED) {
 121                rets = -ENODEV;
 122                goto out;
 123        }
 124
 125        cb = mei_cl_read_cb(cl, NULL);
 126        if (cb)
 127                goto copy;
 128
 129        rets = mei_cl_read_start(cl, length, NULL);
 130        if (rets && rets != -EBUSY)
 131                goto out;
 132
 133        if (nonblock) {
 134                rets = -EAGAIN;
 135                goto out;
 136        }
 137
 138        /* wait on event only if there is no other waiter */
 139        /* synchronized under device mutex */
 140        if (!waitqueue_active(&cl->rx_wait)) {
 141
 142                mutex_unlock(&bus->device_lock);
 143
 144                if (wait_event_interruptible(cl->rx_wait,
 145                                (!list_empty(&cl->rd_completed)) ||
 146                                (!mei_cl_is_connected(cl)))) {
 147
 148                        if (signal_pending(current))
 149                                return -EINTR;
 150                        return -ERESTARTSYS;
 151                }
 152
 153                mutex_lock(&bus->device_lock);
 154
 155                if (!mei_cl_is_connected(cl)) {
 156                        rets = -ENODEV;
 157                        goto out;
 158                }
 159        }
 160
 161        cb = mei_cl_read_cb(cl, NULL);
 162        if (!cb) {
 163                rets = 0;
 164                goto out;
 165        }
 166
 167copy:
 168        if (cb->status) {
 169                rets = cb->status;
 170                goto free;
 171        }
 172
 173        r_length = min_t(size_t, length, cb->buf_idx);
 174        memcpy(buf, cb->buf.data, r_length);
 175        rets = r_length;
 176
 177free:
 178        mei_io_cb_free(cb);
 179out:
 180        mutex_unlock(&bus->device_lock);
 181
 182        return rets;
 183}
 184
 185/**
 186 * mei_cldev_send - me device send  (write)
 187 *
 188 * @cldev: me client device
 189 * @buf: buffer to send
 190 * @length: buffer length
 191 *
 192 * Return: written size in bytes or < 0 on error
 193 */
 194ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
 195{
 196        struct mei_cl *cl = cldev->cl;
 197
 198        return __mei_cl_send(cl, buf, length, MEI_CL_IO_TX_BLOCKING);
 199}
 200EXPORT_SYMBOL_GPL(mei_cldev_send);
 201
 202/**
 203 * mei_cldev_recv_nonblock - non block client receive (read)
 204 *
 205 * @cldev: me client device
 206 * @buf: buffer to receive
 207 * @length: buffer length
 208 *
 209 * Return: read size in bytes of < 0 on error
 210 *         -EAGAIN if function will block.
 211 */
 212ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
 213                                size_t length)
 214{
 215        struct mei_cl *cl = cldev->cl;
 216
 217        return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK);
 218}
 219EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
 220
 221/**
 222 * mei_cldev_recv - client receive (read)
 223 *
 224 * @cldev: me client device
 225 * @buf: buffer to receive
 226 * @length: buffer length
 227 *
 228 * Return: read size in bytes of < 0 on error
 229 */
 230ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
 231{
 232        struct mei_cl *cl = cldev->cl;
 233
 234        return __mei_cl_recv(cl, buf, length, 0);
 235}
 236EXPORT_SYMBOL_GPL(mei_cldev_recv);
 237
 238/**
 239 * mei_cl_bus_rx_work - dispatch rx event for a bus device
 240 *
 241 * @work: work
 242 */
 243static void mei_cl_bus_rx_work(struct work_struct *work)
 244{
 245        struct mei_cl_device *cldev;
 246        struct mei_device *bus;
 247
 248        cldev = container_of(work, struct mei_cl_device, rx_work);
 249
 250        bus = cldev->bus;
 251
 252        if (cldev->rx_cb)
 253                cldev->rx_cb(cldev);
 254
 255        mutex_lock(&bus->device_lock);
 256        mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
 257        mutex_unlock(&bus->device_lock);
 258}
 259
 260/**
 261 * mei_cl_bus_notif_work - dispatch FW notif event for a bus device
 262 *
 263 * @work: work
 264 */
 265static void mei_cl_bus_notif_work(struct work_struct *work)
 266{
 267        struct mei_cl_device *cldev;
 268
 269        cldev = container_of(work, struct mei_cl_device, notif_work);
 270
 271        if (cldev->notif_cb)
 272                cldev->notif_cb(cldev);
 273}
 274
 275/**
 276 * mei_cl_bus_notify_event - schedule notify cb on bus client
 277 *
 278 * @cl: host client
 279 *
 280 * Return: true if event was scheduled
 281 *         false if the client is not waiting for event
 282 */
 283bool mei_cl_bus_notify_event(struct mei_cl *cl)
 284{
 285        struct mei_cl_device *cldev = cl->cldev;
 286
 287        if (!cldev || !cldev->notif_cb)
 288                return false;
 289
 290        if (!cl->notify_ev)
 291                return false;
 292
 293        schedule_work(&cldev->notif_work);
 294
 295        cl->notify_ev = false;
 296
 297        return true;
 298}
 299
 300/**
 301 * mei_cl_bus_rx_event - schedule rx event
 302 *
 303 * @cl: host client
 304 *
 305 * Return: true if event was scheduled
 306 *         false if the client is not waiting for event
 307 */
 308bool mei_cl_bus_rx_event(struct mei_cl *cl)
 309{
 310        struct mei_cl_device *cldev = cl->cldev;
 311
 312        if (!cldev || !cldev->rx_cb)
 313                return false;
 314
 315        schedule_work(&cldev->rx_work);
 316
 317        return true;
 318}
 319
 320/**
 321 * mei_cldev_register_rx_cb - register Rx event callback
 322 *
 323 * @cldev: me client devices
 324 * @rx_cb: callback function
 325 *
 326 * Return: 0 on success
 327 *         -EALREADY if an callback is already registered
 328 *         <0 on other errors
 329 */
 330int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb)
 331{
 332        struct mei_device *bus = cldev->bus;
 333        int ret;
 334
 335        if (!rx_cb)
 336                return -EINVAL;
 337        if (cldev->rx_cb)
 338                return -EALREADY;
 339
 340        cldev->rx_cb = rx_cb;
 341        INIT_WORK(&cldev->rx_work, mei_cl_bus_rx_work);
 342
 343        mutex_lock(&bus->device_lock);
 344        ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
 345        mutex_unlock(&bus->device_lock);
 346        if (ret && ret != -EBUSY)
 347                return ret;
 348
 349        return 0;
 350}
 351EXPORT_SYMBOL_GPL(mei_cldev_register_rx_cb);
 352
 353/**
 354 * mei_cldev_register_notif_cb - register FW notification event callback
 355 *
 356 * @cldev: me client devices
 357 * @notif_cb: callback function
 358 *
 359 * Return: 0 on success
 360 *         -EALREADY if an callback is already registered
 361 *         <0 on other errors
 362 */
 363int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,
 364                                mei_cldev_cb_t notif_cb)
 365{
 366        struct mei_device *bus = cldev->bus;
 367        int ret;
 368
 369        if (!notif_cb)
 370                return -EINVAL;
 371
 372        if (cldev->notif_cb)
 373                return -EALREADY;
 374
 375        cldev->notif_cb = notif_cb;
 376        INIT_WORK(&cldev->notif_work, mei_cl_bus_notif_work);
 377
 378        mutex_lock(&bus->device_lock);
 379        ret = mei_cl_notify_request(cldev->cl, NULL, 1);
 380        mutex_unlock(&bus->device_lock);
 381        if (ret)
 382                return ret;
 383
 384        return 0;
 385}
 386EXPORT_SYMBOL_GPL(mei_cldev_register_notif_cb);
 387
 388/**
 389 * mei_cldev_get_drvdata - driver data getter
 390 *
 391 * @cldev: mei client device
 392 *
 393 * Return: driver private data
 394 */
 395void *mei_cldev_get_drvdata(const struct mei_cl_device *cldev)
 396{
 397        return dev_get_drvdata(&cldev->dev);
 398}
 399EXPORT_SYMBOL_GPL(mei_cldev_get_drvdata);
 400
 401/**
 402 * mei_cldev_set_drvdata - driver data setter
 403 *
 404 * @cldev: mei client device
 405 * @data: data to store
 406 */
 407void mei_cldev_set_drvdata(struct mei_cl_device *cldev, void *data)
 408{
 409        dev_set_drvdata(&cldev->dev, data);
 410}
 411EXPORT_SYMBOL_GPL(mei_cldev_set_drvdata);
 412
 413/**
 414 * mei_cldev_uuid - return uuid of the underlying me client
 415 *
 416 * @cldev: mei client device
 417 *
 418 * Return: me client uuid
 419 */
 420const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev)
 421{
 422        return mei_me_cl_uuid(cldev->me_cl);
 423}
 424EXPORT_SYMBOL_GPL(mei_cldev_uuid);
 425
 426/**
 427 * mei_cldev_ver - return protocol version of the underlying me client
 428 *
 429 * @cldev: mei client device
 430 *
 431 * Return: me client protocol version
 432 */
 433u8 mei_cldev_ver(const struct mei_cl_device *cldev)
 434{
 435        return mei_me_cl_ver(cldev->me_cl);
 436}
 437EXPORT_SYMBOL_GPL(mei_cldev_ver);
 438
 439/**
 440 * mei_cldev_enabled - check whether the device is enabled
 441 *
 442 * @cldev: mei client device
 443 *
 444 * Return: true if me client is initialized and connected
 445 */
 446bool mei_cldev_enabled(struct mei_cl_device *cldev)
 447{
 448        return mei_cl_is_connected(cldev->cl);
 449}
 450EXPORT_SYMBOL_GPL(mei_cldev_enabled);
 451
 452/**
 453 * mei_cldev_enable - enable me client device
 454 *     create connection with me client
 455 *
 456 * @cldev: me client device
 457 *
 458 * Return: 0 on success and < 0 on error
 459 */
 460int mei_cldev_enable(struct mei_cl_device *cldev)
 461{
 462        struct mei_device *bus = cldev->bus;
 463        struct mei_cl *cl;
 464        int ret;
 465
 466        cl = cldev->cl;
 467
 468        if (cl->state == MEI_FILE_UNINITIALIZED) {
 469                mutex_lock(&bus->device_lock);
 470                ret = mei_cl_link(cl);
 471                mutex_unlock(&bus->device_lock);
 472                if (ret)
 473                        return ret;
 474                /* update pointers */
 475                cl->cldev = cldev;
 476        }
 477
 478        mutex_lock(&bus->device_lock);
 479        if (mei_cl_is_connected(cl)) {
 480                ret = 0;
 481                goto out;
 482        }
 483
 484        if (!mei_me_cl_is_active(cldev->me_cl)) {
 485                dev_err(&cldev->dev, "me client is not active\n");
 486                ret = -ENOTTY;
 487                goto out;
 488        }
 489
 490        ret = mei_cl_connect(cl, cldev->me_cl, NULL);
 491        if (ret < 0)
 492                dev_err(&cldev->dev, "cannot connect\n");
 493
 494out:
 495        mutex_unlock(&bus->device_lock);
 496
 497        return ret;
 498}
 499EXPORT_SYMBOL_GPL(mei_cldev_enable);
 500
 501/**
 502 * mei_cldev_unregister_callbacks - internal wrapper for unregistering
 503 *  callbacks.
 504 *
 505 * @cldev: client device
 506 */
 507static void mei_cldev_unregister_callbacks(struct mei_cl_device *cldev)
 508{
 509        if (cldev->rx_cb) {
 510                cancel_work_sync(&cldev->rx_work);
 511                cldev->rx_cb = NULL;
 512        }
 513
 514        if (cldev->notif_cb) {
 515                cancel_work_sync(&cldev->notif_work);
 516                cldev->notif_cb = NULL;
 517        }
 518}
 519
 520/**
 521 * mei_cldev_disable - disable me client device
 522 *     disconnect form the me client
 523 *
 524 * @cldev: me client device
 525 *
 526 * Return: 0 on success and < 0 on error
 527 */
 528int mei_cldev_disable(struct mei_cl_device *cldev)
 529{
 530        struct mei_device *bus;
 531        struct mei_cl *cl;
 532        int err;
 533
 534        if (!cldev)
 535                return -ENODEV;
 536
 537        cl = cldev->cl;
 538
 539        bus = cldev->bus;
 540
 541        mei_cldev_unregister_callbacks(cldev);
 542
 543        mutex_lock(&bus->device_lock);
 544
 545        if (!mei_cl_is_connected(cl)) {
 546                dev_dbg(bus->dev, "Already disconnected");
 547                err = 0;
 548                goto out;
 549        }
 550
 551        err = mei_cl_disconnect(cl);
 552        if (err < 0)
 553                dev_err(bus->dev, "Could not disconnect from the ME client");
 554
 555out:
 556        /* Flush queues and remove any pending read */
 557        mei_cl_flush_queues(cl, NULL);
 558        mei_cl_unlink(cl);
 559
 560        mutex_unlock(&bus->device_lock);
 561        return err;
 562}
 563EXPORT_SYMBOL_GPL(mei_cldev_disable);
 564
 565/**
 566 * mei_cl_bus_module_get - acquire module of the underlying
 567 *    hw module.
 568 *
 569 * @cl: host client
 570 *
 571 * Return: true on success; false if the module was removed.
 572 */
 573bool mei_cl_bus_module_get(struct mei_cl *cl)
 574{
 575        struct mei_cl_device *cldev = cl->cldev;
 576
 577        if (!cldev)
 578                return true;
 579
 580        return try_module_get(cldev->bus->dev->driver->owner);
 581}
 582
 583/**
 584 * mei_cl_bus_module_put -  release the underlying hw module.
 585 *
 586 * @cl: host client
 587 */
 588void mei_cl_bus_module_put(struct mei_cl *cl)
 589{
 590        struct mei_cl_device *cldev = cl->cldev;
 591
 592        if (cldev)
 593                module_put(cldev->bus->dev->driver->owner);
 594}
 595
 596/**
 597 * mei_cl_device_find - find matching entry in the driver id table
 598 *
 599 * @cldev: me client device
 600 * @cldrv: me client driver
 601 *
 602 * Return: id on success; NULL if no id is matching
 603 */
 604static const
 605struct mei_cl_device_id *mei_cl_device_find(struct mei_cl_device *cldev,
 606                                            struct mei_cl_driver *cldrv)
 607{
 608        const struct mei_cl_device_id *id;
 609        const uuid_le *uuid;
 610        u8 version;
 611        bool match;
 612
 613        uuid = mei_me_cl_uuid(cldev->me_cl);
 614        version = mei_me_cl_ver(cldev->me_cl);
 615
 616        id = cldrv->id_table;
 617        while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) {
 618                if (!uuid_le_cmp(*uuid, id->uuid)) {
 619                        match = true;
 620
 621                        if (cldev->name[0])
 622                                if (strncmp(cldev->name, id->name,
 623                                            sizeof(id->name)))
 624                                        match = false;
 625
 626                        if (id->version != MEI_CL_VERSION_ANY)
 627                                if (id->version != version)
 628                                        match = false;
 629                        if (match)
 630                                return id;
 631                }
 632
 633                id++;
 634        }
 635
 636        return NULL;
 637}
 638
 639/**
 640 * mei_cl_device_match  - device match function
 641 *
 642 * @dev: device
 643 * @drv: driver
 644 *
 645 * Return:  1 if matching device was found 0 otherwise
 646 */
 647static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
 648{
 649        struct mei_cl_device *cldev = to_mei_cl_device(dev);
 650        struct mei_cl_driver *cldrv = to_mei_cl_driver(drv);
 651        const struct mei_cl_device_id *found_id;
 652
 653        if (!cldev)
 654                return 0;
 655
 656        if (!cldev->do_match)
 657                return 0;
 658
 659        if (!cldrv || !cldrv->id_table)
 660                return 0;
 661
 662        found_id = mei_cl_device_find(cldev, cldrv);
 663        if (found_id)
 664                return 1;
 665
 666        return 0;
 667}
 668
 669/**
 670 * mei_cl_device_probe - bus probe function
 671 *
 672 * @dev: device
 673 *
 674 * Return:  0 on success; < 0 otherwise
 675 */
 676static int mei_cl_device_probe(struct device *dev)
 677{
 678        struct mei_cl_device *cldev;
 679        struct mei_cl_driver *cldrv;
 680        const struct mei_cl_device_id *id;
 681        int ret;
 682
 683        cldev = to_mei_cl_device(dev);
 684        cldrv = to_mei_cl_driver(dev->driver);
 685
 686        if (!cldev)
 687                return 0;
 688
 689        if (!cldrv || !cldrv->probe)
 690                return -ENODEV;
 691
 692        id = mei_cl_device_find(cldev, cldrv);
 693        if (!id)
 694                return -ENODEV;
 695
 696        ret = cldrv->probe(cldev, id);
 697        if (ret)
 698                return ret;
 699
 700        __module_get(THIS_MODULE);
 701        return 0;
 702}
 703
 704/**
 705 * mei_cl_device_remove - remove device from the bus
 706 *
 707 * @dev: device
 708 *
 709 * Return:  0 on success; < 0 otherwise
 710 */
 711static int mei_cl_device_remove(struct device *dev)
 712{
 713        struct mei_cl_device *cldev = to_mei_cl_device(dev);
 714        struct mei_cl_driver *cldrv;
 715        int ret = 0;
 716
 717        if (!cldev || !dev->driver)
 718                return 0;
 719
 720        cldrv = to_mei_cl_driver(dev->driver);
 721        if (cldrv->remove)
 722                ret = cldrv->remove(cldev);
 723
 724        mei_cldev_unregister_callbacks(cldev);
 725
 726        module_put(THIS_MODULE);
 727        dev->driver = NULL;
 728        return ret;
 729
 730}
 731
 732static ssize_t name_show(struct device *dev, struct device_attribute *a,
 733                             char *buf)
 734{
 735        struct mei_cl_device *cldev = to_mei_cl_device(dev);
 736
 737        return scnprintf(buf, PAGE_SIZE, "%s", cldev->name);
 738}
 739static DEVICE_ATTR_RO(name);
 740
 741static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
 742                             char *buf)
 743{
 744        struct mei_cl_device *cldev = to_mei_cl_device(dev);
 745        const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
 746
 747        return scnprintf(buf, PAGE_SIZE, "%pUl", uuid);
 748}
 749static DEVICE_ATTR_RO(uuid);
 750
 751static ssize_t version_show(struct device *dev, struct device_attribute *a,
 752                             char *buf)
 753{
 754        struct mei_cl_device *cldev = to_mei_cl_device(dev);
 755        u8 version = mei_me_cl_ver(cldev->me_cl);
 756
 757        return scnprintf(buf, PAGE_SIZE, "%02X", version);
 758}
 759static DEVICE_ATTR_RO(version);
 760
 761static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
 762                             char *buf)
 763{
 764        struct mei_cl_device *cldev = to_mei_cl_device(dev);
 765        const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
 766        u8 version = mei_me_cl_ver(cldev->me_cl);
 767
 768        return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:%02X:",
 769                         cldev->name, uuid, version);
 770}
 771static DEVICE_ATTR_RO(modalias);
 772
 773static struct attribute *mei_cldev_attrs[] = {
 774        &dev_attr_name.attr,
 775        &dev_attr_uuid.attr,
 776        &dev_attr_version.attr,
 777        &dev_attr_modalias.attr,
 778        NULL,
 779};
 780ATTRIBUTE_GROUPS(mei_cldev);
 781
 782/**
 783 * mei_cl_device_uevent - me client bus uevent handler
 784 *
 785 * @dev: device
 786 * @env: uevent kobject
 787 *
 788 * Return: 0 on success -ENOMEM on when add_uevent_var fails
 789 */
 790static int mei_cl_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 791{
 792        struct mei_cl_device *cldev = to_mei_cl_device(dev);
 793        const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
 794        u8 version = mei_me_cl_ver(cldev->me_cl);
 795
 796        if (add_uevent_var(env, "MEI_CL_VERSION=%d", version))
 797                return -ENOMEM;
 798
 799        if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
 800                return -ENOMEM;
 801
 802        if (add_uevent_var(env, "MEI_CL_NAME=%s", cldev->name))
 803                return -ENOMEM;
 804
 805        if (add_uevent_var(env, "MODALIAS=mei:%s:%pUl:%02X:",
 806                           cldev->name, uuid, version))
 807                return -ENOMEM;
 808
 809        return 0;
 810}
 811
 812static struct bus_type mei_cl_bus_type = {
 813        .name           = "mei",
 814        .dev_groups     = mei_cldev_groups,
 815        .match          = mei_cl_device_match,
 816        .probe          = mei_cl_device_probe,
 817        .remove         = mei_cl_device_remove,
 818        .uevent         = mei_cl_device_uevent,
 819};
 820
 821static struct mei_device *mei_dev_bus_get(struct mei_device *bus)
 822{
 823        if (bus)
 824                get_device(bus->dev);
 825
 826        return bus;
 827}
 828
 829static void mei_dev_bus_put(struct mei_device *bus)
 830{
 831        if (bus)
 832                put_device(bus->dev);
 833}
 834
 835static void mei_cl_bus_dev_release(struct device *dev)
 836{
 837        struct mei_cl_device *cldev = to_mei_cl_device(dev);
 838
 839        if (!cldev)
 840                return;
 841
 842        mei_me_cl_put(cldev->me_cl);
 843        mei_dev_bus_put(cldev->bus);
 844        kfree(cldev->cl);
 845        kfree(cldev);
 846}
 847
 848static struct device_type mei_cl_device_type = {
 849        .release        = mei_cl_bus_dev_release,
 850};
 851
 852/**
 853 * mei_cl_bus_set_name - set device name for me client device
 854 *
 855 * @cldev: me client device
 856 */
 857static inline void mei_cl_bus_set_name(struct mei_cl_device *cldev)
 858{
 859        dev_set_name(&cldev->dev, "mei:%s:%pUl:%02X",
 860                     cldev->name,
 861                     mei_me_cl_uuid(cldev->me_cl),
 862                     mei_me_cl_ver(cldev->me_cl));
 863}
 864
 865/**
 866 * mei_cl_bus_dev_alloc - initialize and allocate mei client device
 867 *
 868 * @bus: mei device
 869 * @me_cl: me client
 870 *
 871 * Return: allocated device structur or NULL on allocation failure
 872 */
 873static struct mei_cl_device *mei_cl_bus_dev_alloc(struct mei_device *bus,
 874                                                  struct mei_me_client *me_cl)
 875{
 876        struct mei_cl_device *cldev;
 877        struct mei_cl *cl;
 878
 879        cldev = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
 880        if (!cldev)
 881                return NULL;
 882
 883        cl = mei_cl_allocate(bus);
 884        if (!cl) {
 885                kfree(cldev);
 886                return NULL;
 887        }
 888
 889        device_initialize(&cldev->dev);
 890        cldev->dev.parent = bus->dev;
 891        cldev->dev.bus    = &mei_cl_bus_type;
 892        cldev->dev.type   = &mei_cl_device_type;
 893        cldev->bus        = mei_dev_bus_get(bus);
 894        cldev->me_cl      = mei_me_cl_get(me_cl);
 895        cldev->cl         = cl;
 896        mei_cl_bus_set_name(cldev);
 897        cldev->is_added   = 0;
 898        INIT_LIST_HEAD(&cldev->bus_list);
 899
 900        return cldev;
 901}
 902
 903/**
 904 * mei_cl_dev_setup - setup me client device
 905 *    run fix up routines and set the device name
 906 *
 907 * @bus: mei device
 908 * @cldev: me client device
 909 *
 910 * Return: true if the device is eligible for enumeration
 911 */
 912static bool mei_cl_bus_dev_setup(struct mei_device *bus,
 913                                 struct mei_cl_device *cldev)
 914{
 915        cldev->do_match = 1;
 916        mei_cl_bus_dev_fixup(cldev);
 917
 918        /* the device name can change during fix up */
 919        if (cldev->do_match)
 920                mei_cl_bus_set_name(cldev);
 921
 922        return cldev->do_match == 1;
 923}
 924
 925/**
 926 * mei_cl_bus_dev_add - add me client devices
 927 *
 928 * @cldev: me client device
 929 *
 930 * Return: 0 on success; < 0 on failre
 931 */
 932static int mei_cl_bus_dev_add(struct mei_cl_device *cldev)
 933{
 934        int ret;
 935
 936        dev_dbg(cldev->bus->dev, "adding %pUL:%02X\n",
 937                mei_me_cl_uuid(cldev->me_cl),
 938                mei_me_cl_ver(cldev->me_cl));
 939        ret = device_add(&cldev->dev);
 940        if (!ret)
 941                cldev->is_added = 1;
 942
 943        return ret;
 944}
 945
 946/**
 947 * mei_cl_bus_dev_stop - stop the driver
 948 *
 949 * @cldev: me client device
 950 */
 951static void mei_cl_bus_dev_stop(struct mei_cl_device *cldev)
 952{
 953        if (cldev->is_added)
 954                device_release_driver(&cldev->dev);
 955}
 956
 957/**
 958 * mei_cl_bus_dev_destroy - destroy me client devices object
 959 *
 960 * @cldev: me client device
 961 *
 962 * Locking: called under "dev->cl_bus_lock" lock
 963 */
 964static void mei_cl_bus_dev_destroy(struct mei_cl_device *cldev)
 965{
 966
 967        WARN_ON(!mutex_is_locked(&cldev->bus->cl_bus_lock));
 968
 969        if (!cldev->is_added)
 970                return;
 971
 972        device_del(&cldev->dev);
 973
 974        list_del_init(&cldev->bus_list);
 975
 976        cldev->is_added = 0;
 977        put_device(&cldev->dev);
 978}
 979
 980/**
 981 * mei_cl_bus_remove_device - remove a devices form the bus
 982 *
 983 * @cldev: me client device
 984 */
 985static void mei_cl_bus_remove_device(struct mei_cl_device *cldev)
 986{
 987        mei_cl_bus_dev_stop(cldev);
 988        mei_cl_bus_dev_destroy(cldev);
 989}
 990
 991/**
 992 * mei_cl_bus_remove_devices - remove all devices form the bus
 993 *
 994 * @bus: mei device
 995 */
 996void mei_cl_bus_remove_devices(struct mei_device *bus)
 997{
 998        struct mei_cl_device *cldev, *next;
 999
1000        mutex_lock(&bus->cl_bus_lock);
1001        list_for_each_entry_safe(cldev, next, &bus->device_list, bus_list)
1002                mei_cl_bus_remove_device(cldev);
1003        mutex_unlock(&bus->cl_bus_lock);
1004}
1005
1006
1007/**
1008 * mei_cl_bus_dev_init - allocate and initializes an mei client devices
1009 *     based on me client
1010 *
1011 * @bus: mei device
1012 * @me_cl: me client
1013 *
1014 * Locking: called under "dev->cl_bus_lock" lock
1015 */
1016static void mei_cl_bus_dev_init(struct mei_device *bus,
1017                                struct mei_me_client *me_cl)
1018{
1019        struct mei_cl_device *cldev;
1020
1021        WARN_ON(!mutex_is_locked(&bus->cl_bus_lock));
1022
1023        dev_dbg(bus->dev, "initializing %pUl", mei_me_cl_uuid(me_cl));
1024
1025        if (me_cl->bus_added)
1026                return;
1027
1028        cldev = mei_cl_bus_dev_alloc(bus, me_cl);
1029        if (!cldev)
1030                return;
1031
1032        me_cl->bus_added = true;
1033        list_add_tail(&cldev->bus_list, &bus->device_list);
1034
1035}
1036
1037/**
1038 * mei_cl_bus_rescan - scan me clients list and add create
1039 *    devices for eligible clients
1040 *
1041 * @bus: mei device
1042 */
1043static void mei_cl_bus_rescan(struct mei_device *bus)
1044{
1045        struct mei_cl_device *cldev, *n;
1046        struct mei_me_client *me_cl;
1047
1048        mutex_lock(&bus->cl_bus_lock);
1049
1050        down_read(&bus->me_clients_rwsem);
1051        list_for_each_entry(me_cl, &bus->me_clients, list)
1052                mei_cl_bus_dev_init(bus, me_cl);
1053        up_read(&bus->me_clients_rwsem);
1054
1055        list_for_each_entry_safe(cldev, n, &bus->device_list, bus_list) {
1056
1057                if (!mei_me_cl_is_active(cldev->me_cl)) {
1058                        mei_cl_bus_remove_device(cldev);
1059                        continue;
1060                }
1061
1062                if (cldev->is_added)
1063                        continue;
1064
1065                if (mei_cl_bus_dev_setup(bus, cldev))
1066                        mei_cl_bus_dev_add(cldev);
1067                else {
1068                        list_del_init(&cldev->bus_list);
1069                        put_device(&cldev->dev);
1070                }
1071        }
1072        mutex_unlock(&bus->cl_bus_lock);
1073
1074        dev_dbg(bus->dev, "rescan end");
1075}
1076
1077void mei_cl_bus_rescan_work(struct work_struct *work)
1078{
1079        struct mei_device *bus =
1080                container_of(work, struct mei_device, bus_rescan_work);
1081
1082        mei_cl_bus_rescan(bus);
1083}
1084
1085int __mei_cldev_driver_register(struct mei_cl_driver *cldrv,
1086                                struct module *owner)
1087{
1088        int err;
1089
1090        cldrv->driver.name = cldrv->name;
1091        cldrv->driver.owner = owner;
1092        cldrv->driver.bus = &mei_cl_bus_type;
1093
1094        err = driver_register(&cldrv->driver);
1095        if (err)
1096                return err;
1097
1098        pr_debug("mei: driver [%s] registered\n", cldrv->driver.name);
1099
1100        return 0;
1101}
1102EXPORT_SYMBOL_GPL(__mei_cldev_driver_register);
1103
1104void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv)
1105{
1106        driver_unregister(&cldrv->driver);
1107
1108        pr_debug("mei: driver [%s] unregistered\n", cldrv->driver.name);
1109}
1110EXPORT_SYMBOL_GPL(mei_cldev_driver_unregister);
1111
1112
1113int __init mei_cl_bus_init(void)
1114{
1115        return bus_register(&mei_cl_bus_type);
1116}
1117
1118void __exit mei_cl_bus_exit(void)
1119{
1120        bus_unregister(&mei_cl_bus_type);
1121}
1122