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