xref: /netbsd-src/share/man/man9/pci_msi.9 (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1.\" $NetBSD: pci_msi.9,v 1.7 2015/08/13 05:01:04 msaitoh 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 August 13, 2015
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  "struct pci_attach_args *pa" \
51"pci_intr_handle_t **ihps" "int *count"
52.Ft int
53.Fn pci_msi_alloc_exect "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  "struct pci_attach_args *pa" \
60"pci_intr_handle_t **ihps" "int *count"
61.Ft int
62.Fn pci_msix_alloc_exect "struct pci_attach_args *pa" \
63"pci_intr_handle_t **ihps" "int count"
64.Ft int
65.Fn pci_msix_alloc_map "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  "struct pci_attach_args *pa" \
69"pci_intr_handle_t **ihp"
70.Ft int
71.Fn pci_intr_alloc  "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_intr_handle_t ih"
79.Sh DESCRIPTION
80The
81.Nm
82functions exist to allow device drivers to use MSI/MSI-X.
83When the system uses MSI/MSI-X, it must define the
84.Dv __HAVE_PCI_MSI_MSIX
85build option.
86.Pp
87Each driver has an
88.Fn attach
89function which has a bus-specific
90.Ft attach_args
91structure.
92Each driver for a PCI device is passed a pointer to an object of type
93.Ft struct pci_attach_args
94which contains, among other things, information about the location
95of the device in the PCI bus topology sufficient to allow interrupts
96from the device to be handled.
97.Pp
98If a driver wishes to establish an MSI handler for the device,
99it should pass the
100.Ft struct pci_attach_args *
101and
102.Fa count
103.Fn pci_msi_alloc
104or
105.Fn pci_msi_alloc_exact
106functions, which return zero on success, and nonzero on failure.
107When the functions are successful, they return the pointer to the
108allocated handle array in
109.Ft pihs
110whose size is
111.Ft count
112or less.
113The difference between
114.Fn pci_msi_alloc
115and
116.Fn pci_msi_alloc_exact
117is whether
118.Fa count
119can be decremented or not.
120.Fn pci_msi_alloc
121can decrement
122.Fa count ,
123and which is similar to
124.Fx Ap s
125.Fn pci_alloc_msi .
126In contrast,
127.Fn pci_msi_alloc_exact
128can not decrement
129.Ft count .
130.Pp
131If the driver wishes to refer to the MSI source in an attach or
132error message, it should use the value returned by
133.Fn pci_intr_string
134the same as INTx.
135The buffer passed to
136.Fn pci_intr_string
137should be at least
138.Dv PCI_INTRSTR_LEN
139bytes long.
140.Pp
141Subsequently, when the driver is prepared to receive MSIs, it
142should call
143.Fn pci_intr_establish
144the same as INTx to actually establish the handler;
145when the device interrupts,
146.Fa intrhand
147will be called with a single argument
148.Fa intrarg ,
149and will run at the interrupt priority level
150.Fa ipl .
151.Pp
152The return value of
153.Fn pci_intr_establish
154may be saved and passed to
155.Fn pci_intr_disestablish
156to disable the interrupt handler the same as INTx
157when the driver is no longer interested in MSIs from the device.
158After that, the driver should also call
159.Fn pci_intr_release
160to free resources about MSI as well as INTx and MSI-X.
161.Pp
162If a driver wishes to establish an MSI-X handler for the device,
163it is almost the same as MSI.
164The only differences is
165.Fn pci_msix_alloc_map .
166This function can assign separate handlers for each MSI-X table
167entry.
168I.e., if the driver wants to assign the handlers in the following way:
169.Bd -literal
170	msix_handler0 => MSI-X table index: 4
171	msix_handler1 => MSI-X table index: 5
172	msix_handler2 => MSI-X table index: 0
173.Ed
174the driver should set
175.Fa table_indexes
176this way:
177.Bd -literal
178	table_indexes[0] = 4;
179	table_indexes[1] = 5;
180	table_indexes[2] = 0;
181.Ed
182.Pp
183If the driver wants to fall back to INTx, the driver should use
184.Fn pci_intx_alloc
185and
186.Fn pci_intr_release
187instead of
188.Fn pci_intr_map
189to resolve contradiction of the interrupt handler ownership.
190I.e.,
191.Fn pci_intr_map
192does not have the ownership (the function just calculates value),
193in contrast,
194.Fn pci_msi_alloc
195and
196.Fn pci_msix_alloc
197have (the functions allocate memory for interrupt handlers).
198.Pp
199.Fn pci_intr_alloc
200is wrapper function which select and automatically fallback
201allocation functions according to the argument
202.Fa counts .
203The elements of
204.Fa counts
205array means each required interrupt count for INTx, MSI, and MSI-X.
206The index count of
207.Fa counts
208must be
209.Dv PCI_INTR_TYPE_SIZE .
210.Fa max_type
211must be
212.Dv PCI_INTR_TYPE_MSIX ,
213.Dv PCI_INTR_TYPE_MSI ,
214or
215.Dv PCI_INTR_TYPE_INTX .
216The parameter does not mean array index counts of
217.Fa counts .
218The parameter means the interrupt type which
219.Fn pci_intr_alloc
220tries to allocate first.
221I.e., if the driver wants to allocate interrupts in the following way:
222.Bd -literal
223	5 MSI-X
224	1 MSI (if MSI-X allocation failed)
225	INTx (if MSI allocation failed either)
226.Ed
227the driver should call
228.Fn pci_intr_alloc
229in the following way:
230.Bd -literal
231	int counts[PCI_INTR_TYPE_SIZE];
232	counts[PCI_INTR_TYPE_MSIX] = 5;
233	counts[PCI_INTR_TYPE_MSI] = 1;
234	counts[PCI_INTR_TYPE_INTX] = 1;
235	error = pci_intr_alloc(pa, ihps, counts,
236			       PCI_INTR_TYPE_MSIX);
237.Ed
238If the driver wants to allocate interrupts in the following way:
239.Bd -literal
240	hardware max number MSI-X
241	1 MSI (if MSI-X allocation failed)
242.Ed
243that is, the driver does not use INTx, the driver should call
244.Fn pci_intr_alloc
245in the following way:
246.Bd -literal
247	int counts[PCI_INTR_TYPE_SIZE];
248	counts[PCI_INTR_TYPE_MSIX] = -1; /* -1 means max */
249	counts[PCI_INTR_TYPE_MSI] = 1;
250	counts[PCI_INTR_TYPE_INTX] = 0; /* 0 means not use */
251	error = pci_intr_alloc(pa, ihps, counts,
252			       PCI_INTR_TYPE_MSIX);
253.Ed
254If the driver wants to allocate interrupts in the following way:
255.Bd -literal
256	3 MSI
257	INTx (if MSI allocation failed)
258.Ed
259that is, the driver does not use MSI-X, the driver should call
260.Fn pci_intr_alloc
261in the following way:
262.Bd -literal
263	int counts[PCI_INTR_TYPE_SIZE];
264	counts[PCI_INTR_TYPE_MSIX] = 0; /* 0 means not use */
265	counts[PCI_INTR_TYPE_MSI] = 3;
266	counts[PCI_INTR_TYPE_INTX] = 1;
267	error = pci_intr_alloc(pa, ihps, counts,
268			       PCI_INTR_TYPE_MSI);
269.Ed
270If the driver wants to allocate interrupts in the following way:
271.Bd -literal
272	1 MSI
273	INTx (if MSI allocation failed)
274.Ed
275that is, general usage, the driver should call simply
276.Fn pci_intr_alloc
277in the following way:
278.Bd -literal
279	error = pci_intr_alloc(pa, ihps, NULL, 0);
280.Ed
281.Fa max_type
282is ignored in this case.
283.Fn pci_intr_alloc
284returns zero on any allocation function success, and non-zero on
285all allocation function failures.
286On success,
287.Fa counts
288is overwritten by a really allocated count.
289I.e., if 5 MSI-X is allocated,
290.Fa counts
291is
292.Bd -literal
293	counts[PCI_INTR_TYPE_MSIX] == 5
294	counts[PCI_INTR_TYPE_MSI] == 0
295	counts[PCI_INTR_TYPE_INTX] == 0
296.Ed
297on return.
298.Pp
299.Fn pci_intr_type
300returns the interrupt type of
301.Fa ih .
302The return value is
303.Dv PCI_INTR_TYPE_MSIX
304for MSI-X,
305.Dv PCI_INTR_TYPE_MSI
306for MSI, and
307.Dv PCI_INTR_TYPE_INTX
308for others.
309.Sh SEE ALSO
310.Xr pci_intr 9
311