bus.c 23.3 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 120 121
 *
 * Return: read size in bytes of < 0 on error
 */
122 123
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
		      unsigned int mode)
124
{
125 126 127 128
	struct mei_device *bus;
	struct mei_cl_cb *cb;
	size_t r_length;
	ssize_t rets;
129
	bool nonblock = !!(mode & MEI_CL_IO_RX_NONBLOCK);
130

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

134
	bus = cl->dev;
135

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

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

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

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

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

159
		mutex_unlock(&bus->device_lock);
160

161 162 163
		if (wait_event_interruptible(cl->rx_wait,
				(!list_empty(&cl->rd_completed)) ||
				(!mei_cl_is_connected(cl)))) {
164

165 166 167 168 169 170 171 172
			if (signal_pending(current))
				return -EINTR;
			return -ERESTARTSYS;
		}

		mutex_lock(&bus->device_lock);

		if (!mei_cl_is_connected(cl)) {
173
			rets = -ENODEV;
174 175
			goto out;
		}
176 177
	}

178 179 180 181 182
	cb = mei_cl_read_cb(cl, NULL);
	if (!cb) {
		rets = 0;
		goto out;
	}
183

184 185 186 187 188
copy:
	if (cb->status) {
		rets = cb->status;
		goto free;
	}
189

190 191 192
	r_length = min_t(size_t, length, cb->buf_idx);
	memcpy(buf, cb->buf.data, r_length);
	rets = r_length;
193

194 195 196 197 198 199
free:
	mei_io_cb_free(cb);
out:
	mutex_unlock(&bus->device_lock);

	return rets;
200 201
}

202
/**
203
 * mei_cldev_send - me device send  (write)
204 205 206 207 208 209 210
 *
 * @cldev: me client device
 * @buf: buffer to send
 * @length: buffer length
 *
 * Return: written size in bytes or < 0 on error
 */
211
ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
212
{
213
	struct mei_cl *cl = cldev->cl;
214

215
	return __mei_cl_send(cl, buf, length, MEI_CL_IO_TX_BLOCKING);
216
}
217
EXPORT_SYMBOL_GPL(mei_cldev_send);
218

219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
/**
 * 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);

238
/**
239
 * mei_cldev_recv - client receive (read)
240 241
 *
 * @cldev: me client device
242
 * @buf: buffer to receive
243 244 245 246
 * @length: buffer length
 *
 * Return: read size in bytes of < 0 on error
 */
247
ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
248
{
249
	struct mei_cl *cl = cldev->cl;
250

251
	return __mei_cl_recv(cl, buf, length, 0);
252
}
253
EXPORT_SYMBOL_GPL(mei_cldev_recv);
254

255
/**
256
 * mei_cl_bus_rx_work - dispatch rx event for a bus device
257 258 259
 *
 * @work: work
 */
260
static void mei_cl_bus_rx_work(struct work_struct *work)
261
{
262
	struct mei_cl_device *cldev;
263
	struct mei_device *bus;
264

265
	cldev = container_of(work, struct mei_cl_device, rx_work);
266

267 268
	bus = cldev->bus;

269 270
	if (cldev->rx_cb)
		cldev->rx_cb(cldev);
271

272 273 274 275
	mutex_lock(&bus->device_lock);
	mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
	mutex_unlock(&bus->device_lock);
}
276

277 278 279 280 281 282 283 284 285 286 287 288 289
/**
 * 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);
290 291 292 293 294 295
}

/**
 * mei_cl_bus_notify_event - schedule notify cb on bus client
 *
 * @cl: host client
296 297 298
 *
 * Return: true if event was scheduled
 *         false if the client is not waiting for event
299
 */
300
bool mei_cl_bus_notify_event(struct mei_cl *cl)
301 302 303
{
	struct mei_cl_device *cldev = cl->cldev;

304
	if (!cldev || !cldev->notif_cb)
305
		return false;
306 307

	if (!cl->notify_ev)
308
		return false;
309

310
	schedule_work(&cldev->notif_work);
311 312

	cl->notify_ev = false;
313 314

	return true;
315 316
}

317
/**
318
 * mei_cl_bus_rx_event - schedule rx event
319 320
 *
 * @cl: host client
321 322 323
 *
 * Return: true if event was scheduled
 *         false if the client is not waiting for event
324
 */
