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.
>>>
>
>