Commit e46980a10a76ec3282dd6832c1974b880acd23d3

Authored by Samuel Ortiz
Committed by Greg Kroah-Hartman
1 parent d6c36a475f

mei: bus: Add device enabling and disabling API

It should be left to the drivers to enable and disable the device on the
MEI bus when e.g getting probed.
For drivers to be able to safely call the enable and disable hooks, the
mei_cl_ops must be set before it's probed and thus this should happen
before registering the device on the MEI bus. Hence the mei_cl_add_device()
prototype change.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 4 changed files with 123 additions and 14 deletions Side-by-side Diff

Documentation/misc-devices/mei/mei-client-bus.txt
... ... @@ -104,13 +104,16 @@
104 104 struct contact_driver *contact;
105 105  
106 106 [...]
  107 + mei_cl_enable_device(dev);
  108 +
107 109 mei_cl_register_event_cb(dev, contact_event_cb, contact);
108 110  
109 111 return 0;
110 112 }
111 113  
112   -In the probe routine the driver basically registers an ME bus event handler
113   -which is as close as it can get to registering a threaded IRQ handler.
  114 +In the probe routine the driver first enable the MEI device and then registers
  115 +an ME bus event handler which is as close as it can get to registering a
  116 +threaded IRQ handler.
114 117 The handler implementation will typically call some I/O routine depending on
115 118 the pending events:
116 119  
drivers/misc/mei/bus.c
... ... @@ -153,7 +153,8 @@
153 153 return NULL;
154 154 }
155 155 struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
156   - uuid_le uuid, char *name)
  156 + uuid_le uuid, char *name,
  157 + struct mei_cl_ops *ops)
157 158 {
158 159 struct mei_cl_device *device;
159 160 struct mei_cl *cl;
... ... @@ -168,6 +169,7 @@
168 169 return NULL;
169 170  
170 171 device->cl = cl;
  172 + device->ops = ops;
171 173  
172 174 device->dev.parent = &dev->pdev->dev;
173 175 device->dev.bus = &mei_cl_bus_type;
... ... @@ -407,6 +409,101 @@
407 409 dev_set_drvdata(&device->dev, data);
408 410 }
409 411 EXPORT_SYMBOL_GPL(mei_cl_set_drvdata);
  412 +
  413 +int mei_cl_enable_device(struct mei_cl_device *device)
  414 +{
  415 + int err;
  416 + struct mei_device *dev;
  417 + struct mei_cl *cl = device->cl;
  418 +
  419 + if (cl == NULL)
  420 + return -ENODEV;
  421 +
  422 + dev = cl->dev;
  423 +
  424 + mutex_lock(&dev->device_lock);
  425 +
  426 + cl->state = MEI_FILE_CONNECTING;
  427 +
  428 + err = mei_cl_connect(cl, NULL);
  429 + if (err < 0) {
  430 + mutex_unlock(&dev->device_lock);
  431 + dev_err(&dev->pdev->dev, "Could not connect to the ME client");
  432 +
  433 + return err;
  434 + }
  435 +
  436 + mutex_unlock(&dev->device_lock);
  437 +
  438 + if (device->event_cb && !cl->read_cb)
  439 + mei_cl_read_start(device->cl);
  440 +
  441 + if (!device->ops || !device->ops->enable)
  442 + return 0;
  443 +
  444 + return device->ops->enable(device);
  445 +}
  446 +EXPORT_SYMBOL_GPL(mei_cl_enable_device);
  447 +
  448 +int mei_cl_disable_device(struct mei_cl_device *device)
  449 +{
  450 + int err;
  451 + struct mei_device *dev;
  452 + struct mei_cl *cl = device->cl;
  453 +
  454 + if (cl == NULL)
  455 + return -ENODEV;
  456 +
  457 + dev = cl->dev;
  458 +
  459 + mutex_lock(&dev->device_lock);
  460 +
  461 + if (cl->state != MEI_FILE_CONNECTED) {
  462 + mutex_unlock(&dev->device_lock);
  463 + dev_err(&dev->pdev->dev, "Already disconnected");
  464 +
  465 + return 0;
  466 + }
  467 +
  468 + cl->state = MEI_FILE_DISCONNECTING;
  469 +
  470 + err = mei_cl_disconnect(cl);
  471 + if (err < 0) {
  472 + mutex_unlock(&dev->device_lock);
  473 + dev_err(&dev->pdev->dev,
  474 + "Could not disconnect from the ME client");
  475 +
  476 + return err;
  477 + }
  478 +
  479 + /* Flush queues and remove any pending read */
  480 + mei_cl_flush_queues(cl);
  481 +
  482 + if (cl->read_cb) {
  483 + struct mei_cl_cb *cb = NULL;
  484 +
  485 + cb = mei_cl_find_read_cb(cl);
  486 + /* Remove entry from read list */
  487 + if (cb)
  488 + list_del(&cb->list);
  489 +
  490 + cb = cl->read_cb;
  491 + cl->read_cb = NULL;
  492 +
  493 + if (cb) {
  494 + mei_io_cb_free(cb);
  495 + cb = NULL;
  496 + }
  497 + }
  498 +
  499 + mutex_unlock(&dev->device_lock);
  500 +
  501 + if (!device->ops || !device->ops->disable)
  502 + return 0;
  503 +
  504 + return device->ops->disable(device);
  505 +}
  506 +EXPORT_SYMBOL_GPL(mei_cl_disable_device);
