bus.c 22.0 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
/**
 * __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
	cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, NULL);
	if (!cb) {
		rets = -ENOMEM;
		goto out;
81 82
	}

83 84
	cb->internal = !!(mode & MEI_CL_IO_TX_INTERNAL);
	cb->blocking = !!(mode & MEI_CL_IO_TX_BLOCKING);
85 86
	memcpy(cb->buf.data, buf, length);

87
	rets = mei_cl_write(cl, cb);
88 89 90 91 92

out:
	mutex_unlock(&bus->device_lock);

	return rets;
93 94
}

95 96 97 98
/**
 * __mei_cl_recv - internal client receive (read)
 *
 * @cl: host client
99
 * @buf: buffer to receive
100
 * @length: buffer length
101
 * @mode: io mode
102 103 104
 *
 * Return: read size in bytes of < 0 on error
 */
105 106
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
		      unsigned int mode)
107
{
108 109 110 111
	struct mei_device *bus;
	struct mei_cl_cb *cb;
	size_t r_length;
	ssize_t rets;
112
	bool nonblock = !!(mode & MEI_CL_IO_RX_NONBLOCK);
113

114
	if (WARN_ON(!cl || !cl->dev))
115 116
		return -ENODEV;

117
	bus = cl->dev;
118

119
	mutex_lock(&bus->device_lock);
120 121 122 123
	if (bus->dev_state != MEI_DEV_ENABLED) {
		rets = -ENODEV;
		goto out;
	}
124

125 126 127
	cb = mei_cl_read_cb(cl, NULL);
	if (cb)
		goto copy;
128

129 130 131
	rets = mei_cl_read_start(cl, length, NULL);
	if (rets && rets != -EBUSY)
		goto out;
132

133 134 135 136 137
	if (nonblock) {
		rets = -EAGAIN;
		goto out;
	}

138
	/* wait on event only if there is no other waiter */
139 140
	/* synchronized under device mutex */
	if (!waitqueue_active(&cl->rx_wait)) {
141

142
		mutex_unlock(&bus->device_lock);
143

144 145 146
		if (wait_event_interruptible(cl->rx_wait,
				(!list_empty(&cl->rd_completed)) ||
				(!mei_cl_is_connected(cl)))) {
147

148 149 150 151 152 153 154 155
			if (signal_pending(current))
				return -EINTR;
			return -ERESTARTSYS;
		}

		mutex_lock(&bus->device_lock);

		if (!mei_cl_is_connected(cl)) {
156
			rets = -ENODEV;
157 158
			goto out;
		}
159 160
	}

161 162 163 164 165
	cb = mei_cl_read_cb(cl, NULL);
	if (!cb) {
		rets = 0;
		goto out;
	}
166

167 168 169 170 171
copy:
	if (cb->status) {
		rets = cb->status;
		goto free;
	}
172

173 174 175
	r_length = min_t(size_t, length, cb->buf_idx);
	memcpy(buf, cb->buf.data, r_length);
	rets = r_length;
176

177 178 179 180 181 182
free:
	mei_io_cb_free(cb);
out:
	mutex_unlock(&bus->device_lock);

	return rets;
183 184
}

185
/**
186
 * mei_cldev_send - me device send  (write)
187 188 189 190 191 192 193
 *
 * @cldev: me client device
 * @buf: buffer to send
 * @length: buffer length
 *
 * Return: written size in bytes or < 0 on error
 */
194
ssize_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
}
200
EXPORT_SYMBOL_GPL(mei_cldev_send);
201

202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
/**
 * 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;

	return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK);
}
EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);

221
/**
222
 * mei_cldev_recv - client receive (read)
223 224
 *
 * @cldev: me client device
225
 * @buf: buffer to receive
226 227 228 229
 * @length: buffer length
 *
 * Return: read size in bytes of < 0 on error
 */
230
ssize_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
}
236
EXPORT_SYMBOL_GPL(mei_cldev_recv);
237

238
/**
239
 * mei_cl_bus_rx_work - dispatch rx event for a bus device
240 241 242
 *
 * @work: work
 */
243
static 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 251
	bus = cldev->bus;

