bus.c 12.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
static inline uuid_le uuid_le_cast(const __u8 uuid[16])
{
	return *(uuid_le *)uuid;
}

38 39 40 41 42
static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
{
	struct mei_cl_device *device = to_mei_cl_device(dev);
	struct mei_cl_driver *driver = to_mei_cl_driver(drv);
	const struct mei_cl_device_id *id;
43 44
	const uuid_le *uuid;
	const char *name;
45 46 47 48

	if (!device)
		return 0;

49 50 51
	uuid = mei_me_cl_uuid(device->me_cl);
	name = device->name;

52 53 54 55 56
	if (!driver || !driver->id_table)
		return 0;

	id = driver->id_table;

57 58 59 60 61 62 63 64 65 66
	while (uuid_le_cmp(NULL_UUID_LE, uuid_le_cast(id->uuid))) {

		if (!uuid_le_cmp(*uuid, uuid_le_cast(id->uuid))) {
			if (id->name[0]) {
				if (!strncmp(name, id->name, sizeof(id->name)))
					return 1;
			} else {
				return 1;
			}
		}
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88

		id++;
	}

	return 0;
}

static int mei_cl_device_probe(struct device *dev)
{
	struct mei_cl_device *device = to_mei_cl_device(dev);
	struct mei_cl_driver *driver;
	struct mei_cl_device_id id;

	if (!device)
		return 0;

	driver = to_mei_cl_driver(dev->driver);
	if (!driver || !driver->probe)
		return -ENODEV;

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

89
	strlcpy(id.name, device->name, sizeof(id.name));
90 91 92 93 94 95 96 97 98 99 100 101

	return driver->probe(device, &id);
}

static int mei_cl_device_remove(struct device *dev)
{
	struct mei_cl_device *device = to_mei_cl_device(dev);
	struct mei_cl_driver *driver;

	if (!device || !dev->driver)
		return 0;

102 103 104 105 106
	if (device->event_cb) {
		device->event_cb = NULL;
		cancel_work_sync(&device->event_work);
	}

107 108 109 110 111 112 113 114 115 116
	driver = to_mei_cl_driver(dev->driver);
	if (!driver->remove) {
		dev->driver = NULL;

		return 0;
	}

	return driver->remove(device);
}

117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
static ssize_t name_show(struct device *dev, struct device_attribute *a,
			     char *buf)
{
	struct mei_cl_device *device = to_mei_cl_device(dev);
	size_t len;

	len = snprintf(buf, PAGE_SIZE, "%s", device->name);

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

static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
			     char *buf)
{
	struct mei_cl_device *device = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(device->me_cl);
	size_t len;

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

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

142 143 144
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
			     char *buf)
{
145 146 147
	struct mei_cl_device *device = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(device->me_cl);
	size_t len;
148

149 150
	len = snprintf(buf, PAGE_SIZE, "mei:%s:" MEI_CL_UUID_FMT ":",
		device->name, MEI_CL_UUID_ARGS(uuid->b));
151 152 153

	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
}
154
static DEVICE_ATTR_RO(modalias);
155

156
static struct attribute *mei_cl_dev_attrs[] = {
157 158
	&dev_attr_name.attr,
	&dev_attr_uuid.attr,
159 160
	&dev_attr_modalias.attr,
	NULL,
161
};
162
ATTRIBUTE_GROUPS(mei_cl_dev);
163 164 165

static int mei_cl_uevent(struct device *dev, struct kobj_uevent_env *env)
{
166 167 168
	struct mei_cl_device *device = to_mei_cl_device(dev);
	const uuid_le *uuid = mei_me_cl_uuid(device->me_cl);

169 170 171 172 173 174
	if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
		return -ENOMEM;

	if (add_uevent_var(env, "MEI_CL_NAME=%s", device->name))
		return -ENOMEM;

175 176
	if (add_uevent_var(env, "MODALIAS=mei:%s:" MEI_CL_UUID_FMT ":",
		device->name, MEI_CL_UUID_ARGS(uuid->b)))
177 178 179 180 181 182 183
		return -ENOMEM;

	return 0;
}

static struct bus_type mei_cl_bus_type = {
	.name		= "mei",
184
	.dev_groups	= mei_cl_dev_groups,
185 186 187 188 189 190 191 192
	.match		= mei_cl_device_match,
	.probe		= mei_cl_device_probe,
	.remove		= mei_cl_device_remove,
	.uevent		= mei_cl_uevent,
};

static void mei_cl_dev_release(struct device *dev)
{
193 194 195 196 197 198 199
	struct mei_cl_device *device = to_mei_cl_device(dev);

	if (!device)
		return;

	mei_me_cl_put(device->me_cl);
	kfree(device);
200 201 202 203 204 205
}

static struct device_type mei_cl_device_type = {
	.release	= mei_cl_dev_release,
};

206
struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev,
207
					 uuid_le uuid)
208
{
209
	struct mei_cl *cl;
210

211
	list_for_each_entry(cl, &dev->device_list, device_link) {
212 213
		if (cl->device && cl->device->me_cl &&
		    !uuid_le_cmp(uuid, *mei_me_cl_uuid(cl->device->me_cl)))
214 215 216 217 218
			return cl;
	}

	return NULL;
}
219

220
struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
221 222
					struct mei_me_client *me_cl,
					struct mei_cl *cl,
223
					char *name)
224 225 226 227 228 229 230 231
{
	struct mei_cl_device *device;
	int status;

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

232 233 234 235 236
	device->me_cl = mei_me_cl_get(me_cl);
	if (!device->me_cl) {
		kfree(device);
		return NULL;
	}
237

238
	device->cl = cl;
239
	device->dev.parent = dev->dev;
240 241 242
	device->dev.bus = &mei_cl_bus_type;
	device->dev.type = &mei_cl_device_type;

243 244 245
	strlcpy(device->name, name, sizeof(device->name));

	dev_set_name(&device->dev, "mei:%s:%pUl", name, mei_me_cl_uuid(me_cl));
246 247

	status = device_register(&device->dev);
248
	if (status) {
249
		dev_err(dev->dev, "Failed to register MEI device\n");
250
		mei_me_cl_put(device->me_cl);
251 252 253 254 255
		kfree(device);
		return NULL;
	}

	cl->device = device;
256 257 258 259 260 261 262 263 264 265 266 267

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

	return device;
}
EXPORT_SYMBOL_GPL(mei_cl_add_device);

void mei_cl_remove_device(struct mei_cl_device *device)
{
	device_unregister(&device->dev);
}
EXPORT_SYMBOL_GPL(mei_cl_remove_device);
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293

int __mei_cl_driver_register(struct mei_cl_driver *driver, struct module *owner)
{
	int err;

	driver->driver.name = driver->name;
	driver->driver.owner = owner;
	driver->driver.bus = &mei_cl_bus_type;

	err = driver_register(&driver->driver);
	if (err)
		return err;

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

	return 0;
}
EXPORT_SYMBOL_GPL(__mei_cl_driver_register);

void mei_cl_driver_unregister(struct mei_cl_driver *driver)
{
	driver_unregister(&driver->driver);

	pr_debug("mei: driver [%s] unregistered\n", driver->driver.name);
}
EXPORT_SYMBOL_GPL(mei_cl_driver_unregister);
294

295
ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
296
			bool blocking)
297 298
{
	struct mei_device *dev;
299
	struct mei_cl_cb *cb = NULL;
300
	ssize_t rets;
301 302 303 304

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

T
Tomas Winkler 已提交
305 306
	dev = cl->dev;

307
	mutex_lock(&dev->device_lock);
308
	if (!mei_cl_is_connected(cl)) {
309 310 311
		rets = -ENODEV;
		goto out;
	}
312

T
Tomas Winkler 已提交
313
	/* Check if we have an ME client device */
314
	if (!mei_me_cl_is_active(cl->me_cl)) {
315 316 317
		rets = -ENOTTY;
		goto out;
	}
T
Tomas Winkler 已提交
318

319
	if (length > mei_cl_mtu(cl)) {
320 321 322
		rets = -EFBIG;
		goto out;
	}
T
Tomas Winkler 已提交
323

324
	cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, NULL);
325 326 327 328
	if (!cb) {
		rets = -ENOMEM;
		goto out;
	}
329

330
	memcpy(cb->buf.data, buf, length);
331

T
Tomas Winkler 已提交
332
	rets = mei_cl_write(cl, cb, blocking);
333

334
out:
335
	mutex_unlock(&dev->device_lock);
T
Tomas Winkler 已提交
336 337
	if (rets < 0)
		mei_io_cb_free(cb);
338

T
Tomas Winkler 已提交
339
	return rets;
340 341
}

342
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
343 344 345 346
{
	struct mei_device *dev;
	struct mei_cl_cb *cb;
	size_t r_length;
347
	ssize_t rets;
348 349 350 351 352 353 354 355

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

	dev = cl->dev;

	mutex_lock(&dev->device_lock);

T
Tomas Winkler 已提交
356 357 358 359 360 361 362
	cb = mei_cl_read_cb(cl, NULL);
	if (cb)
		goto copy;

	rets = mei_cl_read_start(cl, length, NULL);
	if (rets && rets != -EBUSY)
		goto out;
363

T
Tomas Winkler 已提交
364
	if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
365

366 367 368
		mutex_unlock(&dev->device_lock);

		if (wait_event_interruptible(cl->rx_wait,
T
Tomas Winkler 已提交
369
				(!list_empty(&cl->rd_completed)) ||
370
				(!mei_cl_is_connected(cl)))) {
371

372 373 374 375 376 377 378
			if (signal_pending(current))
				return -EINTR;
			return -ERESTARTSYS;
		}

		mutex_lock(&dev->device_lock);

379
		if (!mei_cl_is_connected(cl)) {
T
Tomas Winkler 已提交
380 381 382 383
			rets = -EBUSY;
			goto out;
		}
	}
384

T
Tomas Winkler 已提交
385 386
	cb = mei_cl_read_cb(cl, NULL);
	if (!cb) {
387
		rets = 0;
388 389 390
		goto out;
	}

T
Tomas Winkler 已提交
391
copy:
392 393 394 395 396
	if (cb->status) {
		rets = cb->status;
		goto free;
	}

397
	r_length = min_t(size_t, length, cb->buf_idx);
398
	memcpy(buf, cb->buf.data, r_length);
399
	rets = r_length;
400

401
free:
402 403 404 405
	mei_io_cb_free(cb);
out:
	mutex_unlock(&dev->device_lock);

406
	return rets;
407 408
}

409
ssize_t mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length)
410
{
411
	struct mei_cl *cl = device->cl;
412

413 414
	if (cl == NULL)
		return -ENODEV;
415

416
	return __mei_cl_send(cl, buf, length, 1);
417 418 419
}
EXPORT_SYMBOL_GPL(mei_cl_send);

420
ssize_t mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length)
421
{
422
	struct mei_cl *cl = device->cl;
423

424 425
	if (cl == NULL)
		return -ENODEV;
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442

	return __mei_cl_recv(cl, buf, length);
}
EXPORT_SYMBOL_GPL(mei_cl_recv);

static void mei_bus_event_work(struct work_struct *work)
{
	struct mei_cl_device *device;

	device = container_of(work, struct mei_cl_device, event_work);

	if (device->event_cb)
		device->event_cb(device, device->events, device->event_context);

	device->events = 0;

	/* Prepare for the next read */
443
	mei_cl_read_start(device->cl, 0, NULL);
444 445 446 447 448 449 450 451 452 453 454 455 456
}

int mei_cl_register_event_cb(struct mei_cl_device *device,
			  mei_cl_event_cb_t event_cb, void *context)
{
	if (device->event_cb)
		return -EALREADY;

	device->events = 0;
	device->event_cb = event_cb;
	device->event_context = context;
	INIT_WORK(&device->event_work, mei_bus_event_work);

457
	mei_cl_read_start(device->cl, 0, NULL);
458 459 460 461

	return 0;
}
EXPORT_SYMBOL_GPL(mei_cl_register_event_cb);
462

463 464 465 466 467 468 469 470 471 472 473 474
void *mei_cl_get_drvdata(const struct mei_cl_device *device)
{
	return dev_get_drvdata(&device->dev);
}
EXPORT_SYMBOL_GPL(mei_cl_get_drvdata);

void mei_cl_set_drvdata(struct mei_cl_device *device, void *data)
{
	dev_set_drvdata(&device->dev, data);
}
EXPORT_SYMBOL_GPL(mei_cl_set_drvdata);

475 476 477 478 479 480 481 482 483 484 485 486 487
int mei_cl_enable_device(struct mei_cl_device *device)
{
	int err;
	struct mei_device *dev;
	struct mei_cl *cl = device->cl;

	if (cl == NULL)
		return -ENODEV;

	dev = cl->dev;

	mutex_lock(&dev->device_lock);

T
Tomas Winkler 已提交
488 489 490 491 492 493
	if (mei_cl_is_connected(cl)) {
		mutex_unlock(&dev->device_lock);
		dev_warn(dev->dev, "Already connected");
		return -EBUSY;
	}

494
	err = mei_cl_connect(cl, device->me_cl, NULL);
495 496
	if (err < 0) {
		mutex_unlock(&dev->device_lock);
497
		dev_err(dev->dev, "Could not connect to the ME client");
498 499 500 501 502 503

		return err;
	}

	mutex_unlock(&dev->device_lock);

T
Tomas Winkler 已提交
504
	if (device->event_cb)
505
		mei_cl_read_start(device->cl, 0, NULL);
506

507
	return 0;
508 509 510 511 512 513 514 515 516 517 518 519 520 521
}
EXPORT_SYMBOL_GPL(mei_cl_enable_device);

int mei_cl_disable_device(struct mei_cl_device *device)
{
	int err;
	struct mei_device *dev;
	struct mei_cl *cl = device->cl;

	if (cl == NULL)
		return -ENODEV;

	dev = cl->dev;

522 523
	device->event_cb = NULL;

524 525
	mutex_lock(&dev->device_lock);

526
	if (!mei_cl_is_connected(cl)) {
527
		dev_err(dev->dev, "Already disconnected");
528 529
		err = 0;
		goto out;
530 531 532 533
	}

	err = mei_cl_disconnect(cl);
	if (err < 0) {
534 535
		dev_err(dev->dev, "Could not disconnect from the ME client");
		goto out;
536 537 538
	}

	/* Flush queues and remove any pending read */
T
Tomas Winkler 已提交
539
	mei_cl_flush_queues(cl, NULL);
540

541
out:
542
	mutex_unlock(&dev->device_lock);
543
	return err;
544 545 546 547

}
EXPORT_SYMBOL_GPL(mei_cl_disable_device);

548 549 550 551 552 553 554 555 556 557 558 559
void mei_cl_bus_rx_event(struct mei_cl *cl)
{
	struct mei_cl_device *device = cl->device;

	if (!device || !device->event_cb)
		return;

	set_bit(MEI_CL_EVENT_RX, &device->events);

	schedule_work(&device->event_work);
}

560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
void mei_cl_bus_remove_devices(struct mei_device *dev)
{
	struct mei_cl *cl, *next;

	mutex_lock(&dev->device_lock);
	list_for_each_entry_safe(cl, next, &dev->device_list, device_link) {
		if (cl->device)
			mei_cl_remove_device(cl->device);

		list_del(&cl->device_link);
		mei_cl_unlink(cl);
		kfree(cl);
	}
	mutex_unlock(&dev->device_lock);
}

576 577 578 579 580 581 582 583 584
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);
}