/** * hsi_port_unregister_clients - Unregister an HSI port * @port: The HSI port to unregister
*/ void hsi_port_unregister_clients(struct hsi_port *port)
{
device_for_each_child(&port->device, NULL, hsi_remove_client);
}
EXPORT_SYMBOL_GPL(hsi_port_unregister_clients);
/** * hsi_unregister_controller - Unregister an HSI controller * @hsi: The HSI controller to register
*/ void hsi_unregister_controller(struct hsi_controller *hsi)
{
device_for_each_child(&hsi->device, NULL, hsi_remove_port);
device_unregister(&hsi->device);
}
EXPORT_SYMBOL_GPL(hsi_unregister_controller);
/** * hsi_register_controller - Register an HSI controller and its ports * @hsi: The HSI controller to register * * Returns -errno on failure, 0 on success.
*/ int hsi_register_controller(struct hsi_controller *hsi)
{ unsignedint i; int err;
err = device_add(&hsi->device); if (err < 0) return err; for (i = 0; i < hsi->num_ports; i++) {
hsi->port[i]->device.parent = &hsi->device;
err = device_add(&hsi->port[i]->device); if (err < 0) goto out;
} /* Populate HSI bus with HSI clients */
hsi_scan_board_info(hsi);
return 0;
out: while (i-- > 0)
device_del(&hsi->port[i]->device);
device_del(&hsi->device);
/** * hsi_register_client_driver - Register an HSI client to the HSI bus * @drv: HSI client driver to register * * Returns -errno on failure, 0 on success.
*/ int hsi_register_client_driver(struct hsi_client_driver *drv)
{
drv->driver.bus = &hsi_bus_type;
/** * hsi_put_controller - Free an HSI controller * * @hsi: Pointer to the HSI controller to freed * * HSI controller drivers should only use this function if they need * to free their allocated hsi_controller structures before a successful * call to hsi_register_controller. Other use is not allowed.
*/ void hsi_put_controller(struct hsi_controller *hsi)
{ unsignedint i;
if (!hsi) return;
for (i = 0; i < hsi->num_ports; i++) if (hsi->port && hsi->port[i])
put_device(&hsi->port[i]->device);
put_device(&hsi->device);
}
EXPORT_SYMBOL_GPL(hsi_put_controller);
/** * hsi_alloc_controller - Allocate an HSI controller and its ports * @n_ports: Number of ports on the HSI controller * @flags: Kernel allocation flags * * Return NULL on failure or a pointer to an hsi_controller on success.
*/ struct hsi_controller *hsi_alloc_controller(unsignedint n_ports, gfp_t flags)
{ struct hsi_controller *hsi; struct hsi_port **port; unsignedint i;
if (!n_ports) return NULL;
hsi = kzalloc(sizeof(*hsi), flags); if (!hsi) return NULL;
port = kcalloc(n_ports, sizeof(*port), flags); if (!port) {
kfree(hsi); return NULL;
}
hsi->num_ports = n_ports;
hsi->port = port;
hsi->device.release = hsi_controller_release;
device_initialize(&hsi->device);
/** * hsi_free_msg - Free an HSI message * @msg: Pointer to the HSI message * * Client is responsible to free the buffers pointed by the scatterlists.
*/ void hsi_free_msg(struct hsi_msg *msg)
{ if (!msg) return;
sg_free_table(&msg->sgt);
kfree(msg);
}
EXPORT_SYMBOL_GPL(hsi_free_msg);
/** * hsi_alloc_msg - Allocate an HSI message * @nents: Number of memory entries * @flags: Kernel allocation flags * * nents can be 0. This mainly makes sense for read transfer. * In that case, HSI drivers will call the complete callback when * there is data to be read without consuming it. * * Return NULL on failure or a pointer to an hsi_msg on success.
*/ struct hsi_msg *hsi_alloc_msg(unsignedint nents, gfp_t flags)
{ struct hsi_msg *msg; int err;
msg = kzalloc(sizeof(*msg), flags); if (!msg) return NULL;
/** * hsi_async - Submit an HSI transfer to the controller * @cl: HSI client sending the transfer * @msg: The HSI transfer passed to controller * * The HSI message must have the channel, ttype, complete and destructor * fields set beforehand. If nents > 0 then the client has to initialize * also the scatterlists to point to the buffers to write to or read from. * * HSI controllers relay on pre-allocated buffers from their clients and they * do not allocate buffers on their own. * * Once the HSI message transfer finishes, the HSI controller calls the * complete callback with the status and actual_len fields of the HSI message * updated. The complete callback can be called before returning from * hsi_async. * * Returns -errno on failure or 0 on success
*/ int hsi_async(struct hsi_client *cl, struct hsi_msg *msg)
{ struct hsi_port *port = hsi_get_port(cl);
/** * hsi_claim_port - Claim the HSI client's port * @cl: HSI client that wants to claim its port * @share: Flag to indicate if the client wants to share the port or not. * * Returns -errno on failure, 0 on success.
*/ int hsi_claim_port(struct hsi_client *cl, unsignedint share)
{ struct hsi_port *port = hsi_get_port(cl); int err = 0;
/** * hsi_register_port_event - Register a client to receive port events * @cl: HSI client that wants to receive port events * @handler: Event handler callback * * Clients should register a callback to be able to receive * events from the ports. Registration should happen after * claiming the port. * The handler can be called in interrupt context. * * Returns -errno on error, or 0 on success.
*/ int hsi_register_port_event(struct hsi_client *cl, void (*handler)(struct hsi_client *, unsignedlong))
{ struct hsi_port *port = hsi_get_port(cl);
if (!handler || cl->ehandler) return -EINVAL; if (!hsi_port_claimed(cl)) return -EACCES;
cl->ehandler = handler;
cl->nb.notifier_call = hsi_event_notifier_call;
/** * hsi_unregister_port_event - Stop receiving port events for a client * @cl: HSI client that wants to stop receiving port events * * Clients should call this function before releasing their associated * port. * * Returns -errno on error, or 0 on success.
*/ int hsi_unregister_port_event(struct hsi_client *cl)
{ struct hsi_port *port = hsi_get_port(cl); int err;
WARN_ON(!hsi_port_claimed(cl));
err = blocking_notifier_chain_unregister(&port->n_head, &cl->nb); if (!err)
cl->ehandler = NULL;
/** * hsi_event - Notifies clients about port events * @port: Port where the event occurred * @event: The event type * * Clients should not be concerned about wake line behavior. However, due * to a race condition in HSI HW protocol, clients need to be notified * about wake line changes, so they can implement a workaround for it. * * Events: * HSI_EVENT_START_RX - Incoming wake line high * HSI_EVENT_STOP_RX - Incoming wake line down * * Returns -errno on error, or 0 on success.
*/ int hsi_event(struct hsi_port *port, unsignedlong event)
{ return blocking_notifier_call_chain(&port->n_head, event, NULL);
}
EXPORT_SYMBOL_GPL(hsi_event);
/** * hsi_get_channel_id_by_name - acquire channel id by channel name * @cl: HSI client, which uses the channel * @name: name the channel is known under * * Clients can call this function to get the hsi channel ids similar to * requesting IRQs or GPIOs by name. This function assumes the same * channel configuration is used for RX and TX. * * Returns -errno on error or channel id on success.
*/ int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name)
{ int i;
if (!cl->rx_cfg.channels) return -ENOENT;
for (i = 0; i < cl->rx_cfg.num_channels; i++) if (!strcmp(cl->rx_cfg.channels[i].name, name)) return cl->rx_cfg.channels[i].id;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.