Unleashed v1.4
[unleashed.git] / share / man / man9f / ddi_intr_add_softint.9f
blob7ffbf122e27a8ee42d15148cf3594174e5c999b8
1 '\" te
2 .\" Copyright (c) 2005, Sun Microsystems, Inc. All Rights Reserved.
3 .\" 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.
4 .\" 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.
5 .\" 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]
6 .TH DDI_INTR_ADD_SOFTINT 9F "Oct 16, 2005"
7 .SH NAME
8 ddi_intr_add_softint, ddi_intr_remove_softint, ddi_intr_trigger_softint,
9 ddi_intr_get_softint_pri, ddi_intr_set_softint_pri \- software interrupt
10 handling routines
11 .SH SYNOPSIS
12 .LP
13 .nf
14 #include <sys/types.h>
15 #include <sys/conf.h>
16 #include <sys/ddi.h>
17 #include <sys/sunddi.h>
21 \fBint\fR \fBddi_intr_add_softint\fR(\fBdev_info_t *\fR\fIdip\fR,
22      \fBddi_softint_handle_t *\fR\fIh\fR, \fBint\fR \fIsoft_pri\fR,
23      \fBddi_intr_handler_t\fR \fIhandler\fR, \fBvoid *\fR\fIarg1\fR);
24 .fi
26 .LP
27 .nf
28 \fBint\fR \fBddi_intr_trigger_softint\fR(\fBddi_softint_handle_t\fR \fIh\fR,
29       \fBvoid *\fR\fIarg2\fR);
30 .fi
32 .LP
33 .nf
34 \fBint\fR \fBddi_intr_remove_softint\fR(\fBddi_softint_handle_t\fR \fIh\fR);
35 .fi
37 .LP
38 .nf
39 \fBint\fR \fBddi_intr_get_softint_pri\fR(\fBddi_softint_handle_t\fR \fIh\fR,
40       \fBuint *\fR\fIsoft_prip\fR);
41 .fi
43 .LP
44 .nf
45 \fBint\fR \fBddi_intr_set_softint_pri\fR(\fBddi_softint_handle_t\fR \fIh\fR,
46       \fBuint\fR \fIsoft_pri\fR);
47 .fi
49 .SH INTERFACE LEVEL
50 .sp
51 .LP
52 Solaris DDI specific (Solaris DDI).
53 .SH PARAMETERS
54 .sp
55 .LP
56 \fBddi_intr_add_softint()\fR
57 .sp
58 .ne 2
59 .na
60 \fB\fIdip\fR\fR
61 .ad
62 .RS 12n
63 Pointer to a \fBdev_info\fR structure
64 .RE
66 .sp
67 .ne 2
68 .na
69 \fB\fIh\fR\fR
70 .ad
71 .RS 12n
72 Pointer to the DDI soft interrupt handle
73 .RE
75 .sp
76 .ne 2
77 .na
78 \fB\fIsoft_pri\fR\fR
79 .ad
80 .RS 12n
81 Priority to associate with a soft interrupt
82 .RE
84 .sp
85 .ne 2
86 .na
87 \fB\fIhandler\fR\fR
88 .ad
89 .RS 12n
90 Pointer to soft interrupt handler
91 .RE
93 .sp
94 .ne 2
95 .na
96 \fB\fIarg1\fR\fR
97 .ad
98 .RS 12n
99 Argument for the soft interrupt handler
104 \fBddi_intr_trigger_softint()\fR
106 .ne 2
108 \fB\fIh\fR\fR
110 .RS 8n
111 DDI soft interrupt handle
115 .ne 2
117 \fB\fIarg2\fR\fR
119 .RS 8n
120 Additional argument for the soft interrupt handler
125 \fBddi_intr_remove_softint()\fR
127 .ne 2
129 \fB\fIh\fR\fR
131 .RS 5n
132 DDI soft interrupt handle
137 \fBddi_intr_get_softint_pri()\fR
139 .ne 2
141 \fB\fIh\fR\fR
143 .RS 13n
144 DDI soft interrupt handle
148 .ne 2
150 \fB\fIsoft_prip\fR\fR
152 .RS 13n
153 Soft interrupt priority of the handle
158 \fBddi_intr_set_softint_pri()\fR
160 .ne 2
162 \fB\fIh\fR\fR
164 .RS 13n
165 DDI soft interrupt handle
169 .ne 2
171 \fB\fIsoft_prip\fR\fR
173 .RS 13n
174 Soft interrupt priority of the handle
177 .SH DESCRIPTION
180 The \fBddi_intr_add_softint()\fR function adds the soft interrupt handler given
181 by the \fIhandler\fR argument \fIarg1\fR. The \fIhandler\fR runs at the soft
182 interrupt priority given by the \fIsoft_pri\fR argument.
185 The value returned in the location pointed at by \fIh\fR is the soft interrupt
186 handle. This value is used in later calls to \fBddi_intr_remove_softint()\fR,
187 \fBddi_intr_trigger_softint()\fR and \fBddi_intr_set_softint_pri()\fR.
190 The software priority argument \fIsoft_pri\fR is a relative priority value
191 within the range of \fBDDI_INTR_SOFTPRI_MIN\fR and \fBDDI_INTR_SOFTPRI_MAX\fR.
192 If the driver does not know what priority to use, the default \fIsoft_pri\fR
193 value of \fBDDI_INTR_SOFTPRI_DEFAULT\fR could be specified. The default value
194 is the lowest possible soft interrupt priority value.
197 The \fIsoft_pri\fR argument contains the value needed to initialize the lock
198 associated with a soft interrupt. See \fBmutex_init\fR(9F) and
199 \fBrw_init\fR(9F). The handler cannot be triggered until the lock is
200 initiatized.
203 The \fBddi_intr_remove_softint()\fR function removes the handler for the soft
204 interrupt identified by the interrupt handle \fIh\fR argument. Once removed,
205 the soft interrupt can no longer be triggered, although any trigger calls in
206 progress can still be delivered to the handler.
209 Drivers must remove any soft interrupt handlers before allowing the system to
210 unload the driver. Otherwise, kernel resource leaks might occur.
213 The \fBddi_intr_trigger_softint()\fR function triggers the soft interrupt
214 specified by the interrupt handler \fIh\fR argument. A driver may optionally
215 specify an additional argument \fIarg2\fR that is passed to the soft interrupt
216 handler. Subsequent \fBddi_intr_trigger_softint()\fR events, along with
217 \fIarg2\fR, will be dropped until the one pending is serviced and returns the
218 error code \fBDDI_EPENDING\fR.
221 The routine \fIhandler\fR, with the \fIarg1\fR and \fIarg2\fR arguments, is
222 called upon the receipt of a software interrupt. These were registered through
223 a prior call to \fBddi_intr_add_softint()\fR. Software interrupt handlers must
224 not assume that they have work to do when they run. Like hardware interrupt
225 handlers, they may run because a soft interrupt has occurred for some other
226 reason. For example, another driver may have triggered a soft interrupt at the
227 same level. Before triggering the soft interrupt, the driver must indicate to
228 the soft interrupt handler that it has work to do. This is usually done by
229 setting a flag in the state structure. The routine \fIhandler\fR checks this
230 flag, reached through \fIarg1\fR and \fIarg2\fR, to determine if it should
231 claim the interrupt and do its work.
234 The interrupt handler must return \fBDDI_INTR_CLAIMED\fR if the interrupt was
235 claimed and \fBDDI_INTR_UNCLAIMED\fR otherwise.
238 The \fBddi_intr_get_softint_pri()\fR function retrieves the soft interrupt
239 priority, a small integer value, associated with the soft interrupt handle. The
240 handle is defined by the \fIh\fR argument, and the priority returned is in the
241 value of the integer pointed to by the \fIsoft_prip\fR argument.
242 .SH RETURN VALUES
245 The \fBddi_intr_add_softint()\fR, \fBddi_intr_remove_softint()\fR,
246 \fBddi_intr_trigger_softint()\fR, \fBddi_intr_get_softint_pri()\fR,
247 \fBddi_intr_set_softint_pri()\fR functions return:
249 .ne 2
251 \fB\fBDDI_SUCCESS\fR\fR
253 .RS 16n
254 On success.
258 .ne 2
260 \fB\fBDDI_EAGAIN\fR\fR
262 .RS 16n
263 On encountering internal error regarding currently unavailable resources.
267 .ne 2
269 \fB\fBDDI_EINVAL\fR\fR
271 .RS 16n
272 On encountering invalid input parameters.
276 .ne 2
278 \fB\fBDDI_FAILURE\fR\fR
280 .RS 16n
281 On any implementation specific failure.
285 .ne 2
287 \fB\fBDDI_EPENDING\fR\fR
289 .RS 16n
290 On encountering a previously triggered softint event that is pending.
293 .SH CONTEXT
296 The \fBddi_intr_add_softint()\fR, \fBddi_intr_remove_softint()\fR,
297 \fBddi_intr_trigger_softint()\fR, \fBddi_intr_get_softint_pri()\fR,
298 \fBddi_intr_set_softint_pri()\fR functions can be called from either user or
299 kernel non-interrupt context.
300 .SH EXAMPLES
302 \fBExample 1 \fRDevice using high-level interrupts
305 In the following example, the device uses high-level interrupts. High-level
306 interrupts are those that interrupt at the level of the scheduler and above.
307 High-level interrupts must be handled without using system services that
308 manipulate thread or process states, because these interrupts are not blocked
309 by the scheduler. In addition, high-level interrupt handlers must take care to
310 do a minimum of work because they are not preemptable. See
311 \fBddi_intr_get_hilevel_pri\fR(9F).
315 In the example, the high-level interrupt routine minimally services the device,
316 and enqueues the data for later processing by the soft interrupt handler. If
317 the soft interrupt handler is not currently running, the high-level interrupt
318 routine triggers a soft interrupt so the soft interrupt handler can process the
319 data. Once running, the soft interrupt handler processes all the enqueued data
320 before returning.
324 The state structure contains two mutexes. The high-level mutex is used to
325 protect data shared between the high-level interrupt handler and the soft
326 interrupt handler. The low-level mutex is used to protect the rest of the
327 driver from the soft interrupt handler.
330 .in +2
332 struct xxstate {
333   ...
334   ddi_intr_handle_t       int_hdl;
335   int                     high_pri;
336   kmutex_t                high_mutex;
337   ddi_softint_handle_t    soft_hdl;
338   int                     low_soft_pri;
339   kmutex_t                low_mutex;
340   int                     softint_running;
341   ...
344 struct xxstate *xsp;
345 static uint_t xxsoftint_handler(void *, void *);
346 static uint_t xxhighintr(void *, void *);
347 \&...
349 .in -2
352 \fBExample 2 \fRSample \fBattach()\fR routine
355 The following code fragment would usually appear in the driver's
356 \fBattach\fR(9E) routine. \fBddi_intr_add_handler\fR(9F) is used to add the
357 high-level interrupt handler and \fBddi_intr_add_softint()\fR is used to add
358 the low-level interrupt routine.
361 .in +2
363 static uint_t
364 xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
366    int             types;
367    int             *actual;
368    int             nintrs;
369    struct xxstate  *xsp;
370    ...
372    (void) ddi_intr_get_supported_types(dip, &types);
373    (void) ddi_intr_get_nintrs(dip< DDI_INTR_TYPE_FIXED, *nintrs);
374    (void) ddi_intr_alloc(dip, &xsp->int_hdl, DDI_INTR_TYPE_FIXED,
375        1, nintrs, *actual, 0);
377    /* initialize high-level mutex */
378    (void) ddi_intr_get_pri(xsp->int_hdl, &>high_pri);
379    mutex_init(&xsp->high_mutex, NULL, MUTEX_DRIVER,
380        DDI_INTR_PRI(xsp->high_pri));
382    /* Ensure that this is a hi-level interrupt */
383    if (ddi_intr_get_hilevel_pri(h) != DDI_SUCCESS) {
384            /* cleanup */
385            return (DDI_FAILURE); /* fail attach */
386    }
388    /* add high-level routine - xxhighintr() */
389    if (ddi_intr_add_handler(xsp->int_hdl, xxhighintr,
390        arg1, NULL) != DDI_SUCCESS) {
391            /* cleanup */
392            return (DDI_FAILURE); /* fail attach */
393    }
395    /* Enable high-level routine - xxhighintr() */
396    if (ddi_intr_enable(xsp->int_hdl) != DDI_SUCCESS) {
397            /* cleanup */
398            return (DDI_FAILURE); /* fail attach */
399    }
401    /* Enable soft interrupts */
402    xsp->low_soft_pri = DDI_INTR_SOFTPRI_MIN;
403    if (ddi_intr_add_softint(dip, &xsp>soft_hdl,
404        xsp->low_soft_pri, xxsoftint_handler, arg1) != DDI_SUCCESS) {
405            /* clean up */
406            return (DDI_FAILURE); /* fail attach */
407    }
409    /* initialize low-level mutex */
410    mutex_init(&xsp->low_mutex, NULL, MUTEX_DRIVER,
411        DDI_INTR_PRI(xsp->low_soft_pri));
413    ...
416 .in -2
419 \fBExample 3 \fRHigh-level interrupt routine
422 The next code fragment represents the high-level interrupt routine. The
423 high-level interrupt routine minimally services the device and enqueues the
424 data for later processing by the soft interrupt routine. If the soft interrupt
425 routine is not already running, \fBddi_intr_trigger_softint()\fR is called to
426 start the routine. The soft interrupt routine will run until there is no more
427 data on the queue.
430 .in +2
432 static uint_t
433 xxhighintr(void *arg1, void *arg2)
435    struct xxstate *xsp = (struct xxstate *)arg1;
436    int need_softint;
437    ...
438    mutex_enter(&xsp->high_mutex);
439    /*
440    * Verify this device generated the interrupt
441    * and disable the device interrupt.
442    * Enqueue data for xxsoftint_handler() processing.
443    */
445    /* is xxsoftint_handler() already running ? */
446    need_softint = (xsp->softint_running) ? 0 : 1;
447    mutex_exit(&xsp->high_mutex);
449    /* read-only access to xsp->id, no mutex needed */
450    if (xsp->soft_hdl && need_softint)
451            ddi_intr_trigger_softint(xsp->soft_hdl, arg2);
452    ...
453    return (DDI_INTR_CLAIMED);
457 static uint_t
458 xxsoftint_handler(void *arg1, void *arg2)
460    struct xxstate *xsp = (struct xxstate *)arg1;
461    ...
462    mutex_enter(&xsp->low_mutex);
463    mutex_enter(&xsp->high_mutex);
465    /* verify there is work to do */
466    if (work queue empty || xsp->softint_running )  {
467            mutex_exit(&xsp->high_mutex);
468            mutex_exit(&xsp->low_mutex);
469            return (DDI_INTR_UNCLAIMED);
470    }
472    xsp->softint_running = 1;
474    while ( data on queue )  {
475            ASSERT(mutex_owned(&xsp->high_mutex));
476            /* de-queue data */
477            mutex_exit(&xsp->high_mutex);
479            /* Process data on queue */
480            mutex_enter(&xsp->high_mutex);
481    }
483    xsp->softint_running = 0;
484    mutex_exit(&xsp->high_mutex);
485    mutex_exit(&xsp->low_mutex);
486    return (DDI_INTR_CLAIMED);
489 .in -2
491 .SH ATTRIBUTES
494 See \fBattributes\fR(5) for descriptions of the following attributes:
499 box;
500 c | c
501 l | l .
502 ATTRIBUTE TYPE  ATTRIBUTE VALUE
504 Interface Stability     Evolving
507 .SH SEE ALSO
510 \fBattributes\fR(5), \fBattach\fR(9E), \fBddi_intr_alloc\fR(9F),
511 \fBddi_intr_free\fR(9F), \fBddi_intr_get_hilevel_pri\fR(9F),
512 \fBmutex_init\fR(9F), \fBrw_init\fR(9F), \fBrwlock\fR(9F)
515 \fIWriting Device Drivers\fR
516 .SH NOTES
519 Consumers of these interfaces should verify that the return value is not equal
520 to \fBDDI_SUCCESS\fR. Incomplete checking for failure codes could result in
521 inconsistent behavior among platforms.
524 The \fBddi_intr_add_softint()\fR may not be used to add the same software
525 interrupt handler more than once. This is true even if a different value is
526 used for \fIarg1\fR in each of the calls to \fBddi_intr_add_softint()\fR.
527 Instead, the argument passed to the interrupt handler should indicate what
528 service(s) the interrupt handler should perform. For example, the argument
529 could be a pointer to the soft state structure of the device that could contain
530 a \fBwhich_service\fR field that the handler examines. The driver must set this
531 field to the appropriate value before calling \fBddi_intr_trigger_softint()\fR.
534 Every time a modifiable valid second argument, \fIarg2\fR, is provided when
535 \fBddi_intr_trigger_softint()\fR is invoked, the DDI framework saves \fIarg2\fR
536 internally and passes it to the interrupt handler \fIhandler\fR.
539 A call to \fBddi_intr_set_softint_pri()\fR could fail if a previously scheduled
540 soft interrupt trigger is still pending.