bus.c 23.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Intel Management Engine Interface (Intel MEI) Linux driver
 * Copyright (c) 2012-2013, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 */

#include <linux/module.h>
#include <linux/device.h>
#include <linux/kernel.h>
19
#include <linux/sched/signal.h>
20 21 22 23 24 25 26 27
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/mei_cl_bus.h>

#include "mei_dev.h"
28
#include "client.h"
29 30 31 32

#define to_mei_cl_driver(d) container_of(d, struct mei_cl_driver, driver)
#define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)

33 34 35 36 37 38
/**
 * __mei_cl_send - internal client send (write)
 *
 * @cl: host client
 * @buf: buffer to send
 * @length: buffer length
39
 * @mode: sending mode
40 41 42 43
 *
 * Return: written size bytes or < 0 on error
 */
ssize_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 51
	if (WARN_ON(!cl || !cl->dev))
		return -ENODEV;
52

53
	bus = cl->dev;
54

55
	mutex_lock(&bus->device_lock);
56 57 58 59 60
	if (bus->dev_state != MEI_DEV_ENABLED) {
		rets = -ENODEV;
		goto out;
	}

61 62 63 64
	if (!mei_cl_is_connected(cl)) {
		rets = -ENODEV;
		goto out;
	}
65

66 67 68 69 70
	/* Check if we have an ME client device */
	if (!mei_me_cl_is_active(cl->me_cl)) {
		rets = -ENOTTY;
		goto out;
	}
71

72 73 74 75
	if (length > mei_cl_mtu(cl)) {
		rets = -EFBIG;
		goto out;
	}
76

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
	while (cl->tx_cb_queued >= bus->tx_queue_limit) {
		mutex_unlock(&bus->device_lock);
		rets = wait_event_interruptible(cl->tx_wait,
				cl->writing_state == MEI_WRITE_COMPLETE ||
				(!mei_cl_is_connected(cl)));
		mutex_lock(&bus->device_lock);
		if (rets) {
			if (signal_pending(current))
				rets = -EINTR;
			goto out;
		}
		if (!mei_cl_is_connected(cl)) {
			rets = -ENODEV;
			goto out;
		}
	}

94 95 96 97
	cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, NULL);
	if (!cb) {
		rets = -ENOMEM;
		goto out;
98 99
	}

100 101
	cb->internal = !!(mode & MEI_CL_IO_TX_INTERNAL);
	cb->blocking = !!(mode & MEI_CL_IO_TX_BLOCKING);
102 103
	memcpy(cb->buf.data, buf, length);

104
	rets = mei_cl_write(cl, cb);
105 106 107 108 109

out:
	mutex_unlock(&bus->device_lock);

	return rets;
110 111
}

112 113 114 115
/**
 * __mei_cl_recv - internal client receive (read)
 *
 * @cl: host client
116
 * @buf: buffer to receive
117
 * @length: buffer length
118
 * @mode: io mode
119
 * @timeout: recv timeout, 0 for infinite timeout
120 121 122
 *
 * Return: read size in bytes of < 0 on error
 */
123
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
124
		      unsigned int mode, unsigned long timeout)
