From b5176d9952357a282bd4ef71edb8a20a4ea59ade Mon Sep 17 00:00:00 2001 From: Federico Vaga <federico.vaga@gmail.com> Date: Tue, 15 Nov 2011 19:22:12 +0100 Subject: [PATCH] Documentation: updated to match code and partially upgraded. Signed-off-by: Federico Vaga <federico.vaga@gmail.com> Signed-off-by: Alessandro Rubini <rubini@gnudd.com> --- Documentation/zio/buffer.txt | 96 +++++++++++++++++++---------------- Documentation/zio/device.txt | 2 +- Documentation/zio/trigger.txt | 83 +++++++++++++++--------------- 3 files changed, 93 insertions(+), 88 deletions(-) diff --git a/Documentation/zio/buffer.txt b/Documentation/zio/buffer.txt index 294fedd..f80e63a 100644 --- a/Documentation/zio/buffer.txt +++ b/Documentation/zio/buffer.txt @@ -14,10 +14,10 @@ Please read <linux/zio-buffer.h> together with this file. Buffers may be device-specific or generic. A generic buffer called "kmalloc" is provided within zio-core; it uses kmalloc for allocation -of control and data blocks. Such buffer is activated by default on -all new csets being registered but is not special in any other way, you -can write your own generic buffer (and if it's better than ours, we -may use it as default buffer in future releases). +data blocks. Such buffer is activated by default on all new csets +being registered but is not special in any other way, you can write +your own generic buffer (and if it's better than ours, we may use it +as default buffer in future releases). A device-specific buffer declares to be such within its attributes. A device-specific buffer can only be used by csets that declare its name @@ -27,7 +27,7 @@ of "kmalloc". Sometimes people write drivers for a set of similar devices, with similar DMA capabilities. In this case, all of them may refer to the -same device-specific buffer type; the buffer type will be registered +same device-specific buffer type; the buffer type may be registered as a standalone kernel module. The ZIO buffer data structures includes two sets of operations: @@ -41,18 +41,22 @@ Each buffer type must provide the following buffer operations. All of them are implemented in zio-buf-kmalloc.c, which may be used as reference to better understand the role of each method: - void *(*create)(struct zio_buffer *buffer, struct zio_channel *ch, - fmode_t f_flags); - void (*destroy)(void *b_instance); + struct zio_bi *(*create)(struct zio_buffer_type *zbuf, + struct zio_channel *ch, + fmode_t f_flags); + void (*destroy)(struct zio_bi *bi); -The create operation allocates and initializes an instance of the +The create() operation allocates and initializes an instance of the buffer type. It is called by ZIO when a channel is opened for the -first time. The instance is a void pointer because each buffer needs a -different (private) data structure to represent an own instance. +first time. The operation return a zio buffer instance (zio_bi), +which is the generic descriptor of a buffer instance. ZIO handles +only zio_bi, so complex buffer structures must contain the zio_bi +structure and use container_of() to access the private enclosing +structure. -Destroy deallocates the buffer. ZIO calls destroy when the channel -is unregistered from ZIO or when the user assigns a different buffer -type to the channel. +Destroy() deallocates a buffer instance. ZIO calls destroy when the +channel is unregistered from ZIO or when the user assigns a different +buffer type to the channel. When the control/data devices are closed, ZIO doesn't call destroy, so incoming data can queue up while the application leaves it closed @@ -60,47 +64,51 @@ incoming data can queue up while the application leaves it closed handled by ZIO, so it couldn't call destroy on close even if it wanted to. - void *(*alloc_block)(void *b_instance, void **handle_ret, - size_t size, gfp_t gfp); - void (*free_block)(void *handle); + struct zio_block *(*alloc_block)(struct zio_bi *bi, + struct zio_control *ctrl, + size_t datalen, gfp_t gfp); + void (*free_block)(struct zio_bi *bi, struct zio_block *block); -For input channels, a block is allocated when the trigger fills it, -and it is freed when user has read or ignored it. For output, -allocation happens on user write and free is called by the trigger. -Thus, the function are sometimes called by buffer code itself, and -sometimes by the trigger. The data structure hosting a block is -returned as a void pointer because each buffer needs its own -private structure. +For input channels, a block is allocated before the trigger fires, and +it is freed when the user has read or explicitly ignored it. For +output, allocation happens on user write and free is called by the +trigger when it is done. Thus, the functions are sometimes called by +buffer code itself, and sometimes by the trigger. The generic +structure hosting a block is zio_block which contain both data +(samples) and control informations. If needed, buffers may use a more +complex structure, which will include zio_block, which is the only +structure that ZIO handles; by using container_of you can retrieve the +enclosing complex structure used in your buffer - ssize_t (*store_block)(void *handle, struct zio_control *ctrl, - void *data, size_t len); - ssize_t (*retr_block) (void *handle, struct zio_control *ctrl, - void *data, size_t len); + int (*store_block)(struct zio_bi *bi, struct zio_block *block); + struct zio_block (*retr_block) (struct zio_bi *bi); -The trigger calls the store method when it has data to push for input -channels. If uses an handle it received from the alloc_block method. -The trigger for output channels uses the retrieve method to extract -data from the buffer and send it to the hardware driver. After -retrieving data, it is responsible for freeing it. -FIXME: how can the trigger know the handle to retrieve? +For input the trigger calls store_block() and the read system call issues +retr_block(). For output, the write system call runs store_block() +and the trigger may call retr_block() (although the buffer pushes to +the trigger when it receives the first data block). File Operations =============== -These are the file_operations used by the char devices (control and -data) for every channel using this buffer type. The open method of -the zio file operations kmallocs f->private_data to point to this -structure: +This field hosts the file_operations used by the char devices (control and +data) for every channel using this buffer type. When char devices are +initially opened, the open method being run is within zio-code; +it kmallocs f->private_data before calling the buffer-specific open +method. The private data being used is: struct zio_f_priv { - void *b_instance; + struct zio_channel *chan; enum zio_cdev_type type; }; -All buffer file operations can thus refer to the buffer instance for -this channel and know if the current file is ZIO_CDEV_CTRL or -ZIO_CDEV_DATA. The release file operation is expected to free this -structure. +All buffer file operations can thus refer to the current channel (and +its buffer and its trigger), and know if the current file is +ZIO_CDEV_CTRL or ZIO_CDEV_DATA. Every buffer is expected to +call zio_generic_release() at the end of its own release operation, or +used zio_generic_release() directly in the file operations. -See zio-buf-kmalloc.c for a working example of buffer file operations. +ZIO offers other generic file operations, that may be enough for your +buffer code or not. See zio-buf-kmalloc.c for a working example of +buffer file operations. diff --git a/Documentation/zio/device.txt b/Documentation/zio/device.txt index 75bd102..c75a38d 100644 --- a/Documentation/zio/device.txt +++ b/Documentation/zio/device.txt @@ -56,7 +56,7 @@ Similarly, data is discarded if you re-read the control device after having retrieved the description of a data block you are not interested in. For output, writing data without writing control uses the default control information, or the one from the previous -transfer). +transfer. The full set of rules for data and control transfers is described elsewhere (FIXME: link to other docs) but it is pretty intuitive once diff --git a/Documentation/zio/trigger.txt b/Documentation/zio/trigger.txt index 491d59b..1aa701f 100644 --- a/Documentation/zio/trigger.txt +++ b/Documentation/zio/trigger.txt @@ -7,6 +7,7 @@ as an attribute of the cset. When the trigger fires, it acts on all the non-disabled channels of the cset. Only the "app-request" trigger can act on a single channel at a time. +Please read <linux/zio-trigger.h> together with this file. Trigger Types ============= @@ -27,37 +28,30 @@ of "app-request". Trigger Operations ================== -(NOTE: this is still subject to fine-tuning, as we are still writing code) - Trigger operations are the following: - struct zio_trigger_instance *(*create)(struct zio_buffer *buffer, - struct zio_cset *cset); - void (*destroy)(struct zio_trigger_instance *t_instance); + struct zio_ti *(*create)(struct zio_trigger_type *trig, + struct zio_cset *cset, + struct zio_control *ctrl, + fmode_t flags); + void (*destroy)(struct zio_ti *ti); -Create and destroy a trigger instance for a cset. ZIO calls create when -attaching the trigger to a cset; it calls destroy when the trigger is +Create and destroy a trigger instance for a cset. ZIO calls create() when +attaching the trigger to a cset; it calls destroy() when the trigger is replaced by a different one or the cset is being unregistered from ZIO. -The instance structure is trigger-specific, but it must include this -generic structure: - - struct zio_trigger_instance { - struct zio_trigger *trig; - struct zio_cset *cset; - }; - -Every time this structure is passed over, trigger code may use container_of -if it needs to access the private enclosing structure. +The instance structure is trigger-specific, but it must include the +generic structure zio_ti. Every time this structure is passed over, trigger +code may use container_of if it needs to access the private enclosing +structure. - int (*config)(struct zio_trigger_instance *t_instance); + int (*config)(struct zio_ti *ti, stuct zio_control *ctrl); The method is called by ZIO whenever the attributes for a trigger instance are modified by the user (by writing to sysfs or otherwise). - int (*enqueue_block)(struct zio_trigger_instance *t_instance, - struct zio_channel *ch, - struct zio_control *ctrl, - void *data, size_t len); + int (*push_block)(struct zio_ti *ti, + struct zio_channel *chan, + struct zio_control *ctrl); This is used for output channels: when a new data block is ready, it must be sent to the trigger so it can be output when the event fires. @@ -66,17 +60,20 @@ function can return -EAGAIN if it has no space in the queue, or 0 on success. If EAGAIN happens, the buffer should handle it (by storing locally or notifying the user). - int (*space_in_buffer)(struct zio_trigger_instance *t_instance); + struct zio_block (*pull_block)(struct zio_ti *ti, + struct zio_channel *chan,); + +The method retrives a block from the trigger. I may be called by +the buffer, if it wants a block immediately. The method returns a +valid pointer to a block or NULL if there is no valid block that +can be retrieved immediately. The returned block may be shorter +than what the trigger would have stored in the buffer by itself. -The method return either 0 (there is space for one block), a positive -value (the maximum size of the next block that can be enqueued) or --EAGAIN. This can be used by the poll file operation, to ask -whether the next write(2) will succeed or not. File Operations =============== -The trigger may include a non-NULL f_ops pointer. Most trigger will +The trigger may include a non-NULL f_ops pointer. Most triggers will not need it, but for example "app-request" does, because it needs to look at individual read and write calls performed by applications. ZIO will use these file operations (instead of the buffer file operations) @@ -96,30 +93,30 @@ a time when the trigger fires, so input or output may happen. data has already happened when the trigger interrupt runs, but this doesn't change the software flow). -For output triggers, the trigger instance is already hosting the data -blocks (received through the enqueue_block method), so the code will -just loop over all the channels and free such data blocks. In some cases -the trigger will need to perform the output before freeing data, in -most cases data has been prepared for DMA during enqueue_block, -so output already happened when the trigger run. - -ZIO offers this help macro to loop over all non-disabled channels: +Hardware-driven triggers will need to make their own work by themselves, +but ZIO offers this help macro to loop over all non-disabled channels: cset_for_each(struct zio_cset *cset, struct zio_channel *ch) The macro works like "task_for_each" or "list_for_each" in the kernel headers. -For input triggers, the asynchronous code that runs the event will just -need to call +For software-based triggers (where actual I/O happens when software +wants it to happen, even if it is in response to an interrupt), the +asynchronous code that runs the event will just need to call - zio_fire_trigger(struct zio_trigger_instance *instance); + zio_fire_trigger(struct zio_ti *ti); -This function, part of zio-core, internally runs "cset_for_each". -For each non-disabled channel, it calls the drv->input_block method -and the stores it in the active buffer. +This function, part of zio-core, calls the internal helpers +__zio_fire_input_trigger for input or __zio_fire_output_trigger for +output. These, in turn, internally run "cset_for_each". For each +non-disabled channel, the input trigger function calls the +drv->input_block and buffer->store_block; +the output trigger function calls the drv->output_block method (which +will free the block when it is done) and the buffer->retr_block +method to prepare for the next operation. -You can refer to "zio-trig-ktimer" for an example of a multi-instance +You can refer to "zio-trig-timer" for an example of a multi-instance generic timer and to "zio-trig-app-request" for a non-conventional implementation based on trigger-local file_operations. -- GitLab