xref: /netbsd-src/share/man/man9/pci_msi.9 (revision c8dbf241c195446330ae759ffe6e694fc25da2d0)
1.\" $NetBSD: pci_msi.9,v 1.18 2021/01/12 05:08:50 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 January 12, 2021
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_exact "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_exact "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
99.Fn pci_msi_count
100returns the max number of the device's MSI.
101If the device can not use MSI,
102.Fn pci_msi_count
103returns zero.
104.Fn pci_msix_count
105works in the same manner for MSI-X.
106.Pp
107If a driver wishes to establish an MSI handler for the device,
108it should pass the
109.Ft struct pci_attach_args *
110and
111.Fa count
112.Fn pci_msi_alloc
113or
114.Fn pci_msi_alloc_exact
115functions, which return zero on success, and nonzero on failure.
116When the functions are successful, they return the pointer to the
117allocated handle array in
118.Ft pihs
119whose size is
120.Ft count
121or less.
122The difference between
123.Fn pci_msi_alloc
124and
125.Fn pci_msi_alloc_exact
126is whether
127.Fa count
128can be decremented or not.
129.Fn pci_msi_alloc
130can decrement
131.Fa count ,
132and which is similar to
133.Fx Ap s
134.Fn pci_alloc_msi .
135In contrast,
136.Fn pci_msi_alloc_exact
137can not decrement
138.Ft count .
139.Pp
140If the driver wishes to refer to the MSI source in an attach or
141error message, it should use the value returned by
142.Fn pci_intr_string
143the same as INTx.
144The buffer passed to
145.Fn pci_intr_string
146should be at least
147.Dv PCI_INTRSTR_LEN
148bytes long.
149.Pp
150Subsequently, when the driver is prepared to receive MSIs, it
151should call
152.Fn pci_intr_establish
153the same as INTx to actually establish the handler;
154when the device interrupts,
155.Fa intrhand
156will be called with a single argument
157.Fa intrarg ,
158and will run at the interrupt priority level
159.Fa ipl .
160.Pp
161The return value of
162.Fn pci_intr_establish
163may be saved and passed to
164.Fn pci_intr_disestablish
165to disable the interrupt handler the same as INTx
166when the driver is no longer interested in MSIs from the device.
167After that, the driver should also call
168.Fn pci_intr_release
169to free resources about MSI as well as INTx and MSI-X.
170If
171.Fa pih
172is NULL,
173.Fn pci_intr_release
174does nothing.
175.Pp
176If a driver wishes to establish an MSI-X handler for the device,
177it is almost the same as MSI.
178The only differences is
179.Fn pci_msix_alloc_map .
180This function can assign separate handlers for each MSI-X table
181entry.
182I.e., if the driver wants to assign the handlers in the following way:
183.Bd -literal
184	msix_handler0 => MSI-X table index: 4
185	msix_handler1 => MSI-X table index: 5
186	msix_handler2 => MSI-X table index: 0
187.Ed
188the driver should set
189.Fa table_indexes
190this way:
191.Bd -literal
192	table_indexes[0] = 4;
193	table_indexes[1] = 5;
194	table_indexes[2] = 0;
195.Ed
196.Pp
197If the driver wants to fall back to INTx, the driver should use
198.Fn pci_intx_alloc
199and
200.Fn pci_intr_release
201instead of
202.Fn pci_intr_map
203to resolve contradiction of the interrupt handler ownership.
204I.e.,
205.Fn pci_intr_map
206does not have the ownership (the function just calculates value),
207in contrast,
208.Fn pci_msi_alloc
209and
210.Fn pci_msix_alloc
211have (the functions allocate memory for interrupt handlers).
212.Pp
213.Fn pci_intr_alloc
214is wrapper function which select and automatically fallback
215allocation functions according to the argument
216.Fa counts .
217The elements of
218.Fa counts
219array means each required interrupt count for INTx, MSI, and MSI-X.
220The index count of
221.Fa counts
222must be
223.Dv PCI_INTR_TYPE_SIZE .
224.Fa max_type
225must be
226.Dv PCI_INTR_TYPE_MSIX ,
227.Dv PCI_INTR_TYPE_MSI ,
228or
229.Dv PCI_INTR_TYPE_INTX .
230The parameter does not mean array index counts of
231.Fa counts .
232The parameter means the interrupt type which
233.Fn pci_intr_alloc
234tries to allocate first.
235I.e., if the driver wants to allocate interrupts in the following way:
236.Bd -literal
237	5 MSI-X
238	1 MSI (if MSI-X allocation failed)
239	INTx (if MSI allocation failed either)
240.Ed
241the driver should call
242.Fn pci_intr_alloc
243in the following way:
244.Bd -literal
245	int counts[PCI_INTR_TYPE_SIZE];
246	counts[PCI_INTR_TYPE_MSIX] = 5;
247	counts[PCI_INTR_TYPE_MSI] = 1;
248	counts[PCI_INTR_TYPE_INTX] = 1;
249	error = pci_intr_alloc(pa, ihps, counts,
250			       PCI_INTR_TYPE_MSIX);
251.Ed
252If the driver wants to allocate interrupts in the following way:
253.Bd -literal
254	hardware max number MSI-X
255	1 MSI (if MSI-X allocation failed)
256.Ed
257that is, the driver does not use INTx, the driver should call
258.Fn pci_intr_alloc
259in the following way:
260.Bd -literal
261	int counts[PCI_INTR_TYPE_SIZE];
262	counts[PCI_INTR_TYPE_MSIX] = -1; /* -1 means max */
263	counts[PCI_INTR_TYPE_MSI] = 1;
264	counts[PCI_INTR_TYPE_INTX] = 0; /* 0 means not use */
265	error = pci_intr_alloc(pa, ihps, counts,
266			       PCI_INTR_TYPE_MSIX);
267.Ed
268If the driver wants to allocate interrupts in the following way:
269.Bd -literal
270	3 MSI
271	INTx (if MSI allocation failed)
272.Ed
273that is, the driver does not use MSI-X, the driver should call
274.Fn pci_intr_alloc
275in the following way:
276.Bd -literal
277	int counts[PCI_INTR_TYPE_SIZE];
278	counts[PCI_INTR_TYPE_MSIX] = 0; /* 0 means not use */
279	counts[PCI_INTR_TYPE_MSI] = 3;
280	counts[PCI_INTR_TYPE_INTX] = 1;
281	error = pci_intr_alloc(pa, ihps, counts,
282			       PCI_INTR_TYPE_MSI);
283.Ed
284If the driver wants to allocate interrupts in the following way:
285.Bd -literal
286	1 MSI-X
287	1 MSI
288	INTx (if MSI/MSI-X allocation failed)
289.Ed
290that is, general usage, the driver should call simply
291.Fn pci_intr_alloc
292in the following way:
293.Bd -literal
294	error = pci_intr_alloc(pa, ihps, NULL, 0);
295.Ed
296.Fa max_type
297is ignored in this case.
298.Fn pci_intr_alloc
299returns zero on any allocation function success, and non-zero on
300all allocation function failures.
301On success,
302.Fa counts
303is overwritten by a really allocated count.
304I.e., if 5 MSI-X is allocated,
305.Fa counts
306is
307.Bd -literal
308	counts[PCI_INTR_TYPE_MSIX] == 5
309	counts[PCI_INTR_TYPE_MSI] == 0
310	counts[PCI_INTR_TYPE_INTX] == 0
311.Ed
312on return.
313.Pp
314.Fn pci_intr_type
315returns the interrupt type of
316.Fa ih .
317The return value is
318.Dv PCI_INTR_TYPE_MSIX
319for MSI-X,
320.Dv PCI_INTR_TYPE_MSI
321for MSI, and
322.Dv PCI_INTR_TYPE_INTX
323for others.
324.Sh SEE ALSO
325.Xr pci_intr 9
326.Sh HISTORY
327.Nm
328support first appeared in
329.Nx 8.0 .
330Support is present on
331.Em i386 ,
332.Em amd64
333and
334.Em aarch64
335architectures.
336.Sh AUTHORS
337The
338.Nm
339interfaces were designed and implemented by
340.An Kengo Nakahara
341.Aq Mt knakahara@NetBSD.org .
342