125
{
126 127 128 129
	struct mei_device *bus;
	struct mei_cl_cb *cb;
	size_t r_length;
	ssize_t rets;
130
	bool nonblock = !!(mode & MEI_CL_IO_RX_NONBLOCK);
131

132
	if (WARN_ON(!cl || !cl->dev))
133 134
		return -ENODEV;

135
	bus = cl->dev;
136

137
	mutex_lock(&bus->device_lock);
138 139 140 141
	if (bus->dev_state != MEI_DEV_ENABLED) {
		rets = -ENODEV;
		goto out;
	}
142

143 144 145
	cb = mei_cl_read_cb(cl, NULL);
	if (cb)
		goto copy;
146

147 148 149
	rets = mei_cl_read_start(cl, length, NULL);
	if (rets && rets != -EBUSY)
		goto out;
150

151 152 153 154 155
	if (nonblock) {
		rets = -EAGAIN;
		goto out;
	}

156
	/* wait on event only if there is no other waiter */
157 158
	/* synchronized under device mutex */
	if (!waitqueue_active(&cl->rx_wait)) {
159

160
		mutex_unlock(&bus->device_lock);
161

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
		if (timeout) {
			rets = wait_event_interruptible_timeout
					(cl->rx_wait,
					(!list_empty(&cl->rd_completed)) ||
					(!mei_cl_is_connected(cl)),
					msecs_to_jiffies(timeout));
			if (rets == 0)
				return -ETIME;
			if (rets < 0) {
				if (signal_pending(current))
					return -EINTR;
				return -ERESTARTSYS;
			}
		} else {
			if (wait_event_interruptible
					(cl->rx_wait,
					(!list_empty(&cl->rd_completed)) ||
					(!mei_cl_is_connected(cl)))) {
				if (signal_pending(current))
					return -EINTR;
				return -ERESTARTSYS;
			}
184 185 186 187 188
		}

		mutex_lock(&bus->device_lock);

		if (!mei_cl_is_connected(cl)) {
189
			rets = -ENODEV;
190 191
			goto out;
		}
192 193
	}

194 195 196 197 198
	cb = mei_cl_read_cb(cl, NULL);
	if (!cb) {
		rets = 0;
		goto out;
	}
199

200 201 202 203 204
copy:
	if (cb->status) {
		rets = cb->status;
		goto free;
	}
205

206 207 208
	r_length = min_t(size_t, length, cb->buf_idx);
	memcpy(buf, cb->buf.data, r_length);
	rets = r_length;
209

210 211 212 213 214 215
free:
	mei_io_cb_free(cb);
out:
	mutex_unlock(&bus->device_lock);

	return rets;
216 217
}

218
/**
219
 * mei_cldev_send - me device send  (write)
220 221 222 223 224 225 226
 *
 * @cldev: me client device
 * @buf: buffer to send
 * @length: buffer length
 *
 * Return: written size in bytes or < 0 on error
 */
227
ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
228
{
229
	struct mei_cl *cl = cldev->cl;
230

231
	return __mei_cl_send(cl, buf, length, MEI_CL_IO_TX_BLOCKING);
232
}
233
EXPORT_SYMBOL_GPL(mei_cldev_send);
234

235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
/**
 * mei_cldev_recv_nonblock - non block client receive (read)
 *
 * @cldev: me client device
 * @buf: buffer to receive
 * @length: buffer length
 *
 * Return: read size in bytes of < 0 on error
 *         -EAGAIN if function will block.
 */
ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
				size_t length)
{
	struct mei_cl *cl = cldev->cl;

250
	return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK, 0);
251 252 253
}
EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);

254
/**
255
 * mei_cldev_recv - client receive (read)
256 257
 *
 * @cldev: me client device
258
 * @buf: buffer to receive
259 260 261 262
 * @length: buffer length
 *
 * Return: read size in bytes of < 0 on error
 */
263
ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
264
{
265
	struct mei_cl *cl = cldev->cl;
266

267
	return __mei_cl_recv(cl, buf, length, 0, 0);
268
}
269
EXPORT_SYMBOL_GPL(mei_cldev_recv);
270

271
/**
272
 * mei_cl_bus_rx_work - dispatch rx event for a bus device
273 274 275
 *
 * @work: work
 */
276
static void mei_cl_bus_rx_work(struct work_struct *work)
277
{
278
	struct mei_cl_device *cldev;
279
	struct mei_device *bus;
280

281
	cldev = container_of(work, struct mei_cl_device, rx_work);
282

283 284
	bus = cldev->bus;

285 286
	if (cldev->rx_cb)
		cldev->rx_cb(cldev);
287

288 289 290 291
	mutex_lock(&bus->device_lock);
	mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
	mutex_unlock(&bus->device_lock);
}
292

293 294 295 296 297 298 299 300 301 302 303 304 305
/**
 * mei_cl_bus_notif_work - dispatch FW notif event for a bus device
 *
 * @work: work
 */
static void mei_cl_bus_notif_work(struct work_struct *work)
{
	struct mei_cl_device *cldev;

	cldev = container_of(work, struct mei_cl_device, notif_work);

	if (cldev->notif_cb)
		cldev->notif_cb(cldev);
306 307 308 309 310 311
}

/**
 * mei_cl_bus_notify_event - schedule notify cb on bus client
 *
 * @cl: host client
312 313 314
 *
 * Return: true if event was scheduled
 *         false if the client is not waiting for event
315
 */
