bus.c 20.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.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 39 40 41 42 43 44
/**
 * __mei_cl_send - internal client send (write)
 *
 * @cl: host client
 * @buf: buffer to send
 * @length: buffer length
 * @blocking: wait for write completion
 *
 * Return: written size bytes or < 0 on error
 */
ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
			bool blocking)
45
{
46 47 48
	struct mei_device *bus;
	struct mei_cl_cb *cb = NULL;
	ssize_t rets;
49

50 51
	if (WARN_ON(!cl || !cl->dev))
		return -ENODEV;
52

53
	bus = cl->dev;
54

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

61 62 63 64 65
	/* Check if we have an ME client device */
	if (!mei_me_cl_is_active(cl->me_cl)) {
		rets = -ENOTTY;
		goto out;
	}
66

67 68 69 70
	if (length > mei_cl_mtu(cl)) {
		rets = -EFBIG;
		goto out;
	}
71

72 73 74 75
	cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, NULL);
	if (!cb) {
		rets = -ENOMEM;
		goto out;
76 77
	}

78 79 80 81 82 83 84 85 86 87
	memcpy(cb->buf.data, buf, length);

	rets = mei_cl_write(cl, cb, blocking);

out:
	mutex_unlock(&bus->device_lock);
	if (rets < 0)
		mei_io_cb_free(cb);

	return rets;
88 89
}

90 91 92 93
/**
 * __mei_cl_recv - internal client receive (read)
 *
 * @cl: host client
94
 * @buf: buffer to receive
95 96 97 98 99
 * @length: buffer length
 *
 * Return: read size in bytes of < 0 on error
 */
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
100
{
101 102 103 104
	struct mei_device *bus;
	struct mei_cl_cb *cb;
	size_t r_length;
	ssize_t rets;
105

106
	if (WARN_ON(!cl || !cl->dev))
107 108
		return -ENODEV;

109
	bus = cl->dev;
110

111
	mutex_lock(&bus->device_lock);
112

113 114 115
	cb = mei_cl_read_cb(cl, NULL);
	if (cb)
		goto copy;
116

117 118 119
	rets = mei_cl_read_start(cl, length, NULL);
	if (rets && rets != -EBUSY)
		goto out;
120

121 122
	/* wait on event only if there is no other waiter */
	if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
123

124
		mutex_unlock(&bus->device_lock);
125

126 127 128
		if (wait_event_interruptible(cl->rx_wait,
				(!list_empty(&cl->rd_completed)) ||
				(!mei_cl_is_connected(cl)))) {
129

130 131 132 133 134 135 136 137 138 139 140
			if (signal_pending(current))
				return -EINTR;
			return -ERESTARTSYS;
		}

		mutex_lock(&bus->device_lock);

		if (!mei_cl_is_connected(cl)) {
			rets = -EBUSY;
			goto out;
		}
141 142
	}

143 144 145 146 147
	cb = mei_cl_read_cb(cl, NULL);
	if (!cb) {
		rets = 0;
		goto out;
	}
148

149 150 151 152 153
copy:
	if (cb->status) {
		rets = cb->status;
		goto free;
	}
154

155 156 157
	r_length = min_t(size_t, length, cb->buf_idx);
	memcpy(buf, cb->buf.data, r_length);
	rets = r_length;
158

159 160 161 162 163 164
free:
	mei_io_cb_free(cb);
out:
	mutex_unlock(&bus->device_lock);

	return rets;
165 166
}

167
/**
168
 * mei_cldev_send - me device send  (write)
169 170 171 172 173 174 175
 *
 * @cldev: me client device
 * @buf: buffer to send
 * @length: buffer length
 *
 * Return: written size in bytes or < 0 on error
 */
176
ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
177
{
178
	struct mei_cl *cl = cldev->cl;
179

180 181
	if (cl == NULL)
		return -ENODEV;
182

183
	return __mei_cl_send(cl, buf, length, 1);
184
}
185
EXPORT_SYMBOL_GPL(mei_cldev_send);
186

