MyWebUniversity.com Home Page
 



OpenSolaris man pages main menu


Kernel Functions for Drivers             ddiintrduphandler(9F)



NAME
     ddiintrduphandler - reuse interrupt handler and arguments
     for MSI-X interrupts

SYNOPSIS
     #include 
     #include 
     #include 
     #include 

     int ddiintrduphandler(ddiintrhandlet primary, int vector,
          ddiintrhandlet *new);


INTERFACE LEVEL
     Solaris DI specific (Solaris DI).

PARAMETERS
     primary    Original DI interrupt handle


     vector     Interrupt number to duplicate


     new        Pointer to new DI interrupt handle


DESCRIPTION
     The ddiintrduphandler() function is a feature  for  MSI-X
     interrupts  that allows an unallocated interrupt vector of a
     device to use a  previously  initialized  or  added  primary
     MSI-X  interrupt  vector  in  order to share the same vector
     address, vector data, interrupt handler, and  handler  argu-
     ments.  This  feature allows a driver to alias the resources
     provided by the Solaris Operating System to the  unallocated
     interrupt vectors on an associated device. For example, if 2
     MSI-X interrupts were allocated to a driver  and  32  inter-
     rupts  were  supported on the device, the driver could alias
     the 2 interrupts it received to the 30 remaining on the dev-
     ice.


     The ddiintrduphandler() function must be called after the
     primary  interrupt  handle  has  been added to the system or
     enabled by ddiintraddhandler(9F) and  ddiintrenable(9F)
     calls, respectively. If successful, the function returns the
     new interrupt handle for a given vector in the new  argument
     passed  to  the  function. The new interrupt handle must not
     have been previously allocated with ddiintralloc(9F). Oth-
     erwise, the ddiintrduphandler() call will fail.





SunOS 5.11          Last change: 09 May 2006                    1






Kernel Functions for Drivers             ddiintrduphandler(9F)



     The only supported calls on  dup-ed  interrupt  handles  are
     ddiintrsetmask(9F),                ddiintrclrmask(9F),
     ddiintrgetpending(9F),               ddiintrenable(9F),
     ddiintrdisable(9F), and ddiintrfree(9F).


     A call to ddiintrduphandler() does  not  imply  that  the
     interrupt  source  is  automatically enabled. Initially, the
     dup-ed handle is in the disabled state and must  be  enabled
     before  it  can  be used by calling ddiintrenable(). Like-
     wise, ddiintrdisable()  must  be  called  to  disable  the
     enabled dup-ed interrupt source.


     A dup-ed interrupt is  removed  by  calling  ddiintrfree()
     after  it has been disabled. The ddiintrremovehandler(9F)
     call is not required for a dup-ed handle.


     Before removing the original MSI-X  interrupt  handler,  all
     dup-ed  interrupt handlers associated with this MSI-X inter-
     rupt must have been disabled and freed. Otherwise, calls  to
     ddiintrremovehandler() will fail with DIFAILURE.


     See the EXAMPLES section for code that illustrates  the  use
     of the ddiintrduphandler() function.

RETURN VALUES
     The ddiintrduphandler() function returns:

     DISUCES    On success.

                    Note that the interface should be verified to
                    ensure  that the return value is not equal to
                    DISUCES. Incomplete checking for  failure
                    codes  could  result in inconsistent behavior
                    among platforms.


     DIEINVAL     On  encountering  invalid  input  parameters.
                    DIEINVAL  is  also  returned  if  a  dup is
                    attempted from a dup-ed interrupt or  if  the
                    hardware device is found not to support MSI-X
                    interrupts.


     DIFAILURE    On any implementation specific failure.


EXAMPLES




SunOS 5.11          Last change: 09 May 2006                    2






