xref: /netbsd-src/share/man/man9/dmover.9 (revision 08c81a9c2dc8c7300e893321eb65c0925d60871c)
1.\"	$NetBSD: dmover.9,v 1.5 2002/08/04 04:54:19 thorpej Exp $
2.\"
3.\" Copyright (c) 2002 Wasabi Systems, Inc.
4.\" All rights reserved.
5.\"
6.\" Written by Jason R. Thorpe for Wasabi Systems, Inc.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\"    notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\"    notice, this list of conditions and the following disclaimer in the
15.\"    documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software
17.\"    must display the following acknowledgement:
18.\"	This product includes software developed for the NetBSD Project by
19.\"	Wasabi Systems, Inc.
20.\" 4. The name of Wasabi Systems, Inc. may not be used to endorse
21.\"    or promote products derived from this software without specific prior
22.\"    written permission.
23.\"
24.\" THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
25.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
28.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34.\" POSSIBILITY OF SUCH DAMAGE.
35.\"
36.Dd July 15, 2002
37.Dt DMOVER 9
38.Os
39.Sh NAME
40.Nm dmover_backend_register ,
41.Nm dmover_backend_unregister ,
42.Nm dmover_session_create ,
43.Nm dmover_session_destroy ,
44.Nm dmover_request_alloc ,
45.Nm dmover_request_free ,
46.Nm dmover_process ,
47.Nm dmover_done
48.Nd hardware-assisted data mover interface
49.Sh SYNOPSIS
50.Fd #include \*[Lt]dev/dmover/dmovervar.h\*[Gt]
51.Pp
52Client interface routines:
53.Pp
54.Ft int
55.Fn "dmover_session_create" "const char *" "struct dmover_session **"
56.Ft void
57.Fn "dmover_session_destroy" "struct dmover_session *"
58.Ft "struct dmover_request *"
59.Fn "dmover_request_alloc" "struct dmover_session *" "dmover_buffer *"
60.Ft void
61.Fn "dmover_request_free" "struct dmover_request *"
62.Ft void
63.Fn "dmover_process" "struct dmover_request *"
64.Pp
65Back-end interface routines:
66.Pp
67.Ft void
68.Fn "dmover_backend_register" "struct dmover_backend *"
69.Ft void
70.Fn "dmover_backend_unregister" "struct dmover_backend *"
71.Ft void
72.Fn "dmover_done" "struct dmover_request *"
73.Sh DESCRIPTION
74The
75.Nm dmover
76facility provides an interface to hardware-assisted data movers.  This
77can be used to copy data from one location in memory to another, clear
78a region of memory, fill a region of memory with a pattern, and perform
79simple operations on multiple regions of memory, such as an XOR, without
80intervention by the CPU.
81.Pp
82The drivers for hardware-assisted data movers present themselves to
83.Nm dmover
84by registering their capabilities.  When a client wishes to use a
85.Nm dmover
86function, it creates a session for that function, which identifies back-ends
87capable of performing that function.  The client then enqueues requests
88on that session, which the back-ends process asynchronously.  The client
89may choose to block until the request is completed, or may have a call-back
90invoked once the request has been completed.
91.Pp
92When a client creates a session, the
93.Nm dmover
94facility identifies back-ends which are capable of handling the requested
95function.  When a request is scheduled for processing, the
96.Nm dmover
97scheduler will identify the best back-end to process the request from
98the list of candidate back-ends, in an effort to provide load balancing,
99while considering the relative performance of each back-end.
100.Pp
101A
102.Nm dmover
103function always has one output region.  A function may have zero or more
104input regions, or may use an immediate value as an input.  For functions
105which use input regions, the lengths of each input region and the output
106region must be the same.  All
107.Nm dmover
108functions with the same name will have the same number of and type inputs.
109If a back-end attempts to register a function which violates this invariant,
110behavior is undefined.
111.Pp
112The
113.Nm dmover
114facility supports several types of buffer descriptors.  For functions
115which use input regions, each input buffer descriptor and the output buffer
116descriptor must be of the same type.  This restriction may be removed in
117a future revision of the interface.
118.Pp
119The
120.Nm dmover
121facility may need to interrupt request processing and restart it.
122Clients of the
123.Nm dmover
124facility should take care to avoid unwanted side-effects should this occur.
125In particular, for functions which use input regions, no input region may
126overlap with the output region.
127.Ss DATA STRUCTURES
128The
129.Nm dmover
130facility shares several data structures between the client and
131back-end in order to describe sessions and requests.
132.Bd -literal -offset indent
133typedef enum {
134	DMOVER_BUF_LINEAR,
135	DMOVER_BUF_UIO
136} dmover_buffer_type;
137
138typedef struct {
139	void *l_addr;
140	size_t l_len;
141} dmover_buf_linear;
142
143typedef union {
144	dmover_buf_linear dmbuf_linear;
145	struct uio *dmbuf_uio;
146} dmover_buffer;
147.Ed
148.Pp
149Together, these data types are used to describe buffer data structures
150which the
151.Nm dmover
152facility understands.  Additional buffer types may be added in future
153revisions of the
154.Nm dmover
155interface.
156.Pp
157The
158.Fa dmover_assignment
159structure contains the information about the back-end to which a
160request is currently assigned.  It contains the following public members:
161.Bl -tag -width "XXXX"
162.It struct dmover_backend *das_backend
163This is a pointer to the back-end.
164.It const struct dmover_algdesc *das_algdesc
165This is a pointer to the algorithm description provided by
166the back-end for the request's function.
167.El
168.Pp
169The
170.Fa dmover_session
171structure contains the following public members:
172.Bl -tag -width "XXXX"
173.It void *dses_cookie
174This is a pointer to client private data.
175.It int dses_ninputs
176This is the number of inputs used by the selected function.
177.El
178.Pp
179The
180.Fa dmover_request
181structure contains the following public members:
182.Bl -tag -width "XXXX"
183.It TAILQ_ENTRY(dmover_request) dreq_dmbq
184Linkage on the back-end's queue of pending requests.
185.It struct dmover_session *dreq_session
186Pointer to the session with which this request is associated.  This
187is intended for use by the back-end.
188.It struct dmover_assignment *dreq_assignment
189Pointer to the
190.Fa dmover_assignment
191structure which describes the back-end to which the request is
192currently assigned.  The back-end is assigned when the request
193is scheduled with
194.Fn dmover_process .
195.It void (*dreq_callback)(struct dmover_request *)
196This is a pointer to an optional call-back function provided by the
197client.  If provided, the call-back is invoked when the request is
198complete.  This field must be
199.Dv NULL
200if
201.Em DMOVER_REQ_WAIT
202is set in
203.Em dreq_flags .
204.It void *dreq_cookie
205This is a pointer to client private data specific to the request.
206.It void *dreq_dmbcookie
207This is a pointer to back-end private data, for use while the back-end
208is actively processing a request.
209.It __volatile int dreq_flags
210The following flags are defined:
211.Bl -tag -width "DMOVER_REQ_RUNNINGXX"
212.It DMOVER_REQ_DONE
213The request has been completed.  If not using a call-back, the client
214may poll this bit to determine if a request has been processed.
215.It DMOVER_REQ_ERROR
216An error has occurred while processing the request.
217.It DMOVER_REQ_RUNNING
218The request is currently being executed by the back-end.  Once a
219command is running, it cannot be cancelled, and must run to completion.
220.It DMOVER_REQ_WAIT
221If set by the client,
222.Fn dmover_process
223will wait for the request to complete using
224.Xr tsleep 9 .
225This flag may only be used if the caller has a valid thread context.
226If this flag is set, a callback may not be used.
227.El
228.It int dreq_error
229If the
230.Em DMOVER_REQ_ERROR
231bit is set, this contains the
232.Xr errno 2
233value indicating the error that occurred during processing.
234.It dmover_buffer_type dreq_outbuf_type
235The type of the output buffer.
236.It dmover_buffer dreq_outbuf
237The output buffer.
238.It uint8_t dreq_immediate[8]
239This is the input for algorithms which use an immediate value.  Values
240smaller than 8 bytes should use the least-significant bytes first.  For
241example, a 32-bit integer would occupy bytes 0, 1, 2, and 3.
242.It dmover_buffer_type dreq_inbuf_type
243The type of the input buffer.  This is only used if the
244.Nm dmover
245function has one or more inputs.
246.It dmover_buffer *dreq_inbuf
247A pointer to an array of input buffers.  This is only used if the
248.Nm dmover
249function has one or more inputs.  The number of inputs, and thus the
250number of valid elements in the array, is specified by the algorithm
251description for the session.
252.El
253.Ss CLIENT INTERFACE
254The following functions are provided to the client:
255.Bl -tag -width "XXXX"
256.It int Fn dmover_session_create "const char *function" \
257    "struct dmover_session **sessionp"
258.Pp
259The
260.Fn dmover_session_create
261function creates a data mover session for the specified data movement
262function
263.Fa function .
264A handle to the new session is returned in
265.Fa *sessionp .
266.Pp
267The following are valid data movement function names:
268.Bl -tag -width "fill8xx"
269.It Dq zero
270Fill a memory region with zeros.  This algorithm has an input count of 0.
271.It Dq fill8
272Fill a memory region with an 8-bit pattern.  This algorithm has an input
273count of 0.  The pattern is provided in the
274.Em dreq_imm8
275member of the
276.Fa dmover_request
277structure.
278.It Dq copy
279Copy a memory region from one location to another.  This algorithm has an
280input count of 1.
281.It Dq xor2
282Perform an XOR operation on 2 inputs.  This algorithm has an input count
283of 2.
284.It Dq xor3
285Perform an XOR operation on 3 inputs.  This algorithm has an input count
286of 3.
287.It Dq xor4
288Perform an XOR operation on 4 inputs.  This algorithm has an input count
289of 4.
290.It Dq xor5
291Perform an XOR operation on 5 inputs.  This algorithm has an input count
292of 5.
293.It Dq xor6
294Perform an XOR operation on 6 inputs.  This algorithm has an input count
295of 6.
296.It Dq xor7
297Perform an XOR operation on 7 inputs.  This algorithm has an input count
298of 7.
299.It Dq xor8
300Perform an XOR operation on 8 inputs.  This algorithm has an input count
301of 8.
302.El
303.Pp
304Users of the
305.Nm dmover
306facility are encouraged to use the following aliases for the well-known
307function names, as doing so saves space and reduces the chance of programming
308errors:
309.Bl -tag -width "DMOVER_FUNC_FILL32xx"
310.It DMOVER_FUNC_ZERO
311.Dq zero
312.Pq Va dmover_funcname_zero
313.It DMOVER_FUNC_FILL8
314.Dq fill8
315.Pq Va dmover_funcname_fill8
316.It DMOVER_FUNC_COPY
317.Dq copy
318.Pq Va dmover_funcname_copy
319.It DMOVER_FUNC_XOR2
320.Dq xor2
321.Pq Va dmover_funcname_xor2
322.It DMOVER_FUNC_XOR3
323.Dq xor3
324.Pq Va dmover_funcname_xor3
325.It DMOVER_FUNC_XOR4
326.Dq xor4
327.Pq Va dmover_funcname_xor4
328.It DMOVER_FUNC_XOR5
329.Dq xor5
330.Pq Va dmover_funcname_xor5
331.It DMOVER_FUNC_XOR6
332.Dq xor6
333.Pq Va dmover_funcname_xor6
334.It DMOVER_FUNC_XOR7
335.Dq xor7
336.Pq Va dmover_funcname_xor7
337.It DMOVER_FUNC_XOR8
338.Dq xor8
339.Pq Va dmover_funcname_xor8
340.El
341.It void Fn dmover_session_destroy "struct dmover_session *session"
342.Pp
343The
344.Fn dmover_session_destroy
345function tears down a data mover session and releases all resources
346associated with it.
347.It struct dmover_request * Fn dmover_request_alloc \
348    "struct dmover_session *session" "dmover_buffer *inbuf"
349.Pp
350The
351.Fn dmover_request_alloc
352function allocates a
353.Nm dmover
354request structure and associates it with the specified session.
355If the
356.Fa inbuf
357argument is not
358.Dv NULL ,
359.Fa inbuf
360is used as the array of input buffer descriptors in the request.
361Otherwise, if
362.Fa inbuf
363is
364.Dv NULL
365and the
366.Nm dmover
367function requires input buffers, the input buffer descriptors will be
368allocated automatically using
369.Xr malloc 9 .
370.Pp
371If the request structure or input buffer descriptors cannot be allocated,
372.Fn dmover_request_alloc
373return
374.Dv NULL
375to indicate failure.
376.It void Fn dmover_request_free "struct dmover_request *req"
377.Pp
378The
379.Fn dmover_request_free
380function frees a
381.Nm dmover
382request structure.  If the
383.Nm dmover
384function requires input buffers, and the input buffer descriptors
385associated with
386.Fa req
387were allocated by
388.Fn dmover_request_alloc ,
389then the input buffer descriptors will also be freed.
390.It void Fn dmover_process "struct dmover_request *req"
391.Pp
392The
393.Fn dmover_process
394function submits the
395.Nm dmover
396request
397.Fa req
398for processing.  The call-back specified by the request is
399invoked when processing is complete.
400.El
401.Pp
402The
403.Fn dmover_session_create
404and
405.Fn dmover_session_destroy
406functions must not be called from interrupt context.
407.Pp
408The
409.Fn dmover_request_alloc ,
410.Fn dmover_request_free ,
411and
412.Fn dmover_process
413functions may be called from interrupt handlers at levels
414.Em IPL_BIO ,
415.Em IPL_SOFTCLOCK ,
416and
417.Em IPL_SOFTNET ,
418or in non-interrupt context.
419.Pp
420The request completion call-back is called from a software interrupt
421handler at
422.Em IPL_SOFTCLOCK .
423.Ss BACK-END INTERFACE
424A back-end describes the
425.Nm dmover
426functions it can perform using an array of
427.Fa dmover_algdesc
428structures:
429.Bd -literal -offset indent
430struct dmover_algdesc {
431	const char *dad_name;	/* algorithm name */
432	void *dad_data;		/* opaque algorithm description */
433	int dad_ninputs;	/* number of inputs */
434};
435.Ed
436.Pp
437The
438.Em dad_name
439member points to a valid
440.Nm dmover
441function name which the client may specify.  The
442.Em dad_data
443member points to a back-end-specific description of the algorithm.
444.Pp
445A back-end presents itself to the
446.Nm dmover
447facility using the
448.Fa dmover_backend
449structure.  The back-end must initialize the following members
450of the structure:
451.Bl -tag -width "XXXX"
452.It const char *dmb_name
453This is the name of the back-end.
454.It u_int dmb_speed
455This is an estimate of the number of kilobytes/second that the
456back-end can process.
457.It void *dmb_cookie
458This is a pointer to back-end private data.
459.It const struct dmover_algdesc *dmb_algdescs
460This points to an array of
461.Fa dmover_algdesc
462structures which describe the functions the data mover can perform.
463.It int dmb_nalgdescs
464This is the number of elements in the
465.Em dmb_algdescs
466array.
467.It void (*dmb_process)(struct dmover_backend *)
468This is the entry point to the back-end used to process requests.
469.El
470.Pp
471When invoked by the
472.Nm dmover
473facility, the back-end's
474.Fn (*dmb_process)
475function should examine the pending request queue in it's
476.Fa dmover_backend
477structure:
478.Bl -tag -width "XXXX"
479.It TAILQ_HEAD(, dmover_request) dmb_pendreqs
480This is the queue of pending requests.
481.It int dmb_npendreqs
482This is the number of requests in the
483.Em dmb_pendreqs
484queue.
485.El
486.Pp
487If an error occurs when processing the request, the
488.Em DMOVER_REQ_ERROR
489bit must be set in the
490.Em dreq_flags
491member of the request, and the
492.Em dreq_error
493member set to an
494.Xr errno 2
495value to indicate the error.
496.Pp
497When the back-end has finished processing the request, it must call
498the
499.Fn dmover_done
500function.  This function eventually invokes the client's call-back
501routine.
502.Pp
503If a hardware-assisted data mover uses interrupts, the interrupt handlers
504should be registered at IPL_BIO.
505.Pp
506The following functions are provided to the back-ends:
507.Bl -tag -width "XXXX"
508.It void Fn dmover_backend_register "struct dmover_backend *backend"
509.Pp
510The
511.Fn dmover_backend_register
512function registers the back-end
513.Fa backend
514with the
515.Nm dmover
516facility.
517.It void Fn dmover_backend_unregister "struct dmover_backend *backend"
518.Pp
519The
520.Fn dmover_backend_unregister
521function removes the back-end
522.Fa backend
523from the
524.Nm dmover
525facility.  The back-end must already be registered.
526.It void Fn dmover_done "struct dmover_request *req"
527.Pp
528The
529.Fn dmover_done
530function is called by the back-end when it has finished processing
531a request, whether the request completed successfully or not.
532.El
533.Pp
534The
535.Fn dmover_backend_register
536and
537.Fn dmover_backend_unregister
538functions must not be called from interrupt context.
539.Pp
540The
541.Fn dmover_done
542function may be called at
543.Em IPL_BIO ,
544.Em IPL_SOFTCLOCK ,
545.Em IPL_SOFTNET ,
546or in non-interrupt context.
547.Sh EXAMPLES
548The following is an example of a client using
549.Nm dmover
550to zero-fill a region of memory.  In this example, the CPU will be
551able to context switch to another thread and perform work while the
552hardware-assisted data mover clears the specified block of memory.
553.Bd -literal
554int
555hw_bzero(void *buf, size_t len)
556{
557	struct dmover_session *dses;
558	struct dmover_request *dreq;
559	int error;
560
561	error = dmover_session_create(DMOVER_FUNC_ZERO, &dses);
562	if (error)
563		return (error);
564
565	dreq = dmover_request_alloc(dses, NULL);
566	if (dreq == NULL) {
567		dmover_session_destroy(dses);
568		return (ENOMEM);
569	}
570
571	dreq->dreq_flags = DMOVER_REQ_WAIT;
572	dreq->dreq_callback = NULL;
573	dreq->dreq_outbuf.dreq_outbuf_type = DMOVER_BUF_LINEAR;
574	dreq->dreq_outbuf.dreq_outbuf_linear = buf;
575	dreq->dreq_outbuf.dreq_outbuf_len = len;
576
577	dmover_process(dreq);
578
579	error = (dreq->dreq_flags & DMOVER_REQ_ERROR) ?
580	    dreq->dreq_error : 0;
581
582	dmover_request_free(dreq, NULL);
583	dmover_session_destroy(dses);
584
585	return (error);
586}
587.Ed
588.Sh SEE ALSO
589.Xr queue 3 ,
590.Xr dmoverio 4
591.Sh HISTORY
592The
593.Nm dmover
594facility first appeared in
595.Nx 2.0 .
596.Sh AUTHORS
597The
598.Nm dmover
599facility was designed and implemented by
600.An Jason R. Thorpe
601.Aq thorpej@wasabisystems.com
602and contributed by Wasabi Systems, Inc.
603.Sh BUGS
604The mechanism by which a back-end should advertise its performance to
605the request scheduler is not well-defined.  Therefore, the load-balancing
606mechanism within the request scheduler is also not well-defined.
607