bus.c 13.4 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 94 95 96 97 98 99
/**
 * __mei_cl_recv - internal client receive (read)
 *
 * @cl: host client
 * @buf: buffer to send
 * @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 169 170 171 172 173 174 175 176
/**
 * mei_cl_send - me device send  (write)
 *
 * @cldev: me client device
 * @buf: buffer to send
 * @length: buffer length
 *
 * Return: written size in bytes or < 0 on error
 */
ssize_t mei_cl_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_cl_send);
186

187 188 189 190 191 192 193 194 195 196
/**
 * mei_cl_recv - client receive (read)
 *
 * @cldev: me client device
 * @buf: buffer to send
 * @length: buffer length
 *
 * Return: read size in bytes of < 0 on error
 */
ssize_t mei_cl_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_cl_recv);
206

207 208 209 210 211 212 213
/**
 * mei_bus_event_work  - dispatch rx event for a bus device
 *    and schedule new work
 *
 * @work: work
 */
static void mei_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 225
	/* Prepare for the next read */
	mei_cl_read_start(cldev->cl, 0, NULL);
226 227
}

228 229 230 231 232 233
/**
 * mei_cl_bus_rx_event  - schedule rx evenet
 *
 * @cl: host client
 */
void mei_cl_bus_rx_event(struct mei_cl *cl)
234
{
235
	struct mei_cl_device *cldev = cl->cldev;
236

237
	if (!cldev || !cldev->event_cb)
238 239
		return;

240
	set_bit(MEI_CL_EVENT_RX, &cldev->events);
241

242
	schedule_work(&cldev->event_work);
243
}
244

245 246 247 248 249 250 251 252 253 254 255 256 257
/**
 * mei_cl_register_event_cb - register event callback
 *
 * @cldev: me client devices
 * @event_cb: callback function
 * @context: driver context data
 *
 * Return: 0 on success
 *         -EALREADY if an callback is already registered
 *         <0 on other errors
 */
int mei_cl_register_event_cb(struct mei_cl_device *cldev,
			  mei_cl_event_cb_t event_cb, void *context)
258
{
259 260
	int ret;

261 262
	if (cldev->event_cb)
		return -EALREADY;
263

264 265 266 267
	cldev->events = 0;
	cldev->event_cb = event_cb;
	cldev->event_context = context;
	INIT_WORK(&cldev->event_work, mei_bus_event_work);
268

269 270 271
	ret = mei_cl_read_start(cldev->cl, 0, NULL);
	if (ret && ret != -EBUSY)
		return ret;
272

273 274 275
	return 0;
}
EXPORT_SYMBOL_GPL(mei_cl_register_event_cb);
276

277 278 279 280 281 282 283 284 285 286
/**
 * mei_cl_get_drvdata - driver data getter
 *
 * @cldev: mei client device
 *
 * Return: driver private data
 */
void *mei_cl_get_drvdata(const struct mei_cl_device *cldev)
{
	return dev_get_drvdata(&cldev->dev);
287
}
288
EXPORT_SYMBOL_GPL(mei_cl_get_drvdata);
289

290 291 292 293 294 295 296
/**
 * mei_cl_set_drvdata - driver data setter
 *
 * @cldev: mei client device
 * @data: data to store
 */
void mei_cl_set_drvdata(struct mei_cl_device *cldev, void *data)
297
{
298
	dev_set_drvdata(&cldev->dev, data);
299
}
300
EXPORT_SYMBOL_GPL(mei_cl_set_drvdata);
301

302 303 304 305 306 307 308 309 310
/**
 * mei_cl_enable_device - enable me client device
 *     create connection with me client
 *
 * @cldev: me client device
 *
 * Return: 0 on success and < 0 on error
 */
int mei_cl_enable_device(struct mei_cl_device *cldev)
311 312
{
	int err;
313 314
	struct mei_device *bus;
	struct mei_cl *cl = cldev->cl;
315

316 317
	if (cl == NULL)
		return -ENODEV;
318

319
	bus = cl->dev;
320

321
	mutex_lock(&bus->device_lock);
322

323 324 325 326 327
	if (mei_cl_is_connected(cl)) {
		mutex_unlock(&bus->device_lock);
		dev_warn(bus->dev, "Already connected");
		return -EBUSY;
	}
328

329 330 331 332
	err = mei_cl_connect(cl, cldev->me_cl, NULL);
	if (err < 0) {
		mutex_unlock(&bus->device_lock);
		dev_err(bus->dev, "Could not connect to the ME client");
333

334 335 336 337 338 339
		return err;
	}

	mutex_unlock(&bus->device_lock);

	return 0;
340
}
341
EXPORT_SYMBOL_GPL(mei_cl_enable_device);
342

