Chris Horne wrote:
> Hi Ed
>
>   
>> hey chris,
>>
>> the current ddi soft state interfaces are "special" in my mind because i
>> thought they were designed to be "fast".  (note that i wasn't around for
>> the original design, so my opinion is based off the implmentation.)
>> their implementation uses direct array indexing, avoids locking, and
>> avoids free memory, all seemingly in the name of soft state lookup
>> speed.  i guess i'm worried that other people may be making the same
>> assumptions about the performance of the ddi soft state interfaces, and
>> these assumptions don't really carry over to the new interfaces since
>> they are really a thin wrapper around modhash.
>>     
>
>
> Yes, performance is an issue for interfaces used in the per-IO code
> path.  For the intended use case, the proposed ddi_ssoft_state will not
> be 'directly' involved in the performance path. In the intended use
> case, the performance path 'indirectly' gains access to the
> "target-port" granularity ddi_ssoft_state via a private pointer
> maintained in the finer-grained "target-port,lun" per-scsi_device(9S)
> hba private soft state (PSARC/2008/675). At tran_tgt_init(9E) time of
> a scsi_device(9S), the hba driver is expected to
> ddi_ssoft_state_get(9F) the coarser "target-port" softstate, and
> increment a private "target-port" softstate reference count to account
> for storing a "target-port" softstate pointer in the finer-grained
> per-scsi_device(9S) hba private softstate.
>
>
>   
>> hence, i'd rather see something more straitforward, like some
>> version/subset of the modhash interfaces promoted to public, or some new
>> ddi*hash* interfaces.
>>     
>
> I want the ability to say "its a softstate, but you feed it strings
> instead of integers". With that simple statement, I believe that anyone
> who has written a solaris driver would "get it". I don't want to loose
> that.
>   

But in your intended usage, it *isn't* a soft state, at least not like I 
suspect most people thing of such things (one per device instance, the 
master private state for the devinfo node.)

I actually fear that this naming will increase confusion (which soft 
state interfaces should I use?)

> Keep in mind that any part of the device tree that has multiple complex
> addressing levels compressed into a single devinfo node unit-address
> ("@<component-a>,<component-b>,<component-c>") will face this problem -
> which is why I thought the ddi_ssoft_* prefix was warranted. The solution
> to performance path issues will likely involve a private ref_count
> approach similar to our use case above.
>
> If the above explanation is insufficient, to make progress, I am
> willing to change the interface prefix from ddi_ssoft_state_* to
> scsi_taddr_ssoft_state_*, indicating a more restricted use case
> that meets immediate needs.
>   

FWIW, I'd be happy with that.  I'd be equally happy with a generic hash 
table interface.  Though I'd suggest you just call it 
"scsi_taddr_state_*()" or somesuch.  (Avoid the non-descriptive "s" 
prefix, and keep the identifier short.)

    -- Garrett