187
/**
188
 * mei_cldev_recv - client receive (read)
189 190
 *
 * @cldev: me client device
191
 * @buf: buffer to receive
192 193 194 195
 * @length: buffer length
 *
 * Return: read size in bytes of < 0 on error
 */
196
ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
197
{
198
	struct mei_cl *cl = cldev->cl;
199

200 201
	if (cl == NULL)
		return -ENODEV;
202

203
	return __mei_cl_recv(cl, buf, length);
204
}
205
EXPORT_SYMBOL_GPL(mei_cldev_recv);
206

207
/**
208
 * mei_cl_bus_event_work  - dispatch rx event for a bus device
209 210 211 212
 *    and schedule new work
 *
 * @work: work
 */
213
static void mei_cl_bus_event_work(struct work_struct *work)
214
{
215
	struct mei_cl_device *cldev;
216

217
	cldev = container_of(work, struct mei_cl_device, event_work);
218

219 220
	if (cldev->event_cb)
		cldev->event_cb(cldev, cldev->events, cldev->event_context);
221

222
	cldev->events = 0;
223

224
	/* Prepare for the next read */
225 226 227 228 229 230 231 232
	if (cldev->events_mask & BIT(MEI_CL_EVENT_RX))
		mei_cl_read_start(cldev->cl, 0, NULL);
}

/**
 * mei_cl_bus_notify_event - schedule notify cb on bus client
 *
 * @cl: host client
233 234 235
 *
 * Return: true if event was scheduled
 *         false if the client is not waiting for event
236
 */
237
bool mei_cl_bus_notify_event(struct mei_cl *cl)
238 239 240 241
{
	struct mei_cl_device *cldev = cl->cldev;

	if (!cldev || !cldev->event_cb)
242
		return false;
243 244

	if (!(cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)))
245
		return false;
246 247

	if (!cl->notify_ev)
248
		return false;
249 250 251 252 253 254

	set_bit(MEI_CL_EVENT_NOTIF, &cldev->events);

	schedule_work(&cldev->event_work);

	cl->notify_ev = false;
255 256

	return true;
257 258
}

259
/**
260
 * mei_cl_bus_rx_event  - schedule rx event
261 262
 *
 * @cl: host client
263 264 265
 *
 * Return: true if event was scheduled
 *         false if the client is not waiting for event
266
 */
267
bool mei_cl_bus_rx_event(struct mei_cl *cl)
268
{
269
	struct mei_cl_device *cldev = cl->cldev;
270

271
	if (!cldev || !cldev->event_cb)
272
		return false;
273

274
	if (!(cldev->events_mask & BIT(MEI_CL_EVENT_RX)))
275
		return false;
276

277
	set_bit(MEI_CL_EVENT_RX, &cldev->events);
278

279
	schedule_work(&cldev->event_work);
280 281

	return true;
282
}
283

284
/**
285
 * mei_cldev_register_event_cb - register event callback
286 287 288
 *
 * @cldev: me client devices
 * @event_cb: callback function
289
 * @events_mask: requested events bitmask
290 291 292 293 294 295
 * @context: driver context data
 *
 * Return: 0 on success
 *         -EALREADY if an callback is already registered
 *         <0 on other errors
 */
296 297 298
int mei_cldev_register_event_cb(struct mei_cl_device *cldev,
				unsigned long events_mask,
				mei_cldev_event_cb_t event_cb, void *context)
299
{
300 301
	int ret;

302 303
	if (cldev->event_cb)
		return -EALREADY;
304

305
	cldev->events = 0;
306
	cldev->events_mask = events_mask;
307 308
	cldev->event_cb = event_cb;
	cldev->event_context = context;
309
	INIT_WORK(&cldev->event_work, mei_cl_bus_event_work);
310

311 312 313 314 315 316 317 318 319 320 321 322 323
	if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
		ret = mei_cl_read_start(cldev->cl, 0, NULL);
		if (ret && ret != -EBUSY)
			return ret;
	}

	if (cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)) {
		mutex_lock(&cldev->cl->dev->device_lock);
		ret = mei_cl_notify_request(cldev->cl, NULL, event_cb ? 1 : 0);
		mutex_unlock(&cldev->cl->dev->device_lock);
		if (ret)
			return ret;
	}