316
bool mei_cl_bus_notify_event(struct mei_cl *cl)
317 318 319
{
	struct mei_cl_device *cldev = cl->cldev;

320
	if (!cldev || !cldev->notif_cb)
321
		return false;
322 323

	if (!cl->notify_ev)
324
		return false;
325

326
	schedule_work(&cldev->notif_work);
327 328

	cl->notify_ev = false;
329 330

	return true;
331 332
}

333
/**
334
 * mei_cl_bus_rx_event - schedule rx event
335 336
 *
 * @cl: host client
337 338 339
 *
 * Return: true if event was scheduled
 *         false if the client is not waiting for event
340
 */
341
bool mei_cl_bus_rx_event(struct mei_cl *cl)
342
{
343
	struct mei_cl_device *cldev = cl->cldev;
344

345
	if (!cldev || !cldev->rx_cb)
346
		return false;
347

348
	schedule_work(&cldev->rx_work);
349 350

	return true;
351
}
352

353
/**
354
 * mei_cldev_register_rx_cb - register Rx event callback
355 356
 *
 * @cldev: me client devices
357
 * @rx_cb: callback function
358 359 360 361 362
 *
 * Return: 0 on success
 *         -EALREADY if an callback is already registered
 *         <0 on other errors
 */
363
int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb)
364
{
365
	struct mei_device *bus = cldev->bus;
366 367
	int ret;

368 369 370
	if (!rx_cb)
		return -EINVAL;
	if (cldev->rx_cb)
371
		return -EALREADY;
372

373 374
	cldev->rx_cb = rx_cb;
	INIT_WORK(&cldev->rx_work, mei_cl_bus_rx_work);
375

376 377 378 379 380
	mutex_lock(&bus->device_lock);
	ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
	mutex_unlock(&bus->device_lock);
	if (ret && ret != -EBUSY)
		return ret;
381

382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
	return 0;
}
EXPORT_SYMBOL_GPL(mei_cldev_register_rx_cb);

/**
 * mei_cldev_register_notif_cb - register FW notification event callback
 *
 * @cldev: me client devices
 * @notif_cb: callback function
 *
 * Return: 0 on success
 *         -EALREADY if an callback is already registered
 *         <0 on other errors
 */
int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,
				mei_cldev_cb_t notif_cb)
{
	struct mei_device *bus = cldev->bus;
	int ret;

	if (!notif_cb)
		return -EINVAL;

	if (cldev->notif_cb)
		return -EALREADY;

	cldev->notif_cb = notif_cb;
	INIT_WORK(&cldev->notif_work, mei_cl_bus_notif_work);

	mutex_lock(&bus->device_lock);
	ret = mei_cl_notify_request(cldev->cl, NULL, 1);
	mutex_unlock(&bus->device_lock);
	if (ret)
		return ret;
416

417 418
	return 0;
}
419
EXPORT_SYMBOL_GPL(mei_cldev_register_notif_cb);
420

421
/**
422
 * mei_cldev_get_drvdata - driver data getter
423 424 425 426 427
 *
 * @cldev: mei client device
 *
 * Return: driver private data
 */
428
void *mei_cldev_get_drvdata(const struct mei_cl_device *cldev)
429 430
{
	return dev_get_drvdata(&cldev->dev);
431
}
432
EXPORT_SYMBOL_GPL(mei_cldev_get_drvdata);
433

434
/**
435
 * mei_cldev_set_drvdata - driver data setter
436 437 438 439
 *
 * @cldev: mei client device
 * @data: data to store
 */
440
void mei_cldev_set_drvdata(struct mei_cl_device *cldev, void *data)
441
{
442
	dev_set_drvdata(&cldev->dev, data);
443
}
444
EXPORT_SYMBOL_GPL(mei_cldev_set_drvdata);
445

446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
/**
 * mei_cldev_uuid - return uuid of the underlying me client
 *
 * @cldev: mei client device
 *
 * Return: me client uuid
 */
const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev)
{
	return mei_me_cl_uuid(cldev->me_cl);
}
EXPORT_SYMBOL_GPL(mei_cldev_uuid);

/**
 * mei_cldev_ver - return protocol version of the underlying me client
 *
 * @cldev: mei client device
 *
 * Return: me client protocol version
 */
u8 mei_cldev_ver(const struct mei_cl_device *cldev)
{
	return mei_me_cl_ver(cldev->me_cl);
}
EXPORT_SYMBOL_GPL(mei_cldev_ver);