252 253
	if (cldev->rx_cb)
		cldev->rx_cb(cldev);
254

255 256 257 258
	mutex_lock(&bus->device_lock);
	mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
	mutex_unlock(&bus->device_lock);
}
259

260 261 262 263 264 265 266 267 268 269 270 271 272
/**
 * 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);
273 274 275 276 277 278
}

/**
 * mei_cl_bus_notify_event - schedule notify cb on bus client
 *
 * @cl: host client
279 280 281
 *
 * Return: true if event was scheduled
 *         false if the client is not waiting for event
282
 */
283
bool mei_cl_bus_notify_event(struct mei_cl *cl)
284 285 286
{
	struct mei_cl_device *cldev = cl->cldev;

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 306
 *
 * Return: true if event was scheduled
 *         false if the client is not waiting for event
307
 */
308
bool 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 327 328 329
 *
 * Return: 0 on success
 *         -EALREADY if an callback is already registered
 *         <0 on other errors
 */
330
int 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 334
	int ret;

335 336 337
	if (!rx_cb)
		return -EINVAL;
	if (cldev->rx_cb)
338
		return -EALREADY;
339

340 341
	cldev->rx_cb = rx_cb;
	INIT_WORK(&cldev->rx_work, mei_cl_bus_rx_work);
342

343 344 345 346 347
	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;
348

349 350 351 352 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 380 381 382
	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;
383

384 385
	return 0;
}
386
EXPORT_SYMBOL_GPL(mei_cldev_register_notif_cb);
387

388
/**
389
 * mei_cldev_get_drvdata - driver data getter
390 391 392 393 394
 *
 * @cldev: mei client device
 *
 * Return: driver private data
 */
395
void *mei_cldev_get_drvdata(const struct mei_cl_device *cldev)
396 397
{
	return dev_get_drvdata(&cldev->dev);
398
}
399
EXPORT_SYMBOL_GPL(mei_cldev_get_drvdata);
400

401
/**
402
 * mei_cldev_set_drvdata - driver data setter
403 404 405 406
 *
 * @cldev: mei client device
 * @data: data to store
 */
407
void mei_cldev_set_drvdata(struct mei_cl_device *cldev, void *data)
408
{
409
	dev_set_drvdata(&cldev->dev, data);
410
}
411
EXPORT_SYMBOL_GPL(mei_cldev_set_drvdata);
412

413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
/**
 * 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);

439 440 441 442 443 444 445 446 447
/**
 * 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)
{
448
	return mei_cl_is_connected(cldev->cl);
449 450 451
}
EXPORT_SYMBOL_GPL(mei_cldev_enabled);

452
/**
453
 * mei_cldev_enable - enable me client device
454 455 456 457 458 459
 *     create connection with me client
 *
 * @cldev: me client device
 *
 * Return: 0 on success and < 0 on error
 */
460
int mei_cldev_enable(struct mei_cl_device *cldev)
461
{
462 463 464
	struct mei_device *bus = cldev->bus;
	struct mei_cl *cl;
	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 473
		if (ret)
			return ret;
474 475 476
		/* update pointers */
		cl->cldev = cldev;
	}
477

478 479
	mutex_lock(&bus->device_lock);
	if (mei_cl_is_connected(cl)) {
480 481
		ret = 0;
		goto out;
482
	}
483

484 485 486 487
	if (!mei_me_cl_is_active(cldev->me_cl)) {
		dev_err(&cldev->dev, "me client is not active\n");
		ret = -ENOTTY;
		goto out;
488 489
	}

490 491 492 493 494
	ret = mei_cl_connect(cl, cldev->me_cl, NULL);
	if (ret < 0)
		dev_err(&cldev->dev, "cannot connect\n");

out:
495 496
	mutex_unlock(&bus->device_lock);

497
	return ret;
498
}
499
EXPORT_SYMBOL_GPL(mei_cldev_enable);
500

501
/**
502
 * mei_cldev_disable - disable me client device
503 504 505 506 507 508
 *     disconnect form the me client
 *
 * @cldev: me client device
 *
 * Return: 0 on success and < 0 on error
 */
