ddi_trigger_softintr man page on SmartOS

Man page or keyword search:  
man Server   16655 pages
apropos Keyword Search (all sections)
Output format
SmartOS logo
[printable version]

DDI_ADD_SOFTINTR(9F)					  DDI_ADD_SOFTINTR(9F)

NAME
       ddi_add_softintr,    ddi_get_soft_iblock_cookie,	  ddi_remove_softintr,
       ddi_trigger_softintr - software interrupt handling routines

SYNOPSIS
       #include <sys/types.h>
       #include <sys/conf.h>
       #include <sys/ddi.h>
       #include <sys/sunddi.h>

       int ddi_get_soft_iblock_cookie(dev_info_t *dip,
       int preference, ddi_iblock_cookie_t *iblock_cookiep);

       int ddi_add_softintr(dev_info_t *dip, int preference, ddi_softintr_t *idp,
	    ddi_iblock_cookie_t *iblock_cookiep, ddi_idevice_cookie_t *
	    idevice_cookiep,
	    uint_t(*int_handler) (caddr_t int_handler_arg), caddr_t
	    int_handler_arg);

       void ddi_remove_softintr(ddi_softintr_t id);

       void ddi_trigger_softintr(ddi_softintr_t id);

INTERFACE LEVEL
       Solaris DDI specific (Solaris DDI). These interfaces are obsolete.  Use
       the  new interrupt interfaces referenced in Intro(9F). Refer to Writing
       Device Drivers for more information.

PARAMETERS
       ddi_get_soft_iblock_cookie()

       dip
			 Pointer to a dev_info structure.

       preference
			 The type of soft interrupt  to	 retrieve  the	cookie
			 for.

       iblock_cookiep
			 Pointer  to  a	 location to store the interrupt block
			 cookie.

       ddi_add_softintr()

       dip
			  Pointer to dev_info structure.

       preference
			  A hint value describing the type of  soft  interrupt
			  to generate.

       idp
			  Pointer  to  a  soft	interrupt  identifier  where a
			  returned soft interrupt identifier is stored.

       iblock_cookiep
			  Optional pointer to an interrupt block cookie	 where
			  a returned interrupt block cookie is stored.

       idevice_cookiep
			  Optional pointer to an interrupt device cookie where
			  a returned interrupt device cookie  is  stored  (not
			  used).

       int_handler
			  Pointer to interrupt handler.

       int_handler_arg
			  Argument for interrupt handler.

       ddi_remove_softintr()

       id
	     The identifier specifying which soft interrupt handler to remove.

       ddi_trigger_softintr()

       id
	     The  identifier  specifying  which	 soft interrupt to trigger and
	     which soft interrupt handler will be called.