325
bool mei_cl_bus_rx_event(struct mei_cl *cl)
326
{
327
	struct mei_cl_device *cldev = cl->cldev;
328

329
	if (!cldev || !cldev->rx_cb)
330
		return false;
331

332
	schedule_work(&cldev->rx_work);
333 334

	return true;
335
}
336

337
/**
338
 * mei_cldev_register_rx_cb - register Rx event callback
339 340
 *
 * @cldev: me client devices
341
 * @rx_cb: callback function
342 343 344 345 346
 *
 * Return: 0 on success
 *         -EALREADY if an callback is already registered
 *         <0 on other errors
 */
347
int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb)
348
{
349
	struct mei_device *bus = cldev->bus;
350 351
	int ret;

352 353 354
	if (!rx_cb)
		return -EINVAL;
	if (cldev->rx_cb)
355
		return -EALREADY;
356

357 358
	cldev->rx_cb = rx_cb;
	INIT_WORK(&cldev->rx_work, mei_cl_bus_rx_work);
359

360 361 362 363 364
	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;
365

366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
	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;
400

401 402
	return 0;
}
403
EXPORT_SYMBOL_GPL(mei_cldev_register_notif_cb);
404

405
/**
406
 * mei_cldev_get_drvdata - driver data getter
407 408 409 410 411
 *
 * @cldev: mei client device
 *
 * Return: driver private data
 */
412
void *mei_cldev_get_drvdata(const struct mei_cl_device *cldev)
413 414
{
	return dev_get_drvdata(&cldev->dev);
415
}
416
EXPORT_SYMBOL_GPL(mei_cldev_get_drvdata);
417

418
/**
419
 * mei_cldev_set_drvdata - driver data setter
420 421 422 423
 *
 * @cldev: mei client device
 * @data: data to store
 */
424
void mei_cldev_set_drvdata(struct mei_cl_device *cldev, void *data)
425
{
426
	dev_set_drvdata(&cldev->dev, data);
427
}
428
EXPORT_SYMBOL_GPL(mei_cldev_set_drvdata);
429

430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
/**
 * 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);

456 457 458 459 460 461 462 463 464
/**
 * 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)
{
465
	return mei_cl_is_connected(cldev->cl);
466 467 468
}
EXPORT_SYMBOL_GPL(mei_cldev_enabled);

469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
/**
 * 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);
}

492
/**
493
 * mei_cldev_enable - enable me client device
494 495 496 497 498 499
 *     create connection with me client
 *
 * @cldev: me client device
 *
 * Return: 0 on success and < 0 on error
 */
500
int mei_cldev_enable(struct mei_cl_device *cldev)
501
{
502 503 504
	struct mei_device *bus = cldev->bus;
	struct mei_cl *cl;
	int ret;
505

506
	cl = cldev->cl;
507

508
	if (cl->state == MEI_FILE_UNINITIALIZED) {
509
		mutex_lock(&bus->device_lock);
510
		ret = mei_cl_link(cl);
511
		mutex_unlock(&bus->device_lock);
512 513
		if (ret)
			return ret;
514 515 516
		/* update pointers */
		cl->cldev = cldev;
	}
517

518 519
	mutex_lock(&bus->device_lock);
	if (mei_cl_is_connected(cl)) {
520 521
		ret = 0;
		goto out;
522
	}
523

524 525 526 527
	if (!mei_me_cl_is_active(cldev->me_cl)) {
		dev_err(&cldev->dev, "me client is not active\n");
		ret = -ENOTTY;
		goto out;
528 529
	}

530 531 532 533 534 535
	if (!mei_cl_bus_module_get(cldev)) {
		dev_err(&cldev->dev, "get hw module failed");
		ret = -ENODEV;
		goto out;
	}

536
	ret = mei_cl_connect(cl, cldev->me_cl, NULL);
537
	if (ret < 0) {
538
		dev_err(&cldev->dev, "cannot connect\n");
539 540
		mei_cl_bus_module_put(cldev);
	}
541 542

out:
543 544
	mutex_unlock(&bus->device_lock);

545
	return ret;
546
}
547
EXPORT_SYMBOL_GPL(mei_cldev_enable);
548

