Description

The ddi_intr_add_softint() function adds the soft interrupt handler given by the handler
argument arg1. The handler runs at the soft interrupt priority given by
the soft_pri argument.

The value returned in the location pointed at by h is the
soft interrupt handle. This value is used in later calls to ddi_intr_remove_softint(),
ddi_intr_trigger_softint() and ddi_intr_set_softint_pri().

The software priority argument soft_pri is a relative priority value within the
range of DDI_INTR_SOFTPRI_MIN and DDI_INTR_SOFTPRI_MAX. If the driver does not know what
priority to use, the default soft_pri value of DDI_INTR_SOFTPRI_DEFAULT could be specified. The
default value is the lowest possible soft interrupt priority value.

The soft_pri argument contains the value needed to initialize the lock associated
with a soft interrupt. See mutex_init(9F) and rw_init(9F). The handler cannot be
triggered until the lock is initiatized.

The ddi_intr_remove_softint() function removes the handler for the soft interrupt identified by
the interrupt handle h argument. Once removed, the soft interrupt can no
longer be triggered, although any trigger calls in progress can still be
delivered to the handler.

Drivers must remove any soft interrupt handlers before allowing the system to
unload the driver. Otherwise, kernel resource leaks might occur.

The ddi_intr_trigger_softint() function triggers the soft interrupt specified by the interrupt handler
h argument. A driver may optionally specify an additional argument arg2 that
is passed to the soft interrupt handler. Subsequent ddi_intr_trigger_softint() events, along with
arg2, will be dropped until the one pending is serviced and returns
the error code DDI_EPENDING.

The routine handler, with the arg1 and arg2 arguments, is called upon
the receipt of a software interrupt. These were registered through a prior
call to ddi_intr_add_softint(). Software interrupt handlers must not assume that they have work
to do when they run. Like hardware interrupt handlers, they may run
because a soft interrupt has occurred for some other reason. For example,
another driver may have triggered a soft interrupt at the same level.
Before triggering the soft interrupt, the driver must indicate to the soft interrupt
handler that it has work to do. This is usually done by
setting a flag in the state structure. The routine handler checks this
flag, reached through arg1 and arg2, to determine if it should claim the
interrupt and do its work.

The interrupt handler must return DDI_INTR_CLAIMED if the interrupt was claimed and
DDI_INTR_UNCLAIMED otherwise.

The ddi_intr_get_softint_pri() function retrieves the soft interrupt priority, a small integer value,
associated with the soft interrupt handle. The handle is defined by the
h argument, and the priority returned is in the value of the
integer pointed to by the soft_prip argument.

Context

The ddi_intr_add_softint(), ddi_intr_remove_softint(), ddi_intr_trigger_softint(), ddi_intr_get_softint_pri(), ddi_intr_set_softint_pri() functions can be called from either
user or kernel non-interrupt context.

Examples

Example 1 Device using high-level interrupts

In the following example, the device uses high-level interrupts. High-level interrupts are
those that interrupt at the level of the scheduler and above. High-level
interrupts must be handled without using system services that manipulate thread or
process states, because these interrupts are not blocked by the scheduler. In addition,
high-level interrupt handlers must take care to do a minimum of work
because they are not preemptable. See ddi_intr_get_hilevel_pri(9F).

In the example, the high-level interrupt routine minimally services the device, and
enqueues the data for later processing by the soft interrupt handler. If
the soft interrupt handler is not currently running, the high-level interrupt routine
triggers a soft interrupt so the soft interrupt handler can process the data.
Once running, the soft interrupt handler processes all the enqueued data before
returning.

The state structure contains two mutexes. The high-level mutex is used to
protect data shared between the high-level interrupt handler and the soft interrupt
handler. The low-level mutex is used to protect the rest of the
driver from the soft interrupt handler.

The following code fragment would usually appear in the driver's attach(9E) routine.
ddi_intr_add_handler(9F) is used to add the high-level interrupt handler and ddi_intr_add_softint() is
used to add the low-level interrupt routine.

The next code fragment represents the high-level interrupt routine. The high-level interrupt
routine minimally services the device and enqueues the data for later processing
by the soft interrupt routine. If the soft interrupt routine is not
already running, ddi_intr_trigger_softint() is called to start the routine. The soft interrupt routine
will run until there is no more data on the queue.

See Also

Notes

Consumers of these interfaces should verify that the return value is not
equal to DDI_SUCCESS. Incomplete checking for failure codes could result in inconsistent
behavior among platforms.

The ddi_intr_add_softint() may not be used to add the same software interrupt
handler more than once. This is true even if a different value
is used for arg1 in each of the calls to ddi_intr_add_softint(). Instead,
the argument passed to the interrupt handler should indicate what service(s) the interrupt
handler should perform. For example, the argument could be a pointer to
the soft state structure of the device that could contain a which_service
field that the handler examines. The driver must set this field to the
appropriate value before calling ddi_intr_trigger_softint().

Every time a modifiable valid second argument, arg2, is provided when ddi_intr_trigger_softint()
is invoked, the DDI framework saves arg2 internally and passes it to
the interrupt handler handler.

A call to ddi_intr_set_softint_pri() could fail if a previously scheduled soft interrupt
trigger is still pending.