DESCRIPTION
       For ddi_get_soft_iblock_cookie():

       ddi_get_soft_iblock_cookie() retrieves the interrupt block cookie asso‐
       ciated  with a particular soft interrupt preference level. This routine
       should be called before ddi_add_softintr() to  retrieve	the  interrupt
       block  cookie  needed to initialize locks ( mutex(9F), rwlock(9F)) used
       by the software interrupt routine. preference determines which type  of
       soft  interrupt	to  retrieve  the  cookie for. The possible values for
       preference are:

       DDI_SOFTINT_LOW
			   Low priority soft interrupt.

       DDI_SOFTINT_MED
			   Medium priority soft interrupt.

       DDI_SOFTINT_HIGH
			   High priority soft interrupt.

       On a successful return, iblock_cookiep contains information needed  for
       initializing   locks   associated   with	  this	 soft  interrupt  (see
       mutex_init(9F) and rw_init(9F)). The driver can then initialize mutexes
       acquired	 by  the  interrupt  routine before calling ddi_add_softintr()
       which prevents a possible race condition where the driver's soft inter‐
       rupt  handler  is  called  immediately  after  the  driver  has	called
       ddi_add_softintr() but before the driver has initialized	 the  mutexes.
       This  can happen when a soft interrupt for a different device occurs on
       the same soft interrupt priority level. If the soft  interrupt  routine
       acquires	 the  mutex before it has been initialized, undefined behavior
       may result.

       For ddi_add_softintr():

       ddi_add_softintr() adds a soft interrupt to the system. The user speci‐
       fied  hint  preference identifies three suggested levels for the system
       to attempt to allocate the soft interrupt priority at.  The  value  for
       preference should be the same as that used in the corresponding call to
       ddi_get_soft_iblock_cookie().   Refer	to    the    description    of
       ddi_get_soft_iblock_cookie() above.

       The value returned in the location pointed at by idp is the soft inter‐
       rupt identifier. This value is used in later calls to  ddi_remove_soft‐
       intr()  and  ddi_trigger_softintr()  to identify the soft interrupt and
       the soft interrupt handler.

       The value returned in the location pointed at by iblock_cookiep	is  an
       interrupt block cookie which contains information used for initializing
       mutexes associated with this soft  interrupt  (see  mutex_init(9F)  and
       rw_init(9F)). Note that the interrupt block cookie is normally obtained
       using  ddi_get_soft_iblock_cookie()  to	avoid  the   race   conditions
       described      above	 (refer	     to	    the	    description	    of
       ddi_get_soft_iblock_cookie() above).  For this  reason,	iblock_cookiep
       is no longer useful and should be set to NULL.

       idevice_cookiep is not used and should be set to NULL.

       The  routine  int_handler, with its argument int_handler_arg, is called
       upon receipt of a software interrupt. Software interrupt handlers  must
       not  assume  that they have work to do when they run, since (like hard‐
       ware interrupt handlers) they may run because a soft interrupt occurred
       for some other reason. For example, another driver may have triggered a
       soft interrupt at the same level. For this  reason,  before  triggering
       the soft interrupt, the driver must indicate to its soft interrupt han‐
       dler that it should do work. This is usually done by setting a flag  in
       the  state  structure. The routine int_handler checks this flag, reach‐
       able through int_handler_arg, 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, DDI_INTR_UNCLAIMED otherwise.

       If successful,  ddi_add_softintr()  will	 return	 DDI_SUCCESS;  if  the
       interrupt information cannot be found, it will return DDI_FAILURE.

       For ddi_remove_softintr():

       ddi_remove_softintr()  removes  a  soft	interrupt from the system. The
       soft interrupt identifier  id,  which  was  returned  from  a  call  to
       ddi_add_softintr(), is used to determine which soft interrupt and which
       soft interrupt handler to remove. Drivers must remove any  soft	inter‐
       rupt handlers before allowing the system to unload the driver.

       For ddi_trigger_softintr():

       ddi_trigger_softintr()  triggers	 a  soft interrupt. The soft interrupt
       identifier id is used to determine which	 soft  interrupt  to  trigger.
       This  function  is  used	 by device drivers when they wish to trigger a
       soft interrupt which has been set up using ddi_add_softintr().

RETURN VALUES
       ddi_add_softintr() and ddi_get_soft_iblock_cookie() return:

       DDI_SUCCESS
		      on success

       DDI_FAILURE
		      on failure