324

325 326
	return 0;
}
327
EXPORT_SYMBOL_GPL(mei_cldev_register_event_cb);
328

329
/**
330
 * mei_cldev_get_drvdata - driver data getter
331 332 333 334 335
 *
 * @cldev: mei client device
 *
 * Return: driver private data
 */
336
void *mei_cldev_get_drvdata(const struct mei_cl_device *cldev)
337 338
{
	return dev_get_drvdata(&cldev->dev);
339
}
340
EXPORT_SYMBOL_GPL(mei_cldev_get_drvdata);
341

342
/**
343
 * mei_cldev_set_drvdata - driver data setter
344 345 346 347
 *
 * @cldev: mei client device
 * @data: data to store
 */
348
void mei_cldev_set_drvdata(struct mei_cl_device *cldev, void *data)
349
{
350
	dev_set_drvdata(&cldev->dev, data);
351
}
352
EXPORT_SYMBOL_GPL(mei_cldev_set_drvdata);
353

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
/**
 * 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);

380 381 382 383 384 385 386 387 388 389 390 391 392
/**
 * 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)
{
	return cldev->cl && mei_cl_is_connected(cldev->cl);
}
EXPORT_SYMBOL_GPL(mei_cldev_enabled);

393
/**
394
 * mei_cldev_enable_device - enable me client device
395 396 397 398 399 400
 *     create connection with me client
 *
 * @cldev: me client device
 *
 * Return: 0 on success and < 0 on error
 */
401
int mei_cldev_enable(struct mei_cl_device *cldev)
402
{
403 404 405
	struct mei_device *bus = cldev->bus;
	struct mei_cl *cl;
	int ret;
406

407
	cl = cldev->cl;
408

409 410 411 412 413 414 415 416 417 418
	if (!cl) {
		mutex_lock(&bus->device_lock);
		cl = mei_cl_alloc_linked(bus, MEI_HOST_CLIENT_ID_ANY);
		mutex_unlock(&bus->device_lock);
		if (IS_ERR(cl))
			return PTR_ERR(cl);
		/* update pointers */
		cldev->cl = cl;
		cl->cldev = cldev;
	}
419

420 421
	mutex_lock(&bus->device_lock);
	if (mei_cl_is_connected(cl)) {
422 423
		ret = 0;
		goto out;
424
	}
425

426 427 428 429
	if (!mei_me_cl_is_active(cldev->me_cl)) {
		dev_err(&cldev->dev, "me client is not active\n");
		ret = -ENOTTY;
		goto out;
430 431
	}

432 433 434 435 436
	ret = mei_cl_connect(cl, cldev->me_cl, NULL);
	if (ret < 0)
		dev_err(&cldev->dev, "cannot connect\n");

out:
437 438
	mutex_unlock(&bus->device_lock);

439
	return ret;
440
}
441
EXPORT_SYMBOL_GPL(mei_cldev_enable);
442

443
/**
444
 * mei_cldev_disable - disable me client device
445 446 447 448 449 450
 *     disconnect form the me client
 *
 * @cldev: me client device
 *
 * Return: 0 on success and < 0 on error
 */