410 507  
411 508 void mei_cl_bus_rx_event(struct mei_cl *cl)
412 509 {
drivers/misc/mei/mei_dev.h
... ... @@ -269,30 +269,36 @@
269 269 };
270 270  
271 271 /* MEI bus API*/
272   -struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
273   - uuid_le uuid, char *name);
274   -void mei_cl_remove_device(struct mei_cl_device *device);
275 272  
276   -int __mei_cl_async_send(struct mei_cl *cl, u8 *buf, size_t length);
277   -int __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length);
278   -int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length);
279   -
280 273 /**
281   - * struct mei_cl_transport_ops - MEI CL device transport ops
  274 + * struct mei_cl_ops - MEI CL device ops
282 275 * This structure allows ME host clients to implement technology
283   - * specific transport layers.
  276 + * specific operations.
284 277 *
  278 + * @enable: Enable an MEI CL device. Some devices require specific
  279 + * HECI commands to initialize completely.
  280 + * @disable: Disable an MEI CL device.
285 281 * @send: Tx hook for the device. This allows ME host clients to trap
286 282 * the device driver buffers before actually physically
287 283 * pushing it to the ME.
288 284 * @recv: Rx hook for the device. This allows ME host clients to trap the
289 285 * ME buffers before forwarding them to the device driver.
290 286 */
291   -struct mei_cl_transport_ops {
  287 +struct mei_cl_ops {
  288 + int (*enable)(struct mei_cl_device *device);
  289 + int (*disable)(struct mei_cl_device *device);
292 290 int (*send)(struct mei_cl_device *device, u8 *buf, size_t length);
293 291 int (*recv)(struct mei_cl_device *device, u8 *buf, size_t length);
294 292 };
295 293  
  294 +struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
  295 + uuid_le uuid, char *name,
  296 + struct mei_cl_ops *ops);
  297 +void mei_cl_remove_device(struct mei_cl_device *device);
  298 +
  299 +int __mei_cl_async_send(struct mei_cl *cl, u8 *buf, size_t length);
  300 +int __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length);
  301 +int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length);
296 302 void mei_cl_bus_rx_event(struct mei_cl *cl);
297 303 int mei_cl_bus_init(void);
298 304 void mei_cl_bus_exit(void);
... ... @@ -319,7 +325,7 @@
319 325  
320 326 struct mei_cl *cl;
321 327  
322   - const struct mei_cl_transport_ops *ops;
  328 + const struct mei_cl_ops *ops;
323 329  
324 330 struct work_struct event_work;
325 331 mei_cl_event_cb_t event_cb;
include/linux/mei_cl_bus.h
... ... @@ -38,5 +38,8 @@
38 38 void *mei_cl_get_drvdata(const struct mei_cl_device *device);
39 39 void mei_cl_set_drvdata(struct mei_cl_device *device, void *data);
40 40  
  41 +int mei_cl_enable_device(struct mei_cl_device *device);
  42 +int mei_cl_disable_device(struct mei_cl_device *device);
  43 +
41 44 #endif /* _LINUX_MEI_CL_BUS_H */