xref: /netbsd-src/share/man/man9/pci_msi.9 (revision d909946ca08dceb44d7d0f22ec9488679695d976)
1.\" $NetBSD: pci_msi.9,v 1.10 2016/07/12 03:39:55 knakahara Exp $
2.\"
3.\" Copyright (c) 2015 Internet Initiative Japan Inc.
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\"    notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\"    notice, this list of conditions and the following disclaimer in the
13.\"    documentation and/or other materials provided with the distribution.
14.\"
15.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25.\" POSSIBILITY OF SUCH DAMAGE.
26.\"
27.Dd July 12, 2016
28.Dt PCI_MSI 9
29.Os
30.Sh NAME
31.Nm pci_msi ,
32.Nm pci_msix ,
33.Nm pci_msi_count ,
34.Nm pci_msi_alloc ,
35.Nm pci_msi_alloc_exact ,
36.Nm pci_msix_count ,
37.Nm pci_msix_alloc ,
38.Nm pci_msix_alloc_exact ,
39.Nm pci_msix_alloc_map ,
40.Nm pci_intx_alloc ,
41.Nm pci_intr_alloc ,
42.Nm pci_intr_release ,
43.Nm pci_intr_type
44.Nd PCI MSI{,-X} manipulation functions
45.Sh SYNOPSIS
46.Ft int
47.Fn pci_msi_count "pci_chipset_tag_t pc" \
48"pcitag_t tag"
49.Ft int
50.Fn pci_msi_alloc  "const struct pci_attach_args *pa" \
51"pci_intr_handle_t **ihps" "int *count"
52.Ft int
53.Fn pci_msi_alloc_exect "const struct pci_attach_args *pa" \
54"pci_intr_handle_t **ihps" "int count"
55.Ft int
56.Fn pci_msix_count "pci_chipset_tag_t pc" \
57"pcitag_t tag"
58.Ft int
59.Fn pci_msix_alloc  "const struct pci_attach_args *pa" \
60"pci_intr_handle_t **ihps" "int *count"
61.Ft int
62.Fn pci_msix_alloc_exect "const struct pci_attach_args *pa" \
63"pci_intr_handle_t **ihps" "int count"
64.Ft int
65.Fn pci_msix_alloc_map "const struct pci_attach_args *pa" \
66"pci_intr_handle_t **ihps" "u_int *table_indexes" "int count"
67.Ft int
68.Fn pci_intx_alloc  "const struct pci_attach_args *pa" \
69"pci_intr_handle_t **ihp"
70.Ft int
71.Fn pci_intr_alloc  "const struct pci_attach_args *pa" \
72"pci_intr_handle_t **ihp" "int *counts" \
73"pci_intr_type_t max_type"
74.Ft void
75.Fn pci_intr_release "pci_chipset_tag_t pc" \
76"pci_intr_handle_t *pih" "int count"
77.Ft pci_intr_type_t
78.Fn pci_intr_type "pci_chipset_tag_t pc" \
79"pci_intr_handle_t ih"
80.Sh DESCRIPTION
81The
82.Nm
83functions exist to allow device drivers to use MSI/MSI-X.
84When the system uses MSI/MSI-X, it must define the
85.Dv __HAVE_PCI_MSI_MSIX
86build option.
87.Pp
88Each driver has an
89.Fn attach
90function which has a bus-specific
91.Ft attach_args
92structure.
93Each driver for a PCI device is passed a pointer to an object of type
94.Ft struct pci_attach_args
95which contains, among other things, information about the location
96of the device in the PCI bus topology sufficient to allow interrupts
97from the device to be handled.
98.Pp
99If a driver wishes to establish an MSI handler for the device,
100it should pass the
101.Ft struct pci_attach_args *
102and
103.Fa count
104.Fn pci_msi_alloc
105or
106.Fn pci_msi_alloc_exact
107functions, which return zero on success, and nonzero on failure.
108When the functions are successful, they return the pointer to the
109allocated handle array in
110.Ft pihs
111whose size is
112.Ft count
113or less.
114The difference between
115.Fn pci_msi_alloc
116and
117.Fn pci_msi_alloc_exact
118is whether
119.Fa count
120can be decremented or not.
121.Fn pci_msi_alloc
122can decrement
123.Fa count ,
124and which is similar to
125.Fx Ap s
126.Fn pci_alloc_msi .
127In contrast,
128.Fn pci_msi_alloc_exact
129can not decrement
130.Ft count .
131.Pp
132If the driver wishes to refer to the MSI source in an attach or
133error message, it should use the value returned by
134.Fn pci_intr_string
135the same as INTx.
136The buffer passed to
137.Fn pci_intr_string
138should be at least
139.Dv PCI_INTRSTR_LEN
140bytes long.
141.Pp
142Subsequently, when the driver is prepared to receive MSIs, it
143should call
144.Fn pci_intr_establish
145the same as INTx to actually establish the handler;
146when the device interrupts,
147.Fa intrhand
148will be called with a single argument
149.Fa intrarg ,
150and will run at the interrupt priority level
151.Fa ipl .
152.Pp
153The return value of
154.Fn pci_intr_establish
155may be saved and passed to
156.Fn pci_intr_disestablish
157to disable the interrupt handler the same as INTx
158when the driver is no longer interested in MSIs from the device.
159After that, the driver should also call
160.Fn pci_intr_release
161to free resources about MSI as well as INTx and MSI-X.
162.Pp
163If a driver wishes to establish an MSI-X handler for the device,
164it is almost the same as MSI.
165The only differences is
166.Fn pci_msix_alloc_map .
167This function can assign separate handlers for each MSI-X table
168entry.
169I.e., if the driver wants to assign the handlers in the following way:
170.Bd -literal
171	msix_handler0 => MSI-X table index: 4
172	msix_handler1 => MSI-X table index: 5
173	msix_handler2 => MSI-X table index: 0
174.Ed
175the driver should set
176.Fa table_indexes
177this way:
178.Bd -literal
179	table_indexes[0] = 4;
180	table_indexes[1] = 5;
181	table_indexes[2] = 0;
182.Ed
183.Pp
184If the driver wants to fall back to INTx, the driver should use
185.Fn pci_intx_alloc
186and
187.Fn pci_intr_release
188instead of
189.Fn pci_intr_map
190to resolve contradiction of the interrupt handler ownership.
191I.e.,
192.Fn pci_intr_map
193does not have the ownership (the function just calculates value),
194in contrast,
195.Fn pci_msi_alloc
196and
197.Fn pci_msix_alloc
198have (the functions allocate memory for interrupt handlers).
199.Pp
200.Fn pci_intr_alloc
201is wrapper function which select and automatically fallback
202allocation functions according to the argument
203.Fa counts .
204The elements of
205.Fa counts
206array means each required interrupt count for INTx, MSI, and MSI-X.
207The index count of
208.Fa counts
209must be
210.Dv PCI_INTR_TYPE_SIZE .
211.Fa max_type
212must be
213.Dv PCI_INTR_TYPE_MSIX ,
214.Dv PCI_INTR_TYPE_MSI ,
215or
216.Dv PCI_INTR_TYPE_INTX .
217The parameter does not mean array index counts of
218.Fa counts .
219The parameter means the interrupt type which
220.Fn pci_intr_alloc
221tries to allocate first.
222I.e., if the driver wants to allocate interrupts in the following way:
223.Bd -literal
224	5 MSI-X
225	1 MSI (if MSI-X allocation failed)
226	INTx (if MSI allocation failed either)
227.Ed
228the driver should call
229.Fn pci_intr_alloc
230in the following way:
231.Bd -literal
232	int counts[PCI_INTR_TYPE_SIZE];
233	counts[PCI_INTR_TYPE_MSIX] = 5;
234	counts[PCI_INTR_TYPE_MSI] = 1;
235	counts[PCI_INTR_TYPE_INTX] = 1;
236	error = pci_intr_alloc(pa, ihps, counts,
237			       PCI_INTR_TYPE_MSIX);
238.Ed
239If the driver wants to allocate interrupts in the following way:
240.Bd -literal
241	hardware max number MSI-X
242	1 MSI (if MSI-X allocation failed)
243.Ed
244that is, the driver does not use INTx, the driver should call
245.Fn pci_intr_alloc
246in the following way:
247.Bd -literal
248	int counts[PCI_INTR_TYPE_SIZE];
249	counts[PCI_INTR_TYPE_MSIX] = -1; /* -1 means max */
250	counts[PCI_INTR_TYPE_MSI] = 1;
251	counts[PCI_INTR_TYPE_INTX] = 0; /* 0 means not use */
252	error = pci_intr_alloc(pa, ihps, counts,
253			       PCI_INTR_TYPE_MSIX);
254.Ed
255If the driver wants to allocate interrupts in the following way:
256.Bd -literal
257	3 MSI
258	INTx (if MSI allocation failed)
259.Ed
260that is, the driver does not use MSI-X, the driver should call
261.Fn pci_intr_alloc
262in the following way:
263.Bd -literal
264	int counts[PCI_INTR_TYPE_SIZE];
265	counts[PCI_INTR_TYPE_MSIX] = 0; /* 0 means not use */
266	counts[PCI_INTR_TYPE_MSI] = 3;
267	counts[PCI_INTR_TYPE_INTX] = 1;
268	error = pci_intr_alloc(pa, ihps, counts,
269			       PCI_INTR_TYPE_MSI);
270.Ed
271If the driver wants to allocate interrupts in the following way:
272.Bd -literal
273	1 MSI
274	INTx (if MSI allocation failed)
275.Ed
276that is, general usage, the driver should call simply
277.Fn pci_intr_alloc
278in the following way:
279.Bd -literal
280	error = pci_intr_alloc(pa, ihps, NULL, 0);
281.Ed
282.Fa max_type
283is ignored in this case.
284.Fn pci_intr_alloc
285returns zero on any allocation function success, and non-zero on
286all allocation function failures.
287On success,
288.Fa counts
289is overwritten by a really allocated count.
290I.e., if 5 MSI-X is allocated,
291.Fa counts
292is
293.Bd -literal
294	counts[PCI_INTR_TYPE_MSIX] == 5
295	counts[PCI_INTR_TYPE_MSI] == 0
296	counts[PCI_INTR_TYPE_INTX] == 0
297.Ed
298on return.
299.Pp
300.Fn pci_intr_type
301returns the interrupt type of
302.Fa ih .
303The return value is
304.Dv PCI_INTR_TYPE_MSIX
305for MSI-X,
306.Dv PCI_INTR_TYPE_MSI
307for MSI, and
308.Dv PCI_INTR_TYPE_INTX
309for others.
310.Sh SEE ALSO
311.Xr pci_intr 9
312