mei: bus: Add bus related structures to mei_cl
[deliverable/linux.git] / drivers / misc / mei / bus.c
CommitLineData
e5354107
SO
1/*
2 * Intel Management Engine Interface (Intel MEI) Linux driver
3 * Copyright (c) 2012-2013, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <linux/module.h>
17#include <linux/device.h>
18#include <linux/kernel.h>
3e833295 19#include <linux/sched.h>
e5354107
SO
20#include <linux/init.h>
21#include <linux/errno.h>
22#include <linux/slab.h>
23#include <linux/mutex.h>
24#include <linux/interrupt.h>
25#include <linux/pci.h>
26#include <linux/mei_cl_bus.h>
27
28#include "mei_dev.h"
3e833295
SO
29#include "hw-me.h"
30#include "client.h"
e5354107
SO
31
32#define to_mei_cl_driver(d) container_of(d, struct mei_cl_driver, driver)
33#define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)
34
35static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
36{
37 struct mei_cl_device *device = to_mei_cl_device(dev);
38 struct mei_cl_driver *driver = to_mei_cl_driver(drv);
39 const struct mei_cl_device_id *id;
40
41 if (!device)
42 return 0;
43
44 if (!driver || !driver->id_table)
45 return 0;
46
47 id = driver->id_table;
48
49 while (id->name[0]) {
50 if (!strcmp(dev_name(dev), id->name))
51 return 1;
52
53 id++;
54 }
55
56 return 0;
57}
58
59static int mei_cl_device_probe(struct device *dev)
60{
61 struct mei_cl_device *device = to_mei_cl_device(dev);
62 struct mei_cl_driver *driver;
63 struct mei_cl_device_id id;
64
65 if (!device)
66 return 0;
67
68 driver = to_mei_cl_driver(dev->driver);
69 if (!driver || !driver->probe)
70 return -ENODEV;
71
72 dev_dbg(dev, "Device probe\n");
73
74 strncpy(id.name, dev_name(dev), MEI_CL_NAME_SIZE);
75
76 return driver->probe(device, &id);
77}
78
79static int mei_cl_device_remove(struct device *dev)
80{
81 struct mei_cl_device *device = to_mei_cl_device(dev);
82 struct mei_cl_driver *driver;
83
84 if (!device || !dev->driver)
85 return 0;
86
3e833295
SO
87 if (device->event_cb) {
88 device->event_cb = NULL;
89 cancel_work_sync(&device->event_work);
90 }
91
e5354107
SO
92 driver = to_mei_cl_driver(dev->driver);
93 if (!driver->remove) {
94 dev->driver = NULL;
95
96 return 0;
97 }
98
99 return driver->remove(device);
100}
101
102static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
103 char *buf)
104{
105 int len;
106
107 len = snprintf(buf, PAGE_SIZE, "mei:%s\n", dev_name(dev));
108
109 return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
110}
111
112static struct device_attribute mei_cl_dev_attrs[] = {
113 __ATTR_RO(modalias),
114 __ATTR_NULL,
115};
116
117static int mei_cl_uevent(struct device *dev, struct kobj_uevent_env *env)
118{
119 if (add_uevent_var(env, "MODALIAS=mei:%s", dev_name(dev)))
120 return -ENOMEM;
121
122 return 0;
123}
124
125static struct bus_type mei_cl_bus_type = {
126 .name = "mei",
127 .dev_attrs = mei_cl_dev_attrs,
128 .match = mei_cl_device_match,
129 .probe = mei_cl_device_probe,
130 .remove = mei_cl_device_remove,
131 .uevent = mei_cl_uevent,
132};
133
134static void mei_cl_dev_release(struct device *dev)
135{
136 kfree(to_mei_cl_device(dev));
137}
138
139static struct device_type mei_cl_device_type = {
140 .release = mei_cl_dev_release,
141};
142
a7b71bc0
SO
143static struct mei_cl *mei_bus_find_mei_cl_by_uuid(struct mei_device *dev,
144 uuid_le uuid)
145{
146 struct mei_cl *cl, *next;
147
148 list_for_each_entry_safe(cl, next, &dev->device_list, device_link) {
149 if (!uuid_le_cmp(uuid, cl->device_uuid))
150 return cl;
151 }
152
153 return NULL;
154}
155struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
e5354107
SO
156 uuid_le uuid, char *name)
157{
158 struct mei_cl_device *device;
a7b71bc0 159 struct mei_cl *cl;
e5354107
SO
160 int status;
161
a7b71bc0
SO
162 cl = mei_bus_find_mei_cl_by_uuid(dev, uuid);
163 if (cl == NULL)
164 return NULL;
165
e5354107
SO
166 device = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
167 if (!device)
168 return NULL;
169
a7b71bc0
SO
170 device->cl = cl;
171
172 device->dev.parent = &dev->pdev->dev;
e5354107
SO
173 device->dev.bus = &mei_cl_bus_type;
174 device->dev.type = &mei_cl_device_type;
175
176 dev_set_name(&device->dev, "%s", name);
177
178 status = device_register(&device->dev);
a7b71bc0
SO
179 if (status) {
180 dev_err(&dev->pdev->dev, "Failed to register MEI device\n");
181 kfree(device);
182 return NULL;
183 }
184
185 cl->device = device;
e5354107
SO
186
187 dev_dbg(&device->dev, "client %s registered\n", name);
188
189 return device;
e5354107
SO
190}
191EXPORT_SYMBOL_GPL(mei_cl_add_device);
192
193void mei_cl_remove_device(struct mei_cl_device *device)
194{
195 device_unregister(&device->dev);
196}
197EXPORT_SYMBOL_GPL(mei_cl_remove_device);
333e4ee0
SO
198
199int __mei_cl_driver_register(struct mei_cl_driver *driver, struct module *owner)
200{
201 int err;
202
203 driver->driver.name = driver->name;
204 driver->driver.owner = owner;
205 driver->driver.bus = &mei_cl_bus_type;
206
207 err = driver_register(&driver->driver);
208 if (err)
209 return err;
210
211 pr_debug("mei: driver [%s] registered\n", driver->driver.name);
212
213 return 0;
214}
215EXPORT_SYMBOL_GPL(__mei_cl_driver_register);
216
217void mei_cl_driver_unregister(struct mei_cl_driver *driver)
218{
219 driver_unregister(&driver->driver);
220
221 pr_debug("mei: driver [%s] unregistered\n", driver->driver.name);
222}
223EXPORT_SYMBOL_GPL(mei_cl_driver_unregister);
3e833295
SO
224
225int __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length)
226{
227 struct mei_device *dev;
228 struct mei_msg_hdr mei_hdr;
229 struct mei_cl_cb *cb;
230 int me_cl_id, err;
231
232 if (WARN_ON(!cl || !cl->dev))
233 return -ENODEV;
234
235 if (cl->state != MEI_FILE_CONNECTED)
236 return -ENODEV;
237
238 cb = mei_io_cb_init(cl, NULL);
239 if (!cb)
240 return -ENOMEM;
241
242 err = mei_io_cb_alloc_req_buf(cb, length);
243 if (err < 0) {
244 mei_io_cb_free(cb);
245 return err;
246 }
247
248 memcpy(cb->request_buffer.data, buf, length);
249 cb->fop_type = MEI_FOP_WRITE;
250
251 dev = cl->dev;
252
253 mutex_lock(&dev->device_lock);
254
255 /* Check if we have an ME client device */
256 me_cl_id = mei_me_cl_by_id(dev, cl->me_client_id);
257 if (me_cl_id == dev->me_clients_num) {
258 err = -ENODEV;
259 goto out_err;
260 }
261
262 if (length > dev->me_clients[me_cl_id].props.max_msg_length) {
263 err = -EINVAL;
264 goto out_err;
265 }
266
267 err = mei_cl_flow_ctrl_creds(cl);
268 if (err < 0)
269 goto out_err;
270
271 /* Host buffer is not ready, we queue the request */
272 if (err == 0 || !dev->hbuf_is_ready) {
273 cb->buf_idx = 0;
274 mei_hdr.msg_complete = 0;
275 cl->writing_state = MEI_WRITING;
276 list_add_tail(&cb->list, &dev->write_list.list);
277
278 mutex_unlock(&dev->device_lock);
279
280 return length;
281 }
282
283 dev->hbuf_is_ready = false;
284
285 /* Check for a maximum length */
286 if (length > mei_hbuf_max_len(dev)) {
287 mei_hdr.length = mei_hbuf_max_len(dev);
288 mei_hdr.msg_complete = 0;
289 } else {
290 mei_hdr.length = length;
291 mei_hdr.msg_complete = 1;
292 }
293
294 mei_hdr.host_addr = cl->host_client_id;
295 mei_hdr.me_addr = cl->me_client_id;
296 mei_hdr.reserved = 0;
297
298 if (mei_write_message(dev, &mei_hdr, buf)) {
299 err = -EIO;
300 goto out_err;
301 }
302
303 cl->writing_state = MEI_WRITING;
304 cb->buf_idx = mei_hdr.length;
305
306 if (!mei_hdr.msg_complete) {
307 list_add_tail(&cb->list, &dev->write_list.list);
308 } else {
309 if (mei_cl_flow_ctrl_reduce(cl)) {
310 err = -EIO;
311 goto out_err;
312 }
313
314 list_add_tail(&cb->list, &dev->write_waiting_list.list);
315 }
316
317 mutex_unlock(&dev->device_lock);
318
319 return mei_hdr.length;
320
321out_err:
322 mutex_unlock(&dev->device_lock);
323 mei_io_cb_free(cb);
324
325 return err;
326}
327
328int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
329{
330 struct mei_device *dev;
331 struct mei_cl_cb *cb;
332 size_t r_length;
333 int err;
334
335 if (WARN_ON(!cl || !cl->dev))
336 return -ENODEV;
337
338 dev = cl->dev;
339
340 mutex_lock(&dev->device_lock);
341
342 if (!cl->read_cb) {
343 err = mei_cl_read_start(cl);
344 if (err < 0) {
345 mutex_unlock(&dev->device_lock);
346 return err;
347 }
348 }
349
350 if (cl->reading_state != MEI_READ_COMPLETE &&
351 !waitqueue_active(&cl->rx_wait)) {
352 mutex_unlock(&dev->device_lock);
353
354 if (wait_event_interruptible(cl->rx_wait,
355 (MEI_READ_COMPLETE == cl->reading_state))) {
356 if (signal_pending(current))
357 return -EINTR;
358 return -ERESTARTSYS;
359 }
360
361 mutex_lock(&dev->device_lock);
362 }
363
364 cb = cl->read_cb;
365
366 if (cl->reading_state != MEI_READ_COMPLETE) {
367 r_length = 0;
368 goto out;
369 }
370
371 r_length = min_t(size_t, length, cb->buf_idx);
372
373 memcpy(buf, cb->response_buffer.data, r_length);
374
375 mei_io_cb_free(cb);
376 cl->reading_state = MEI_IDLE;
377 cl->read_cb = NULL;
378
379out:
380 mutex_unlock(&dev->device_lock);
381
382 return r_length;
383}
384
385int mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length)
386{
a7b71bc0 387 struct mei_cl *cl = device->cl;
3e833295 388
a7b71bc0
SO
389 if (cl == NULL)
390 return -ENODEV;
3e833295
SO
391
392 if (device->ops && device->ops->send)
393 return device->ops->send(device, buf, length);
394
395 return __mei_cl_send(cl, buf, length);
396}
397EXPORT_SYMBOL_GPL(mei_cl_send);
398
399int mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length)
400{
a7b71bc0 401 struct mei_cl *cl = device->cl;
3e833295 402
a7b71bc0
SO
403 if (cl == NULL)
404 return -ENODEV;
3e833295
SO
405
406 if (device->ops && device->ops->recv)
407 return device->ops->recv(device, buf, length);
408
409 return __mei_cl_recv(cl, buf, length);
410}
411EXPORT_SYMBOL_GPL(mei_cl_recv);
412
413static void mei_bus_event_work(struct work_struct *work)
414{
415 struct mei_cl_device *device;
416
417 device = container_of(work, struct mei_cl_device, event_work);
418
419 if (device->event_cb)
420 device->event_cb(device, device->events, device->event_context);
421
422 device->events = 0;
423
424 /* Prepare for the next read */
425 mei_cl_read_start(device->cl);
426}
427
428int mei_cl_register_event_cb(struct mei_cl_device *device,
429 mei_cl_event_cb_t event_cb, void *context)
430{
431 if (device->event_cb)
432 return -EALREADY;
433
434 device->events = 0;
435 device->event_cb = event_cb;
436 device->event_context = context;
437 INIT_WORK(&device->event_work, mei_bus_event_work);
438
439 mei_cl_read_start(device->cl);
440
441 return 0;
442}
443EXPORT_SYMBOL_GPL(mei_cl_register_event_cb);
This page took 0.098058 seconds and 5 git commands to generate.