472 473 474 475 476 477 478 479 480
/**
 * mei_cldev_enabled - check whether the device is enabled
 *
 * @cldev: mei client device
 *
 * Return: true if me client is initialized and connected
 */
bool mei_cldev_enabled(struct mei_cl_device *cldev)
{
481
	return mei_cl_is_connected(cldev->cl);
482 483 484
}
EXPORT_SYMBOL_GPL(mei_cldev_enabled);

485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
/**
 * mei_cl_bus_module_get - acquire module of the underlying
 *    hw driver.
 *
 * @cldev: mei client device
 *
 * Return: true on success; false if the module was removed.
 */
static bool mei_cl_bus_module_get(struct mei_cl_device *cldev)
{
	return try_module_get(cldev->bus->dev->driver->owner);
}

/**
 * mei_cl_bus_module_put -  release the underlying hw module.
 *
 * @cldev: mei client device
 */
static void mei_cl_bus_module_put(struct mei_cl_device *cldev)
{
	module_put(cldev->bus->dev->driver->owner);
}

508
/**
509
 * mei_cldev_enable - enable me client device
510 511 512 513 514 515
 *     create connection with me client
 *
 * @cldev: me client device
 *
 * Return: 0 on success and < 0 on error
 */
516
int mei_cldev_enable(struct mei_cl_device *cldev)
517
{
518 519 520
	struct mei_device *bus = cldev->bus;
	struct mei_cl *cl;
	int ret;
521

522
	cl = cldev->cl;
523

524
	mutex_lock(&bus->device_lock);
525 526 527
	if (cl->state == MEI_FILE_UNINITIALIZED) {
		ret = mei_cl_link(cl);
		if (ret)
528
			goto out;
529 530 531
		/* update pointers */
		cl->cldev = cldev;
	}
532

533
	if (mei_cl_is_connected(cl)) {
534 535
		ret = 0;
		goto out;
536
	}
537

538 539 540 541
	if (!mei_me_cl_is_active(cldev->me_cl)) {
		dev_err(&cldev->dev, "me client is not active\n");
		ret = -ENOTTY;
		goto out;
542 543
	}

544 545 546 547 548 549
	if (!mei_cl_bus_module_get(cldev)) {
		dev_err(&cldev->dev, "get hw module failed");
		ret = -ENODEV;
		goto out;
	}

550
	ret = mei_cl_connect(cl, cldev->me_cl, NULL);
551
	if (ret < 0) {
552
		dev_err(&cldev->dev, "cannot connect\n");
553 554
		mei_cl_bus_module_put(cldev);
	}
555 556

out:
557 558
	mutex_unlock(&bus->device_lock);

559
	return ret;
560
}
561
EXPORT_SYMBOL_GPL(mei_cldev_enable);
562

563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581
/**
 * mei_cldev_unregister_callbacks - internal wrapper for unregistering
 *  callbacks.
 *
 * @cldev: client device
 */
static void mei_cldev_unregister_callbacks(struct mei_cl_device *cldev)
{
	if (cldev->rx_cb) {
		cancel_work_sync(&cldev->rx_work);
		cldev->rx_cb = NULL;
	}

	if (cldev->notif_cb) {
		cancel_work_sync(&cldev->notif_work);
		cldev->notif_cb = NULL;
	}
}

582
/**
583
 * mei_cldev_disable - disable me client device
584 585 586 587 588 589
 *     disconnect form the me client
 *
 * @cldev: me client device
 *
 * Return: 0 on success and < 0 on error
 */
590
int mei_cldev_disable(struct mei_cl_device *cldev)
591
{
592
	struct mei_device *bus;
593 594
	struct mei_cl *cl;
	int err;
595

596
	if (!cldev)
597 598
		return -ENODEV;

599 600 601
	cl = cldev->cl;

	bus = cldev->bus;
T
Tomas Winkler 已提交
602

603 604
	mei_cldev_unregister_callbacks(cldev);

605
	mutex_lock(&bus->device_lock);
T
Tomas Winkler 已提交
606

607
	if (!mei_cl_is_connected(cl)) {
T
Tomas Winkler 已提交
608 609 610 611 612
		dev_dbg(bus->dev, "Already disconnected\n");
		err = 0;
		goto out;
	}

613
	err = mei_cl_disconnect(cl);
614
	if (err < 0)
T
Tomas Winkler 已提交
615
		dev_err(bus->dev, "Could not disconnect from the ME client\n");
616

617
	mei_cl_bus_module_put(cldev);
618
out:
619 620
	/* Flush queues and remove any pending read */
	mei_cl_flush_queues(cl, NULL);
621 622
	mei_cl_unlink(cl);

623
	mutex_unlock(&bus->device_lock);
624
	return err;
625
}
626
EXPORT_SYMBOL_GPL(mei_cldev_disable);
627