Kernel Functions for Drivers             ddiintrduphandler(9F)



     Example 1 Using the ddiintrduphandler() function

       int
       addmsixinterrupts(intrstatet *state)
       {
         int x, y;

         /*
          * For this example, assume the device supports multiple
          * interrupt vectors, but only request to be allocated
          * 1 MSI-X to use and then dup the rest.
          */
         if (ddiintrgetnintrs(state->dip, DINTRTYPEMSIX,
            &state->intrcount) != DISUCES) {
                 cmnerr(CEWARN, "Failed to retrieve the MSI-X interrupt count");
                 return (DIFAILURE);
         }

         state->intrsize = state->intrcount * sizeof (ddiintrhandlet);
         state->intrhtable = kmemzalloc(state->intrsize, KMSLEP);

         /* Allocate one MSI-X interrupt handle */
         if (ddiintralloc(state->dip, state->intrhtable,
             DINTRTYPEMSIX, state->inum, 1, &state->actual,
             DINTRALOCSTRICT) != DISUCES) {
                 cmnerr(CEWARN, "Failed to allocate MSI-X interrupt");
                 kmemfree(state->intrhtable, state->intrsize);
                 return (DIFAILURE);
         }

         /* Get the count of how many MSI-X interrupts we dup */
         state->dupcnt = state->intrcount - state->actual;

         if (ddiintrgetpri(state->intrhtable[0],
             &state->intrpri) != DISUCES) {
                 cmnerr(CEWARN, "Failed to get interrupt priority");
                 goto error1;
         }

         /* Make sure the MSI-X priority is below 'high level' */
         if (state->intrpri >= ddiintrgethilevelpri()) {
                cmnerr(CEWARN, "Interrupt PRI is too high");
                 goto error1;
         }

         /*
          * Add the handler for the interrupt
          */
         if (ddiintraddhandler(state->intrhtable[0],
             (ddiintrhandlert *)intrisr, (caddrt)state,
             NUL) != DISUCES) {
                 cmnerr(CEWARN, "Failed to add interrupt handler");



SunOS 5.11          Last change: 09 May 2006                    3






Kernel Functions for Drivers             ddiintrduphandler(9F)



                 goto error1;
         }

         /* Enable the main MSI-X handle first */
         if (ddiintrenable(state->intrhtable[0]) != DISUCES) {
                 cmnerr(CEWARN, "Failed to enable interrupt");
                 goto error2;
         }

         /*
          * Create and enable dups of the original MSI-X handler, note
          * that the inum we are using starts at 0.
          */
         for (x = 1; x < state->dupcnt; x]) {
             if (ddiintrduphandler(state->intrhtable[0],
                 state->inum ] x, &state->intrhtable[x]) != DISUCES) {
                     for (y = x - 1; y > 0; y--) {
                         (void) ddiintrdisable(state->intrhtable[y]);
                         (void) ddiintrfree(state->intrhtable[y]);
                     }

                 goto error2;
             }
             if (ddiintrenable(state->intrhtable[x]) != DISUCES) {
                 for (y = x; y > 0; y--) {
                     (void) ddiintrdisable(state->intrhtable[y]);
                     (void) ddiintrfree(state->intrhtable[y]);
                 }

                 goto error2;
             }
         }

         return (DISUCES);

       error2:
           (void) ddiintrremovehandler(state->intrhtable[0]);
       error1:
           (void) ddiintrfree(state->intrhtable[0]);

           kmemfree(state->intrhtable, state->intrsize);
           return (DIFAILURE);
       }

       void
       removemsixinterrupts(intrstatet *state)
       {
           int x;

           /*
            * Disable all the handles and free the dup-ed handles
            * before we can remove the main MSI-X interrupt handle.



SunOS 5.11          Last change: 09 May 2006                    4






Kernel Functions for Drivers             ddiintrduphandler(9F)



            */
           for (x = 1; x < state->dupcnt; x]) {
               (void) ddiintrdisable(state->intrhtable[x]);
               (void) ddiintrfree(state->intrhtable[x]);
           }

           /*
            * We can remove and free the main MSI-X handler now
            * that all the dups have been freed.
            */
           (void) ddiintrdisable(state->intrhtable[0]);
           (void) ddiintrremovehandler(state->intrhtable[0]);
           (void) ddiintrfree(state->intrhtable[0]);

           kmemfree(state->intrhtable, state->intrsize);
       }


CONTEXT
     The ddiintrduphandler() function can be called from  ker-
     nel non-interrupt context.

ATRIBUTES
     See attributes(5) for descriptions of the  following  attri-
     butes:



     
           ATRIBUTE TYPE               ATRIBUTE VALUE       
    
     Interface Stability          Committed                   
    


SEE ALSO
     attributes(5), ddiintraddhandler(9F), ddiintralloc(9F),
     ddiintrclrmask(9F),                 ddiintrdisable(9F),
     ddiintrenable(9F),                      ddiintrfree(9F),
     ddiintrgetpending(9F),  ddiintrgetsupportedtypes(9F),
     ddiintrsetmask(9F)


     Writing Device Drivers











SunOS 5.11          Last change: 09 May 2006                    5



OpenSolaris man pages main menu

Contact us      |       About us      |       Term of use      |       Copyright © 2000-2010 MyWebUniversity.com ™