549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
/**
 * 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;
	}
}

568
/**
569
 * mei_cldev_disable - disable me client device
570 571 572 573 574 575
 *     disconnect form the me client
 *
 * @cldev: me client device
 *
 * Return: 0 on success and < 0 on error
 */
576
int mei_cldev_disable(struct mei_cl_device *cldev)
577
{
578
	struct mei_device *bus;
579 580
	struct mei_cl *cl;
	int err;
581

582
	if (!cldev)
583 584
		return -ENODEV;

585 586 587
	cl = cldev->cl;

	bus = cldev->bus;
Tomas Winkler's avatar
Tomas Winkler committed
588

589 590
	mei_cldev_unregister_callbacks(cldev);

591
	mutex_lock(&bus->device_lock);
Tomas Winkler's avatar
Tomas Winkler committed
592

593
	if (!mei_cl_is_connected(cl)) {
594 595 596 597 598
		dev_dbg(bus->dev, "Already disconnected\n");
		err = 0;
		goto out;
	}

599
	err = mei_cl_disconnect(cl);
600
	if (err < 0)
601
		dev_err(bus->dev, "Could not disconnect from the ME client\n");
602

603
out:
604 605
	mei_cl_bus_module_put(cldev);

606 607
	/* Flush queues and remove any pending read */
	mei_cl_flush_queues(cl, NULL);
608 609
	mei_cl_unlink(cl);

610
	mutex_unlock(&bus->device_lock);
611
	return err;
612
}
613
EXPORT_SYMBOL_GPL(mei_cldev_disable);
614

615 616 617 618 619 620 621 622 623 624 625
/**
 * 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)
626
{
627 628
	const struct mei_cl_device_id *id;
	const uuid_le *uuid;
629 630
	u8 version;
	bool match;
631

632
	uuid = mei_me_cl_uuid(cldev->me_cl);
633
	version = mei_me_cl_ver(cldev->me_cl);
634

635 636 637
	id = cldrv->id_table;
	while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) {
		if (!uuid_le_cmp(*uuid, id->uuid)) {
638
			match = true;
639

640 641 642 643
			if (cldev->name[0])
				if (strncmp(cldev->name, id->name,
					    sizeof(id->name)))
					match = false;
644

645 646 647 648
			if (id->version != MEI_CL_VERSION_ANY)
				if (id->version != version)
					match = false;
			if (match)
649
				return id;
650
		}
651

652 653
		id++;
	}
654

655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
	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;

675 676 677
	if (!cldev->do_match)
		return 0;

678 679 680 681 682 683 684
	if (!cldrv || !cldrv->id_table)
		return 0;

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

685 686
	return 0;
}
687

688 689 690 691 692 693 694
/**
 * mei_cl_device_probe - bus probe function
 *
 * @dev: device
 *
 * Return:  0 on success; < 0 otherwise
 */
695 696
static int mei_cl_device_probe(struct device *dev)
{
697
	struct mei_cl_device *cldev;
698
	struct mei_cl_driver *cldrv;
699
	const struct mei_cl_device_id *id;
700
	int ret;
701 702 703

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

705 706
	if (!cldev)
		return 0;
707

708 709 710
	if (!cldrv || !cldrv->probe)
		return -ENODEV;

711 712 713
	id = mei_cl_device_find(cldev, cldrv);
	if (!id)
		return -ENODEV;
714

715 716 717
	ret = cldrv->probe(cldev, id);
	if (ret)
		return ret;
718

719 720
	__module_get(THIS_MODULE);
	return 0;
721
}
722

723 724 725 726 727 728 729
/**
 * mei_cl_device_remove - remove device from the bus
 *
 * @dev: device
 *
 * Return:  0 on success; < 0 otherwise
 */
730 731 732 733
static int mei_cl_device_remove(struct device *dev)
{
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	struct mei_cl_driver *cldrv;
734
	int ret = 0;
735

736 737 738
	if (!cldev || !dev->driver)
		return 0;

739 740 741 742
	cldrv = to_mei_cl_driver(dev->driver);
	if (cldrv->remove)
		ret = cldrv->remove(cldev);

743
	mei_cldev_unregister_callbacks(cldev);
744

745 746 747
	module_put(THIS_MODULE);
	dev->driver = NULL;
	return ret;
748 749 750

}

751 752
static ssize_t name_show(struct device *dev, struct device_attribute *a,
			     char *buf)
