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