| DMOVER(9) | Kernel Developer's Manual | DMOVER(9) | 
dmover_backend_register,
  dmover_backend_unregister,
  dmover_session_create,
  dmover_session_destroy,
  dmover_request_alloc,
  dmover_request_free,
  dmover_process, dmover_done
  —
#include
  <dev/dmover/dmovervar.h>
Client interface routines:
  
  int
  
  dmover_session_create(const
    char *, struct
    dmover_session **);
void
  
  dmover_session_destroy(struct
    dmover_session *);
struct dmover_request *
  
  dmover_request_alloc(struct
    dmover_session *,
    dmover_buffer *);
void
  
  dmover_request_free(struct
    dmover_request *);
void
  
  dmover_process(struct
    dmover_request *);
Back-end interface routines:
  
  void
  
  dmover_backend_register(struct
    dmover_backend *);
void
  
  dmover_backend_unregister(struct
    dmover_backend *);
void
  
  dmover_done(struct
    dmover_request *);
dmover facility provides an interface to
  hardware-assisted data movers. This can be used to copy data from one location
  in memory to another, clear a region of memory, fill a region of memory with a
  pattern, and perform simple operations on multiple regions of memory, such as
  an XOR, without intervention by the CPU.
The drivers for hardware-assisted data movers present themselves
    to dmover by registering their capabilities. When a
    client wishes to use a dmover function, it creates a
    session for that function, which identifies back-ends capable of performing
    that function. The client then enqueues requests on that session, which the
    back-ends process asynchronously. The client may choose to block until the
    request is completed, or may have a call-back invoked once the request has
    been completed.
When a client creates a session, the
    dmover facility identifies back-ends which are
    capable of handling the requested function. When a request is scheduled for
    processing, the dmover scheduler will identify the
    best back-end to process the request from the list of candidate back-ends,
    in an effort to provide load balancing, while considering the relative
    performance of each back-end.
A dmover function always has one output
    region. A function may have zero or more input regions, or may use an
    immediate value as an input. For functions which use input regions, the
    lengths of each input region and the output region must be the same. All
    dmover functions with the same name will have the
    same number of and type inputs. If a back-end attempts to register a
    function which violates this invariant, behavior is undefined.
The dmover facility supports several types
    of buffer descriptors. For functions which use input regions, each input
    buffer descriptor and the output buffer descriptor must be of the same type.
    This restriction may be removed in a future revision of the interface.
The dmover facility may need to interrupt
    request processing and restart it. Clients of the
    dmover facility should take care to avoid unwanted
    side-effects should this occur. In particular, for functions which use input
    regions, no input region may overlap with the output region.
dmover facility shares several data structures
  between the client and back-end in order to describe sessions and requests.
typedef enum {
	DMOVER_BUF_LINEAR,
	DMOVER_BUF_UIO
} dmover_buffer_type;
typedef struct {
	void *l_addr;
	size_t l_len;
} dmover_buf_linear;
typedef union {
	dmover_buf_linear dmbuf_linear;
	struct uio *dmbuf_uio;
} dmover_buffer;
Together, these data types are used to describe buffer data
    structures which the dmover facility understands.
    Additional buffer types may be added in future revisions of the
    dmover interface.
The dmover_assignment structure contains the information about the back-end to which a request is currently assigned. It contains the following public members:
The dmover_session structure contains the following public members:
The dmover_request structure contains the following public members:
dmover_process().NULL if
      DMOVER_REQ_WAIT is set in
    dreq_flags.dmover_process() will
          wait for the request to complete using
          cv_wait(9). This flag
          may only be used if the caller has a valid thread context. If this
          flag is set, a callback may not be used.dmover function has one or more inputs.dmover function has one or more inputs. The number
      of inputs, and thus the number of valid elements in the array, is
      specified by the algorithm description for the session.dmover_session_create(function,
    sessionp)The dmover_session_create() function
        creates a data mover session for the specified data movement function
        function. A handle to the new session is returned
        in sessionp.
The following are valid data movement function names:
Users of the dmover facility are
        encouraged to use the following aliases for the well-known function
        names, as doing so saves space and reduces the chance of programming
        errors:
dmover_session_destroy(session)The dmover_session_destroy() function
        tears down a data mover session and releases all resources associated
        with it.