T
Tomas Winkler 已提交
628 629 630 631 632 633 634 635 636 637 638
/**
 * mei_cl_device_find - find matching entry in the driver id table
 *
 * @cldev: me client device
 * @cldrv: me client driver
 *
 * Return: id on success; NULL if no id is matching
 */
static const
struct mei_cl_device_id *mei_cl_device_find(struct mei_cl_device *cldev,
					    struct mei_cl_driver *cldrv)
639
{
640 641
	const struct mei_cl_device_id *id;
	const uuid_le *uuid;
642 643
	u8 version;
	bool match;
644

645
	uuid = mei_me_cl_uuid(cldev->me_cl);
646
	version = mei_me_cl_ver(cldev->me_cl);
647

648 649 650
	id = cldrv->id_table;
	while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) {
		if (!uuid_le_cmp(*uuid, id->uuid)) {
651
			match = true;
T
Tomas Winkler 已提交
652

653 654 655 656
			if (cldev->name[0])
				if (strncmp(cldev->name, id->name,
					    sizeof(id->name)))
					match = false;
T
Tomas Winkler 已提交
657

658 659 660 661
			if (id->version != MEI_CL_VERSION_ANY)
				if (id->version != version)
					match = false;
			if (match)
T
Tomas Winkler 已提交
662
				return id;
663
		}
664

665 666
		id++;
	}
667

T
Tomas Winkler 已提交
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687
	return NULL;
}

/**
 * mei_cl_device_match  - device match function
 *
 * @dev: device
 * @drv: driver
 *
 * Return:  1 if matching device was found 0 otherwise
 */
static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
{
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	struct mei_cl_driver *cldrv = to_mei_cl_driver(drv);
	const struct mei_cl_device_id *found_id;

	if (!cldev)
		return 0;

688 689 690
	if (!cldev->do_match)
		return 0;

T
Tomas Winkler 已提交
691 692 693 694 695 696 697
	if (!cldrv || !cldrv->id_table)
		return 0;

	found_id = mei_cl_device_find(cldev, cldrv);
	if (found_id)
		return 1;

698 699
	return 0;
}
700

701 702 703 704 705 706 707
/**
 * mei_cl_device_probe - bus probe function
 *
 * @dev: device
 *
 * Return:  0 on success; < 0 otherwise
 */
708 709
static int mei_cl_device_probe(struct device *dev)
{
710
	struct mei_cl_device *cldev;
711
	struct mei_cl_driver *cldrv;
712
	const struct mei_cl_device_id *id;
713
	int ret;
714 715 716

	cldev = to_mei_cl_device(dev);
	cldrv = to_mei_cl_driver(dev->driver);
717

718 719
	if (!cldev)
		return 0;
720

721 722 723
	if (!cldrv || !cldrv->probe)
		return -ENODEV;

724 725 726
	id = mei_cl_device_find(cldev, cldrv);
	if (!id)
		return -ENODEV;
727

728 729 730
	ret = cldrv->probe(cldev, id);
	if (ret)
		return ret;
731

732 733
	__module_get(THIS_MODULE);
	return 0;
734
}
735

736 737 738 739 740 741 742
/**
 * mei_cl_device_remove - remove device from the bus
 *
 * @dev: device
 *
 * Return:  0 on success; < 0 otherwise
 */
743 744 745 746
static int mei_cl_device_remove(struct device *dev)
{
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	struct mei_cl_driver *cldrv;
747
	int ret = 0;
748

749 750 751
	if (!cldev || !dev->driver)
		return 0;

752 753 754 755
	cldrv = to_mei_cl_driver(dev->driver);
	if (cldrv->remove)
		ret = cldrv->remove(cldev);

756
	mei_cldev_unregister_callbacks(cldev);
757

758 759 760
	module_put(THIS_MODULE);
	dev->driver = NULL;
	return ret;
761 762 763

}