509
int mei_cldev_disable(struct mei_cl_device *cldev)
510
{
511
	struct mei_device *bus;
512 513
	struct mei_cl *cl;
	int err;
514

515
	if (!cldev)
516 517
		return -ENODEV;

518 519 520
	cl = cldev->cl;

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

522
	mutex_lock(&bus->device_lock);
T
Tomas Winkler 已提交
523

524
	if (!mei_cl_is_connected(cl)) {
525
		dev_dbg(bus->dev, "Already disconnected");
526
		err = 0;
527 528
		goto out;
	}
T
Tomas Winkler 已提交
529

530
	err = mei_cl_disconnect(cl);
531
	if (err < 0)
532
		dev_err(bus->dev, "Could not disconnect from the ME client");
533

534
out:
535 536
	/* Flush queues and remove any pending read */
	mei_cl_flush_queues(cl, NULL);
537 538
	mei_cl_unlink(cl);

539
	mutex_unlock(&bus->device_lock);
540
	return err;
541
}
542
EXPORT_SYMBOL_GPL(mei_cldev_disable);
543

T
Tomas Winkler 已提交
544 545 546 547 548 549 550 551 552 553 554
/**
 * 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)
555
{
556 557
	const struct mei_cl_device_id *id;
	const uuid_le *uuid;
558 559
	u8 version;
	bool match;
560

561
	uuid = mei_me_cl_uuid(cldev->me_cl);
562
	version = mei_me_cl_ver(cldev->me_cl);
563

564 565 566
	id = cldrv->id_table;
	while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) {
		if (!uuid_le_cmp(*uuid, id->uuid)) {
567
			match = true;
T
Tomas Winkler 已提交
568

569 570 571 572
			if (cldev->name[0])
				if (strncmp(cldev->name, id->name,
					    sizeof(id->name)))
					match = false;
T
Tomas Winkler 已提交
573

574 575 576 577
			if (id->version != MEI_CL_VERSION_ANY)
				if (id->version != version)
					match = false;
			if (match)
T
Tomas Winkler 已提交
578
				return id;
579
		}
580

581 582
		id++;
	}
583

T
Tomas Winkler 已提交
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
	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;

604 605 606
	if (!cldev->do_match)
		return 0;

T
Tomas Winkler 已提交
607 608 609 610 611 612 613
	if (!cldrv || !cldrv->id_table)
		return 0;

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

614 615
	return 0;
}
616

617 618 619 620 621 622 623
/**
 * mei_cl_device_probe - bus probe function
 *
 * @dev: device
 *
 * Return:  0 on success; < 0 otherwise
 */
624 625
static int mei_cl_device_probe(struct device *dev)
{
626
	struct mei_cl_device *cldev;
627
	struct mei_cl_driver *cldrv;
628
	const struct mei_cl_device_id *id;
629
	int ret;
630 631 632

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

634 635
	if (!cldev)
		return 0;
636

637 638 639
	if (!cldrv || !cldrv->probe)
		return -ENODEV;

640 641 642
	id = mei_cl_device_find(cldev, cldrv);
	if (!id)
		return -ENODEV;
643

644 645 646
	ret = cldrv->probe(cldev, id);
	if (ret)
		return ret;
647

648 649
	__module_get(THIS_MODULE);
	return 0;
650
}
651

652 653 654 655 656 657 658
/**
 * mei_cl_device_remove - remove device from the bus
 *
 * @dev: device
 *
 * Return:  0 on success; < 0 otherwise
 */
659 660 661 662
static int mei_cl_device_remove(struct device *dev)
{
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	struct mei_cl_driver *cldrv;
663
	int ret = 0;
664

665 666 667
	if (!cldev || !dev->driver)
		return 0;

668 669 670 671 672 673 674
	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;
675 676
	}

677
	cldrv = to_mei_cl_driver(dev->driver);
678 679
	if (cldrv->remove)
		ret = cldrv->remove(cldev);
680

681 682 683
	module_put(THIS_MODULE);
	dev->driver = NULL;
	return ret;
684 685 686

}

687 688
static ssize_t name_show(struct device *dev, struct device_attribute *a,
			     char *buf)
689
{
690
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
691

692
	return scnprintf(buf, PAGE_SIZE, "%s", cldev->name);
693
}
694
static DEVICE_ATTR_RO(name);
695

