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