The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Интерактивная система просмотра системных руководств (man-ов)

 ТемаНаборКатегория 
 
 [Cписок руководств | Печать]

ddi_intr_dup_handler (9)
  • >> ddi_intr_dup_handler (9) ( Solaris man: Ядро )
  •  

    NAME

    ddi_intr_dup_handler - reuse interrupt handler and arguments for MSI-X interrupts
     
    

    SYNOPSIS

    #include <sys/types.h>
    #include <sys/conf.h>
    #include <sys/ddi.h>
    #include <sys/sunddi.h>
    
    int ddi_intr_dup_handler(ddi_intr_handle_t primary, int vector, 
        ddi_intr_handle_t *new);
    

     

    INTERFACE LEVEL

    Solaris DDI specific (Solaris DDI).  

    PARAMETERS

    primary

    Original DDI interrupt handle

    vector

    Interrupt number to duplicate

    new

    Pointer to new DDI interrupt handle

     

    DESCRIPTION

    The ddi_intr_dup_handler() 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 arguments. 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 interrupts were supported on the device, the driver could alias the 2 interrupts it received to the 30 remaining on the device.

    The ddi_intr_dup_handler() function must be called after the primary interrupt handle has been added to the system or enabled by ddi_intr_add_handler(9F) and ddi_intr_enable(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 ddi_intr_alloc(9F). Otherwise, the ddi_intr_dup_handler() call will fail.

    The only supported calls on dup-ed interrupt handles are ddi_intr_set_mask(9F), ddi_intr_clr_mask(9F), ddi_intr_get_pending(9F), ddi_intr_enable(9F), ddi_intr_disable(9F), and ddi_intr_free(9F).

    A call to ddi_intr_dup_handler() 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 ddi_intr_enable(). Likewise, ddi_intr_disable() must be called to disable the enabled dup-ed interrupt source.

    A dup-ed interrupt is removed by calling ddi_intr_free() after it has been disabled. The ddi_intr_remove_handler(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 interrupt must have been disabled and freed. Otherwise, calls to ddi_intr_remove_handler() will fail with DDI_FAILURE.

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

    RETURN VALUES

    The ddi_intr_dup_handler() function returns:

    DDI_SUCCESS

    On success.

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

    DDI_EINVAL

    On encountering invalid input parameters. DDI_EINVAL 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.

    DDI_FAILURE

    On any implementation specific failure.

     

    EXAMPLES

    Example 1 Using the ddi_intr_dup_handler() function

    int
    add_msix_interrupts(intr_state_t *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 (ddi_intr_get_nintrs(state->dip, DDI_INTR_TYPE_MSIX,
        &state->intr_count) != DDI_SUCCESS) {
             cmn_err(CE_WARN, "Failed to retrieve the MSI-X interrupt count");
             return (DDI_FAILURE);
     }
    
     state->intr_size = state->intr_count * sizeof (ddi_intr_handle_t);
     state->intr_htable = kmem_zalloc(state->intr_size, KM_SLEEP);
    
     /* Allocate one MSI-X interrupt handle */
     if (ddi_intr_alloc(state->dip, state->intr_htable,
         DDI_INTR_TYPE_MSIX, state->inum, 1, &state->actual,
         DDI_INTR_ALLOC_STRICT) != DDI_SUCCESS) {
             cmn_err(CE_WARN, "Failed to allocate MSI-X interrupt");
             kmem_free(state->intr_htable, state->intr_size);
             return (DDI_FAILURE);
     }
    
     /* Get the count of how many MSI-X interrupts we dup */
     state->dup_cnt = state->intr_count - state->actual;
    
     if (ddi_intr_get_pri(state->intr_htable[0],
         &state->intr_pri) != DDI_SUCCESS) {
             cmn_err(CE_WARN, "Failed to get interrupt priority");
             goto error1;
     }
    
     /* Make sure the MSI-X priority is below 'high level' */
     if (state->intr_pri >= ddi_intr_get_hilevel_pri()) {
            cmn_err(CE_WARN, "Interrupt PRI is too high");
             goto error1;
     }
    
     /*
      * Add the handler for the interrupt
      */
     if (ddi_intr_add_handler(state->intr_htable[0],
         (ddi_intr_handler_t *)intr_isr, (caddr_t)state,
         NULL) != DDI_SUCCESS) {
             cmn_err(CE_WARN, "Failed to add interrupt handler");
             goto error1;
     }
    
     /* Enable the main MSI-X handle first */
     if (ddi_intr_enable(state->intr_htable[0]) != DDI_SUCCESS) {
             cmn_err(CE_WARN, "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->dup_cnt; x++) {
         if (ddi_intr_dup_handler(state->intr_htable[0],
             state->inum + x, &state->intr_htable[x]) != DDI_SUCCESS) {
                 for (y = x - 1; y > 0; y--) {
                     (void) ddi_intr_disable(state->intr_htable[y]);
                     (void) ddi_intr_free(state->intr_htable[y]);
                 }
    
             goto error2;
         }
         if (ddi_intr_enable(state->intr_htable[x]) != DDI_SUCCESS) {
             for (y = x; y > 0; y--) {
                 (void) ddi_intr_disable(state->intr_htable[y]);
                 (void) ddi_intr_free(state->intr_htable[y]);
             }
                   
             goto error2;
         }
     }
    
     return (DDI_SUCCESS);
    
    error2:
       (void) ddi_intr_remove_handler(state->intr_htable[0]);
    error1:
       (void) ddi_intr_free(state->intr_htable[0]);
    
       kmem_free(state->intr_htable, state->intr_size);
       return (DDI_FAILURE);
    }
    
    void
    remove_msix_interrupts(intr_state_t *state)
    {
       int x;
    
       /* 
        * Disable all the handles and free the dup-ed handles
        * before we can remove the main MSI-X interrupt handle.
        */
       for (x = 1; x < state->dup_cnt; x++) {
           (void) ddi_intr_disable(state->intr_htable[x]);
           (void) ddi_intr_free(state->intr_htable[x]);
       }
    
       /*
        * We can remove and free the main MSI-X handler now
        * that all the dups have been freed.
        */
       (void) ddi_intr_disable(state->intr_htable[0]);
       (void) ddi_intr_remove_handler(state->intr_htable[0]);
       (void) ddi_intr_free(state->intr_htable[0]);
    
       kmem_free(state->intr_htable, state->intr_size);
    }
    

     

    CONTEXT

    The ddi_intr_dup_handler() function can be called from kernel non-interrupt context.  

    ATTRIBUTES

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

    ATTRIBUTE TYPEATTRIBUTE VALUE

    Interface StabilityCommitted

     

    SEE ALSO

    attributes(5), ddi_intr_add_handler(9F), ddi_intr_alloc(9F), ddi_intr_clr_mask(9F), ddi_intr_disable(9F), ddi_intr_enable(9F), ddi_intr_free(9F), ddi_intr_get_pending(9F), ddi_intr_get_supported_types(9F), ddi_intr_set_mask(9F)

    Writing Device Drivers


     

    Index

    NAME
    SYNOPSIS
    INTERFACE LEVEL
    PARAMETERS
    DESCRIPTION
    RETURN VALUES
    EXAMPLES
    CONTEXT
    ATTRIBUTES
    SEE ALSO


    Поиск по тексту MAN-ов: 




    Партнёры:
    PostgresPro
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2024 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру