bus.c 11.2 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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

#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)

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;

	if (!device)
		return 0;

	if (!driver || !driver->id_table)
		return 0;

	id = driver->id_table;

	while (id->name[0]) {
48
		if (!strncmp(dev_name(dev), id->name, sizeof(id->name)))
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
			return 1;

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

72
	strlcpy(id.name, dev_name(dev), sizeof(id.name));
73 74 75 76 77 78 79 80 81 82 83 84

	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;

85 86 87 88 89
	if (device->event_cb) {
		device->event_cb = NULL;
		cancel_work_sync(&device->event_work);
	}

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
	driver = to_mei_cl_driver(dev->driver);
	if (!driver->remove) {
		dev->driver = NULL;

		return 0;
	}

	return driver->remove(device);
}

static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
			     char *buf)
{
	int len;

	len = snprintf(buf, PAGE_SIZE, "mei:%s\n", dev_name(dev));

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

111 112 113
static struct attribute *mei_cl_dev_attrs[] = {
	&dev_attr_modalias.attr,
	NULL,
114
};
115
ATTRIBUTE_GROUPS(mei_cl_dev);
116 117 118 119 120 121 122 123 124 125 126

static int mei_cl_uevent(struct device *dev, struct kobj_uevent_env *env)
{
	if (add_uevent_var(env, "MODALIAS=mei:%s", dev_name(dev)))
		return -ENOMEM;

	return 0;
}

static struct bus_type mei_cl_bus_type = {
	.name		= "mei",
127
	.dev_groups	= mei_cl_dev_groups,
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
	.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)
{
	kfree(to_mei_cl_device(dev));
}

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

143
struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev,
144 145
						uuid_le uuid)
{
146
	struct mei_cl *cl;
147

148
	list_for_each_entry(cl, &dev->device_list, device_link) {
149
		if (!uuid_le_cmp(uuid, cl->cl_uuid))
150 151 152 153 154 155
			return cl;
	}

	return NULL;
}
struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
156 157
					uuid_le uuid, char *name,
					struct mei_cl_ops *ops)
158 159
{
	struct mei_cl_device *device;
160
	struct mei_cl *cl;
161 162
	int status;

163
	cl = mei_cl_bus_find_cl_by_uuid(dev, uuid);
164 165 166
	if (cl == NULL)
		return NULL;

167 168 169 170
	device = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
	if (!device)
		return NULL;

171
	device->cl = cl;
172
	device->ops = ops;
173

174
	device->dev.parent = dev->dev;
175 176 177 178 179 180
	device->dev.bus = &mei_cl_bus_type;
	device->dev.type = &mei_cl_device_type;

	dev_set_name(&device->dev, "%s", name);

	status = device_register(&device->dev);
181
	if (status) {
182
		dev_err(dev->dev, "Failed to register MEI device\n");
183 184 185 186 187
		kfree(device);
		return NULL;
	}

	cl->device = device;
188 189 190 191 192 193 194 195 196 197 198 199

	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);
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225

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

227
static ssize_t ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
228
			bool blocking)
229 230
{
	struct mei_device *dev;
231 232
	struct mei_me_client *me_cl = NULL;
	struct mei_cl_cb *cb = NULL;
233
	ssize_t rets;
234 235 236 237

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

T
Tomas Winkler 已提交
238 239
	dev = cl->dev;

240 241 242 243 244
	mutex_lock(&dev->device_lock);
	if (cl->state != MEI_FILE_CONNECTED) {
		rets = -ENODEV;
		goto out;
	}
245

T
Tomas Winkler 已提交
246
	/* Check if we have an ME client device */
247
	me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
248 249 250 251
	if (!me_cl) {
		rets = -ENOTTY;
		goto out;
	}
T
Tomas Winkler 已提交
252

253 254 255 256
	if (length > me_cl->props.max_msg_length) {
		rets = -EFBIG;
		goto out;
	}
T
Tomas Winkler 已提交
257

258
	cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, NULL);
259 260 261 262
	if (!cb) {
		rets = -ENOMEM;
		goto out;
	}
263

264
	memcpy(cb->buf.data, buf, length);
265

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

268 269
out:
	mei_me_cl_put(me_cl);
270
	mutex_unlock(&dev->device_lock);
T
Tomas Winkler 已提交
271 272
	if (rets < 0)
		mei_io_cb_free(cb);
273

T
Tomas Winkler 已提交
274
	return rets;
275 276
}

