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