dmover_request_alloc(session,
    inbuf)The dmover_request_alloc() function
        allocates a dmover request structure and
        associates it with the specified session. If the
        inbuf argument is not
        NULL, inbuf is used as the
        array of input buffer descriptors in the request. Otherwise, if
        inbuf is NULL and the
        dmover function requires input buffers, the
        input buffer descriptors will be allocated automatically using
        malloc(9).
If the request structure or input buffer descriptors cannot be
        allocated, dmover_request_alloc() return
        NULL to indicate failure.
dmover_request_free(req)The dmover_request_free() function
        frees a dmover request structure. If the
        dmover function requires input buffers, and the
        input buffer descriptors associated with req were
        allocated by dmover_request_alloc(), then the
        input buffer descriptors will also be freed.
dmover_process(req)The dmover_process() function submits
        the dmover request req for
        processing. The call-back specified by the request is invoked when
        processing is complete.
The dmover_session_create() and
    dmover_session_destroy() functions must not be
    called from interrupt context.
The dmover_request_alloc(),
    dmover_request_free(), and
    dmover_process() functions may be called from
    interrupt handlers at levels IPL_VM,
    IPL_SOFTCLOCK, and IPL_SOFTNET, or in
    non-interrupt context.
The request completion call-back is called from a software interrupt handler at IPL_SOFTCLOCK.
dmover functions it can perform
  using an array of dmover_algdesc structures:
struct dmover_algdesc {
	const char *dad_name;	/* algorithm name */
	void *dad_data;		/* opaque algorithm description */
	int dad_ninputs;	/* number of inputs */
};
The dad_name member points to a valid
    dmover function name which the client may specify.
    The dad_data member points to a back-end-specific
    description of the algorithm.
A back-end presents itself to the dmover
    facility using the dmover_backend structure. The
    back-end must initialize the following members of the structure:
When invoked by the dmover facility, the
    back-end's (*dmb_process)() function should examine
    the pending request queue in its dmover_backend
    structure:
If an error occurs when processing the request, the DMOVER_REQ_ERROR bit must be set in the dreq_flags member of the request, and the dreq_error member set to an errno(2) value to indicate the error.
When the back-end has finished processing the request, it must
    call the dmover_done() function. This function
    eventually invokes the client's call-back routine.
If a hardware-assisted data mover uses interrupts, the interrupt handlers should be registered at IPL_VM.
The following functions are provided to the back-ends:
dmover_backend_register(backend)The dmover_backend_register() function
        registers the back-end backend with the
        dmover facility.
dmover_backend_unregister(backend)The dmover_backend_unregister()
        function removes the back-end backend from the
        dmover facility. The back-end must already be
        registered.
dmover_done(req)The dmover_done() function is called
        by the back-end when it has finished processing a request, whether the
        request completed successfully or not.
The dmover_backend_register() and
    dmover_backend_unregister() functions must not be
    called from interrupt context.
The dmover_done() function may be called
    at IPL_VM, IPL_SOFTCLOCK,
    IPL_SOFTNET, or in non-interrupt context.
dmover to
  zero-fill a region of memory. In this example, the CPU will be able to context
  switch to another thread and perform work while the hardware-assisted data
  mover clears the specified block of memory.
int
hw_bzero(void *buf, size_t len)
{
	struct dmover_session *dses;
	struct dmover_request *dreq;
	int error;
	error = dmover_session_create(DMOVER_FUNC_ZERO, &dses);
	if (error)
		return (error);
	dreq = dmover_request_alloc(dses, NULL);
	if (dreq == NULL) {
		dmover_session_destroy(dses);
		return (ENOMEM);
	}
	dreq->dreq_flags = DMOVER_REQ_WAIT;
	dreq->dreq_callback = NULL;
	dreq->dreq_outbuf.dreq_outbuf_type = DMOVER_BUF_LINEAR;
	dreq->dreq_outbuf.dmbuf_linear.l_addr = buf;
	dreq->dreq_outbuf.dmbuf_linear.l_len = len;
	dmover_process(dreq);
	error = (dreq->dreq_flags & DMOVER_REQ_ERROR) ?
	    dreq->dreq_error : 0;
	dmover_request_free(dreq);
	dmover_session_destroy(dses);
	return (error);
}
dmover facility first appeared in
  NetBSD 2.0.
dmover facility was designed and implemented by
  Jason R. Thorpe
  ⟨thorpej@wasabisystems.com⟩ and contributed by Wasabi Systems,
  Inc.
| December 4, 2007 | NetBSD 9.3 |