343 344 345 346 347 348 349 350 351
/**
 * mei_cl_disable_device - disable me client device
 *     disconnect form the me client
 *
 * @cldev: me client device
 *
 * Return: 0 on success and < 0 on error
 */
int mei_cl_disable_device(struct mei_cl_device *cldev)
352
{
353
	int err;
354
	struct mei_device *bus;
355
	struct mei_cl *cl = cldev->cl;
356

357
	if (cl == NULL)
358 359
		return -ENODEV;

360
	bus = cl->dev;
T
Tomas Winkler 已提交
361

362
	cldev->event_cb = NULL;
363

364
	mutex_lock(&bus->device_lock);
T
Tomas Winkler 已提交
365

366 367 368
	if (!mei_cl_is_connected(cl)) {
		dev_err(bus->dev, "Already disconnected");
		err = 0;
369 370
		goto out;
	}
T
Tomas Winkler 已提交
371

372 373 374
	err = mei_cl_disconnect(cl);
	if (err < 0) {
		dev_err(bus->dev, "Could not disconnect from the ME client");
375 376
		goto out;
	}
377

378 379
	/* Flush queues and remove any pending read */
	mei_cl_flush_queues(cl, NULL);
380

381
out:
382
	mutex_unlock(&bus->device_lock);
383
	return err;
384 385

}
386
EXPORT_SYMBOL_GPL(mei_cl_disable_device);
387

388
static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
389
{
390 391 392 393 394
	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 *id;
	const uuid_le *uuid;
	const char *name;
395

396 397
	if (!cldev)
		return 0;
398

399 400
	uuid = mei_me_cl_uuid(cldev->me_cl);
	name = cldev->name;
401

402 403
	if (!cldrv || !cldrv->id_table)
		return 0;
404

405
	id = cldrv->id_table;
T
Tomas Winkler 已提交
406

407
	while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) {
408

409 410 411 412 413 414 415 416
		if (!uuid_le_cmp(*uuid, id->uuid)) {
			if (id->name[0]) {
				if (!strncmp(name, id->name, sizeof(id->name)))
					return 1;
			} else {
				return 1;
			}
		}
417

418 419
		id++;
	}
420

421 422
	return 0;
}
423

424 425 426 427 428
static int mei_cl_device_probe(struct device *dev)
{
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	struct mei_cl_driver *cldrv;
	struct mei_cl_device_id id;
429

430 431
	if (!cldev)
		return 0;
432

433 434 435 436 437 438 439 440 441 442
	cldrv = to_mei_cl_driver(dev->driver);
	if (!cldrv || !cldrv->probe)
		return -ENODEV;

	dev_dbg(dev, "Device probe\n");

	strlcpy(id.name, cldev->name, sizeof(id.name));

	return cldrv->probe(cldev, &id);
}
443

444 445 446 447
static int mei_cl_device_remove(struct device *dev)
{
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	struct mei_cl_driver *cldrv;
448

449 450 451 452 453 454
	if (!cldev || !dev->driver)
		return 0;

	if (cldev->event_cb) {
		cldev->event_cb = NULL;
		cancel_work_sync(&cldev->event_work);
455 456
	}

457 458 459
	cldrv = to_mei_cl_driver(dev->driver);
	if (!cldrv->remove) {
		dev->driver = NULL;
460

461 462
		return 0;
	}
463

464
	return cldrv->remove(cldev);
465 466
}

467 468
static ssize_t name_show(struct device *dev, struct device_attribute *a,
			     char *buf)
469
{
470 471
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	size_t len;
472

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

475
	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
476
}
477
static DEVICE_ATTR_RO(name);
478

479 480
static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
			     char *buf)
481
{
482 483 484
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
	size_t len;
485

486
	len = snprintf(buf, PAGE_SIZE, "%pUl", uuid);
487

488
	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
489
}
490
static DEVICE_ATTR_RO(uuid);
491

492 493
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
			     char *buf)
494
{
495 496 497
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
	size_t len;
498

499 500
	len = snprintf(buf, PAGE_SIZE, "mei:%s:" MEI_CL_UUID_FMT ":",
		cldev->name, MEI_CL_UUID_ARGS(uuid->b));
501

502
	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
503
}
504
static DEVICE_ATTR_RO(modalias);
505

506 507 508 509 510 511 512 513
static struct attribute *mei_cl_dev_attrs[] = {
	&dev_attr_name.attr,
	&dev_attr_uuid.attr,
	&dev_attr_modalias.attr,
	NULL,
};
ATTRIBUTE_GROUPS(mei_cl_dev);

