NetBSD/share/man/man9/pci_msi.9

334 lines
8.9 KiB
Groff
Raw Normal View History

.\" $NetBSD: pci_msi.9,v 1.17 2018/11/27 20:13:43 jdolecek Exp $
2015-04-27 10:03:57 +03:00
.\"
.\" Copyright (c) 2015 Internet Initiative Japan Inc.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd November 27, 2018
2015-04-27 13:37:20 +03:00
.Dt PCI_MSI 9
2015-04-27 10:03:57 +03:00
.Os
2015-04-27 13:37:20 +03:00
.Sh NAME
2015-04-27 10:03:57 +03:00
.Nm pci_msi ,
2015-04-27 13:37:20 +03:00
.Nm pci_msix ,
2015-04-27 10:03:57 +03:00
.Nm pci_msi_count ,
.Nm pci_msi_alloc ,
.Nm pci_msi_alloc_exact ,
.Nm pci_msix_count ,
.Nm pci_msix_alloc ,
.Nm pci_msix_alloc_exact ,
.Nm pci_msix_alloc_map ,
.Nm pci_intx_alloc ,
2015-07-21 06:12:50 +03:00
.Nm pci_intr_alloc ,
.Nm pci_intr_release ,
2015-07-21 06:12:50 +03:00
.Nm pci_intr_type
2015-04-27 10:03:57 +03:00
.Nd PCI MSI{,-X} manipulation functions
.Sh SYNOPSIS
.Ft int
2015-08-13 08:01:04 +03:00
.Fn pci_msi_count "pci_chipset_tag_t pc" \
"pcitag_t tag"
2015-04-27 10:03:57 +03:00
.Ft int
.Fn pci_msi_alloc "const struct pci_attach_args *pa" \
2015-04-27 10:03:57 +03:00
"pci_intr_handle_t **ihps" "int *count"
.Ft int
2016-09-15 12:41:33 +03:00
.Fn pci_msi_alloc_exact "const struct pci_attach_args *pa" \
2015-04-27 10:03:57 +03:00
"pci_intr_handle_t **ihps" "int count"
.Ft int
2015-08-13 08:01:04 +03:00
.Fn pci_msix_count "pci_chipset_tag_t pc" \
"pcitag_t tag"
2015-04-27 10:03:57 +03:00
.Ft int
.Fn pci_msix_alloc "const struct pci_attach_args *pa" \
2015-04-27 10:03:57 +03:00
"pci_intr_handle_t **ihps" "int *count"
.Ft int
2016-09-15 12:41:33 +03:00
.Fn pci_msix_alloc_exact "const struct pci_attach_args *pa" \
2015-04-27 10:03:57 +03:00
"pci_intr_handle_t **ihps" "int count"
.Ft int
.Fn pci_msix_alloc_map "const struct pci_attach_args *pa" \
2015-04-27 10:03:57 +03:00
"pci_intr_handle_t **ihps" "u_int *table_indexes" "int count"
.Ft int
.Fn pci_intx_alloc "const struct pci_attach_args *pa" \
2015-04-27 10:03:57 +03:00
"pci_intr_handle_t **ihp"
2015-07-21 06:12:50 +03:00
.Ft int
.Fn pci_intr_alloc "const struct pci_attach_args *pa" \
2015-07-21 06:12:50 +03:00
"pci_intr_handle_t **ihp" "int *counts" \
"pci_intr_type_t max_type"
2015-04-27 10:03:57 +03:00
.Ft void
2015-05-15 11:39:14 +03:00
.Fn pci_intr_release "pci_chipset_tag_t pc" \
"pci_intr_handle_t *pih" "int count"
2015-07-21 06:12:50 +03:00
.Ft pci_intr_type_t
.Fn pci_intr_type "pci_chipset_tag_t pc" \
"pci_intr_handle_t ih"
2015-04-27 10:03:57 +03:00
.Sh DESCRIPTION
The
.Nm
functions exist to allow device drivers to use MSI/MSI-X.
2015-04-27 13:37:20 +03:00
When the system uses MSI/MSI-X, it must define the
.Dv __HAVE_PCI_MSI_MSIX
2015-04-27 10:03:57 +03:00
build option.
.Pp
Each driver has an
.Fn attach
function which has a bus-specific
.Ft attach_args
structure.
Each driver for a PCI device is passed a pointer to an object of type
.Ft struct pci_attach_args
which contains, among other things, information about the location
of the device in the PCI bus topology sufficient to allow interrupts
from the device to be handled.
.Pp
If a driver wishes to establish an MSI handler for the device,
it should pass the
.Ft struct pci_attach_args *
and
2015-04-27 13:37:20 +03:00
.Fa count
2015-04-27 10:03:57 +03:00
.Fn pci_msi_alloc
or
.Fn pci_msi_alloc_exact
2015-04-27 13:37:20 +03:00
functions, which return zero on success, and nonzero on failure.
When the functions are successful, they return the pointer to the
allocated handle array in
2015-04-27 10:03:57 +03:00
.Ft pihs
whose size is
.Ft count
2015-04-27 13:37:20 +03:00
or less.
The difference between
2015-04-27 10:03:57 +03:00
.Fn pci_msi_alloc
and
.Fn pci_msi_alloc_exact
2015-04-27 13:37:20 +03:00
is whether
.Fa count
2015-04-27 10:03:57 +03:00
can be decremented or not.
.Fn pci_msi_alloc
can decrement
2015-04-27 13:37:20 +03:00
.Fa count ,
and which is similar to
.Fx Ap s
2015-04-27 10:03:57 +03:00
.Fn pci_alloc_msi .
In contrast,
.Fn pci_msi_alloc_exact
can not decrement
.Ft count .
.Pp
If the driver wishes to refer to the MSI source in an attach or
error message, it should use the value returned by
2015-05-15 11:39:14 +03:00
.Fn pci_intr_string
the same as INTx.
2015-04-27 10:03:57 +03:00
The buffer passed to
2015-05-15 11:39:14 +03:00
.Fn pci_intr_string
2015-04-27 10:03:57 +03:00
should be at least
.Dv PCI_INTRSTR_LEN
2015-04-27 13:37:20 +03:00
bytes long.
2015-04-27 10:03:57 +03:00
.Pp
Subsequently, when the driver is prepared to receive MSIs, it
should call
2015-05-15 11:39:14 +03:00
.Fn pci_intr_establish
the same as INTx to actually establish the handler;
when the device interrupts,
2015-04-27 10:03:57 +03:00
.Fa intrhand
will be called with a single argument
.Fa intrarg ,
and will run at the interrupt priority level
.Fa ipl .
.Pp
The return value of
2015-05-15 11:39:14 +03:00
.Fn pci_intr_establish
2015-04-27 10:03:57 +03:00
may be saved and passed to
2015-05-15 11:39:14 +03:00
.Fn pci_intr_disestablish
to disable the interrupt handler the same as INTx
2015-04-27 10:03:57 +03:00
when the driver is no longer interested in MSIs from the device.
2015-04-27 13:37:20 +03:00
After that, the driver should also call
2015-05-15 11:39:14 +03:00
.Fn pci_intr_release
to free resources about MSI as well as INTx and MSI-X.
If
.Fa pih
is NULL,
.Fn pci_intr_release
does nothing.
2015-04-27 10:03:57 +03:00
.Pp
If a driver wishes to establish an MSI-X handler for the device,
2015-04-27 13:37:20 +03:00
it is almost the same as MSI.
2015-04-27 10:03:57 +03:00
The only differences is
.Fn pci_msix_alloc_map .
2015-04-27 13:37:20 +03:00
This function can assign separate handlers for each MSI-X table
entry.
I.e., if the driver wants to assign the handlers in the following way:
2015-04-27 10:03:57 +03:00
.Bd -literal
msix_handler0 => MSI-X table index: 4
msix_handler1 => MSI-X table index: 5
msix_handler2 => MSI-X table index: 0
.Ed
2015-04-27 13:37:20 +03:00
the driver should set
.Fa table_indexes
this way:
2015-04-27 10:03:57 +03:00
.Bd -literal
table_indexes[0] = 4;
table_indexes[1] = 5;
table_indexes[2] = 0;
.Ed
.Pp
2015-04-27 13:37:20 +03:00
If the driver wants to fall back to INTx, the driver should use
2015-04-27 10:03:57 +03:00
.Fn pci_intx_alloc
and
2015-05-15 11:39:14 +03:00
.Fn pci_intr_release
2015-04-27 10:03:57 +03:00
instead of
.Fn pci_intr_map
to resolve contradiction of the interrupt handler ownership.
2015-04-27 13:37:20 +03:00
I.e.,
2015-04-27 10:03:57 +03:00
.Fn pci_intr_map
2015-04-27 13:37:20 +03:00
does not have the ownership (the function just calculates value),
2015-04-27 10:03:57 +03:00
in contrast,
.Fn pci_msi_alloc
and
.Fn pci_msix_alloc
2015-04-27 13:37:20 +03:00
have (the functions allocate memory for interrupt handlers).
2015-07-21 06:12:50 +03:00
.Pp
.Fn pci_intr_alloc
is wrapper function which select and automatically fallback
allocation functions according to the argument
.Fa counts .
The elements of
.Fa counts
array means each required interrupt count for INTx, MSI, and MSI-X.
The index count of
.Fa counts
must be
.Dv PCI_INTR_TYPE_SIZE .
.Fa max_type
must be
.Dv PCI_INTR_TYPE_MSIX ,
.Dv PCI_INTR_TYPE_MSI ,
or
.Dv PCI_INTR_TYPE_INTX .
2015-07-21 06:12:50 +03:00
The parameter does not mean array index counts of
.Fa counts .
The parameter means the interrupt type which
.Fn pci_intr_alloc
tries to allocate first.
I.e., if the driver wants to allocate interrupts in the following way:
2015-07-21 06:12:50 +03:00
.Bd -literal
5 MSI-X
1 MSI (if MSI-X allocation failed)
INTx (if MSI allocation failed either)
.Ed
the driver should call
.Fn pci_intr_alloc
in the following way:
.Bd -literal
int counts[PCI_INTR_TYPE_SIZE];
counts[PCI_INTR_TYPE_MSIX] = 5;
counts[PCI_INTR_TYPE_MSI] = 1;
counts[PCI_INTR_TYPE_INTX] = 1;
error = pci_intr_alloc(pa, ihps, counts,
PCI_INTR_TYPE_MSIX);
.Ed
If the driver wants to allocate interrupts in the following way:
2015-07-21 06:12:50 +03:00
.Bd -literal
hardware max number MSI-X
1 MSI (if MSI-X allocation failed)
.Ed
that is, the driver does not use INTx, the driver should call
.Fn pci_intr_alloc
in the following way:
.Bd -literal
int counts[PCI_INTR_TYPE_SIZE];
counts[PCI_INTR_TYPE_MSIX] = -1; /* -1 means max */
counts[PCI_INTR_TYPE_MSI] = 1;
counts[PCI_INTR_TYPE_INTX] = 0; /* 0 means not use */
error = pci_intr_alloc(pa, ihps, counts,
PCI_INTR_TYPE_MSIX);
.Ed
If the driver wants to allocate interrupts in the following way:
2015-07-21 06:12:50 +03:00
.Bd -literal
3 MSI
INTx (if MSI allocation failed)
.Ed
that is, the driver does not use MSI-X, the driver should call
.Fn pci_intr_alloc
in the following way:
.Bd -literal
int counts[PCI_INTR_TYPE_SIZE];
counts[PCI_INTR_TYPE_MSIX] = 0; /* 0 means not use */
counts[PCI_INTR_TYPE_MSI] = 3;
counts[PCI_INTR_TYPE_INTX] = 1;
error = pci_intr_alloc(pa, ihps, counts,
PCI_INTR_TYPE_MSI);
.Ed
If the driver wants to allocate interrupts in the following way:
2015-07-21 06:12:50 +03:00
.Bd -literal
1 MSI-X
2015-07-21 06:12:50 +03:00
1 MSI
INTx (if MSI/MSI-X allocation failed)
2015-07-21 06:12:50 +03:00
.Ed
that is, general usage, the driver should call simply
.Fn pci_intr_alloc
in the following way:
.Bd -literal
error = pci_intr_alloc(pa, ihps, NULL, 0);
.Ed
.Fa max_type
is ignored in this case.
.Fn pci_intr_alloc
returns zero on any allocation function success, and non-zero on
all allocation function failures.
On success,
2015-07-21 06:12:50 +03:00
.Fa counts
is overwritten by a really allocated count.
I.e., if 5 MSI-X is allocated,
2015-07-21 06:12:50 +03:00
.Fa counts
is
.Bd -literal
counts[PCI_INTR_TYPE_MSIX] == 5
counts[PCI_INTR_TYPE_MSI] == 0
counts[PCI_INTR_TYPE_INTX] == 0
.Ed
on return.
.Pp
2015-07-24 10:40:58 +03:00
.Fn pci_intr_type
returns the interrupt type of
2015-07-21 06:12:50 +03:00
.Fa ih .
The return value is
.Dv PCI_INTR_TYPE_MSIX
for MSI-X,
.Dv PCI_INTR_TYPE_MSI
for MSI, and
2015-07-21 06:12:50 +03:00
.Dv PCI_INTR_TYPE_INTX
for others.
2015-05-15 11:39:14 +03:00
.Sh SEE ALSO
.Xr pci_intr 9
.Sh HISTORY
.Nm
support first appeared in
.Nx 8.0 .
Support is present on
.Em i386 ,
.Em amd64
and
.Em aarch64
architectures.
.Sh AUTHORS
The
.Nm
interfaces were designed and implemented by
.An Kengo Nakahara
2016-09-17 23:46:35 +03:00
.Aq Mt knakahara@NetBSD.org .