277
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
278 279 280 281
{
	struct mei_device *dev;
	struct mei_cl_cb *cb;
	size_t r_length;
282
	ssize_t rets;
283 284 285 286 287 288 289 290 291

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

	dev = cl->dev;

	mutex_lock(&dev->device_lock);

	if (!cl->read_cb) {
292
		rets = mei_cl_read_start(cl, length, NULL);
293 294
		if (rets < 0)
			goto out;
295 296 297 298
	}

	if (cl->reading_state != MEI_READ_COMPLETE &&
	    !waitqueue_active(&cl->rx_wait)) {
299

300 301 302
		mutex_unlock(&dev->device_lock);

		if (wait_event_interruptible(cl->rx_wait,
303 304 305
				cl->reading_state == MEI_READ_COMPLETE  ||
				mei_cl_is_transitioning(cl))) {

306 307 308 309 310 311 312 313 314 315 316
			if (signal_pending(current))
				return -EINTR;
			return -ERESTARTSYS;
		}

		mutex_lock(&dev->device_lock);
	}

	cb = cl->read_cb;

	if (cl->reading_state != MEI_READ_COMPLETE) {
317
		rets = 0;
318 319 320
		goto out;
	}

321 322 323 324 325
	if (cb->status) {
		rets = cb->status;
		goto free;
	}

326
	r_length = min_t(size_t, length, cb->buf_idx);
327
	memcpy(buf, cb->buf.data, r_length);
328
	rets = r_length;
329

330
free:
331 332 333 334 335 336 337
	mei_io_cb_free(cb);
	cl->reading_state = MEI_IDLE;
	cl->read_cb = NULL;

out:
	mutex_unlock(&dev->device_lock);

338
	return rets;
339 340
}

341
inline ssize_t __mei_cl_async_send(struct mei_cl *cl, u8 *buf, size_t length)
342 343 344 345
{
	return ___mei_cl_send(cl, buf, length, 0);
}

346
inline ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length)
347 348 349 350
{
	return ___mei_cl_send(cl, buf, length, 1);
}

351
ssize_t mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length)
352
{
353
	struct mei_cl *cl = device->cl;
354

355 356
	if (cl == NULL)
		return -ENODEV;
357 358 359 360 361 362 363 364

	if (device->ops && device->ops->send)
		return device->ops->send(device, buf, length);

	return __mei_cl_send(cl, buf, length);
}
EXPORT_SYMBOL_GPL(mei_cl_send);

365
ssize_t mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length)
366
{
367
	struct mei_cl *cl =  device->cl;
368

369 370
	if (cl == NULL)
		return -ENODEV;
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390

	if (device->ops && device->ops->recv)
		return device->ops->recv(device, buf, length);

	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 */
391
	mei_cl_read_start(device->cl, 0, NULL);
392 393 394 395 396 397 398 399 400 401 402 403 404
}

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

405
	mei_cl_read_start(device->cl, 0, NULL);
406 407 408 409

	return 0;
}
EXPORT_SYMBOL_GPL(mei_cl_register_event_cb);
410

411 412 413 414 415 416 417 418 419 420 421 422
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);

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
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);

	err = mei_cl_connect(cl, NULL);
	if (err < 0) {
		mutex_unlock(&dev->device_lock);
439
		dev_err(dev->dev, "Could not connect to the ME client");
440 441 442 443 444 445 446

		return err;
	}

	mutex_unlock(&dev->device_lock);

	if (device->event_cb && !cl->read_cb)
447
		mei_cl_read_start(device->cl, 0, NULL);
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470

	if (!device->ops || !device->ops->enable)
		return 0;

	return device->ops->enable(device);
}
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;

	mutex_lock(&dev->device_lock);

	if (cl->state != MEI_FILE_CONNECTED) {
		mutex_unlock(&dev->device_lock);
471
		dev_err(dev->dev, "Already disconnected");
472 473 474 475 476 477 478 479 480

		return 0;
	}

	cl->state = MEI_FILE_DISCONNECTING;

	err = mei_cl_disconnect(cl);
	if (err < 0) {
		mutex_unlock(&dev->device_lock);
481
		dev_err(dev->dev,
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
			"Could not disconnect from the ME client");

		return err;
	}

	/* Flush queues and remove any pending read */
	mei_cl_flush_queues(cl);

	if (cl->read_cb) {
		struct mei_cl_cb *cb = NULL;

		cb = mei_cl_find_read_cb(cl);
		/* Remove entry from read list */
		if (cb)
			list_del(&cb->list);

		cb = cl->read_cb;
		cl->read_cb = NULL;

		if (cb) {
			mei_io_cb_free(cb);
			cb = NULL;
		}
	}

507 508
	device->event_cb = NULL;

509 510 511 512 513 514 515 516 517
	mutex_unlock(&dev->device_lock);

	if (!device->ops || !device->ops->disable)
		return 0;

	return device->ops->disable(device);
}
EXPORT_SYMBOL_GPL(mei_cl_disable_device);

518 519 520 521 522 523 524 525 526 527 528 529
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);
}

530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
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);
}

546 547 548 549 550 551 552 553 554
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);
}