764 765
static ssize_t name_show(struct device *dev, struct device_attribute *a,
			     char *buf)
766
{
767
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
768

769
	return scnprintf(buf, PAGE_SIZE, "%s", cldev->name);
770
}
771
static DEVICE_ATTR_RO(name);
772

773 774
static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
			     char *buf)
775
{
776 777
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
778

779
	return scnprintf(buf, PAGE_SIZE, "%pUl", uuid);
780
}
781
static DEVICE_ATTR_RO(uuid);
782

783 784 785 786 787 788
static ssize_t version_show(struct device *dev, struct device_attribute *a,
			     char *buf)
{
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	u8 version = mei_me_cl_ver(cldev->me_cl);

789
	return scnprintf(buf, PAGE_SIZE, "%02X", version);
790 791 792
}
static DEVICE_ATTR_RO(version);

793 794
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
			     char *buf)
795
{
796 797
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
798
	u8 version = mei_me_cl_ver(cldev->me_cl);
799

800 801
	return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:%02X:",
			 cldev->name, uuid, version);
802
}
803
static DEVICE_ATTR_RO(modalias);
804

805
static struct attribute *mei_cldev_attrs[] = {
806 807
	&dev_attr_name.attr,
	&dev_attr_uuid.attr,
808
	&dev_attr_version.attr,
809 810 811
	&dev_attr_modalias.attr,
	NULL,
};
812
ATTRIBUTE_GROUPS(mei_cldev);
813

814 815 816 817 818 819 820 821 822
/**
 * mei_cl_device_uevent - me client bus uevent handler
 *
 * @dev: device
 * @env: uevent kobject
 *
 * Return: 0 on success -ENOMEM on when add_uevent_var fails
 */
static int mei_cl_device_uevent(struct device *dev, struct kobj_uevent_env *env)
823
{
824 825
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
826 827 828 829
	u8 version = mei_me_cl_ver(cldev->me_cl);

	if (add_uevent_var(env, "MEI_CL_VERSION=%d", version))
		return -ENOMEM;
830

831 832
	if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
		return -ENOMEM;
833

834 835 836
	if (add_uevent_var(env, "MEI_CL_NAME=%s", cldev->name))
		return -ENOMEM;

837 838
	if (add_uevent_var(env, "MODALIAS=mei:%s:%pUl:%02X:",
			   cldev->name, uuid, version))
839
		return -ENOMEM;
840 841 842

	return 0;
}
843

844 845
static struct bus_type mei_cl_bus_type = {
	.name		= "mei",
846
	.dev_groups	= mei_cldev_groups,
847 848 849
	.match		= mei_cl_device_match,
	.probe		= mei_cl_device_probe,
	.remove		= mei_cl_device_remove,
850
	.uevent		= mei_cl_device_uevent,
851 852
};

853 854 855 856 857 858 859 860 861 862 863 864 865 866
static struct mei_device *mei_dev_bus_get(struct mei_device *bus)
{
	if (bus)
		get_device(bus->dev);

	return bus;
}

static void mei_dev_bus_put(struct mei_device *bus)
{
	if (bus)
		put_device(bus->dev);
}

867
static void mei_cl_bus_dev_release(struct device *dev)
868
{
869 870 871 872 873 874
	struct mei_cl_device *cldev = to_mei_cl_device(dev);

	if (!cldev)
		return;

	mei_me_cl_put(cldev->me_cl);
875
	mei_dev_bus_put(cldev->bus);
876
	mei_cl_unlink(cldev->cl);
877
	kfree(cldev->cl);
878
	kfree(cldev);
879 880
}

B
Bhumika Goyal 已提交
881
static const struct device_type mei_cl_device_type = {
882
	.release = mei_cl_bus_dev_release,
883 884
};

885 886 887 888 889 890 891 892 893 894 895 896 897
/**
 * mei_cl_bus_set_name - set device name for me client device
 *
 * @cldev: me client device
 */
static inline void mei_cl_bus_set_name(struct mei_cl_device *cldev)
{
	dev_set_name(&cldev->dev, "mei:%s:%pUl:%02X",
		     cldev->name,
		     mei_me_cl_uuid(cldev->me_cl),
		     mei_me_cl_ver(cldev->me_cl));
}