514 515 516 517 518 519 520 521 522
/**
 * 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)
523
{
524 525
	struct mei_cl_device *cldev = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
526

527 528
	if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
		return -ENOMEM;
529

530 531 532 533 534 535
	if (add_uevent_var(env, "MEI_CL_NAME=%s", cldev->name))
		return -ENOMEM;

	if (add_uevent_var(env, "MODALIAS=mei:%s:" MEI_CL_UUID_FMT ":",
		cldev->name, MEI_CL_UUID_ARGS(uuid->b)))
		return -ENOMEM;
536 537 538

	return 0;
}
539

540 541 542 543 544 545
static struct bus_type mei_cl_bus_type = {
	.name		= "mei",
	.dev_groups	= mei_cl_dev_groups,
	.match		= mei_cl_device_match,
	.probe		= mei_cl_device_probe,
	.remove		= mei_cl_device_remove,
546
	.uevent		= mei_cl_device_uevent,
547 548 549
};

static void mei_cl_dev_release(struct device *dev)
550
{
551 552 553 554 555 556 557
	struct mei_cl_device *cldev = to_mei_cl_device(dev);

	if (!cldev)
		return;

	mei_me_cl_put(cldev->me_cl);
	kfree(cldev);
558 559
}

560 561 562 563 564 565
static struct device_type mei_cl_device_type = {
	.release	= mei_cl_dev_release,
};

struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *bus,
					 uuid_le uuid)
566
{
567 568 569 570 571 572 573 574 575
	struct mei_cl *cl;

	list_for_each_entry(cl, &bus->device_list, device_link) {
		if (cl->cldev && cl->cldev->me_cl &&
		    !uuid_le_cmp(uuid, *mei_me_cl_uuid(cl->cldev->me_cl)))
			return cl;
	}

	return NULL;
576 577
}

578 579 580 581
struct mei_cl_device *mei_cl_add_device(struct mei_device *bus,
					struct mei_me_client *me_cl,
					struct mei_cl *cl,
					char *name)
582
{
583 584
	struct mei_cl_device *cldev;
	int status;
585

586 587 588
	cldev = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
	if (!cldev)
		return NULL;
589

590 591 592 593 594
	cldev->me_cl = mei_me_cl_get(me_cl);
	if (!cldev->me_cl) {
		kfree(cldev);
		return NULL;
	}
595

596 597 598 599
	cldev->cl = cl;
	cldev->dev.parent = bus->dev;
	cldev->dev.bus = &mei_cl_bus_type;
	cldev->dev.type = &mei_cl_device_type;
600

601
	strlcpy(cldev->name, name, sizeof(cldev->name));
T
Tomas Winkler 已提交
602

603
	dev_set_name(&cldev->dev, "mei:%s:%pUl", name, mei_me_cl_uuid(me_cl));
604

605 606 607 608 609 610
	status = device_register(&cldev->dev);
	if (status) {
		dev_err(bus->dev, "Failed to register MEI device\n");
		mei_me_cl_put(cldev->me_cl);
		kfree(cldev);
		return NULL;
611 612
	}

613
	cl->cldev = cldev;
614

615
	dev_dbg(&cldev->dev, "client %s registered\n", name);
616

617
	return cldev;
618
}
619
EXPORT_SYMBOL_GPL(mei_cl_add_device);
620

621
void mei_cl_remove_device(struct mei_cl_device *cldev)
622
{
623 624 625
	device_unregister(&cldev->dev);
}
EXPORT_SYMBOL_GPL(mei_cl_remove_device);
626

627 628 629
int __mei_cl_driver_register(struct mei_cl_driver *cldrv, struct module *owner)
{
	int err;
630

631 632 633
	cldrv->driver.name = cldrv->name;
	cldrv->driver.owner = owner;
	cldrv->driver.bus = &mei_cl_bus_type;
634

635 636 637
	err = driver_register(&cldrv->driver);
	if (err)
		return err;
638

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

641
	return 0;
642
}
643
EXPORT_SYMBOL_GPL(__mei_cl_driver_register);
644

645
void mei_cl_driver_unregister(struct mei_cl_driver *cldrv)
646
{
647
	driver_unregister(&cldrv->driver);
648

649
	pr_debug("mei: driver [%s] unregistered\n", cldrv->driver.name);
650
}
651
EXPORT_SYMBOL_GPL(mei_cl_driver_unregister);
652 653 654 655 656 657 658 659 660 661

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);
}