Chris Horne wrote:
> Hi Garrett
>
> Garrett D'Amore wrote:
>
>> 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.)
>>
>
>
> ...and I am proposing a peer that is string based. If we had a separate
> devinfo node to represent the target port addressing, we would have an
> instance-oriented softstate there - but that is not how the IEEE1275
> binding for scsi devices works.
>
> Who says that all forms of soft state need to be indexed by integers (or
> that those integers need to be instance numbers)? I view soft state
> as a generic term for "(private) software state".
>
Of course you can use ddi_soft_state_xxx for other purposes, but its
pretty clear from the examples, naming, and existing practice that this
is what it is intended for. Some of the specific details of memory
allocation and life time of objects really make sense only in the
context of soft state that is managed like instance data.
>
>
>> 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.
>>
>
> not this case.
>
Why not? What you're proposing (or rather what you need) is a generic
dictionary lookup mechanism mapping strings to some state. The only
additional bits are that this case also imposes some additional memory
management "features" (i.e. state structures are fixed sized, and
allocation is managed by the API rather than by the calling driver.)
>
>> Though I'd suggest you just call it
>> "scsi_taddr_state_*()" or somesuch. (Avoid the non-descriptive "s"
>> prefix, and keep the identifier short.)
>>
>
> Even in my immediate use case the scsi_taddr prefix is misleading because
> we will be using it for scsi, smp, and sata device target port addresses
> seen on a sas transport - but I will make the prefix change if people insist.
>
How about "ddi_named_state_xxx"? That will avoid the problem of
confusion with ddi_soft_state, and make it a bit clearer (IMO).
I'd recommend that you also consider a set of APIs to *walk* the data
structure, because in my own experience the inability to easily walk the
ddi_soft_state_xxx list is one of the limiting factors in its use. (On
more than one occasion I've had to either make my own global linked list
in addition to, or instead of, ddi_soft_state, because I needed a way to
search through all soft state structures. For example, when mapping a
potentially large dynamic dev_t to a specific device structure.)
-- Garrett
> -Chris
>
>> -- 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
>>>>> Even in my immediate use case the scsi_taddr prefix is misleading because
>>>>> we will be using it for scsi, smp, _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.
>>>>>
>>>>>
>>>
>>>
>>
>
>