898
/**
899
 * mei_cl_bus_dev_alloc - initialize and allocate mei client device
900 901 902 903 904 905
 *
 * @bus: mei device
 * @me_cl: me client
 *
 * Return: allocated device structur or NULL on allocation failure
 */
906 907
static struct mei_cl_device *mei_cl_bus_dev_alloc(struct mei_device *bus,
						  struct mei_me_client *me_cl)
908 909
{
	struct mei_cl_device *cldev;
910
	struct mei_cl *cl;
911 912 913 914 915

	cldev = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
	if (!cldev)
		return NULL;

916 917 918 919 920 921
	cl = mei_cl_allocate(bus);
	if (!cl) {
		kfree(cldev);
		return NULL;
	}

922 923 924 925 926 927
	device_initialize(&cldev->dev);
	cldev->dev.parent = bus->dev;
	cldev->dev.bus    = &mei_cl_bus_type;
	cldev->dev.type   = &mei_cl_device_type;
	cldev->bus        = mei_dev_bus_get(bus);
	cldev->me_cl      = mei_me_cl_get(me_cl);
928
	cldev->cl         = cl;
929
	mei_cl_bus_set_name(cldev);
930 931 932 933 934 935 936 937 938 939 940 941 942 943 944
	cldev->is_added   = 0;
	INIT_LIST_HEAD(&cldev->bus_list);

	return cldev;
}

/**
 * mei_cl_dev_setup - setup me client device
 *    run fix up routines and set the device name
 *
 * @bus: mei device
 * @cldev: me client device
 *
 * Return: true if the device is eligible for enumeration
 */
945 946
static bool mei_cl_bus_dev_setup(struct mei_device *bus,
				 struct mei_cl_device *cldev)
947 948
{
	cldev->do_match = 1;
949
	mei_cl_bus_dev_fixup(cldev);
950

951
	/* the device name can change during fix up */
952
	if (cldev->do_match)
953
		mei_cl_bus_set_name(cldev);
954 955 956 957 958 959 960 961 962 963 964 965 966 967 968

	return cldev->do_match == 1;
}

/**
 * mei_cl_bus_dev_add - add me client devices
 *
 * @cldev: me client device
 *
 * Return: 0 on success; < 0 on failre
 */
static int mei_cl_bus_dev_add(struct mei_cl_device *cldev)
{
	int ret;

969 970 971
	dev_dbg(cldev->bus->dev, "adding %pUL:%02X\n",
		mei_me_cl_uuid(cldev->me_cl),
		mei_me_cl_ver(cldev->me_cl));
972 973 974 975 976 977 978
	ret = device_add(&cldev->dev);
	if (!ret)
		cldev->is_added = 1;

	return ret;
}

979 980 981 982 983 984 985 986 987 988 989 990 991 992 993
/**
 * mei_cl_bus_dev_stop - stop the driver
 *
 * @cldev: me client device
 */
static void mei_cl_bus_dev_stop(struct mei_cl_device *cldev)
{
	if (cldev->is_added)
		device_release_driver(&cldev->dev);
}

/**
 * mei_cl_bus_dev_destroy - destroy me client devices object
 *
 * @cldev: me client device
994 995
 *
 * Locking: called under "dev->cl_bus_lock" lock
996 997 998
 */
static void mei_cl_bus_dev_destroy(struct mei_cl_device *cldev)
{
999 1000 1001

	WARN_ON(!mutex_is_locked(&cldev->bus->cl_bus_lock));

1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
	if (!cldev->is_added)
		return;

	device_del(&cldev->dev);

	list_del_init(&cldev->bus_list);

	cldev->is_added = 0;
	put_device(&cldev->dev);
}

/**
 * mei_cl_bus_remove_device - remove a devices form the bus
 *
 * @cldev: me client device
 */
static void mei_cl_bus_remove_device(struct mei_cl_device *cldev)
{
	mei_cl_bus_dev_stop(cldev);
	mei_cl_bus_dev_destroy(cldev);
}

/**
 * mei_cl_bus_remove_devices - remove all devices form the bus
 *
 * @bus: mei device
 */
void mei_cl_bus_remove_devices(struct mei_device *bus)
{
	struct mei_cl_device *cldev, *next;

1033
	mutex_lock(&bus->cl_bus_lock);
1034 1035
	list_for_each_entry_safe(cldev, next, &bus->device_list, bus_list)
		mei_cl_bus_remove_device(cldev);
1036
	mutex_unlock(&bus->cl_bus_lock);
1037 1038 1039 1040
}


