summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@fingolfin.org>2019-12-18 06:18:35 +0000
committerRobert Mustacchi <rm@fingolfin.org>2020-01-31 19:47:17 +0000
commit9a63ec2733c93e3ee31e95779a4f2f45a57eda59 (patch)
treea9d528bb69cde12db927f721fe42fabbe63c8d9a
parent31ad075e90bf5afda8ab4b8cc4d3ca3e89946115 (diff)
downloadillumos-joyent-9a63ec2733c93e3ee31e95779a4f2f45a57eda59.tar.gz
12183 Want new IPD 13 DMA Cookie APIs
Reviewed by: Alex Wilson <alex@uq.edu.au> Reviewed by: Paul Winder <paul@winders.demon.co.uk> Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> Reviewed by: Garrett D'Amore <garrett@damore.org> Approved by: Garrett D'Amore <garrett@damore.org>
-rw-r--r--usr/src/man/man9f/Intro.9f4
-rw-r--r--usr/src/man/man9f/Makefile11
-rw-r--r--usr/src/man/man9f/ddi_dma_addr_bind_handle.9f36
-rw-r--r--usr/src/man/man9f/ddi_dma_buf_bind_handle.9f34
-rw-r--r--usr/src/man/man9f/ddi_dma_cookie_iter.9f282
-rw-r--r--usr/src/man/man9f/ddi_dma_getwin.9f32
-rw-r--r--usr/src/man/man9f/ddi_dma_nextcookie.9f104
-rw-r--r--usr/src/man/man9f/ddi_dmae.9f21
-rw-r--r--usr/src/pkg/manifests/system-kernel.man9f.inc6
-rw-r--r--usr/src/uts/common/io/scsi/impl/scsi_resource.c1
-rw-r--r--usr/src/uts/common/os/sunddi.c98
-rw-r--r--usr/src/uts/common/sys/ddi_impldefs.h4
-rw-r--r--usr/src/uts/common/sys/sunddi.h14
-rw-r--r--usr/src/uts/i86pc/io/rootnex.c13
-rw-r--r--usr/src/uts/sun4/io/px/px.c12
-rw-r--r--usr/src/uts/sun4/io/px/px_dma.c6
-rw-r--r--usr/src/uts/sun4u/io/pci/pci.c12
-rw-r--r--usr/src/uts/sun4u/io/pci/pci_dma.c6
-rw-r--r--usr/src/uts/sun4v/io/niumx/niumx.c5
19 files changed, 526 insertions, 175 deletions
diff --git a/usr/src/man/man9f/Intro.9f b/usr/src/man/man9f/Intro.9f
index ba32b2978e..3b72a53425 100644
--- a/usr/src/man/man9f/Intro.9f
+++ b/usr/src/man/man9f/Intro.9f
@@ -356,10 +356,14 @@ _
\fBddi_dma_alloc_handle\fR illumos DDI
\fBddi_dma_buf_bind_handle\fR illumos DDI
\fBddi_dma_burstsizes\fR illumos DDI
+\fBddi_dma_cookie_get\fR illumos DDI
+\fBddi_dma_cookie_next\fR illumos DDI
+\fBddi_dma_cookie_one\fR illumos DDI
\fBddi_dma_free_handle\fR illumos DDI
\fBddi_dma_getwin\fR illumos DDI
\fBddi_dma_mem_alloc\fR illumos DDI
\fBddi_dma_mem_free\fR illumos DDI
+\fBddi_dma_ncookies\fR illumos DDI
\fBddi_dma_nextcookie\fR illumos DDI
\fBddi_dma_numwin\fR illumos DDI
\fBddi_dma_set_sbus64\fR illumos DDI
diff --git a/usr/src/man/man9f/Makefile b/usr/src/man/man9f/Makefile
index 825dab0e0c..24d74a300e 100644
--- a/usr/src/man/man9f/Makefile
+++ b/usr/src/man/man9f/Makefile
@@ -154,11 +154,11 @@ MANFILES= ASSERT.9f \
ddi_dma_alloc_handle.9f \
ddi_dma_buf_bind_handle.9f \
ddi_dma_burstsizes.9f \
+ ddi_dma_cookie_iter.9f \
ddi_dma_free_handle.9f \
ddi_dma_getwin.9f \
ddi_dma_mem_alloc.9f \
ddi_dma_mem_free.9f \
- ddi_dma_nextcookie.9f \
ddi_dma_numwin.9f \
ddi_dma_set_sbus64.9f \
ddi_dma_sync.9f \
@@ -748,6 +748,10 @@ MANLINKS= AVL_NEXT.9f \
ddi_devid_unregister.9f \
ddi_devid_valid.9f \
ddi_devmap_segmap.9f \
+ ddi_dma_cookie_get.9f \
+ ddi_dma_cookie_one.9f \
+ ddi_dma_ncookies.9f \
+ ddi_dma_nextcookie.9f \
ddi_dmae_1stparty.9f \
ddi_dmae_alloc.9f \
ddi_dmae_disable.9f \
@@ -1557,6 +1561,11 @@ ddi_devid_str_free.9f := LINKSRC = ddi_devid_compare.9f
ddi_devid_unregister.9f := LINKSRC = ddi_devid_compare.9f
ddi_devid_valid.9f := LINKSRC = ddi_devid_compare.9f
+ddi_dma_cookie_get.9f := LINKSRC = ddi_dma_cookie_iter.9f
+ddi_dma_cookie_one.9f := LINKSRC = ddi_dma_cookie_iter.9f
+ddi_dma_ncookies.9f := LINKSRC = ddi_dma_cookie_iter.9f
+ddi_dma_nextcookie.9f := LINKSRC = ddi_dma_cookie_iter.9f
+
ddi_dmae_1stparty.9f := LINKSRC = ddi_dmae.9f
ddi_dmae_alloc.9f := LINKSRC = ddi_dmae.9f
ddi_dmae_disable.9f := LINKSRC = ddi_dmae.9f
diff --git a/usr/src/man/man9f/ddi_dma_addr_bind_handle.9f b/usr/src/man/man9f/ddi_dma_addr_bind_handle.9f
index 71f9a00354..fa94c3cdf5 100644
--- a/usr/src/man/man9f/ddi_dma_addr_bind_handle.9f
+++ b/usr/src/man/man9f/ddi_dma_addr_bind_handle.9f
@@ -3,7 +3,7 @@
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH DDI_DMA_ADDR_BIND_HANDLE 9F "Jul 26, 1996"
+.TH DDI_DMA_ADDR_BIND_HANDLE 9F "Jan 18, 2020"
.SH NAME
ddi_dma_addr_bind_handle \- binds an address to a DMA handle
.SH SYNOPSIS
@@ -20,11 +20,9 @@ ddi_dma_addr_bind_handle \- binds an address to a DMA handle
.fi
.SH INTERFACE LEVEL
-.sp
.LP
Solaris DDI specific (Solaris DDI).
.SH PARAMETERS
-.sp
.ne 2
.na
\fB\fIhandle\fR \fR
@@ -178,7 +176,8 @@ function is specified.
\fB\fIcookiep\fR \fR
.ad
.RS 13n
-A pointer to the first \fBddi_dma_cookie\fR(9S) structure.
+A pointer to the first \fBddi_dma_cookie\fR(9S) structure. This should
+be left as \fBNULL\fR in new callers.
.RE
.sp
@@ -188,11 +187,12 @@ A pointer to the first \fBddi_dma_cookie\fR(9S) structure.
.ad
.RS 13n
Upon a successful return, \fIccountp\fR points to a value representing the
-number of cookies for this \fBDMA\fR object.
+number of cookies for this \fBDMA\fR object. This can
+be left as \fBNULL\fR in new callers. The cookie count can be obtained
+by calling \fBddi_dma_ncookies\fR(9F).
.RE
.SH DESCRIPTION
-.sp
.LP
\fBddi_dma_addr_bind_handle()\fR allocates \fBDMA\fR resources for a memory
object such that a device can perform \fBDMA\fR to or from the object.
@@ -200,12 +200,15 @@ object such that a device can perform \fBDMA\fR to or from the object.
as expressed by \fBddi_dma_attr\fR(9S) (see \fBddi_dma_alloc_handle\fR(9F)).
.sp
.LP
-\fBddi_dma_addr_bind_handle()\fR fills in the first \fBDMA\fR cookie pointed to
-by \fIcookiep\fR with the appropriate address, length, and bus type.
-\fB*\fR\fIccountp\fR is set to the number of \fBDMA\fR cookies representing
-this \fBDMA\fR object. Subsequent \fBDMA\fR cookies must be retrieved by
-calling \fBddi_dma_nextcookie\fR(9F) the number of times specified by
-\fB*\fR\fIcountp\fR-1.
+\fBddi_dma_addr_bind_handle()\fR allocates and associates a number of
+\fBDMA\fR cookies with \fIhandle\fR. To get the total number of
+cookies, callers should use the \fBddi_dma_ncookies\fR(9F) function. To
+get all of the cookies, callers should use the
+\fBddi_dma_cookie_iter\fR(9F) or \fBddi_dma_cookie_get\fR(9F) functions.
+Callers should pass \fBNULL\fR for \fIcookiep\fR and \fIccountp\fR.
+These values are required if using the deprecated
+\fBddi_dma_nextcookie\fR(9F) interface, in which case \fIcookiep\fR is
+filled in with the first \fBddi_dma_cookie\fR(9S) structure.
.sp
.LP
When a \fBDMA\fR transfer completes, the driver frees up system \fBDMA\fR
@@ -307,7 +310,6 @@ functions accessible from interrupt context are be available. The callback
function must take whatever steps are necessary to protect its critical
resources, data structures, queues, and so on.
.SH RETURN VALUES
-.sp
.LP
\fBddi_dma_addr_bind_handle()\fR returns:
.sp
@@ -369,24 +371,22 @@ configuration.
.RE
.SH CONTEXT
-.sp
.LP
\fBddi_dma_addr_bind_handle()\fR can be called from user, kernel, or interrupt
context, except when \fIcallback\fR is set to \fBDDI_DMA_SLEEP\fR, in which
case it can only be called from user or kernel context.
.SH SEE ALSO
-.sp
.LP
-\fBddi_dma_alloc_handle\fR(9F), \fBddi_dma_free_handle\fR(9F),
+\fBddi_dma_alloc_handle\fR(9F), \fBddi_dma_cookie_get\fR(9F),
+\fBddi_dma_cookie_iter\fR(9F), \fBddi_dma_free_handle\fR(9F),
\fBddi_dma_getwin\fR(9F), \fBddi_dma_mem_alloc\fR(9F),
-\fBddi_dma_mem_free\fR(9F), \fBddi_dma_nextcookie\fR(9F),
+\fBddi_dma_mem_free\fR(9F), \fBddi_dma_ncookies\fR(9F),
\fBddi_dma_sync\fR(9F), \fBddi_dma_unbind_handle\fR(9F),
\fBddi_umem_iosetup\fR(9F), \fBddi_dma_attr\fR(9S), \fBddi_dma_cookie\fR(9S)
.sp
.LP
\fIWriting Device Drivers\fR
.SH NOTES
-.sp
.LP
If the driver permits partial mapping with the \fBDDI_DMA_PARTIAL\fR flag, the
number of cookies in each window may exceed the size of the device's
diff --git a/usr/src/man/man9f/ddi_dma_buf_bind_handle.9f b/usr/src/man/man9f/ddi_dma_buf_bind_handle.9f
index 5b8265605e..e68135a8bd 100644
--- a/usr/src/man/man9f/ddi_dma_buf_bind_handle.9f
+++ b/usr/src/man/man9f/ddi_dma_buf_bind_handle.9f
@@ -3,7 +3,7 @@
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH DDI_DMA_BUF_BIND_HANDLE 9F "Jul 27, 1996"
+.TH DDI_DMA_BUF_BIND_HANDLE 9F "Jan 18, 2020"
.SH NAME
ddi_dma_buf_bind_handle \- binds a system buffer to a DMA handle
.SH SYNOPSIS
@@ -20,11 +20,9 @@ ddi_dma_buf_bind_handle \- binds a system buffer to a DMA handle
.fi
.SH INTERFACE LEVEL
-.sp
.LP
Solaris DDI specific (Solaris DDI).
.SH PARAMETERS
-.sp
.ne 2
.na
\fB\fIhandle\fR\fR
@@ -159,7 +157,8 @@ function is specified.
\fB\fIcookiep\fR\fR
.ad
.RS 12n
-A pointer to the first \fBddi_dma_cookie\fR(9S) structure.
+A pointer to the first \fBddi_dma_cookie\fR(9S) structure. This should
+be left as \fBNULL\fR in new callers.
.RE
.sp
@@ -169,11 +168,12 @@ A pointer to the first \fBddi_dma_cookie\fR(9S) structure.
.ad
.RS 12n
Upon a successful return, \fIccountp\fR points to a value representing the
-number of cookies for this \fBDMA\fR object.
+number of cookies for this \fBDMA\fR object. This can
+be left as \fBNULL\fR in new callers. The cookie count can be obtained
+by calling \fBddi_dma_ncookies\fR(9F).
.RE
.SH DESCRIPTION
-.sp
.LP
\fBddi_dma_buf_bind_handle()\fR allocates \fBDMA\fR resources for a system
buffer such that a device can perform \fBDMA\fR to or from the buffer.
@@ -181,11 +181,16 @@ buffer such that a device can perform \fBDMA\fR to or from the buffer.
as expressed by \fBddi_dma_attr\fR(9S) (see \fBddi_dma_alloc_handle\fR(9F)).
.sp
.LP
-\fBddi_dma_buf_bind_handle()\fR fills in the first \fBDMA\fR cookie pointed to
-by \fIcookiep\fR with the appropriate address, length, and bus type.
-\fB*\fR\fIccountp\fR is set to the number of \fBDMA\fR cookies representing
-this \fBDMA\fR object. Subsequent \fBDMA\fR cookies must be retrieved by
-calling \fBddi_dma_nextcookie\fR(9F) \fB*\fR\fIcountp\fR-1 times.
+\fBddi_dma_buf_bind_handle()\fR allocates and associates a number of
+\fBDMA\fR cookies with \fIhandle\fR. To get the total number of
+cookies, callers should use the \fBddi_dma_ncookies\fR(9F) function. To
+get all of the cookies, callers should use the
+\fBddi_dma_cookie_iter\fR(9F) or \fBddi_dma_cookie_get\fR(9F) functions.
+Callers should pass \fBNULL\fR for \fIcookiep\fR and \fIccountp\fR.
+These values are required if using the deprecated
+\fBddi_dma_nextcookie\fR(9F) interface, in which case \fIcookiep\fR is
+filled in with the first \fBddi_dma_cookie\fR(9S) structure.
+
.sp
.LP
When a \fBDMA\fR transfer completes, the driver should free up system \fBDMA\fR
@@ -287,7 +292,6 @@ functions accessible from interrupt context are be available. The callback
function must take whatever steps necessary to protect its critical resources,
data structures, queues, etc.
.SH RETURN VALUES
-.sp
.LP
\fBddi_dma_buf_bind_handle()\fR returns:
.sp
@@ -349,24 +353,22 @@ configuration.
.RE
.SH CONTEXT
-.sp
.LP
\fBddi_dma_buf_bind_handle()\fR can be called from user, kernel, or interrupt
context, except when \fIcallback\fR is set to \fBDDI_DMA_SLEEP\fR, in which
case it can be called from user or kernel context only.
.SH SEE ALSO
-.sp
.LP
\fBddi_dma_addr_bind_handle\fR(9F), \fBddi_dma_alloc_handle\fR(9F),
+\fBddi_dma_cookie_get\fR(9F), \fBddi_dma_cookie_iter\fR(9F),
\fBddi_dma_free_handle\fR(9F), \fBddi_dma_getwin\fR(9F),
-\fBddi_dma_nextcookie\fR(9F), \fBddi_dma_sync\fR(9F),
+\fBddi_dma_ncookies\fR(9F), \fBddi_dma_sync\fR(9F),
\fBddi_dma_unbind_handle\fR(9F), \fBbuf\fR(9S), \fBddi_dma_attr\fR(9S),
\fBddi_dma_cookie\fR(9S)
.sp
.LP
\fIWriting Device Drivers\fR
.SH NOTES
-.sp
.LP
If the driver permits partial mapping with the \fBDDI_DMA_PARTIAL\fR flag, the
number of cookies in each window may exceed the size of the device's
diff --git a/usr/src/man/man9f/ddi_dma_cookie_iter.9f b/usr/src/man/man9f/ddi_dma_cookie_iter.9f
new file mode 100644
index 0000000000..5f10d4fcf2
--- /dev/null
+++ b/usr/src/man/man9f/ddi_dma_cookie_iter.9f
@@ -0,0 +1,282 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2019 Robert Mustacchi
+.\"
+.Dd December 9, 2019
+.Dt DDI_DMA_COOKIE_ITER 9F
+.Os
+.Sh NAME
+.Nm ddi_dma_cookie_get ,
+.Nm ddi_dma_cookie_iter ,
+.Nm ddi_dma_cookie_one ,
+.Nm ddi_dma_ncookies ,
+.Nm ddi_dma_nextcookie
+.Nd retrieve DMA cookies
+.Sh SYNOPSIS
+.In sys/ddi.h
+.In sys/sunddi.h
+.Ft "const ddi_dma_cookie_t *"
+.Fo ddi_dma_cookie_iter
+.Fa "ddi_dma_handle_t handle"
+.Fa "const ddi_dma_cookie_t *cookiep"
+.Fc
+.Ft "const ddi_dma_cookie_t *"
+.Fo ddi_dma_cookie_get
+.Fa "ddi_dma_handle_t handle"
+.Fa "uint_t index"
+.Fc
+.Ft "const ddi_dma_cookie_t *"
+.Fo ddi_dma_cookie_one
+.Fa "ddi_dma_handle_t handle"
+.Fc
+.Ft "uint_t"
+.Fo ddi_dma_ncookies
+.Fa "ddi_dma_handle_t handle"
+.Fc
+.Ft void
+.Fo ddi_dma_nextcookie
+.Fa "ddi_dma_handle_t handle"
+.Fa "ddi_dma_cookie_t *cookiep"
+.Fc
+.Sh PARAMETERS
+.Bl -tag -width Fa
+.It Fa handle
+The DMA handle obtained by a call to
+.Xr ddi_dma_alloc_handle 9F .
+.It Fa cookie
+A pointer to a
+.Xr ddi_dma_cookie 9S
+structure.
+.It Fa index
+An unsigned integer that represents the index of a cookie to obtain.
+The first entry is at index zero.
+.El
+.Sh DESCRIPTION
+The
+.Fn ddi_dma_cookie_iter ,
+.Fn ddi_dma_cookie_get ,
+and
+.Fn ddi_dma_cookie_one
+functions obtain information about DMA cookies.
+When a DMA request, represented by the DMA handle
+.Fa handle ,
+has been bound to a series of addresses with the
+.Xr ddi_dma_addr_bind_handle 9F
+or
+.Xr ddi_dma_buf_bind_handle 9F
+functions, the resulting addresses are stored in one or more
+.Xr ddi_dma_cookie 9S
+structures.
+the three different functions provide different ways to obtain cookies
+and are safe alternatives to the unsafe
+.Fn ddi_dma_nextcookie
+function.
+To see how to use these functions, please see the
+.Sx EXAMPLES
+section.
+.Pp
+The
+.Fn ddi_dma_cookie_iter
+function provides a way to iterate over all the cookies that are
+associated with the DMA handle
+.Fa handle .
+To get the first handle, pass
+.Dv NULL
+in
+.Fa cookiep .
+Do not use the DMA cookie returned from either of the
+.Xr ddi_dma_addr_bind_handle 9F
+or
+.Xr ddi_dma_buf_bind_handle 9F
+functions.
+To get subsequent cookies, pass the returned cookie as the argument
+.Fa cookiep .
+When the function returns
+.Dv NULL
+then that indicates that the last handle has been iterated over.
+.Pp
+The
+.Fn ddi_dma_cookie_get
+function returns a specific cookie.
+The
+.Fa index
+indicates which of the cookies should be returned.
+The first cookie is at index
+.Sy 0 .
+If an invalid index is specified, the function returns
+.Dv NULL .
+.Pp
+The
+.Ft ddi_dma_cookie_one
+function is a convenience function for DMA requests that have a single
+cookie.
+This function always returns the single cookie assosciated with the DMA
+handle
+.Fa handle .
+If this function is used when there is a DMA request with multiple
+cookies, then it will panic the system.
+It can never return
+.Dv NULL .
+.Pp
+The
+.Fn ddi_dma_ncookies
+function returns the number of DMA cookies that are associated with the
+DMA handle
+.Fa handle .
+If there are no DMA resources bound to the handle, then this will return
+.Sy 0 .
+.Pp
+The
+.Fn ddi_dma_nextcookie
+function was the historical function that was associated with obtaining
+DMA cookies.
+It should not be used due to several flaws.
+The
+.Fn ddi_dma_nextcookie
+function mutates the underlying DMA handle meaning that a driver cannot
+obtain a cookie a second time and thus a device driver using this
+interface must either manually keep storage of the cookie around wasting
+space or rebind the handle, wasting time.
+In addition, there is no way for the function to indicate that a driver
+has consumed all of its cookies.
+If for some reason a device driver calls the
+.Fn ddi_dma_nextcookie
+function more times than there are cookies, the results are undefined.
+In short, this function should not be used for any purpose.
+Use the
+.Fn ddi_dma_cookie_iter ,
+.Fn ddi_dma_cookie_get ,
+or
+.Fn ddi_dma_cookie_one
+functions instead.
+.Sh CONTEXT
+The
+.Fn ddi_dma_cookie_iter ,
+.Fn ddi_dma_cookie_get ,
+.Fn ddi_dma_cookie_one ,
+.Fn ddi_dma_ncookies ,
+and
+.Fn ddi_dma_nextcookie
+functions may be called from
+.Sy user ,
+.Sy kernel ,
+or
+.Sy interrupt
+context.
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn ddi_dma_cookie_iter ,
+.Fn ddi_dma_cookie_get ,
+.Fn ddi_dma_cookie_one
+functions will return the requested DMA cookie.
+If there are no more cookies, or
+.Fa coookiep
+is invalid, the
+.Fn ddi_dma_cookie_iter
+function will return
+.Dv NULL .
+If
+.Fa index
+does not correspond to a valid cookie, the
+.Fn ddi_dma_cookie_get
+function will return
+.Dv NULL .
+If there is not exactly one DMA cookie, or another issue occurs, then the
+.Fn ddi_dma_cookie_one
+function will panic the system.
+.Pp
+Upon successful completion, the
+.Fn ddi_dma_ncookies
+function returns the number of cookies associated with
+.Fa handle .
+If there are none, then
+.Sy 0
+is returned.
+.Pp
+The
+.Fn ddi_dma_nextcookie
+function always updates
+.Fa cookiep
+regardless of whether it is valid or not.
+.Sh EXAMPLES
+.Sy Example 1
+Using the
+.Fn ddi_dma_cookie_iter
+function to obtain all DMA cookies.
+.Bd -literal
+/*
+ * This example assumes that either ddi_dma_addr_bind_handle() or
+ * ddi_dma_buf_bind_handle() has already been successfully called.
+ */
+void
+program_dma(ddi_dma_handle_t handle)
+{
+ const ddi_dma_cookie_t *c;
+
+ for (cookie = ddi_dma_cookie_iter(handle, NULL); c != NULL;
+ c = ddi_dma_cookie_iter(handle, c)) {
+ /*
+ * Use the dmac_laddress and dmac_size members to
+ * properly program the device or descriptor rings.
+ */
+ }
+}
+.Ed
+.Pp
+.Sy Example 2
+Using the
+.Fn ddi_dma_cookie_get
+function.
+.Bd -literal
+/*
+ * This example assumes that either ddi_dma_mem_alloc() has already
+ * been successfully called.
+ */
+int
+bind_dma(ddi_dma_handle_t handle, void *addr, size_t len)
+{
+ int ret;
+ uint_t i, ncookies;
+ ddi_dma_cookie_t first;
+
+ ret = ddi_dma_addr_bind_handle(handle, NULL, addr, len,
+ DDI_DMA_RDWR | DDI_DMA_CONSISTENT, NULL, NULL, &first,
+ &ncookies);
+ if (ret != DDI_DMA_MAPPED) {
+ return (ret);
+ }
+
+ /*
+ * A driver doesn't need to store ncookies. It can get it again
+ * by simply calling ddi_dma_ncookies() and using the result in
+ * place of ncookies from ddi_dma_addr_bind_handle().
+ */
+ for (i = 0; i < ncookies; i++) {
+ const ddi_dma_cookie_t *cookie;
+
+ cookie = ddi_dma_coookie_get(handle, i);
+ /*
+ * Use the dmac_laddress and dmac_size members to
+ * properly program the device or descriptor rings.
+ */
+ }
+}
+.Ed
+.Sh SEE ALSO
+.Xr ddi_dma_addr_bind_handle 9F ,
+.Xr ddi_dma_alloc_handle 9F ,
+.Xr ddi_dma_buf_bind_handle 9F ,
+.Xr ddi_dma_unbind_handle 9F ,
+.Xr ddi_dma_cookie 9S
+.Rs
+.%T Writing Device Drivers
+.Re
diff --git a/usr/src/man/man9f/ddi_dma_getwin.9f b/usr/src/man/man9f/ddi_dma_getwin.9f
index b092ae66e9..aee028587d 100644
--- a/usr/src/man/man9f/ddi_dma_getwin.9f
+++ b/usr/src/man/man9f/ddi_dma_getwin.9f
@@ -3,7 +3,7 @@
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH DDI_DMA_GETWIN 9F "Nov 15, 1996"
+.TH DDI_DMA_GETWIN 9F "Jan 18, 2020"
.SH NAME
ddi_dma_getwin \- activate a new DMA window
.SH SYNOPSIS
@@ -20,11 +20,9 @@ ddi_dma_getwin \- activate a new DMA window
.fi
.SH INTERFACE LEVEL
-.sp
.LP
Solaris DDI specific (Solaris DDI).
.SH PARAMETERS
-.sp
.ne 2
.na
\fB\fIhandle\fR \fR
@@ -69,7 +67,8 @@ current window.
\fB\fIcookiep\fR \fR
.ad
.RS 12n
-A pointer to the first \fBddi_dma_cookie\fR(9S) structure.
+A pointer to the first \fBddi_dma_cookie\fR(9S) structure. This should
+be left as \fBNULL\fR in new callers.
.RE
.sp
@@ -79,11 +78,12 @@ A pointer to the first \fBddi_dma_cookie\fR(9S) structure.
.ad
.RS 12n
Upon a successful return, \fIccountp\fR will contain the number of cookies for
-this \fBDMA\fR window.
+this \fBDMA\fR window. This can
+be left as \fBNULL\fR in new callers. The cookie count can be obtained
+by calling \fBddi_dma_ncookies\fR(9F).
.RE
.SH DESCRIPTION
-.sp
.LP
\fBddi_dma_getwin()\fR activates a new \fBDMA\fR window. If a \fBDMA\fR
resource allocation request returns \fBDDI_DMA_PARTIAL_MAP\fR indicating that
@@ -97,11 +97,15 @@ window number from the range \fI[0..N-1]\fR as the parameter \fIwin\fR and
makes it the current \fBDMA\fR window.
.sp
.LP
-\fBddi_dma_getwin()\fR fills in the first \fBDMA\fR cookie pointed to by
-\fIcookiep\fR with the appropriate address, length, and bus type.
-\fB*\fR\fIccountp\fR is set to the number of \fBDMA\fR cookies representing
-this \fBDMA \fRobject. Subsequent \fBDMA\fR cookies must be retrieved using
-\fBddi_dma_nextcookie\fR(9F).
+\fBddi_dma_getwin()\fR allocates and assosciates a number of
+\fBDMA\fR cookies with \fIhandle\fR. To get the total number of
+cookies, callers should use the \fBddi_dma_ncookies\fR(9F) function. To
+get all of the cookies, callers should use the
+\fBddi_dma_cookie_iter\fR(9F) or \fBddi_dma_cookie_get\fR(9F) functions.
+Callers should pass \fBNULL\fR for \fIcookiep\fR and \fIccountp\fR.
+These values are required if using the deprecated
+\fBddi_dma_nextcookie\fR(9F) interface, in which case \fIcookiep\fR is
+filled in with the first \fBddi_dma_cookie\fR(9S) structure.
.sp
.LP
\fBddi_dma_getwin()\fR takes care of underlying resource synchronizations
@@ -118,7 +122,6 @@ the interrupt routine returns without invoking another \fBDMA\fR transfer.
Otherwise, it calls \fBddi_dma_getwin()\fR to shift the current window and
start another \fBDMA\fR transfer.
.SH RETURN VALUES
-.sp
.LP
\fBddi_dma_getwin()\fR returns:
.sp
@@ -140,14 +143,13 @@ Resources for the specified \fBDMA\fR window are allocated.
.RE
.SH CONTEXT
-.sp
.LP
\fBddi_dma_getwin()\fR can be called from user, kernel, or interrupt context.
.SH SEE ALSO
-.sp
.LP
\fBddi_dma_addr_bind_handle\fR(9F), \fBddi_dma_alloc_handle\fR(9F),
-\fBddi_dma_buf_bind_handle\fR(9F), \fBddi_dma_nextcookie\fR(9F),
+\fBddi_dma_buf_bind_handle\fR(9F), \fBddi_dma_cookie_get\fR(9F),
+\fBddi_dma_cookie_iter\fR(9F), \fBddi_dma_ncookies\fR(9F),
\fBddi_dma_numwin\fR(9F), \fBddi_dma_sync\fR(9F),
\fBddi_dma_unbind_handle\fR(9F), \fBddi_dma_cookie\fR(9S)
.sp
diff --git a/usr/src/man/man9f/ddi_dma_nextcookie.9f b/usr/src/man/man9f/ddi_dma_nextcookie.9f
deleted file mode 100644
index 527e2b8361..0000000000
--- a/usr/src/man/man9f/ddi_dma_nextcookie.9f
+++ /dev/null
@@ -1,104 +0,0 @@
-'\" te
-.\" Copyright (c) 1994, Sun Microsystems, Inc.
-.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
-.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
-.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH DDI_DMA_NEXTCOOKIE 9F "Sep 26, 1994"
-.SH NAME
-ddi_dma_nextcookie \- retrieve subsequent DMA cookie
-.SH SYNOPSIS
-.LP
-.nf
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-
-
-
-\fBvoid\fR \fBddi_dma_nextcookie\fR(\fBddi_dma_handle_t\fR \fIhandle\fR,
- \fBddi_dma_cookie_t *\fR\fIcookiep\fR);
-.fi
-
-.SH PARAMETERS
-.sp
-.ne 2
-.na
-\fB\fIhandle\fR\fR
-.ad
-.RS 11n
-The handle previously allocated by a call to \fBddi_dma_alloc_handle\fR(9F).
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fIcookiep\fR\fR
-.ad
-.RS 11n
-A pointer to a \fBddi_dma_cookie\fR(9S) structure.
-.RE
-
-.SH INTERFACE LEVEL
-.sp
-.LP
-Solaris DDI specific (Solaris DDI).
-.SH DESCRIPTION
-.sp
-.LP
-\fBddi_dma_nextcookie()\fR retrieves subsequent \fBDMA\fR cookies for a
-\fBDMA\fR object. \fBddi_dma_nextcookie()\fR fills in the
-\fBddi_dma_cookie\fR(9S) structure pointed to by \fIcookiep\fR. The
-\fBddi_dma_cookie\fR(9S) structure must be allocated prior to calling
-\fBddi_dma_nextcookie()\fR.
-.sp
-.LP
-The \fBDMA\fR cookie count returned by \fBddi_dma_buf_bind_handle\fR(9F),
-\fBddi_dma_addr_bind_handle\fR(9F), or \fBddi_dma_getwin\fR(9F) indicates the
-number of \fBDMA\fR cookies a \fBDMA\fR object consists of. If the resulting
-cookie count, \fIN\fR, is larger than 1, \fBddi_dma_nextcookie()\fR must be
-called \fIN\fR-1 times to retrieve all \fBDMA\fR cookies.
-.SH CONTEXT
-.sp
-.LP
-\fBddi_dma_nextcookie()\fR can be called from user, kernel, or interrupt
-context.
-.SH EXAMPLES
-.LP
-\fBExample 1 \fRProcess a scatter-gather list of I/O requests.
-.sp
-.LP
-This example demonstrates the use of \fBddi_dma_nextcookie()\fR to process a
-scatter-gather list of I/O requests.
-
-.sp
-.in +2
-.nf
-/* setup scatter-gather list with multiple DMA cookies */
-ddi_dma_cookie_t dmacookie;
-uint_t ccount;
-\&...
-
-status = ddi_dma_buf_bind_handle(handle, bp, DDI_DMA_READ,
- NULL, NULL, &dmacookie, &ccount);
-
-if (status == DDI_DMA_MAPPED) {
-
- /* program DMA engine with first cookie */
-
- while (--ccount > 0) {
- ddi_dma_nextcookie(handle, &dmacookie);
- /* program DMA engine with next cookie */
- }
-}
-\&...
-.fi
-.in -2
-
-.SH SEE ALSO
-.sp
-.LP
-\fBddi_dma_addr_bind_handle\fR(9F), \fBddi_dma_alloc_handle\fR(9F),
-\fBddi_dma_buf_bind_handle\fR(9F), \fBddi_dma_unbind_handle\fR(9F),
-\fBddi_dma_cookie\fR(9S)
-.sp
-.LP
-\fIWriting Device Drivers\fR
diff --git a/usr/src/man/man9f/ddi_dmae.9f b/usr/src/man/man9f/ddi_dmae.9f
index 27f045114c..8bb2d955bd 100644
--- a/usr/src/man/man9f/ddi_dmae.9f
+++ b/usr/src/man/man9f/ddi_dmae.9f
@@ -4,7 +4,7 @@
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH DDI_DMAE 9F "May 24, 2014"
+.TH DDI_DMAE 9F "Jan 18, 2020"
.SH NAME
ddi_dmae, ddi_dmae_alloc, ddi_dmae_release, ddi_dmae_prog, ddi_dmae_disable,
ddi_dmae_enable, ddi_dmae_stop, ddi_dmae_getcnt, ddi_dmae_1stparty,
@@ -58,11 +58,9 @@ ddi_dmae_getattr \- system DMA engine functions
.fi
.SH INTERFACE LEVEL
-.sp
.LP
Solaris DDI specific (Solaris DDI).
.SH PARAMETERS
-.sp
.ne 2
.na
\fB\fIdip\fR\fR
@@ -157,7 +155,6 @@ A pointer to a \fBDMA \fR attribute structure. See \fBddi_dma_attr\fR(9S).
.RE
.SH DESCRIPTION
-.sp
.LP
There are three possible ways that a device can perform \fBDMA\fR engine
functions:
@@ -201,7 +198,6 @@ configuration is necessary to enable this mode.
.RE
.SS "\fBddi_dmae_alloc()\fR"
-.sp
.LP
The \fBddi_dmae_alloc()\fR function is used to acquire a \fBDMA\fR channel of
the system \fBDMA\fR engine. \fBddi_dmae_alloc()\fR allows only one device at a
@@ -228,7 +224,6 @@ the value \fBDDI_DMA_CALLBACK_DONE\fR. If it tries to allocate the channel but
fails to do so, it must return the value \fBDDI_DMA_CALLBACK_RUNOUT\fR. In this
case, the callback function is put back on a list to be called again later.
.SS "\fBddi_dmae_prog()\fR"
-.sp
.LP
The \fBddi_dmae_prog()\fR function programs the \fBDMA\fR channel for a
\fBDMA\fR transfer. The \fBddi_dmae_req\fR structure contains all the
@@ -250,30 +245,25 @@ resources using \fBDMA\fR setup functions such as \fBddi_dma_mem_alloc\fR(9F).
contains the address and count. Then this cookie is passed to
\fBddi_dmae_prog()\fR.
.SS "\fBddi_dmae_disable()\fR"
-.sp
.LP
The \fBddi_dmae_disable()\fR function disables the \fBDMA\fR channel so that it
no longer responds to a device's \fBDMA\fR service requests.
.SS "\fBddi_dmae_enable()\fR"
-.sp
.LP
The \fBddi_dmae_enable()\fR function enables the \fBDMA\fR channel for
operation. This may be used to re-enable the channel after a call to
\fBddi_dmae_disable()\fR. The channel is automatically enabled after successful
programming by \fBddi_dmae_prog()\fR.
.SS "\fBddi_dmae_stop()\fR"
-.sp
.LP
The \fBddi_dmae_stop()\fR function disables the channel and terminates any
active operation.
.SS "\fBddi_dmae_getcnt()\fR"
-.sp
.LP
The \fBddi_dmae_getcnt()\fR function examines the count register of the
\fBDMA\fR channel and sets \fI*countp\fR to the number of bytes remaining to be
transferred. The channel is assumed to be stopped.
.SS "\fBddi_dmae_1stparty()\fR"
-.sp
.LP
In the case of \fBISA\fR buses, \fBddi_dmae_1stparty()\fR configures a channel
in the system's \fBDMA\fR engine to operate in a ``slave'' (``cascade'') mode.
@@ -285,7 +275,6 @@ first be allocated using \fBddi_dmae_alloc()\fR and then configured using
I/O, including the necessary \fBDMA\fR address and count values obtained from
the \fBddi_dma_cookie\fR(9S).
.SS "\fBddi_dmae_getattr()\fR"
-.sp
.LP
The \fBddi_dmae_getattr()\fR function fills in the \fBDMA\fR attribute
structure, pointed to by \fIattrp\fR, with the \fBDMA\fR attributes of the
@@ -295,9 +284,8 @@ mastering or use first-party \fBDMA\fR must create and initialize their own
The \fBDMA\fR attribute structure must be passed to the \fBDMA\fR resource
allocation functions to provide the information necessary to break the
\fBDMA\fR request into \fBDMA\fR windows and \fBDMA\fR cookies. See
-\fBddi_dma_nextcookie\fR(9F) and \fBddi_dma_getwin\fR(9F).
+\fBddi_dma_cookie_iter\fR(9F) and \fBddi_dma_getwin\fR(9F).
.SH RETURN VALUES
-.sp
.ne 2
.na
\fB\fBDDI_SUCCESS\fR\fR
@@ -326,14 +314,12 @@ available and the value of \fIdmae_waitfp\fR is not \fBDDI_DMA_SLEEP\fR.
.RE
.SH CONTEXT
-.sp
.LP
If \fBddi_dmae_alloc()\fR is called from interrupt context, then its
\fIdmae_waitfp\fR argument and the callback function must not have the value
\fBDDI_DMA_SLEEP\fR. Otherwise, all these routines can be called from user,
interrupt, or kernel context.
.SH ATTRIBUTES
-.sp
.LP
See \fBattributes\fR(5) for descriptions of the following attributes:
.sp
@@ -349,10 +335,9 @@ Architecture x86
.TE
.SH SEE ALSO
-.sp
.LP
\fBisa\fR(4), \fBattributes\fR(5), \fBddi_dma_buf_setup\fR(9F),
-\fBddi_dma_getwin\fR(9F), \fBddi_dma_nextcookie\fR(9F),
+\fBddi_dma_cookie_iter\fR(9F), \fBddi_dma_getwin\fR(9F),
\fBddi_dma_mem_alloc\fR(9F), \fBddi_dma_addr_bind_handle\fR(9F), \fBddi_dma_attr\fR(9S),
\fBddi_dma_cookie\fR(9S),
\fBddi_dmae_req\fR(9S)
diff --git a/usr/src/pkg/manifests/system-kernel.man9f.inc b/usr/src/pkg/manifests/system-kernel.man9f.inc
index 4076044314..3d10b9ddc9 100644
--- a/usr/src/pkg/manifests/system-kernel.man9f.inc
+++ b/usr/src/pkg/manifests/system-kernel.man9f.inc
@@ -150,11 +150,11 @@ file path=usr/share/man/man9f/ddi_dma_addr_bind_handle.9f
file path=usr/share/man/man9f/ddi_dma_alloc_handle.9f
file path=usr/share/man/man9f/ddi_dma_buf_bind_handle.9f
file path=usr/share/man/man9f/ddi_dma_burstsizes.9f
+file path=usr/share/man/man9f/ddi_dma_cookie_iter.9f
file path=usr/share/man/man9f/ddi_dma_free_handle.9f
file path=usr/share/man/man9f/ddi_dma_getwin.9f
file path=usr/share/man/man9f/ddi_dma_mem_alloc.9f
file path=usr/share/man/man9f/ddi_dma_mem_free.9f
-file path=usr/share/man/man9f/ddi_dma_nextcookie.9f
file path=usr/share/man/man9f/ddi_dma_numwin.9f
file path=usr/share/man/man9f/ddi_dma_set_sbus64.9f
file path=usr/share/man/man9f/ddi_dma_sync.9f
@@ -719,6 +719,10 @@ link path=usr/share/man/man9f/ddi_devid_unregister.9f \
target=ddi_devid_compare.9f
link path=usr/share/man/man9f/ddi_devid_valid.9f target=ddi_devid_compare.9f
link path=usr/share/man/man9f/ddi_devmap_segmap.9f target=devmap_setup.9f
+link path=usr/share/man/man9f/ddi_dma_cookie_get.9f target=ddi_dma_cookie_iter.9f
+link path=usr/share/man/man9f/ddi_dma_cookie_one.9f target=ddi_dma_cookie_iter.9f
+link path=usr/share/man/man9f/ddi_dma_ncookies.9f target=ddi_dma_cookie_iter.9f
+link path=usr/share/man/man9f/ddi_dma_nextcookie.9f target=ddi_dma_cookie_iter.9f
link path=usr/share/man/man9f/ddi_dmae_1stparty.9f target=ddi_dmae.9f
link path=usr/share/man/man9f/ddi_dmae_alloc.9f target=ddi_dmae.9f
link path=usr/share/man/man9f/ddi_dmae_disable.9f target=ddi_dmae.9f
diff --git a/usr/src/uts/common/io/scsi/impl/scsi_resource.c b/usr/src/uts/common/io/scsi/impl/scsi_resource.c
index cd58cd1981..5477435026 100644
--- a/usr/src/uts/common/io/scsi/impl/scsi_resource.c
+++ b/usr/src/uts/common/io/scsi/impl/scsi_resource.c
@@ -258,6 +258,7 @@ scsi_dmaget_attr(struct scsi_pkt_cache_wrapper *pktw)
pktw->pcw_total_xfer += pktp->pkt_dma_len;
pktp->pkt_cookies = hp->dmai_cookie - 1;
hp->dmai_cookie = cp;
+ hp->dmai_curcookie = num_segs;
return (1);
}
diff --git a/usr/src/uts/common/os/sunddi.c b/usr/src/uts/common/os/sunddi.c
index dce7c40462..eee666190f 100644
--- a/usr/src/uts/common/os/sunddi.c
+++ b/usr/src/uts/common/os/sunddi.c
@@ -7074,6 +7074,14 @@ ddi_dma_buf_bind_handle(ddi_dma_handle_t handle, struct buf *bp,
dev_info_t *dip, *rdip;
struct ddi_dma_req dmareq;
int (*funcp)();
+ ddi_dma_cookie_t cookie;
+ uint_t count;
+
+ if (cookiep == NULL)
+ cookiep = &cookie;
+
+ if (ccountp == NULL)
+ ccountp = &count;
dmareq.dmar_flags = flags;
dmareq.dmar_fp = waitfp;
@@ -7130,10 +7138,19 @@ ddi_dma_addr_bind_handle(ddi_dma_handle_t handle, struct as *as,
dev_info_t *dip, *rdip;
struct ddi_dma_req dmareq;
int (*funcp)();
+ ddi_dma_cookie_t cookie;
+ uint_t count;
if (len == (uint_t)0) {
return (DDI_DMA_NOMAPPING);
}
+
+ if (cookiep == NULL)
+ cookiep = &cookie;
+
+ if (ccountp == NULL)
+ ccountp = &count;
+
dmareq.dmar_flags = flags;
dmareq.dmar_fp = waitfp;
dmareq.dmar_arg = arg;
@@ -7156,6 +7173,11 @@ ddi_dma_nextcookie(ddi_dma_handle_t handle, ddi_dma_cookie_t *cookiep)
ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
ddi_dma_cookie_t *cp;
+ if (hp->dmai_curcookie >= hp->dmai_ncookies) {
+ panic("ddi_dma_nextcookie() called too many times on handle %p",
+ hp);
+ }
+
cp = hp->dmai_cookie;
ASSERT(cp);
@@ -7164,6 +7186,74 @@ ddi_dma_nextcookie(ddi_dma_handle_t handle, ddi_dma_cookie_t *cookiep)
cookiep->dmac_address = cp->dmac_address;
cookiep->dmac_size = cp->dmac_size;
hp->dmai_cookie++;
+ hp->dmai_curcookie++;
+}
+
+int
+ddi_dma_ncookies(ddi_dma_handle_t handle)
+{
+ ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
+
+ return (hp->dmai_ncookies);
+}
+
+const ddi_dma_cookie_t *
+ddi_dma_cookie_iter(ddi_dma_handle_t handle, const ddi_dma_cookie_t *iter)
+{
+ ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
+ const ddi_dma_cookie_t *base, *end;
+
+ if (hp->dmai_ncookies == 0) {
+ return (NULL);
+ }
+
+ base = hp->dmai_cookie - hp->dmai_curcookie;
+ end = base + hp->dmai_ncookies;
+ if (iter == NULL) {
+ return (base);
+ }
+
+ if ((uintptr_t)iter < (uintptr_t)base ||
+ (uintptr_t)iter >= (uintptr_t)end) {
+ return (NULL);
+ }
+
+ iter++;
+ if (iter == end) {
+ return (NULL);
+ }
+
+ return (iter);
+}
+
+const ddi_dma_cookie_t *
+ddi_dma_cookie_get(ddi_dma_handle_t handle, uint_t index)
+{
+ ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
+ const ddi_dma_cookie_t *base;
+
+ if (index >= hp->dmai_ncookies) {
+ return (NULL);
+ }
+
+ base = hp->dmai_cookie - hp->dmai_curcookie;
+ return (base + index);
+}
+
+const ddi_dma_cookie_t *
+ddi_dma_cookie_one(ddi_dma_handle_t handle)
+{
+ ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
+ const ddi_dma_cookie_t *base;
+
+ if (hp->dmai_ncookies != 1) {
+ panic("ddi_dma_cookie_one() called with improper handle %p",
+ hp);
+ }
+ ASSERT3P(hp->dmai_cookie, !=, NULL);
+
+ base = hp->dmai_cookie - hp->dmai_curcookie;
+ return (base);
}
int
@@ -7184,11 +7274,19 @@ ddi_dma_getwin(ddi_dma_handle_t h, uint_t win, off_t *offp,
{
int (*funcp)() = ddi_dma_win;
struct bus_ops *bop;
+ ddi_dma_cookie_t cookie;
+ uint_t count;
bop = DEVI(HD)->devi_ops->devo_bus_ops;
if (bop && bop->bus_dma_win)
funcp = bop->bus_dma_win;
+ if (cookiep == NULL)
+ cookiep = &cookie;
+
+ if (ccountp == NULL)
+ ccountp = &count;
+
return ((*funcp)(HD, HD, h, win, offp, lenp, cookiep, ccountp));
}
diff --git a/usr/src/uts/common/sys/ddi_impldefs.h b/usr/src/uts/common/sys/ddi_impldefs.h
index 37329a1c18..1012c904fd 100644
--- a/usr/src/uts/common/sys/ddi_impldefs.h
+++ b/usr/src/uts/common/sys/ddi_impldefs.h
@@ -877,6 +877,8 @@ typedef struct ddi_dma_impl {
uint_t dmai_inuse; /* active handle? */
uint_t dmai_nwin;
uint_t dmai_winsize;
+ uint_t dmai_ncookies;
+ uint_t dmai_curcookie;
caddr_t dmai_nexus_private;
void *dmai_iopte;
uint_t *dmai_sbi;
@@ -901,6 +903,8 @@ typedef struct ddi_dma_impl {
*/
typedef struct ddi_dma_impl {
ddi_dma_cookie_t *dmai_cookie; /* array of DMA cookies */
+ uint_t dmai_ncookies;
+ uint_t dmai_curcookie;
void *dmai_private;
/*
diff --git a/usr/src/uts/common/sys/sunddi.h b/usr/src/uts/common/sys/sunddi.h
index f81a391f41..6d5f4304b4 100644
--- a/usr/src/uts/common/sys/sunddi.h
+++ b/usr/src/uts/common/sys/sunddi.h
@@ -1368,6 +1368,10 @@ ddi_dma_unbind_handle(ddi_dma_handle_t handle);
/*
* get next DMA cookie
+ *
+ * This function has been deprecated because it is unsafe. Please use
+ * ddi_dma_cookie_iter(), ddi_dma_cookie_get(), or ddi_dma_cookie_one() instead.
+ * For more information on the problems, please see the manual page.
*/
void
@@ -1851,6 +1855,16 @@ extern void ddi_dev_report_fault(dev_info_t *, ddi_fault_impact_t,
extern ddi_devstate_t ddi_get_devstate(dev_info_t *);
/*
+ * Replacement DMA cookie functions for ddi_dma_nextcookie().
+ */
+extern int ddi_dma_ncookies(ddi_dma_handle_t);
+extern const ddi_dma_cookie_t *ddi_dma_cookie_iter(ddi_dma_handle_t,
+ const ddi_dma_cookie_t *);
+extern const ddi_dma_cookie_t *ddi_dma_cookie_get(ddi_dma_handle_t, uint_t);
+extern const ddi_dma_cookie_t *ddi_dma_cookie_one(ddi_dma_handle_t);
+
+
+/*
* Miscellaneous redefines
*/
#define uiophysio physio
diff --git a/usr/src/uts/i86pc/io/rootnex.c b/usr/src/uts/i86pc/io/rootnex.c
index 6cbc2132c1..972f726287 100644
--- a/usr/src/uts/i86pc/io/rootnex.c
+++ b/usr/src/uts/i86pc/io/rootnex.c
@@ -2186,6 +2186,8 @@ fast:
*ccountp = sinfo->si_sgl_size;
hp->dmai_cookie++;
hp->dmai_rflags &= ~DDI_DMA_PARTIAL;
+ hp->dmai_ncookies = *ccountp;
+ hp->dmai_curcookie = 1;
ROOTNEX_DPROF_INC(&rootnex_cnt[ROOTNEX_CNT_ACTIVE_BINDS]);
ROOTNEX_DPROBE4(rootnex__bind__fast, dev_info_t *, rdip,
uint64_t, rootnex_cnt[ROOTNEX_CNT_ACTIVE_BINDS],
@@ -2259,6 +2261,8 @@ fast:
}
*cookiep = dma->dp_cookies[0];
hp->dmai_cookie++;
+ hp->dmai_ncookies = *ccountp;
+ hp->dmai_curcookie = 1;
ROOTNEX_DPROF_INC(&rootnex_cnt[ROOTNEX_CNT_ACTIVE_BINDS]);
ROOTNEX_DPROBE4(rootnex__bind__slow, dev_info_t *, rdip, uint64_t,
@@ -2411,6 +2415,7 @@ rootnex_coredma_reset_cookies(dev_info_t *dip, ddi_dma_handle_t handle)
hp->dmai_cookie = dma->dp_cookies;
}
hp->dmai_cookie++;
+ hp->dmai_curcookie = 1;
}
/*ARGSUSED*/
@@ -2671,6 +2676,10 @@ rootnex_clean_dmahdl(ddi_dma_impl_t *hp)
hp->dmai_error.err_status = DDI_FM_OK;
hp->dmai_error.err_expected = DDI_FM_ERR_UNEXPECTED;
hp->dmai_error.err_ontrap = NULL;
+
+ /* Cookie tracking */
+ hp->dmai_ncookies = 0;
+ hp->dmai_curcookie = 0;
}
@@ -4770,6 +4779,8 @@ rootnex_coredma_win(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle,
*ccountp = dma->dp_sglinfo.si_sgl_size;
*cookiep = hp->dmai_cookie[0];
hp->dmai_cookie++;
+ hp->dmai_ncookies = *ccountp;
+ hp->dmai_curcookie = 1;
return (DDI_SUCCESS);
}
@@ -4865,6 +4876,8 @@ rootnex_coredma_win(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle,
*lenp = window->wd_size;
*ccountp = window->wd_cookie_cnt;
*cookiep = hp->dmai_cookie[0];
+ hp->dmai_ncookies = *ccountp;
+ hp->dmai_curcookie = 1;
hp->dmai_cookie++;
#if !defined(__amd64)
diff --git a/usr/src/uts/sun4/io/px/px.c b/usr/src/uts/sun4/io/px/px.c
index 9f8e18e458..6d9c5797c4 100644
--- a/usr/src/uts/sun4/io/px/px.c
+++ b/usr/src/uts/sun4/io/px/px.c
@@ -999,6 +999,8 @@ px_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
mapped:
*ccountp = 1;
MAKE_DMA_COOKIE(cookiep, mp->dmai_mapping, mp->dmai_size);
+ mp->dmai_ncookies = 1;
+ mp->dmai_curcookie = 1;
break;
case PX_DMAI_FLAGS_BYPASS:
case PX_DMAI_FLAGS_PTP:
@@ -1007,6 +1009,10 @@ mapped:
*ccountp = PX_WINLST(mp)->win_ncookies;
*cookiep =
*(ddi_dma_cookie_t *)(PX_WINLST(mp) + 1); /* wholeobj */
+ /*
+ * mp->dmai_ncookies and mp->dmai_curcookie are set by
+ * px_dma_physwin().
+ */
break;
default:
cmn_err(CE_PANIC, "%s%d: px_dma_bindhdl(%p): bad dma type",
@@ -1078,6 +1084,8 @@ px_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle)
ddi_run_callback(&px_kmem_clid);
}
mp->dmai_flags &= PX_DMAI_FLAGS_PRESERVE;
+ mp->dmai_ncookies = 0;
+ mp->dmai_curcookie = 0;
return (DDI_SUCCESS);
}
@@ -1120,6 +1128,8 @@ px_dma_win(dev_info_t *dip, dev_info_t *rdip,
mp->dmai_size);
if (ccountp)
*ccountp = 1;
+ mp->dmai_ncookies = 1;
+ mp->dmai_curcookie = 1;
break;
case PX_DMAI_FLAGS_PTP:
case PX_DMAI_FLAGS_BYPASS: {
@@ -1137,6 +1147,8 @@ px_dma_win(dev_info_t *dip, dev_info_t *rdip,
win_p->win_curseg = 0;
if (ccountp)
*ccountp = win_p->win_ncookies;
+ mp->dmai_ncookies = win_p->win_ncookies;
+ mp->dmai_curcookie = 1;
}
break;
default:
diff --git a/usr/src/uts/sun4/io/px/px_dma.c b/usr/src/uts/sun4/io/px/px_dma.c
index 148699c267..2c88281260 100644
--- a/usr/src/uts/sun4/io/px/px_dma.c
+++ b/usr/src/uts/sun4/io/px/px_dma.c
@@ -76,6 +76,8 @@ px_dma_allocmp(dev_info_t *dip, dev_info_t *rdip, int (*waitfp)(caddr_t),
mp->dmai_flags = 0;
mp->dmai_pfnlst = NULL;
mp->dmai_winlst = NULL;
+ mp->dmai_ncookies = 0;
+ mp->dmai_curcookie = 0;
/*
* kmem_alloc debug: the following fields are not zero-ed
@@ -1229,7 +1231,9 @@ px_dma_physwin(px_t *px_p, ddi_dma_req_t *dmareq, ddi_dma_impl_t *mp)
mp->dmai_rflags &= ~DDI_DMA_REDZONE;
mp->dmai_flags |= PX_DMAI_FLAGS_NOSYNC;
cookie0_p = (ddi_dma_cookie_t *)(PX_WINLST(mp) + 1);
- mp->dmai_cookie = PX_WINLST(mp)->win_ncookies > 1 ? cookie0_p + 1 : 0;
+ mp->dmai_cookie = cookie0_p + 1;
+ mp->dmai_curcookie = 1;
+ mp->dmai_ncookies = PX_WINLST(mp)->win_ncookies;
mp->dmai_mapping = cookie0_p->dmac_laddress;
px_dma_freepfn(mp);
diff --git a/usr/src/uts/sun4u/io/pci/pci.c b/usr/src/uts/sun4u/io/pci/pci.c
index 15cb498378..d52c973b30 100644
--- a/usr/src/uts/sun4u/io/pci/pci.c
+++ b/usr/src/uts/sun4u/io/pci/pci.c
@@ -731,6 +731,8 @@ pci_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
mapped:
*ccountp = 1;
MAKE_DMA_COOKIE(cookiep, mp->dmai_mapping, mp->dmai_size);
+ mp->dmai_ncookies = 1;
+ mp->dmai_curcookie = 1;
break;
case DMAI_FLAGS_BYPASS:
case DMAI_FLAGS_PEER_TO_PEER:
@@ -738,6 +740,10 @@ mapped:
goto map_err;
*ccountp = WINLST(mp)->win_ncookies;
*cookiep = *(ddi_dma_cookie_t *)(WINLST(mp) + 1); /* wholeobj */
+ /*
+ * mp->dmai_ncookies and mp->dmai_curcookie are set by
+ * pci_dma_physwin().
+ */
break;
default:
panic("%s%d: pci_dma_bindhdl(%p): bad dma type",
@@ -809,6 +815,8 @@ pci_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle)
SYNC_BUF_PA(mp) = 0;
mp->dmai_error.err_cf = NULL;
+ mp->dmai_ncookies = 0;
+ mp->dmai_curcookie = 0;
return (DDI_SUCCESS);
}
@@ -845,6 +853,8 @@ pci_dma_win(dev_info_t *dip, dev_info_t *rdip,
mp->dmai_size);
if (ccountp)
*ccountp = 1;
+ mp->dmai_ncookies = 1;
+ mp->dmai_curcookie = 1;
break;
case DMAI_FLAGS_PEER_TO_PEER:
case DMAI_FLAGS_BYPASS: {
@@ -863,6 +873,8 @@ pci_dma_win(dev_info_t *dip, dev_info_t *rdip,
win_p->win_curseg = 0;
if (ccountp)
*ccountp = win_p->win_ncookies;
+ mp->dmai_ncookies = win_p->win_ncookies;
+ mp->dmai_curcookie = 1;
}
break;
default:
diff --git a/usr/src/uts/sun4u/io/pci/pci_dma.c b/usr/src/uts/sun4u/io/pci/pci_dma.c
index 9814a69e68..af68d98c98 100644
--- a/usr/src/uts/sun4u/io/pci/pci_dma.c
+++ b/usr/src/uts/sun4u/io/pci/pci_dma.c
@@ -267,6 +267,8 @@ pci_dma_allocmp(dev_info_t *dip, dev_info_t *rdip, int (*waitfp)(caddr_t),
mp->dmai_flags = 0;
mp->dmai_pfnlst = NULL;
mp->dmai_winlst = NULL;
+ mp->dmai_ncookies = 0;
+ mp->dmai_curcookie = 0;
/*
* kmem_alloc debug: the following fields are not zero-ed
@@ -1410,8 +1412,10 @@ pci_dma_physwin(pci_t *pci_p, ddi_dma_req_t *dmareq, ddi_dma_impl_t *mp)
}
mp->dmai_rflags &= ~DDI_DMA_REDZONE;
cookie0_p = (ddi_dma_cookie_t *)(WINLST(mp) + 1);
- mp->dmai_cookie = WINLST(mp)->win_ncookies > 1 ? cookie0_p + 1 : 0;
+ mp->dmai_cookie = cookie0_p + 1;
mp->dmai_mapping = cookie0_p->dmac_laddress;
+ mp->dmai_ncookies = WINLST(mp)->win_ncookies;
+ mp->dmai_curcookie = 1;
pci_dma_freepfn(mp);
return (DDI_DMA_MAPPED);
diff --git a/usr/src/uts/sun4v/io/niumx/niumx.c b/usr/src/uts/sun4v/io/niumx/niumx.c
index d91b9c4872..b455d287e6 100644
--- a/usr/src/uts/sun4v/io/niumx/niumx.c
+++ b/usr/src/uts/sun4v/io/niumx/niumx.c
@@ -665,6 +665,8 @@ niumx_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attrp,
mp->dmai_rdip = rdip;
mp->dmai_pfnlst = NULL;
mp->dmai_cookie = NULL;
+ mp->dmai_ncookies = 0;
+ mp->dmai_curcookie = 0;
mp->dmai_fault = 0;
mp->dmai_fault_check = NULL;
mp->dmai_fault_notify = NULL;
@@ -775,6 +777,8 @@ niumx_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
}
mp->dmai_cookie->dmac_laddress = mp->dmai_mapping;
mp->dmai_cookie->dmac_size = mp->dmai_size;
+ mp->dmai_ncookies = 1;
+ mp->dmai_curcookie = 0;
*ccountp = 1;
*cookiep = *mp->dmai_cookie;
DBG(NIUMX_DBG_DMA_BINDH, dip, "cookie %" PRIx64 "+%x, count=%d\n",
@@ -801,6 +805,7 @@ niumx_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle)
if (mp->dmai_cookie) {
kmem_free(mp->dmai_cookie, sizeof (ddi_dma_cookie_t));
mp->dmai_cookie = NULL;
+ mp->dmai_ncookies = mp->dmai_curcookie = 0;
}
return (DDI_SUCCESS);