753
{
754
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
755

756
	return scnprintf(buf, PAGE_SIZE, "%s", cldev->name);
757
}
758
static DEVICE_ATTR_RO(name);
759

760 761
static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
			     char *buf)
762
{
763 764
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
765

766
	return scnprintf(buf, PAGE_SIZE, "%pUl", uuid);
767
}
768
static DEVICE_ATTR_RO(uuid);
769

770 771 772 773 774 775
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);

776
	return scnprintf(buf, PAGE_SIZE, "%02X", version);
777 778 779
}
static DEVICE_ATTR_RO(version);

780 781
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
			     char *buf)
782
{
783 784
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
785
	u8 version = mei_me_cl_ver(cldev->me_cl);
786

787 788
	return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:%02X:",
			 cldev->name, uuid, version);
789
}
790
static DEVICE_ATTR_RO(modalias);
791

792
static struct attribute *mei_cldev_attrs[] = {
793 794
	&dev_attr_name.attr,
	&dev_attr_uuid.attr,
795
	&dev_attr_version.attr,
796 797 798
	&dev_attr_modalias.attr,
	NULL,
};
799
ATTRIBUTE_GROUPS(mei_cldev);
800

801 802 803 804 805 806 807 808 809
/**
 * 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)
810
{
811 812
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
813 814 815 816
	u8 version = mei_me_cl_ver(cldev->me_cl);

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

818 819
	if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
		return -ENOMEM;
820

821 822 823
	if (add_uevent_var(env, "MEI_CL_NAME=%s", cldev->name))
		return -ENOMEM;

824 825
	if (add_uevent_var(env, "MODALIAS=mei:%s:%pUl:%02X:",
			   cldev->name, uuid, version))
826
		return -ENOMEM;
827 828 829

	return 0;
}
830

831 832
static struct bus_type mei_cl_bus_type = {
	.name		= "mei",
833
	.dev_groups	= mei_cldev_groups,
834 835 836
	.match		= mei_cl_device_match,
	.probe		= mei_cl_device_probe,
	.remove		= mei_cl_device_remove,
837
	.uevent		= mei_cl_device_uevent,
838 839
};

840 841 842 843 844 845 846 847 848 849 850 851 852 853
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);
}

854
static void mei_cl_bus_dev_release(struct device *dev)
855
{
856 857 858 859 860 861
	struct mei_cl_device *cldev = to_mei_cl_device(dev);

	if (!cldev)
		return;

	mei_me_cl_put(cldev->me_cl);
862
	mei_dev_bus_put(cldev->bus);
863
	kfree(cldev->cl);
864
	kfree(cldev);
865 866
}

Bhumika Goyal's avatar
Bhumika Goyal committed
867
static const struct device_type mei_cl_device_type = {
868
	.release	= mei_cl_bus_dev_release,
869 870
};

871 872 873 874 875 876 877 878 879 880 881 882 883
/**
 * 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));
}

884
/**
885
 * mei_cl_bus_dev_alloc - initialize and allocate mei client device
886 887 888 889 890 891
 *
 * @bus: mei device
 * @me_cl: me client
 *
 * Return: allocated device structur or NULL on allocation failure
 */
892 893
static struct mei_cl_device *mei_cl_bus_dev_alloc(struct mei_device *bus,
						  struct mei_me_client *me_cl)
894 895
{
	struct mei_cl_device *cldev;
896
	struct mei_cl *cl;
897 898 899 900 901

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

902 903 904 905 906 907
	cl = mei_cl_allocate(bus);
	if (!cl) {
		kfree(cldev);
		return NULL;
	}

908 909 910 911 912 913
	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);
914
	cldev->cl         = cl;
915
	mei_cl_bus_set_name(cldev);
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
	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
 */
931 932
static bool mei_cl_bus_dev_setup(struct mei_device *bus,
				 struct mei_cl_device *cldev)
933 934
{
	cldev->do_match = 1;
935
	mei_cl_bus_dev_fixup(cldev);
936

937
	/* the device name can change during fix up */
938
	if (cldev->do_match)
939
		mei_cl_bus_set_name(cldev);
940 941 942 943 944 945 946 947 948 949 950 951 952 953 954

	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;

955 956 957
	dev_dbg(cldev->bus->dev, "adding %pUL:%02X\n",
		mei_me_cl_uuid(cldev->me_cl),
		mei_me_cl_ver(cldev->me_cl));
958 959 960 961 962 963 964
	ret = device_add(&cldev->dev);
	if (!ret)
		cldev->is_added = 1;

	return ret;
}