/**
1041
 * mei_cl_bus_dev_init - allocate and initializes an mei client devices
1042 1043 1044 1045
 *     based on me client
 *
 * @bus: mei device
 * @me_cl: me client
1046 1047
 *
 * Locking: called under "dev->cl_bus_lock" lock
1048
 */
1049 1050
static void mei_cl_bus_dev_init(struct mei_device *bus,
				struct mei_me_client *me_cl)
1051
{
1052
	struct mei_cl_device *cldev;
1053

1054 1055
	WARN_ON(!mutex_is_locked(&bus->cl_bus_lock));

1056 1057 1058 1059
	dev_dbg(bus->dev, "initializing %pUl", mei_me_cl_uuid(me_cl));

	if (me_cl->bus_added)
		return;
1060

1061
	cldev = mei_cl_bus_dev_alloc(bus, me_cl);
1062
	if (!cldev)
1063
		return;
1064

1065 1066
	me_cl->bus_added = true;
	list_add_tail(&cldev->bus_list, &bus->device_list);
T
Tomas Winkler 已提交
1067

1068
}
1069

1070 1071 1072 1073 1074 1075
/**
 * mei_cl_bus_rescan - scan me clients list and add create
 *    devices for eligible clients
 *
 * @bus: mei device
 */
1076
static void mei_cl_bus_rescan(struct mei_device *bus)
1077 1078 1079
{
	struct mei_cl_device *cldev, *n;
	struct mei_me_client *me_cl;
1080

1081 1082
	mutex_lock(&bus->cl_bus_lock);

1083 1084
	down_read(&bus->me_clients_rwsem);
	list_for_each_entry(me_cl, &bus->me_clients, list)
1085
		mei_cl_bus_dev_init(bus, me_cl);
1086
	up_read(&bus->me_clients_rwsem);
1087

1088
	list_for_each_entry_safe(cldev, n, &bus->device_list, bus_list) {
1089

1090 1091 1092 1093
		if (!mei_me_cl_is_active(cldev->me_cl)) {
			mei_cl_bus_remove_device(cldev);
			continue;
		}
1094

1095 1096 1097
		if (cldev->is_added)
			continue;

1098
		if (mei_cl_bus_dev_setup(bus, cldev))
1099 1100 1101 1102 1103 1104 1105 1106 1107
			mei_cl_bus_dev_add(cldev);
		else {
			list_del_init(&cldev->bus_list);
			put_device(&cldev->dev);
		}
	}
	mutex_unlock(&bus->cl_bus_lock);

	dev_dbg(bus->dev, "rescan end");
1108
}
1109

1110 1111 1112 1113 1114 1115 1116 1117
void mei_cl_bus_rescan_work(struct work_struct *work)
{
	struct mei_device *bus =
		container_of(work, struct mei_device, bus_rescan_work);

	mei_cl_bus_rescan(bus);
}

1118 1119
int __mei_cldev_driver_register(struct mei_cl_driver *cldrv,
				struct module *owner)
1120 1121
{
	int err;
1122

1123 1124 1125
	cldrv->driver.name = cldrv->name;
	cldrv->driver.owner = owner;
	cldrv->driver.bus = &mei_cl_bus_type;
1126

1127 1128 1129
	err = driver_register(&cldrv->driver);
	if (err)
		return err;
1130

1131
	pr_debug("mei: driver [%s] registered\n", cldrv->driver.name);
1132

1133
	return 0;
1134
}
1135
EXPORT_SYMBOL_GPL(__mei_cldev_driver_register);
1136

1137
void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv)
1138
{
1139
	driver_unregister(&cldrv->driver);
1140

1141
	pr_debug("mei: driver [%s] unregistered\n", cldrv->driver.name);
1142
}
1143
EXPORT_SYMBOL_GPL(mei_cldev_driver_unregister);
1144

1145

1146 1147 1148 1149 1150 1151 1152 1153 1154
int __init mei_cl_bus_init(void)
{
	return bus_register(&mei_cl_bus_type);
}

void __exit mei_cl_bus_exit(void)
{
	bus_unregister(&mei_cl_bus_type);
}