CONTEXT
       These functions can be called from user or kernel  context.   ddi_trig‐
       ger_softintr() may be called from high-level interrupt context as well.

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 inter‐
       rupts  are not blocked by the scheduler. In addition, high level inter‐
       rupt handlers must take care to do a minimum of work because  they  are
       not preemptable. See ddi_intr_hilevel(9F).

       In the example, the high-level interrupt routine minimally services the
       device, and enqueues the data for later processing by the  soft	inter‐
       rupt  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 inter‐
       rupt 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.

	 struct xxstate {
	       ...
	       ddi_softintr_t		  id;
		  ddi_iblock_cookie_t	  high_iblock_cookie;
		  kmutex_t			high_mutex;
		  ddi_iblock_cookie_t	  low_iblock_cookie;
		  kmutex_t			low_mutex;
		  int				   softint_running;
	       ...
	 };
	 struct xxstate *xsp;
	 static uint_t xxsoftintr(caddr_t);
	 static uint_t xxhighintr(caddr_t);
	 ...

       Example 2 sample attach() routine

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

	 static uint_t
	 xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
	 {
		  struct xxstate *xsp;
		  ...
	       /* get high-level iblock cookie */
		  if (ddi_get_iblock_cookie(dip, inumber,
			 &xsp->high_iblock_cookie) != DDI_SUCCESS)  {
			       /* clean up */
			       return (DDI_FAILURE); /* fail attach */
		  }

		  /* initialize high-level mutex */
		  mutex_init(&xsp->high_mutex, "xx high mutex", MUTEX_DRIVER,
			(void *)xsp->high_iblock_cookie);

		  /* add high-level routine - xxhighintr() */
		  if (ddi_add_intr(dip, inumber, NULL, NULL,
			 xxhighintr, (caddr_t) xsp) != DDI_SUCCESS)  {
			       /* cleanup */
			       return (DDI_FAILURE); /* fail attach */
		  }

		  /* get soft iblock cookie */
		  if (ddi_get_soft_iblock_cookie(dip, DDI_SOFTINT_MED,
			 &xsp->low_iblock_cookie) != DDI_SUCCESS)  {
			       /* clean up */
			       return (DDI_FAILURE); /* fail attach */
		  }

		  /* initialize low-level mutex */
		  mutex_init(&xsp->low_mutex, "xx low mutex", MUTEX_DRIVER,
			 (void *)xsp->low_iblock_cookie);

		  /* add low level routine - xxsoftintr() */
		  if ( ddi_add_softintr(dip, DDI_SOFTINT_MED, &xsp->id,
			 NULL, NULL, xxsoftintr, (caddr_t) xsp) != DDI_SUCCESS) {
			       /* cleanup */
			       return (DDI_FAILURE);  /* fail attach */
		  }

		  ...
	 }

       Example 3 High-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_trigger_soft‐
       intr() is called to start the routine. The soft interrupt routine  will
       run until there is no more data on the queue.

	 static uint_t
	 xxhighintr(caddr_t arg)
	 {
	       struct xxstate *xsp = (struct xxstate *) arg;
		  int need_softint;
		  ...
		  mutex_enter(&xsp->high_mutex);
		  /*
		  * Verify this device generated the interrupt
		  * and disable the device interrupt.
		  * Enqueue data for xxsoftintr() processing.
		  */

		  /* is xxsoftintr() already running ? */
		  if (xsp->softint_running)
			 need_softint = 0;
		   else
			 need_softint = 1;
		   mutex_exit(&xsp->high_mutex);

		   /* read-only access to xsp->id, no mutex needed */
		   if (need_softint)
			 ddi_trigger_softintr(xsp->id);
		   ...
		   return (DDI_INTR_CLAIMED);
	 }

	 static uint_t
	 xxsoftintr(caddr_t arg)
	 {
	       struct xxstate *xsp = (struct xxstate *) arg;
	       ...
		  mutex_enter(&xsp->low_mutex);
	       mutex_enter(&xsp->high_mutex);

	       /* verify there is work to do */
	       if (work queue empty || xsp->softint_running )  {
			 mutex_exit(&xsp->high_mutex);
			 mutex_exit(&xsp->low_mutex);
			 return (DDI_INTR_UNCLAIMED);
	       }

	       xsp->softint_running = 1;

		  while ( data on queue )  {
			 ASSERT(mutex_owned(&xsp->high_mutex));

			 /* de-queue data */

			 mutex_exit(&xsp->high_mutex);

			 /* Process data on queue */

			 mutex_enter(&xsp->high_mutex);
		   }

		   xsp->softint_running = 0;
		   mutex_exit(&xsp->high_mutex);
		   mutex_exit(&xsp->low_mutex);

		   return (DDI_INTR_CLAIMED);
	 }

ATTRIBUTES
       See attributes(5) for descriptions of the following attributes:

       ┌────────────────────┬─────────────────┐
       │  ATTRIBUTE TYPE    │ ATTRIBUTE VALUE │
       ├────────────────────┼─────────────────┤
       │Interface Stability │ Obsolete	      │
       └────────────────────┴─────────────────┘

SEE ALSO
       ddi_add_intr(9F),	ddi_in_panic(9F),	 ddi_intr_hilevel(9F),
       ddi_remove_intr(9F), Intro(9F), mutex_init(9F)

       Writing Device Drivers

NOTES
       ddi_add_softintr() 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  int_handler_arg  in	 each  of  the	calls  to  ddi_add_softintr().
       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 device's soft state structure, which
       could contain a 'which_service' field that the  handler	examines.  The
       driver  must  set  this	field  to the appropriate value before calling
       ddi_trigger_softintr().

				 Oct 19, 2005		  DDI_ADD_SOFTINTR(9F)
[top]

List of man pages available for SmartOS

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net