/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <sys/ddi_periodic.h>
#include <sys/sysevent.h>
#include <sys/damap_impl.h>
#ifdef DEBUG
static int damap_debug = 0;
#endif /* DEBUG */
extern taskq_t *system_taskq;
static void dam_stabilize_map(void *);
static void dam_addr_stable_cb(void *);
static void dam_addrset_stable_cb(void *);
static int dam_kstat_create(dam_t *);
static int dam_map_alloc(dam_t *);
if ((mapp)->dam_kstatsp) { \
}
if ((mapp)->dam_kstatsp) { \
}
/*
* increase damap size by 64 entries at a time
*/
/*
*/
typedef struct {
} cfg_tqd_t;
extern pri_t maxclsyspri;
/*
* Create new device address map
*
* name: map name (kstat unique)
* size: max # of map entries
* mode: style of address reports: per-address or fullset
*
* activate_arg: address provider activation-callout private
* activate_cb: address provider activation callback handler
* deactivate_cb: address provider deactivation callback handler
*
* config_arg: configuration-callout private
* config_cb: class configuration callout
* unconfig_cb: class unconfiguration callout
*
* damapp: pointer to map handle (return)
*
* Returns: DAM_SUCCESS
* DAM_EINVAL Invalid argument(s)
* DAM_FAILURE General failure
*/
int
{
return (DAM_EINVAL);
return (DAM_SUCCESS);
}
/*
* Allocate backing resources
*
* DAMs are lightly backed on create - major allocations occur
* at the time a report is made to the map, and are extended on
* a demand basis.
*/
static int
{
void *softstate_p;
return (DAM_FAILURE);
/*
* dam_high > 0 signals map allocation complete
*/
return (DAM_SUCCESS);
return (DAM_FAILURE);
DDI_SUCCESS) {
return (DAM_FAILURE);
}
return (DAM_FAILURE);
}
return (DAM_SUCCESS);
}
/*
* Destroy address map
*
* damapp: address map
*
* Returns: DAM_SUCCESS
* DAM_EINVAL Invalid argument(s)
* DAM_FAILURE General failure
*/
void
{
int i;
/*
* prevent new reports from being added to the map
*/
/*
* wait for outstanding reports to stabilize and cancel
* the timer for this map
*/
(void) damap_sync(damapp, 0);
/*
* map is at full stop
* release the contents of the map, invoking the
* detactivation protocol as addresses are released
*/
continue;
if (DAM_IS_STABLE(mapp, i)) {
dam_addr_deactivate(mapp, i);
} else {
}
}
} else
}
/*
* Wait for map stability. If sync was successfull then return 1.
* If called with a non-zero sync_usec, then a return value of 0 means a
* timeout occurred prior to sync completion. NOTE: if sync_usec is
* non-zero, it should be much longer than dam_stable_ticks.
*
* damapp: address map
* sync_usec: micorseconds until we give up on sync completion.
*/
int
{
int rv;
int, sync_usec);
/*
* Block when waiting for
* a) stabilization pending or a fullset update pending
* b) the report set to finalize (bitset is null)
* c) any scheduled timeouts to fire
*/
/* Wait for condition relayed via timeout */
if (sync_usec) {
mapp->dam_sync_to_cnt++;
rv = 0; /* return timeout */
break;
}
} else
}
if (rv) {
/*
* Delay one stabilization time after the apparent sync above
* and verify accuracy - resync if not accurate.
*/
goto again;
}
int, rv);
return (rv);
}
/*
* Return 1 if active set is empty
*/
int
{
int rv;
return (rv);
}
/*
* Get the name of a device address map
*
* damapp: address map
*
* Returns: name
*/
char *
{
}
/*
* Get the current size of the device address map
*
* damapp: address map
*
* Returns: size
*/
int
{
}
/*
* Report an address to per-address report
*
* damapp: address map handle
* address: address in ascii string representation
* addridp: address ID
* nvl: optional nvlist of configuration-private data
* addr_priv: optional provider-private (passed to activate/deactivate cb)
*
* Returns: DAM_SUCCESS
* DAM_EINVAL Invalid argument(s)
* DAM_MAPFULL address map exhausted
*/
int
{
return (DAM_EINVAL);
char *, address);
return (DAM_MAPFULL);
}
/*
* If re-reporting the same address (add or remove) clear
* the existing report
*/
char *, address);
}
if (nvl)
return (DAM_SUCCESS);
}
/*
* Report removal of address from per-address report
*
* damapp: address map
* address: address in ascii string representation
*
* Returns: DAM_SUCCESS
* DAM_EINVAL Invalid argument(s)
* DAM_FAILURE General failure
*/
int
{
return (DAM_EINVAL);
char *, address);
return (DAM_MAPFULL);
}
/*
* if reporting the removal of an address which is not in the map
* return success
*/
return (DAM_SUCCESS);
}
char *, address);
}
return (DAM_SUCCESS);
}
static int
{
int idx;
return (DAM_EINVAL);
}
/*
* cancel stabilization timeout
*/
/*
* clear pending reports
*/
}
}
}
return (DAM_SUCCESS);
}
/*
* Initiate full-set report
*
* damapp: address map
*
* Returns: DAM_SUCCESS
* DAM_EINVAL Invalid argument(s)
*/
int
{
int rv;
return (DAM_EINVAL);
}
return (DAM_MAPFULL);
}
if (rv == DAM_SUCCESS) {
}
return (rv);
}
/*
* Cancel full-set report
*
* damapp: address map
*
* Returns: DAM_SUCCESS
* DAM_EINVAL Invalid argument(s)
*/
int
{
int rv;
return (DAM_EINVAL);
}
return (rv);
}
/*
* Report address to full-set report
*
* damapp: address map handle
* address: address in ascii string representation
* rindx: index if address stabilizes
* nvl: optional nvlist of configuration-private data
*
* Returns: DAM_SUCCESS
* DAM_EINVAL Invalid argument(s)
* DAM_MAPFULL address map exhausted
* DAM_FAILURE General failure
*/
int
{
return (DAM_EINVAL);
return (DAM_FAILURE);
}
return (DAM_MAPFULL);
}
char *, address);
}
if (nvl)
if (ridx)
return (DAM_SUCCESS);
}
/*
* Commit full-set report for stabilization
*
* damapp: address map handle
* flags: (currently 0)
*
* Returns: DAM_SUCCESS
* DAM_EINVAL Invalid argument(s)
* DAM_FAILURE General failure
*/
int
{
int i;
return (DAM_EINVAL);
return (DAM_FAILURE);
}
if (flags & DAMAP_END_RESET) {
if (DAM_IN_REPORT(mapp, i))
} else {
}
return (DAM_SUCCESS);
}
/*
* Return nvlist registered with reported address
*
* damapp: address map handle
* addrid: address ID
*
* Returns: nvlist_t * provider supplied via damap_addr{set}_add())
* NULL
*/
nvlist_t *
{
}
return (NULL);
}
/*
* Return address string
*
* damapp: address map handle
* addrid: address ID
*
* Returns: char * Address string
* NULL
*/
char *
{
else
return (NULL);
}
/*
* Release address reference in map
*
* damapp: address map handle
* addrid: address ID
*/
void
{
char *addr;
/*
* teardown address if last outstanding reference
*/
}
/*
* Return current reference count on address reference in map
*
* damapp: address map handle
* addrid: address ID
*
* Returns: DAM_SUCCESS
* DAM_FAILURE
*/
int
{
if (passp)
return (ref);
}
/*
* Return next address ID in list
*
* damapp: address map handle
* damap_list: address ID list passed to config|unconfig
* returned by look by lookup_all
* last: last ID returned, 0 is start of list
*
* Returns: addrid Next ID from the list
* 0 End of the list
*/
{
int i, start;
return ((damap_id_t)0);
if (bitset_in_set(dam_list, i)) {
return ((damap_id_t)i);
}
}
return ((damap_id_t)0);
}
/*
* Set config private data
*
* damapp: address map handle
* addrid: address ID
* cfg_priv: configuration private data
*
*/
void
{
if (!passp) {
return;
}
}
/*
* Get config private data
*
* damapp: address map handle
* addrid: address ID
*
* Returns: configuration private data
*/
void *
{
void *rv;
if (!passp) {
return (NULL);
}
return (rv);
}
/*
* Lookup a single address in the active address map
*
* damapp: address map handle
* address: address string
*
* 0 Address not in stable set
*
* Future: Allow the caller to wait for stabilize before returning not found.
*/
{
char *, address);
addrid = 0;
else
if (addrid) {
if (passp) {
} else {
addrid = 0;
}
} else {
addrid = 0;
}
}
return ((damap_id_t)addrid);
}
/*
* Return the list of stable addresses in the map
*
* damapp: address map handle
* id_listp: pointer to list of address IDs in stable map (returned)
*
* Returns: # of entries returned in alist
*/
int
{
int n_ids, i;
char *addrp;
return (0);
}
if (bitset_in_set(bsp, i)) {
if (passp) {
char *, addrp);
n_ids++;
}
}
}
if (n_ids) {
return (n_ids);
} else {
return (0);
}
}
/*
* Release the address list returned by damap_lookup_all()
*
* mapp: address map handle
* id_list: list of address IDs returned in damap_lookup_all()
*/
void
{
int i;
return;
(void) dam_addr_release(mapp, i);
}
}
/*
* activate an address that has passed the stabilization interval
*/
static void
{
int config_rv;
char *addrstr;
/*
* copy the reported nvlist and provider private data
*/
char *, addrstr);
passp->da_stable_cnt++;
if (mapp->dam_activate_cb) {
}
/*
* call the address-specific configuration action as part of
* activation.
*/
addrid);
if (config_rv != DAM_SUCCESS) {
char *, addrstr);
} else {
char *, addrstr);
}
}
/*
* deactivate a previously stable address
*/
static void
{
char *addrstr;
char *, addrstr);
/*
* call the unconfiguration callback
*/
}
static void
{
if (mapp->dam_deactivate_cb)
/*
* clear the active bit and free the backing info for
* this address
*/
char *, addrstr);
}
/*
* taskq callback for multi-thread activation
*/
static void
{
}
/*
* taskq callback for multi-thread deactivation
*/
static void
{
}
/*
* Activate a set of stabilized addresses
*/
static void
{
int i, nset;
extern pri_t maxclsyspri;
/*
* calculate the # of taskq threads to create
*/
if (bitset_in_set(activate, i))
nset++;
}
if (bitset_in_set(activate, i)) {
if (!tqp)
dam_addr_activate(mapp, i);
else {
/*
* multi-threaded activation
*/
}
}
}
if (tqp) {
}
}
/*
* Deactivate a set of stabilized addresses
*/
static void
{
int i, nset;
/*
* compute the # of taskq threads to dispatch
*/
if (bitset_in_set(deactivate, i))
nset++;
}
if (bitset_in_set(deactivate, i)) {
if (!tqp) {
dam_addr_deactivate(mapp, i);
} else {
(void) taskq_dispatch(tqp,
}
}
}
if (tqp) {
}
}
/*
* Release a previously activated address
*/
static void
{
char *addrstr;
char *, addrstr);
/*
* defer releasing the address until outstanding references
* are released
*/
return;
}
/*
* allow pending reports to stabilize
*/
char *, addrstr);
return;
}
}
/*
* process stabilized address reports
*/
static void
{
bitset_init(&delta);
bitset_init(&cfg);
bitset_init(&uncfg);
/*
* determine which addresses have changed during
* this stabilization cycle
*/
&delta)) {
/*
* no difference
*/
bitset_fini(&uncfg);
bitset_fini(&cfg);
bitset_fini(&delta);
return;
}
/*
* compute the sets of addresses to be activated and deactivated
*/
/*
* drop map lock while invoking callouts
*/
/*
* activate all newly stable addresss
*/
if (has_cfg)
/*
* deactivate addresss which are no longer in the map
*/
if (has_uncfg)
/*
* timestamp the last stable time and increment the kstat keeping
* the # of of stable cycles for the map
*/
mapp->dam_stable_cnt++;
/*
* determine the number of stable addresses
* and update the n_active kstat for this map
*/
n_active++;
int, n_active);
bitset_fini(&uncfg);
bitset_fini(&cfg);
bitset_fini(&delta);
}
/*
* per-address stabilization timeout
*/
static void
{
int i;
int spend = 0;
int tpend = 0;
return;
}
/*
* If still under stabilization, reschedule timeout,
* otherwise dispatch the task to activate and deactivate the
* new stable address
*/
return;
}
mapp->dam_stable_overrun = 0;
/* See if any reports stabalized and compute next timeout. */
ts = ddi_get_lbolt64();
spend++; /* report has stabilized */
else {
/* not stabilized, determine next map timeout */
tpend++;
if (delta_ticks < next_ticks)
}
}
}
/*
* schedule system_taskq activation of stabilized reports
*/
if (spend) {
/*
* The stable_set we compute below stays pending until
* processed by dam_stabilize_map. We can't set
* DAM_SPEND (or bitset_del things from the
* report_set) until we *know* that we can handoff the
* result to dam_stabilize_map. If dam_stabilize_map
* starts executing before we are complete, it will
* block on the dam_lock mutex until we are ready.
*/
/*
* Copy the current active_set to the stable_set, then
* add or remove stabilized report_set address from
* the stable set (and delete them from the report_set).
*/
&mapp->dam_stable_set);
continue;
continue; /* report not stabilized */
/* report has stabilized */
else
}
} else {
/*
* Avoid waiting the entire stabalization
* time again if taskq_diskpatch fails.
*/
tpend++;
if (delta_ticks < next_ticks)
}
}
/*
* reschedule the stabilization timer if there are reports
* still pending
*/
if (tpend) {
}
}
/*
* fullset stabilization timeout callback
*/
static void
{
return;
}
/*
* If map still underoing stabilization reschedule timeout,
* else dispatch the task to configure the new stable set of
* addresses.
*/
return;
}
mapp->dam_stable_overrun = 0;
/* NOTE: don't need cv_signal since DAM_SPEND is still set */
}
/*
* schedule map timeout in 'ticks' ticks
* if map timer is currently running, cancel if ticks == 0
*/
static void
{
if (ticks == 0) {
}
} else {
if (timeout_cb && (ticks != 0))
}
}
/*
* report addition or removal of an address
*/
static void
{
passp->da_report_cnt++;
if (rpt_type == RPT_ADDR_DEL)
else if (rpt_type == RPT_ADDR_ADD)
}
/*
* release an address report
*/
static void
{
char *, addrstr);
/*
* clear the report bit
* if the address has a registered deactivation handler and
* we are holding a private data pointer and the address has not
* stabilized, deactivate the address (private data).
*/
passp->da_ppriv_rpt) {
}
}
/*
* return the map ID of an address
*/
static id_t
{
address)) == (damap_id_t)0) {
return (0);
}
DDI_SUCCESS) {
return (0);
}
/*
* expand bitmaps if ID has outgrown old map size
*/
}
addrid); /* for mdb */
}
return (addrid);
}
/*
* create and install map statistics
*/
static int
{
sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
return (DDI_FAILURE);
return (DDI_SUCCESS);
}