965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
/**
 * 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
980 981
 *
 * Locking: called under "dev->cl_bus_lock" lock
982 983 984
 */
static void mei_cl_bus_dev_destroy(struct mei_cl_device *cldev)
{
985 986 987

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

988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
	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;

1019
	mutex_lock(&bus->cl_bus_lock);
1020 1021
	list_for_each_entry_safe(cldev, next, &bus->device_list, bus_list)
		mei_cl_bus_remove_device(cldev);
1022
	mutex_unlock(&bus->cl_bus_lock);
1023 1024 1025 1026
}


/**
1027
 * mei_cl_bus_dev_init - allocate and initializes an mei client devices
1028 1029 1030 1031
 *     based on me client
 *
 * @bus: mei device
 * @me_cl: me client
1032 1033
 *
 * Locking: called under "dev->cl_bus_lock" lock
1034
 */
1035 1036
static void mei_cl_bus_dev_init(struct mei_device *bus,
				struct mei_me_client *me_cl)
1037
{
1038
	struct mei_cl_device *cldev;
1039

1040 1041
	WARN_ON(!mutex_is_locked(&bus->cl_bus_lock));

1042 1043 1044 1045
	dev_dbg(bus->dev, "initializing %pUl", mei_me_cl_uuid(me_cl));

	if (me_cl->bus_added)
		return;
1046

1047
	cldev = mei_cl_bus_dev_alloc(bus, me_cl);
1048
	if (!cldev)
1049
		return;
1050

1051 1052
	me_cl->bus_added = true;
	list_add_tail(&cldev->bus_list, &bus->device_list);
Tomas Winkler's avatar
Tomas Winkler committed
1053

1054
}
1055

1056 1057 1058 1059 1060 1061
/**
 * mei_cl_bus_rescan - scan me clients list and add create
 *    devices for eligible clients
 *
 * @bus: mei device
 */
1062
static void mei_cl_bus_rescan(struct mei_device *bus)
1063 1064 1065
{
	struct mei_cl_device *cldev, *n;
	struct mei_me_client *me_cl;
1066

1067 1068
	mutex_lock(&bus->cl_bus_lock);

1069 1070
	down_read(&bus->me_clients_rwsem);
	list_for_each_entry(me_cl, &bus->me_clients, list)
1071
		mei_cl_bus_dev_init(bus, me_cl);
1072
	up_read(&bus->me_clients_rwsem);
1073

1074
	list_for_each_entry_safe(cldev, n, &bus->device_list, bus_list) {
1075

1076 1077 1078 1079
		if (!mei_me_cl_is_active(cldev->me_cl)) {
			mei_cl_bus_remove_device(cldev);
			continue;
		}
1080

1081 1082 1083
		if (cldev->is_added)
			continue;

1084
		if (mei_cl_bus_dev_setup(bus, cldev))
1085 1086 1087 1088 1089 1090 1091 1092 1093
			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");
1094
}
1095

1096 1097 1098 1099 1100 1101 1102 1103
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);
}

1104 1105
int __mei_cldev_driver_register(struct mei_cl_driver *cldrv,
				struct module *owner)
1106 1107
{
	int err;
1108

1109 1110 1111
	cldrv->driver.name = cldrv->name;
	cldrv->driver.owner = owner;
	cldrv->driver.bus = &mei_cl_bus_type;
1112

1113 1114 1115
	err = driver_register(&cldrv->driver);
	if (err)
		return err;
1116

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

1119
	return 0;
1120
}
1121
EXPORT_SYMBOL_GPL(__mei_cldev_driver_register);
1122

1123
void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv)
1124
{
1125
	driver_unregister(&cldrv->driver);
1126

1127
	pr_debug("mei: driver [%s] unregistered\n", cldrv->driver.name);
1128
}
1129
EXPORT_SYMBOL_GPL(mei_cldev_driver_unregister);
1130

1131

1132 1133 1134 1135 1136 1137 1138 1139 1140
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);
}