> Thanks
> -Chris
>
>
>   
>> ed
>>
>> On Fri, Dec 05, 2008 at 04:02:24PM -0800, Christopher Horne wrote:
>>
>>     
>>> I am sponsoring the following fasttrack for myself.  Micro/patch
>>> binding is requested. The timer is set to expire on Dec. 17 2008.
>>>
>>> -Chris
>>>
>>>
>>> 1. Introduction
>>>    1.1. Project/Component Working Name:
>>>      ddi_ssoft_state(9F) and ddi_isoft_state(9F)
>>>    1.2. Name of Document Author/Supplier:
>>>         Author: Chris Horne
>>>    1.3. Date of This Document:
>>>      Tue Nov 11 18:10:01 MST 2008
>>>
>>> 4. Technical Description
>>>
>>> 4.1 Background:
>>>
>>>    ddi_soft_state(9F) provides utility interfaces to help device
>>>    drivers manage different context. When small integer values, like
>>>    ddi_get_instance(9F) return values, are directly related to
>>>    context, the current "indexed" soft_state interfaces work well.
>>>
>>> 4.2 Problem:
>>>
>>>    Two IEEE-1275 '@unit-address' issues can make the current
>>>    ddi_soft_state(9F) support ineffective:
>>>
>>>      o Compression: Some IEEE-1275 bindings, like the SCSI
>>>     '@<target-port>,<lun>' notation, compress multiple addressing
>>>     levels into a single 'unit-address' string. If a driver needs
>>>     to maintain soft state at intermediate levels, like the
>>>     <target-port> level, there is no instance number to use with
>>>     ddi_soft_state(9F), and no dev_info node to allow use of
>>>     ddi_[gs]et_driver_private(9F) or ddi_[gs]et_parent_data).
>>>
>>>      o Complexity: An addressing level may be complex: both
>>>     non-numeric, sparse, and large.
>>>
>>>    This situation has forced drivers to maintain soft state context in
>>>    ways that no longer fit the ddi_soft_state(9F) model.
>>>
>>>    An example is SCSA HBA <target-port> unit-address context. For the
>>>    initial SCSI Parallel Interconnect transport the <target-port> was
>>>    as an integer limited to the [0-15] range, and ddi_soft_state(9F)
>>>    worked well. On modern transports the complexity of the
>>>    <target-port> space has mushroomed, as shown below, and the <lun>
>>>    space is now 64-bits and sparse.
>>>
>>>      SPI:   disk at 0,0
>>>      WWN:   disk at w216000c0ff8047dd,0
>>>      GUID:  disk at g600c0ff0000000000047dd270fdf0901   (lun identity: 
>>> MPxIO)
>>>      ISCSI: disk at 
>>> 0000iqn.1986-03.com.sun%3A02%3Ac8a82272-b354-c913-80f9-db9cb378a6f60001,0
>>>
>>> 4.3 Proposal:
>>>
>>>    The proposal is to extend the ddi_soft_state(9F) programming model
>>>    by providing "string" based peers to todays "indexed" soft_state
>>>    interfaces. In addition to "string" support, "indexed" interfaces
>>>    with stronger typing are proposed.
>>>
>>>    Implementation of proposed ddi_ssoft_state(9F) interfaces is built
>>>    on top of the 'modhash' interfaces introduced by [1].
>>>
>>> 4.4 Proposed Interfaces:
>>>
>>>    ------------------------------------------------------------------
>>>    Interface Name           Comm.Lev.       Comments
>>>    ------------------------------------------------------------------
>>>
>>>    ddi_isoft_state          Private         "indexed" soft_state
>>>
>>>    ddi_ssoft_state          "               "string" soft_state
>>>
>>>
>>>    ddi_isoft_state_init     "               typed equivalent of
>>>                                             ddi_soft_state_init(9F)
>>>    ddi_ssoft_state_init     "               string peer of
>>>                                             ddi_isoft_state_init(9F)
>>>
>>>
>>>    ddi_isoft_state_zalloc   "               typed equivalent of
>>>                                             ddi_soft_state_zalloc(9F)
>>>    ddi_ssoft_state_zalloc   "               string peer of
>>>                                             ddi_isoft_state_zalloc(9F)
>>>
>>>    ddi_isoft_state_get              "               typed equivalent of
>>>                                             ddi_soft_state_get(9F)
>>>    ddi_ssoft_state_get              "               string peer of
>>>                                             ddi_isoft_state_get(9F)
>>>
>>>    ddi_isoft_state_free     "               typed equivalent of
>>>                                             ddi_soft_state_free(9F)
>>>    ddi_ssoft_state_free     "               string peer of
>>>                                             ddi_isoft_state_free(9F)
>>>
>>>    ddi_isoft_state_fini     "               typed equivalent of
>>>                                             ddi_soft_state_fini(9F)
>>>    ddi_ssoft_state_fini     "               string peer of
>>>                                             ddi_isoft_state_fini(9F)
>>>
>>>    ddi_isoft_state_unassigned       "               return first unassigned
>>>                                             item of an ddi_isoft_state.
>>>
>>> 4.5 Interface Prototypes: (defined in sunddi.h):
>>>
>>>    typedef  struct __ddi_isoft_state        ddi_isoft_state;
>>>    typedef  struct __ddi_ssoft_state        ddi_ssoft_state;
>>>
>>>    int
>>>    ddi_isoft_state_init(ddi_isoft_state **state_p,
>>>     size_t size, size_t n_items);
>>>    int
>>>    ddi_ssoft_state_init(ddi_ssoft_state **state_p,
>>>     size_t size, int hash_sz);
>>>
>>>    int
>>>    ddi_isoft_state_zalloc(ddi_isoft_state *state, int index);
>>>    int
>>>    ddi_ssoft_state_zalloc(ddi_ssoft_state *state, const char *stringkey);
>>>
>>>    void *
>>>    ddi_isoft_state_get(ddi_isoft_state *state, int index);
>>>    void *
>>>    ddi_ssoft_state_get(ddi_ssoft_state *state, const char *stringkey);
>>>
>>>    void
>>>    ddi_isoft_state_free(ddi_isoft_state *state, int index);
>>>    void
>>>    ddi_ssoft_state_free(ddi_ssoft_state *state, const char *stringkey);
>>>
>>>    void
>>>    ddi_isoft_state_fini(ddi_isoft_state **state_p);
>>>    void
>>>    ddi_ssoft_state_fini(ddi_ssoft_state **state_p);
>>>
>>>    int
>>>    ddi_isoft_state_unassigned(ddi_isoft_state **state_p);
>>>
>>> 4.4 Example:
>>>
>>>    Assuming that 'tpaddr' is the <target-port> portion SCSI
>>>    'unit-address' string, A SCSA HBA driver can use the following to
>>>    access its private <target-port> specific context.
>>>
>>>     ss = ddi_isoft_state_get(xx_state, ddi_get_instance(devi));
>>>     tpss = ddi_ssoft_state_get(ss->ss_tpstate, tpaddr);
>>>
>>>    Where xx_state would be setup in _init(9E) via
>>>    ddi_isoft_state_init(9F), and ss_tpstate would be setup in
>>>    xxattach(9E) via ddi_ssoft_state_init(9F).
>>>
>>> 4.5 Alternatives:
>>>
>>>    An alternative 'compound' approach was considered and prototyped.
>>>    The 'compound' approach implemented a set of 'ddi_strid_*(9E)'
>>>    string-to-id mapping interfaces, and then used the existing
>>>    "indexed" ddi_soft_state(9F) to get from an 'id' to the soft state.
>>>    The 'ddi_strid_(9E)' interfaces, while a good fit for some
>>>    applications, was found to increase SCSI host adapter driver
>>>    complexity compared to the proposed ddi_ssoft_state(9F) interfaces.
>>>    The proposed ddi_ssoft_state(9F) interfaces also present a familiar
>>>    API: they are based on the well-established ddi_soft_state(9F) API
>>>    structure.
>>>
>>> 4.6 Man Pages
>>>
>>>    See Appendix A. Some of the examples are TBS at this point, more
>>>    meaningful examples should be provided before these interfaces are
>>>    promoted.
>>>
>>> 4.7 Release Binding
>>>
>>>    Micro/patch binding is requested.
>>>
>>> 4.8 References
>>>
>>>    [1] PSARC case that introduced modhash interfaces
>>>     PSARC/1998/212 Extensions to Device Autoconfiguration [John Danielson]
>>>     http://sac.sfbay/PSARC/1998/212
>>>     http://www.opensolaris.org/os/community/arc/caselog/PSARC/1998/212
>>>
>>> 
>>> Appendix A:
>>>
>>> A.1: New ddi_ssoft_state(9F)
>>> =========================================
>>>    :r ddi_ssoft_state.9f
>>>
>>> Kernel Functions for Drivers                   ddi_ssoft_state(9F)
>>>
>>> NAME
>>>     ddi_ssoft_state, ddi_ssoft_state_get, ddi_ssoft_state_fini,
>>>     ddi_ssoft_state_free, ddi_ssoft_state_init, ddi_ssoft_state_zalloc -
>>>     driver string soft state utility routines
>>>
>>> SYNOPSIS
>>>     #include <sys/ddi.h>
>>>     #include <sys/sunddi.h>
>>>
>>>     typedef struct __ddi_ssoft_state        ddi_ssoft_state;
>>>
>>>     int ddi_ssoft_state_init(ddi_ssoft_state **state_p,
>>>             size_t size, size_t hash_sz);
>>>
>>>     int ddi_ssoft_state_zalloc(ddi_ssoft_state *state, int stringkey);
>>>
>>>     void *ddi_ssoft_state_get(ddi_ssoft_state *state, int stringkey);
>>>
>>>     void ddi_ssoft_state_free(ddi_ssoft_state *state, int stringkey);
>>>
>>>     void ddi_ssoft_state_fini(ddi_ssoft_state **state_p);
>>>
>>> INTERFACE LEVEL
>>>     Solaris DDI specific (Solaris DDI).
>>>
>>> PARAMETERS
>>>     state_p    Address of the opaque state pointer which will be
>>>             initialized by ddi_ssoft_state_init() to point to
>>>             implementation dependent data.
>>>
>>>     state   An opaque pointer to implementation-dependent data that
>>>             describes the soft state.
>>>
>>>     size    Size of the soft state which will be allocated by subsequent
>>>             calls to ddi_ssoft_state_zalloc(); zero is illegal.
>>>
>>>     hash_sz    The number of hashed lists which will be allocated;
>>>             zero is not allowed. There is a performance
>>>             .vs. space tradeoff in the selection of a hash_sz
>>>             value: for 'n' soft state structures, on average each
>>>             ddi_ssoft_state_get will need to traverse 'n'/hash_sz/2
>>>             entries to locate the requested soft state structure.
>>>
>>>     stringkey  The string key for the soft state structure; usually
>>>             associated with some sub-portion of the device's
>>>             'unit-address'.
>>>
>>> DESCRIPTION
>>>
>>>     Some drivers must maintain state information at a granularity
>>>     unrelated to ddi_get_instance(9F) instance numbers or dev_info
>>>     node ddi_get_driver_private(9F) data.
>>>
>>>     When the needed soft state granularity can be associated with a
>>>     string, such as a sub-portion of a 'unit-address' string, the
>>>     ddi_ssoft_state(9F) utility routines can be used to help device
>>>     drivers manage the space used by the driver to hold such state
>>>     information.
>>>
>>>     For example, if a SCSI HBA driver maintains state for each
>>>     target-port address in a separate state structure, for transports
>>>     with complex target-port address representations these routines
>>>     can be used to dynamically allocate and deallocate a separate
>>>     structure for each target-port as scsi_device(9S) associated with
>>>     the target-port are initialized by tran_tgt_init(9E) and and freed
>>>     by tran_tgt_free(9E).
>>>
>>>     To use the routines, the driver writer needs to declare a state
>>>     pointer, state_p, which the implementation uses as a place to hang
>>>     a set of per-driver structures; everything else is managed by
>>>     these routines.
>>>
>>>     The routine ddi_ssoft_state_init() is usually called in the
>>>     driver's attach(9E) routine to initialize the state pointer, and set
>>>     the size of the soft state structure.
>>>
>>>     The routine ddi_ssoft_state_zalloc() is called to allocate a soft
>>>     state.  The routine is passed a string key, which is used to refer
>>>     to the structure in subsequent calls to ddi_ssoft_state_get() and
>>>     ddi_ssoft_state_free(). The string key is usually some sub-portion
>>>     of a 'unit-address'.  The routine attempts to allocate space for
>>>     the new structure, and if the space allocation was successful,
>>>     DDI_SUCCESS is returned to the caller. Returned memory is zeroed.
>>>
>>>     A pointer to the space previously allocated for a soft state
>>>     structure can be obtained by calling ddi_ssoft_state_get() with the
>>>     appropriate string key.
>>>
>>>     The space used by a given soft state structure can be returned to
>>>     the system using ddi_ssoft_state_free().
>>>
>>>     The space used by all the soft state structures allocated on a
>>>     given state pointer, together with the housekeeping information
>>>     used by the implementation can be returned to the system using
>>>     ddi_ssoft_state_fini(). This routine is typically called from the
>>>     driver's detach(9E) routine.
>>>
>>>     The ddi_ssoft_state_zalloc(), ddi_ssoft_state_free() and
>>>     ddi_ssoft_state_get() routines coordinate access to the underlying
>>>     data structures in an MT-safe fashion, thus no additional locks
>>>     should be necessary.
>>>
>>> RETURN VALUES
>>>
>>>     ddi_ssoft_state_get()
>>>
>>>     NULL               The requested soft state structure was not
>>>                     allocated at the time of the call.
>>>
>>>     pointer            The pointer to the soft state structure.
>>>
>>>
>>>
>>>     ddi_ssoft_state_init()
>>>
>>>     0                  The allocation was successful.
>>>
>>>     EINVAL             Either the size parameter was zero, or the
>>>                     state_p parameter was invalid.
>>>
>>>
>>>     ddi_ssoft_state_zalloc()
>>>
>>>     DDI_SUCCESS        The allocation was successful.
>>>
>>>     DDI_FAILURE        The routine failed to allocate the storage
>>>                     required; either the state parameter was
>>>                     invalid, the string key was NULL, or an attempt
>>>                     was made to allocate using a string key that
>>>                     was already allocated.
>>>
>>>
>>> CONTEXT
>>>     The ddi_ssoft_state_init() and  ddi_ssoft_state_alloc() functions
>>>     can be called from user or kernel context only, since they may
>>>     internally call kmem_zalloc(9F) with the KM_SLEEP flag.
>>>
>>>     The  ddi_ssoft_state_fini(), ddi_ssoft_state_free() and
>>>     ddi_ssoft_state_get() routines can be called from any driver
>>>     context.
>>>
>>> EXAMPLES
>>> <<XXX TBS...>>
>>>
>>> SEE ALSO
>>>     _fini(9E), _init(9E), attach(9E), detach(9E),
>>>     ddi_get_instance(9F), ddi_soft_state(9E), ddi_isoft_state(9E),
>>>     getminor(9F), kmem_zalloc(9F)
>>>
>>> NOTES
>>>     If necessary, a hierarchy of state structures can be constructed
>>>     by embedding state pointers in higher order state structures.
>>>
>>> DIAGNOSTICS
>>> <<XXX VERIFY... with final implementation...>>
>>>
>>>     All of the messages described below usually indicate bugs in the
>>>     driver and should not appear in normal operation of the system.
>>>
>>>       WARNING: ddi_ssoft_state_zalloc: bad handle
>>>       WARNING: ddi_ssoft_state_free: bad handle
>>>       WARNING: ddi_ssoft_state_fini: bad handle
>>>
>>>     The implementation-dependent information kept in the state
>>>     variable is corrupt.
>>>
>>>       WARNING: ddi_ssoft_state_free: null handle
>>>       WARNING: ddi_ssoft_state_fini: null handle
>>>
>>>     The routine has been passed a null or corrupt state pointer.
>>>     Check that ddi_ssoft_state_init() has been called.
>>>
>>>       WARNING: ddi_ssoft_state_free: string key '%s' not allocated
>>>
>>>     The routine has been asked to free a string key which is not
>>>     allocated. The message prints out the invalid string key.
>>> 
>>> A.2: New ddi_isoft_state(9F)
>>> =========================================
>>>    :r ddi_isoft_state.9f
>>>
>>> Kernel Functions for Drivers                   ddi_isoft_state(9F)
>>>
>>> NAME
>>>     ddi_isoft_state, ddi_isoft_state_get, ddi_isoft_state_fini,
>>>     ddi_isoft_state_free, ddi_isoft_state_init, ddi_isoft_state_zalloc -
>>>     driver indexed soft state utility routines
>>>
>>> SYNOPSIS
>>>     #include <sys/ddi.h>
>>>     #include <sys/sunddi.h>
>>>
>>>     typedef struct __ddi_isoft_state        ddi_isoft_state;
>>>
>>>     int ddi_isoft_state_init(ddi_isoft_state **state_p,
>>>             size_t size, size_t n_items);
>>>
>>>     int ddi_isoft_state_zalloc(ddi_isoft_state *state, int item);
>>>
>>>     void *ddi_isoft_state_get(ddi_isoft_state *state, int item);
>>>
>>>     void ddi_isoft_state_free(ddi_isoft_state *state, int item);
>>>
>>>     void ddi_isoft_state_fini(ddi_isoft_state **state_p);
>>>
>>> INTERFACE LEVEL
>>>     Solaris DDI specific (Solaris DDI).
>>>
>>> PARAMETERS
>>>     state_p    Address of the opaque state pointer which will be
>>>             initialized by ddi_isoft_state_init() to point to
>>>             implementation dependent data.
>>>
>>>     state      An opaque pointer to implementation-dependent data that
>>>             describes the soft state.
>>>
>>>     size       Size of the item which will be allocated by subsequent
>>>             calls to ddi_isoft_state_zalloc().
>>>
>>>     n_items    A hint of the number of items which will be
>>>             preallocated; zero is allowed.
>>>
>>>     item       The item number for the state structure; usually the
>>>             instance number of the associated devinfo node.
>>>
>>> DESCRIPTION
>>>     Most device drivers maintain state information with each instance
>>>     of the device they control; for example, a soft copy of a device
>>>     control register, a mutex that must be held while accessing a
>>>     piece of hardware, a partition table, or a unit structure. These
>>>     utility routines are intended to help device drivers manage the
>>>     space used by the driver to hold such state information.
>>>
>>>     For example, if the driver holds the state of each instance in a
>>>     single state structure, these routines can be used to dynamically
>>>     allocate and deallocate a separate structure for each instance of
>>>     the driver as the instance is attached and detached.
>>>
>>>     To use the routines, the driver writer needs to declare a state
>>>     pointer, state_p, which the implementation uses as a place to hang
>>>     a set of per-driver structures; everything else is managed by
>>>     these routines.
>>>
>>>     The routine ddi_isoft_state_init() is usually called in the
>>>     driver's _init(9E) routine to initialize the state pointer, set
>>>     the size of the soft state structure, and to allow the driver to
>>>     pre-allocate a given number of such structures if required.
>>>
>>>     The routine ddi_isoft_state_zalloc() is usually called in the
>>>     driver's attach(9E) routine. The routine is passed an item number
>>>     which is used to refer to the structure in subsequent calls to
>>>     ddi_isoft_state_get() and ddi_isoft_state_free(). The item number is
>>>     usually just the instance number of the devinfo node, obtained
>>>     with ddi_get_instance(9F). The routine attempts to allocate space
>>>     for the new structure, and if the space allocation was successful,
>>>     DDI_SUCCESS is returned to the caller. Returned memory is zeroed.
>>>
>>>     A pointer to the space previously allocated for a soft state
>>>     structure can be obtained by calling ddi_isoft_state_get() with the
>>>     appropriate item number.
>>>
>>>     The space used by a given soft state structure can be returned to
>>>     the system using ddi_isoft_state_free(). This routine is usually
>>>     called from the driver's detach(9E) entry point.
>>>
>>>     The space used by all the soft state structures allocated on a
>>>     given state pointer, together with the housekeeping information
>>>     used by the implementation can be returned to the system using
>>>     ddi_isoft_state_fini(). This routine can be called from the
>>>     driver's _fini(9E) routine.
>>>
>>>     The ddi_isoft_state_zalloc(), ddi_isoft_state_free() and
>>>     ddi_isoft_state_get() routines coordinate access to the underlying
>>>     data structures in an MT-safe fashion, thus no additional locks
>>>     should be necessary.
>>>
>>> RETURN VALUES
>>>
>>>     ddi_isoft_state_get()
>>>
>>>     NULL               The requested state structure was not allocated
>>>                     at the time of the call.
>>>
>>>     pointer            The pointer to the state structure.
>>>
>>>
>>>
>>>     ddi_isoft_state_init()
>>>
>>>     0                  The allocation was successful.
>>>
>>>     EINVAL             Either the size parameter was zero, or the
>>>                     state_p parameter was invalid.
>>>
>>>
>>>     ddi_isoft_state_zalloc()
>>>
>>>     DDI_SUCCESS        The allocation was successful.
>>>
>>>     DDI_FAILURE        The routine failed to allocate the storage
>>>                     required; either the state parameter was
>>>                     invalid, the item number was negative, or an
>>>                     attempt was made to allocate an item number
>>>                     that was already allocated.
>>>
>>>
>>> CONTEXT
>>>     The ddi_isoft_state_init() and  ddi_isoft_state_alloc() functions
>>>     can be called from user or kernel context only, since they may
>>>     internally call kmem_zalloc(9F) with the KM_SLEEP flag.
>>>
>>>     The   ddi_isoft_state_fini(), ddi_isoft_state_free() and
>>>     ddi_isoft_state_get() routines can be called from any driver
>>>     context.
>>>
>>> EXAMPLES
>>>     Example 1 Creating and Removing Data Structures
>>>
>>>     The following example shows how the routines described above can
>>>     be used in terms of the driver entry points of a character-only
>>>     driver. The example concentrates on the portions of the code that
>>>     deal with creating and removing the driver's data structures.
>>>
>>>
>>>     typedef struct {
>>>             volatile caddr_t *csr;        /* device registers */
>>>             kmutex_t         csr_mutex;   /* protects 'csr' field */
>>>             unsigned int     state;
>>>             dev_info_t       *dip;        /* back pointer to devinfo */
>>>     } devstate_t;
>>>     static ddi_isoft_state *statep;
>>>
>>>     int
>>>     _init(void)
>>>     {
>>>             int error;
>>>
>>>             error = ddi_isoft_state_init(&statep, sizeof (devstate_t), 0);
>>>             if (error != 0)
>>>                     return (error);
>>>             if ((error = mod_install(&modlinkage)) != 0)
>>>                     ddi_isoft_state_fini(&statep);
>>>             return (error);
>>>     }
>>>
>>>     int
>>>     _fini(void)
>>>     {
>>>             int error;
>>>
>>>             if ((error = mod_remove(&modlinkage)) != 0)
>>>                     return (error);
>>>             ddi_isoft_state_fini(&statep);
>>>             return (0);
>>>     }
>>>
>>>     static int
>>>     xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
>>>     {
>>>             int instance;
>>>             devstate_t *softc;
>>>
>>>             switch (cmd) {
>>>             case DDI_ATTACH:
>>>                     instance = ddi_get_instance(dip);
>>>                     if (ddi_isoft_state_zalloc(statep, instance) !=
>>>                         DDI_SUCCESS)
>>>                             return (DDI_FAILURE);
>>>                     softc = ddi_isoft_state_get(statep, instance);
>>>                     softc->dip = dip;
>>>                     ...
>>>                     return (DDI_SUCCESS);
>>>             default:
>>>                     return (DDI_FAILURE);
>>>             }
>>>     }
>>>
>>>     static int
>>>     xxdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
>>>     {
>>>             int instance;
>>>
>>>             switch (cmd) {
>>>
>>>             case DDI_DETACH:
>>>                     instance = ddi_get_instance(dip);
>>>                     ...
>>>                     ddi_isoft_state_free(statep, instance);
>>>                     return (DDI_SUCCESS);
>>>
>>>             default:
>>>                     return (DDI_FAILURE);
>>>             }
>>>     }
>>>
>>>     static int
>>>     xxopen(dev_t *devp, int flag, int otyp, cred_t *cred_p)
>>>     {
>>>             devstate_t *softc;
>>>             int   instance;
>>>
>>>             instance = getminor(*devp);
>>>             if ((softc = ddi_isoft_state_get(statep, instance)) == NULL)
>>>                     return (ENXIO);
>>>             ...
>>>             softc->state |= XX_IN_USE;
>>>             ...
>>>             return (0);
>>>     }
>>>
>>> SEE ALSO
>>>     _fini(9E), _init(9E), attach(9E), detach(9E),
>>>     ddi_get_instance(9F), getminor(9F), kmem_zalloc(9F)
>>>
>>> WARNINGS
>>>     There is no attempt to validate the item parameter given to
>>>     ddi_isoft_state_zalloc() other than it must be a positive signed
>>>     integer. Therefore very large item numbers may cause the driver to
>>>     hang forever waiting for virtual memory resources that can never
>>>     be satisfied.
>>>
>>> NOTES
>>>     If necessary, a hierarchy of state structures can be constructed
>>>     by embedding state pointers in higher order state structures.
>>>
>>> DIAGNOSTICS
>>>     All of the messages described below usually indicate bugs in the
>>>     driver and should not appear in normal operation of the system.
>>>
>>>       WARNING: ddi_isoft_state_zalloc: bad handle
>>>       WARNING: ddi_isoft_state_free: bad handle
>>>       WARNING: ddi_isoft_state_fini: bad handle
>>>
>>>     The implementation-dependent information kept in the state
>>>     variable is corrupt.
>>>
>>>       WARNING: ddi_isoft_state_free: null handle
>>>       WARNING: ddi_isoft_state_fini: null handle
>>>
>>>     The routine has been passed a null or corrupt state pointer.
>>>     Check that ddi_isoft_state_init() has been called.
>>>
>>>       WARNING: ddi_isoft_state_free: item %d not in range [0..%d]
>>>
>>>     The routine has been asked to free an item which was never
>>>     allocated. The message prints out the invalid item number and the
>>>     acceptable range.
>>>
>>> 
>>> A.3: Changes to existing ddi_soft_state(9F)
>>> =========================================
>>>    :r!diff -U5 ddi_soft_state.9f.orig ddi_soft_state.9f
>>>
>>> --- ddi_soft_state.9f.orig  Mon Nov 10 11:45:36 2008
>>> +++ ddi_soft_state.9f       Tue Nov 11 18:08:26 2008
>>> @@ -224,22 +224,29 @@
>>>             return (0);
>>>     }
>>>
>>> SEE ALSO
>>>      _fini(9E), _init(9E), attach(9E), detach(9E),
>>> -     ddi_get_instance(9F), getminor(9F), kmem_zalloc(9F)
>>> +     ddi_get_instance(9F), ddi_isoft_state(9E), ddi_ssoft_state(9E),
>>> +     getminor(9F), kmem_zalloc(9F)
>>>
>>> WARNINGS
>>>      There is no attempt to validate the item parameter given to
>>>      ddi_soft_state_zalloc() other than it must be a positive signed
>>>      integer. Therefore very large item numbers may cause the driver to
>>>      hang forever waiting for virtual memory resources that can never
>>>      be satisfied.
>>>
>>> +     Use of the ddi_isoft_state(9E) interfaces is encouraged, it
>>> +     provides stronger typing.
>>> +
>>> NOTES
>>>      If necessary, a hierarchy of state structures can be constructed
>>>      by embedding state pointers in higher order state structures.
>>> +
>>> +     Equivalent functionality with stronger typing is provided
>>> +     by the newer ddi_isoft_state(9F) interfaces.
>>>
>>> DIAGNOSTICS
>>>      All of the messages described below usually indicate bugs in the
>>>      driver and should not appear in normal operation of the system.
>>>       
>
>   


Reply via email to