696 697
static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
			     char *buf)
698
{
699 700
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
701

702
	return scnprintf(buf, PAGE_SIZE, "%pUl", uuid);
703
}
704
static DEVICE_ATTR_RO(uuid);
705

706 707 708 709 710 711
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);

712
	return scnprintf(buf, PAGE_SIZE, "%02X", version);
713 714 715
}
static DEVICE_ATTR_RO(version);

716 717
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
			     char *buf)
718
{
719 720
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
721

722
	return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:", cldev->name, uuid);
723
}
724
static DEVICE_ATTR_RO(modalias);
725

726
static struct attribute *mei_cldev_attrs[] = {
727 728
	&dev_attr_name.attr,
	&dev_attr_uuid.attr,
729
	&dev_attr_version.attr,
730 731 732
	&dev_attr_modalias.attr,
	NULL,
};
733
ATTRIBUTE_GROUPS(mei_cldev);
734

735 736 737 738 739 740 741 742 743
/**
 * 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)
744
{
745 746
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
747 748 749 750
	u8 version = mei_me_cl_ver(cldev->me_cl);

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

752 753
	if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
		return -ENOMEM;
754

755 756 757
	if (add_uevent_var(env, "MEI_CL_NAME=%s", cldev->name))
		return -ENOMEM;

758 759
	if (add_uevent_var(env, "MODALIAS=mei:%s:%pUl:%02X:",
			   cldev->name, uuid, version))
760
		return -ENOMEM;
761 762 763

	return 0;
}
764

765 766
static struct bus_type mei_cl_bus_type = {
	.name		= "mei",
767
	.dev_groups	= mei_cldev_groups,
768 769 770
	.match		= mei_cl_device_match,
	.probe		= mei_cl_device_probe,
	.remove		= mei_cl_device_remove,
771
	.uevent		= mei_cl_device_uevent,
772 773
};

774 775 776 777 778 779 780 781 782 783 784 785 786 787
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);
}

788
static void mei_cl_bus_dev_release(struct device *dev)
789
{
790 791 792 793 794 795
	struct mei_cl_device *cldev = to_mei_cl_device(dev);

	if (!cldev)
		return;

	mei_me_cl_put(cldev->me_cl);
796
	mei_dev_bus_put(cldev->bus);
797
	kfree(cldev->cl);
798
	kfree(cldev);
799 800
}

801
static struct device_type mei_cl_device_type = {
802
	.release	= mei_cl_bus_dev_release,
803 804
};

805 806 807 808 809 810 811 812 813 814 815 816 817
/**
 * 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));
}

818
/**
819
 * mei_cl_bus_dev_alloc - initialize and allocate mei client device
820 821 822 823 824 825
 *
 * @bus: mei device
 * @me_cl: me client
 *
 * Return: allocated device structur or NULL on allocation failure
 */
826 827
static struct mei_cl_device *mei_cl_bus_dev_alloc(struct mei_device *bus,
						  struct mei_me_client *me_cl)
828 829
{
	struct mei_cl_device *cldev;
830
	struct mei_cl *cl;
831 832 833 834 835

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

836 837 838 839 840 841
	cl = mei_cl_allocate(bus);
	if (!cl) {
		kfree(cldev);
		return NULL;
	}

842 843 844 845 846 847
	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);
848
	cldev->cl         = cl;
849
	mei_cl_bus_set_name(cldev);
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
	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
 */
865 866
static bool mei_cl_bus_dev_setup(struct mei_device *bus,
				 struct mei_cl_device *cldev)
867 868
{
	cldev->do_match = 1;
869
	mei_cl_bus_dev_fixup(cldev);
870

871
	/* the device name can change during fix up */
872
	if (cldev->do_match)
873
		mei_cl_bus_set_name(cldev);
874 875 876 877 878 879 880 881 882 883 884 885 886 887 888

	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;

889 890 891
	dev_dbg(cldev->bus->dev, "adding %pUL:%02X\n",
		mei_me_cl_uuid(cldev->me_cl),
		mei_me_cl_ver(cldev->me_cl));
892 893 894 895 896 897 898
	ret = device_add(&cldev->dev);
	if (!ret)
		cldev->is_added = 1;

	return ret;
}

899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
/**
 * 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
914 915
 *
 * Locking: called under "dev->cl_bus_lock" lock
916 917 918
 */
static void mei_cl_bus_dev_destroy(struct mei_cl_device *cldev)
{
919 920 921

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

922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952
	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;

953
	mutex_lock(&bus->cl_bus_lock);
954 955
	list_for_each_entry_safe(cldev, next, &bus->device_list, bus_list)
		mei_cl_bus_remove_device(cldev);
956
	mutex_unlock(&bus->cl_bus_lock);
957 958 959 960
}


/**
961
 * mei_cl_bus_dev_init - allocate and initializes an mei client devices
962 963 964 965
 *     based on me client
 *
 * @bus: mei device
 * @me_cl: me client
966 967
 *
 * Locking: called under "dev->cl_bus_lock" lock
968
 */
969 970
static void mei_cl_bus_dev_init(struct mei_device *bus,
				struct mei_me_client *me_cl)
971
{
972
	struct mei_cl_device *cldev;
973

974 975
	WARN_ON(!mutex_is_locked(&bus->cl_bus_lock));

976 977 978 979
	dev_dbg(bus->dev, "initializing %pUl", mei_me_cl_uuid(me_cl));

	if (me_cl->bus_added)
		return;
980

981
	cldev = mei_cl_bus_dev_alloc(bus, me_cl);
982
	if (!cldev)
983
		return;
984

985 986
	me_cl->bus_added = true;
	list_add_tail(&cldev->bus_list, &bus->device_list);
T
Tomas Winkler 已提交
987

988
}
989

990 991 992 993 994 995 996 997 998 999
/**
 * 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;
1000

1001 1002
	mutex_lock(&bus->cl_bus_lock);

1003 1004
	down_read(&bus->me_clients_rwsem);
	list_for_each_entry(me_cl, &bus->me_clients, list)
1005
		mei_cl_bus_dev_init(bus, me_cl);
1006
	up_read(&bus->me_clients_rwsem);
1007

1008
	list_for_each_entry_safe(cldev, n, &bus->device_list, bus_list) {
1009

1010 1011 1012 1013
		if (!mei_me_cl_is_active(cldev->me_cl)) {
			mei_cl_bus_remove_device(cldev);
			continue;
		}
1014

1015 1016 1017
		if (cldev->is_added)
			continue;

1018
		if (mei_cl_bus_dev_setup(bus, cldev))
1019 1020 1021 1022 1023 1024 1025 1026 1027
			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");
1028
}
1029

1030 1031 1032 1033
void mei_cl_bus_rescan_work(struct work_struct *work)
{
	struct mei_device *bus =
		container_of(work, struct mei_device, bus_rescan_work);
1034 1035 1036 1037 1038 1039
	struct mei_me_client *me_cl;

	me_cl = mei_me_cl_by_uuid(bus, &mei_amthif_guid);
	if (me_cl)
		mei_amthif_host_init(bus, me_cl);
	mei_me_cl_put(me_cl);
1040 1041 1042 1043

	mei_cl_bus_rescan(bus);
}

1044 1045
int __mei_cldev_driver_register(struct mei_cl_driver *cldrv,
				struct module *owner)
1046 1047
{
	int err;
1048

1049 1050 1051
	cldrv->driver.name = cldrv->name;
	cldrv->driver.owner = owner;
	cldrv->driver.bus = &mei_cl_bus_type;
1052

1053 1054 1055
	err = driver_register(&cldrv->driver);
	if (err)
		return err;
1056

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

1059
	return 0;
1060
}
1061
EXPORT_SYMBOL_GPL(__mei_cldev_driver_register);
1062

1063
void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv)
1064
{
1065
	driver_unregister(&cldrv->driver);
1066

1067
	pr_debug("mei: driver [%s] unregistered\n", cldrv->driver.name);
1068
}
1069
EXPORT_SYMBOL_GPL(mei_cldev_driver_unregister);
1070

1071

1072 1073 1074 1075 1076 1077 1078 1079 1080
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);
}