451
int mei_cldev_disable(struct mei_cl_device *cldev)
452
{
453
	struct mei_device *bus;
454 455
	struct mei_cl *cl;
	int err;
456

457
	if (!cldev || !cldev->cl)
458 459
		return -ENODEV;

460 461 462
	cl = cldev->cl;

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

464
	cldev->event_cb = NULL;
465

466
	mutex_lock(&bus->device_lock);
T
Tomas Winkler 已提交
467

468 469 470
	if (!mei_cl_is_connected(cl)) {
		dev_err(bus->dev, "Already disconnected");
		err = 0;
471 472
		goto out;
	}
T
Tomas Winkler 已提交
473

474
	err = mei_cl_disconnect(cl);
475
	if (err < 0)
476
		dev_err(bus->dev, "Could not disconnect from the ME client");
477

478
out:
479 480
	/* Flush queues and remove any pending read */
	mei_cl_flush_queues(cl, NULL);
481 482 483 484
	mei_cl_unlink(cl);

	kfree(cl);
	cldev->cl = NULL;
485

486
	mutex_unlock(&bus->device_lock);
487
	return err;
488
}
489
EXPORT_SYMBOL_GPL(mei_cldev_disable);
490

T
Tomas Winkler 已提交
491 492 493 494 495 496 497 498 499 500 501
/**
 * 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)
502
{
503 504
	const struct mei_cl_device_id *id;
	const uuid_le *uuid;
505 506
	u8 version;
	bool match;
507

508
	uuid = mei_me_cl_uuid(cldev->me_cl);
509
	version = mei_me_cl_ver(cldev->me_cl);
510

511 512 513
	id = cldrv->id_table;
	while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) {
		if (!uuid_le_cmp(*uuid, id->uuid)) {
514
			match = true;
T
Tomas Winkler 已提交
515

516 517 518 519
			if (cldev->name[0])
				if (strncmp(cldev->name, id->name,
					    sizeof(id->name)))
					match = false;
T
Tomas Winkler 已提交
520

521 522 523 524
			if (id->version != MEI_CL_VERSION_ANY)
				if (id->version != version)
					match = false;
			if (match)
T
Tomas Winkler 已提交
525
				return id;
526
		}
527

528 529
		id++;
	}
530

T
Tomas Winkler 已提交
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
	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;

551 552 553
	if (!cldev->do_match)
		return 0;

T
Tomas Winkler 已提交
554 555 556 557 558 559 560
	if (!cldrv || !cldrv->id_table)
		return 0;

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

561 562
	return 0;
}
563

564 565 566 567 568 569 570
/**
 * mei_cl_device_probe - bus probe function
 *
 * @dev: device
 *
 * Return:  0 on success; < 0 otherwise
 */
571 572
static int mei_cl_device_probe(struct device *dev)
{
573
	struct mei_cl_device *cldev;
574
	struct mei_cl_driver *cldrv;
575 576 577 578
	const struct mei_cl_device_id *id;

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

580 581
	if (!cldev)
		return 0;
582

583 584 585
	if (!cldrv || !cldrv->probe)
		return -ENODEV;

586 587 588
	id = mei_cl_device_find(cldev, cldrv);
	if (!id)
		return -ENODEV;
589

590
	__module_get(THIS_MODULE);
591

592
	return cldrv->probe(cldev, id);
593
}
594

595 596 597 598 599 600 601
/**
 * mei_cl_device_remove - remove device from the bus
 *
 * @dev: device
 *
 * Return:  0 on success; < 0 otherwise
 */
602 603 604 605
static int mei_cl_device_remove(struct device *dev)
{
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	struct mei_cl_driver *cldrv;
606
	int ret = 0;
607

608 609 610 611 612 613
	if (!cldev || !dev->driver)
		return 0;

	if (cldev->event_cb) {
		cldev->event_cb = NULL;
		cancel_work_sync(&cldev->event_work);
614 615
	}

616
	cldrv = to_mei_cl_driver(dev->driver);
617 618
	if (cldrv->remove)
		ret = cldrv->remove(cldev);
619

620 621 622
	module_put(THIS_MODULE);
	dev->driver = NULL;
	return ret;
623 624 625

}

626 627
static ssize_t name_show(struct device *dev, struct device_attribute *a,
			     char *buf)
628
{
629 630
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	size_t len;
631

632
	len = snprintf(buf, PAGE_SIZE, "%s", cldev->name);
633

634
	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
635
}
636
static DEVICE_ATTR_RO(name);
637

638 639
static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
			     char *buf)
640
{
641 642 643
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
	size_t len;
644

645
	len = snprintf(buf, PAGE_SIZE, "%pUl", uuid);
646

647
	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
648
}
649
static DEVICE_ATTR_RO(uuid);
650

651 652 653 654 655 656 657 658 659 660 661 662 663
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);
	size_t len;

	len = snprintf(buf, PAGE_SIZE, "%02X", version);

	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
}
static DEVICE_ATTR_RO(version);

664 665
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
			     char *buf)
666
{
667 668 669
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
	size_t len;
670

671
	len = snprintf(buf, PAGE_SIZE, "mei:%s:%pUl:", cldev->name, uuid);
672
	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
673
}
674
static DEVICE_ATTR_RO(modalias);
675

676
static struct attribute *mei_cldev_attrs[] = {
677 678
	&dev_attr_name.attr,
	&dev_attr_uuid.attr,
679
	&dev_attr_version.attr,
680 681 682
	&dev_attr_modalias.attr,
	NULL,
};
683
ATTRIBUTE_GROUPS(mei_cldev);
684

685 686 687 688 689 690 691 692 693
/**
 * 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)
694
{
695 696
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
697 698 699 700
	u8 version = mei_me_cl_ver(cldev->me_cl);

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

702 703
	if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
		return -ENOMEM;
704

705 706 707
	if (add_uevent_var(env, "MEI_CL_NAME=%s", cldev->name))
		return -ENOMEM;

708 709
	if (add_uevent_var(env, "MODALIAS=mei:%s:%pUl:%02X:",
			   cldev->name, uuid, version))
710
		return -ENOMEM;
711 712 713

	return 0;
}
714

715 716
static struct bus_type mei_cl_bus_type = {
	.name		= "mei",
717
	.dev_groups	= mei_cldev_groups,
718 719 720
	.match		= mei_cl_device_match,
	.probe		= mei_cl_device_probe,
	.remove		= mei_cl_device_remove,
721
	.uevent		= mei_cl_device_uevent,
722 723
};

724 725 726 727 728 729 730 731 732 733 734 735 736 737
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);
}

738
static void mei_cl_bus_dev_release(struct device *dev)
739
{
740 741 742 743 744 745
	struct mei_cl_device *cldev = to_mei_cl_device(dev);

	if (!cldev)
		return;

	mei_me_cl_put(cldev->me_cl);
746
	mei_dev_bus_put(cldev->bus);
747
	kfree(cldev);
748 749
}

750
static struct device_type mei_cl_device_type = {
751
	.release	= mei_cl_bus_dev_release,
752 753
};

754 755 756 757 758 759 760 761 762 763 764 765 766
/**
 * 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));
}

767
/**
768
 * mei_cl_bus_dev_alloc - initialize and allocate mei client device
769 770 771 772 773 774
 *
 * @bus: mei device
 * @me_cl: me client
 *
 * Return: allocated device structur or NULL on allocation failure
 */
775 776
static struct mei_cl_device *mei_cl_bus_dev_alloc(struct mei_device *bus,
						  struct mei_me_client *me_cl)
777 778 779 780 781 782 783 784 785 786 787 788 789
{
	struct mei_cl_device *cldev;

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

	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);
790
	mei_cl_bus_set_name(cldev);
791 792 793 794 795 796 797 798 799 800 801 802 803 804 805
	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
 */
806 807
static bool mei_cl_bus_dev_setup(struct mei_device *bus,
				 struct mei_cl_device *cldev)
808 809
{
	cldev->do_match = 1;
810
	mei_cl_bus_dev_fixup(cldev);
811

812
	/* the device name can change during fix up */
813
	if (cldev->do_match)
814
		mei_cl_bus_set_name(cldev);
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829

	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;

830 831 832
	dev_dbg(cldev->bus->dev, "adding %pUL:%02X\n",
		mei_me_cl_uuid(cldev->me_cl),
		mei_me_cl_ver(cldev->me_cl));
833 834 835 836 837 838 839
	ret = device_add(&cldev->dev);
	if (!ret)
		cldev->is_added = 1;

	return ret;
}

840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
/**
 * 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
855 856
 *
 * Locking: called under "dev->cl_bus_lock" lock
857 858 859
 */
static void mei_cl_bus_dev_destroy(struct mei_cl_device *cldev)
{
860 861 862

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

863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
	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;

894
	mutex_lock(&bus->cl_bus_lock);
895 896
	list_for_each_entry_safe(cldev, next, &bus->device_list, bus_list)
		mei_cl_bus_remove_device(cldev);
897
	mutex_unlock(&bus->cl_bus_lock);
898 899 900 901
}


/**
902
 * mei_cl_bus_dev_init - allocate and initializes an mei client devices
903 904 905 906
 *     based on me client
 *
 * @bus: mei device
 * @me_cl: me client
907 908
 *
 * Locking: called under "dev->cl_bus_lock" lock
909
 */
910 911
static void mei_cl_bus_dev_init(struct mei_device *bus,
				struct mei_me_client *me_cl)
912
{
913
	struct mei_cl_device *cldev;
914

915 916
	WARN_ON(!mutex_is_locked(&bus->cl_bus_lock));

917 918 919 920
	dev_dbg(bus->dev, "initializing %pUl", mei_me_cl_uuid(me_cl));

	if (me_cl->bus_added)
		return;
921

922
	cldev = mei_cl_bus_dev_alloc(bus, me_cl);
923
	if (!cldev)
924
		return;
925

926 927
	me_cl->bus_added = true;
	list_add_tail(&cldev->bus_list, &bus->device_list);
T
Tomas Winkler 已提交
928

929
}
930

931 932 933 934 935 936 937 938 939 940
/**
 * mei_cl_bus_rescan - scan me clients list and add create
 *    devices for eligible clients
 *
 * @bus: mei device
 */
void mei_cl_bus_rescan(struct mei_device *bus)
{
	struct mei_cl_device *cldev, *n;
	struct mei_me_client *me_cl;
941

942 943
	mutex_lock(&bus->cl_bus_lock);

944 945
	down_read(&bus->me_clients_rwsem);
	list_for_each_entry(me_cl, &bus->me_clients, list)
946
		mei_cl_bus_dev_init(bus, me_cl);
947
	up_read(&bus->me_clients_rwsem);
948

949
	list_for_each_entry_safe(cldev, n, &bus->device_list, bus_list) {
950

951 952 953 954
		if (!mei_me_cl_is_active(cldev->me_cl)) {
			mei_cl_bus_remove_device(cldev);
			continue;
		}
955

956 957 958
		if (cldev->is_added)
			continue;

959
		if (mei_cl_bus_dev_setup(bus, cldev))
960 961 962 963 964 965 966 967 968
			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");
969
}
970

971 972
int __mei_cldev_driver_register(struct mei_cl_driver *cldrv,
				struct module *owner)
973 974
{
	int err;
975

976 977 978
	cldrv->driver.name = cldrv->name;
	cldrv->driver.owner = owner;
	cldrv->driver.bus = &mei_cl_bus_type;
979

980 981 982
	err = driver_register(&cldrv->driver);
	if (err)
		return err;
983

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

986
	return 0;
987
}
988
EXPORT_SYMBOL_GPL(__mei_cldev_driver_register);
989

990
void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv)
991
{
992
	driver_unregister(&cldrv->driver);
993

994
	pr_debug("mei: driver [%s] unregistered\n", cldrv->driver.name);
995
}
996
EXPORT_SYMBOL_GPL(mei_cldev_driver_unregister);
997

998

999 1000 1001 1002 1003 1004 1005 1006 1007
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);
}